Skip to content

Commit 3e5e3f0

Browse files
authored
Some code clean-ups and performance improvements (#2799)
Some trivial code clean-up and performance improvements: isNull instead of "= null": latkin.org/blog/2015/05/18/null-checking-considerations-in-f-its-harder-than-you-think Structs/ValueTuples on active patterns that doesn't carry lot of data Seq.map + Seq.concat = Seq.collect
1 parent 32ee50e commit 3e5e3f0

22 files changed

Lines changed: 115 additions & 108 deletions

File tree

src/app/Fake.BuildServer.TeamCity/TeamCityInternal.fs

Lines changed: 59 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -222,28 +222,34 @@ module private JavaPropertiesFile =
222222
| KeyValue of key: string * value: string
223223

224224
module private Parser =
225-
type CharReader = unit -> char option
225+
type CharReader = unit -> char voption
226226

227+
[<return: Struct>]
227228
let inline (|IsWhitespace|_|) c =
228229
match c with
229-
| Some c -> if c = ' ' || c = '\t' || c = '\u00ff' then Some c else None
230-
| None -> None
230+
| ValueSome c ->
231+
if c = ' ' || c = '\t' || c = '\u00ff' then
232+
ValueSome c
233+
else
234+
ValueNone
235+
| ValueNone -> ValueNone
231236

232237
type IsEof =
233238
| Yes = 1y
234239
| No = 0y
235240

236-
let rec readToFirstChar (c: char option) (reader: CharReader) =
241+
let rec readToFirstChar (c: char voption) (reader: CharReader) =
237242
match c with
238243
| IsWhitespace _ -> readToFirstChar (reader ()) reader
239-
| Some '\r'
240-
| Some '\n' -> None, IsEof.No
241-
| Some _ -> c, IsEof.No
242-
| None -> None, IsEof.Yes
244+
| ValueSome '\r'
245+
| ValueSome '\n' -> ValueNone, IsEof.No
246+
| ValueSome _ -> c, IsEof.No
247+
| ValueNone -> ValueNone, IsEof.Yes
243248

249+
[<return: Struct>]
244250
let inline (|EscapeSequence|_|) c =
245251
match c with
246-
| Some c ->
252+
| ValueSome c ->
247253
if
248254
c = 'r'
249255
|| c = 'n'
@@ -254,10 +260,10 @@ module private JavaPropertiesFile =
254260
|| c = '''
255261
|| c = '\\'
256262
then
257-
Some c
263+
ValueSome c
258264
else
259-
None
260-
| None -> None
265+
ValueNone
266+
| ValueNone -> ValueNone
261267

262268
let inline isHex c =
263269
(c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')
@@ -270,7 +276,9 @@ module private JavaPropertiesFile =
270276
| 't' -> '\t'
271277
| 'u' ->
272278
match reader (), reader (), reader (), reader () with
273-
| Some c1, Some c2, Some c3, Some c4 when isHex c1 && isHex c2 && isHex c3 && isHex c4 ->
279+
| ValueSome c1, ValueSome c2, ValueSome c3, ValueSome c4 when
280+
isHex c1 && isHex c2 && isHex c3 && isHex c4
281+
->
274282
let hex = String([| c1; c2; c3; c4 |])
275283

276284
let value =
@@ -280,89 +288,89 @@ module private JavaPropertiesFile =
280288
| _ -> failwith "Invalid unicode escape"
281289
| _ -> c
282290

283-
let inline readKey (c: char option) (reader: CharReader) (buffer: StringBuilder) =
291+
let inline readKey (c: char voption) (reader: CharReader) (buffer: StringBuilder) =
284292
let rec recurseEnd (result: string) =
285293
match reader () with
286-
| Some ':'
287-
| Some '='
294+
| ValueSome ':'
295+
| ValueSome '='
288296
| IsWhitespace _ -> recurseEnd result
289-
| Some '\r'
290-
| Some '\n' -> result, false, None, IsEof.No
291-
| None -> result, false, None, IsEof.Yes
292-
| Some c -> result, true, Some c, IsEof.No
297+
| ValueSome '\r'
298+
| ValueSome '\n' -> result, false, ValueNone, IsEof.No
299+
| ValueNone -> result, false, ValueNone, IsEof.Yes
300+
| ValueSome c -> result, true, ValueSome c, IsEof.No
293301

294-
let rec recurse (c: char option) (buffer: StringBuilder) (escaping: bool) =
302+
let rec recurse (c: char voption) (buffer: StringBuilder) (escaping: bool) =
295303
match c with
296304
| EscapeSequence c when escaping ->
297305
let realChar = readEscapeSequence c reader
298306
recurse (reader ()) (buffer.Append(realChar)) false
299-
| Some ' ' -> recurseEnd (buffer.ToString())
300-
| Some ':'
301-
| Some '=' when not escaping -> recurseEnd (buffer.ToString())
302-
| Some '\r'
303-
| Some '\n' -> buffer.ToString(), false, None, IsEof.No
304-
| None -> buffer.ToString(), false, None, IsEof.Yes
305-
| Some '\\' -> recurse (reader ()) buffer true
306-
| Some c -> recurse (reader ()) (buffer.Append(c)) false
307+
| ValueSome ' ' -> recurseEnd (buffer.ToString())
308+
| ValueSome ':'
309+
| ValueSome '=' when not escaping -> recurseEnd (buffer.ToString())
310+
| ValueSome '\r'
311+
| ValueSome '\n' -> buffer.ToString(), false, ValueNone, IsEof.No
312+
| ValueNone -> buffer.ToString(), false, ValueNone, IsEof.Yes
313+
| ValueSome '\\' -> recurse (reader ()) buffer true
314+
| ValueSome c -> recurse (reader ()) (buffer.Append(c)) false
307315

308316
recurse c buffer false
309317

310318
let rec readComment (reader: CharReader) (buffer: StringBuilder) =
311319
match reader () with
312-
| Some '\r'
313-
| Some '\n' -> Some(Comment(buffer.ToString())), IsEof.No
314-
| None -> Some(Comment(buffer.ToString())), IsEof.Yes
315-
| Some c -> readComment reader (buffer.Append(c))
320+
| ValueSome '\r'
321+
| ValueSome '\n' -> Some(Comment(buffer.ToString())), IsEof.No
322+
| ValueNone -> Some(Comment(buffer.ToString())), IsEof.Yes
323+
| ValueSome c -> readComment reader (buffer.Append(c))
316324

317-
let inline readValue (c: char option) (reader: CharReader) (buffer: StringBuilder) =
318-
let rec recurse (c: char option) (buffer: StringBuilder) (escaping: bool) (cr: bool) (lineStart: bool) =
325+
let inline readValue (c: char voption) (reader: CharReader) (buffer: StringBuilder) =
326+
let rec recurse (c: char voption) (buffer: StringBuilder) (escaping: bool) (cr: bool) (lineStart: bool) =
319327
match c with
320328
| EscapeSequence c when escaping ->
321329
let realChar = readEscapeSequence c reader
322330
recurse (reader ()) (buffer.Append(realChar)) false false false
323-
| Some '\r'
324-
| Some '\n' ->
325-
if escaping || (cr && c = Some '\n') then
326-
recurse (reader ()) buffer false (c = Some '\r') true
331+
| ValueSome '\r'
332+
| ValueSome '\n' ->
333+
if escaping || (cr && c = ValueSome '\n') then
334+
recurse (reader ()) buffer false (c = ValueSome '\r') true
327335
else
328336
buffer.ToString(), IsEof.No
329-
| None -> buffer.ToString(), IsEof.Yes
330-
| Some _ when lineStart ->
337+
| ValueNone -> buffer.ToString(), IsEof.Yes
338+
| ValueSome _ when lineStart ->
331339
let firstChar, _ = readToFirstChar c reader
332340
recurse firstChar buffer false false false
333-
| Some '\\' -> recurse (reader ()) buffer true false false
334-
| Some c -> recurse (reader ()) (buffer.Append(c)) false false false
341+
| ValueSome '\\' -> recurse (reader ()) buffer true false false
342+
| ValueSome c -> recurse (reader ()) (buffer.Append(c)) false false false
335343

336344
recurse c buffer false false true
337345

338346
let rec readLine (reader: CharReader) (buffer: StringBuilder) =
339347
match readToFirstChar (reader ()) reader with
340-
| Some '#', _
341-
| Some '!', _ -> readComment reader (buffer.Clear())
342-
| Some firstChar, _ ->
343-
let key, hasValue, c, isEof = readKey (Some firstChar) reader (buffer.Clear())
348+
| ValueSome '#', _
349+
| ValueSome '!', _ -> readComment reader (buffer.Clear())
350+
| ValueSome firstChar, _ ->
351+
let key, hasValue, c, isEof = readKey (ValueSome firstChar) reader (buffer.Clear())
344352

345353
let value, isEof =
346354
if hasValue then
347355
// We know that we aren't at the end of the buffer, but readKey can return None if it didn't need the next char
348356
let firstChar =
349357
match c with
350-
| Some c -> Some c
351-
| None -> reader ()
358+
| ValueSome c -> ValueSome c
359+
| ValueNone -> reader ()
352360

353361
readValue firstChar reader (buffer.Clear())
354362
else
355363
"", isEof
356364

357365
Some(KeyValue(key, value)), isEof
358-
| None, isEof -> None, isEof
366+
| ValueNone, isEof -> None, isEof
359367

360368
let inline textReaderToReader (reader: TextReader) =
361369
let buffer = [| '\u0000' |]
362370

363371
fun () ->
364372
let eof = reader.Read(buffer, 0, 1) = 0
365-
if eof then None else Some(buffer[0])
373+
if eof then ValueNone else ValueSome(buffer[0])
366374

367375
let parseWithReader reader =
368376
let buffer = StringBuilder(255)

src/app/Fake.Core.CommandLineParsing/docopt.fs/Docopt/Docopt.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ module DocHelper =
3333
let title = line'.Substring(0, idxCol)
3434

3535
let sectionName =
36-
let startIdx = title.IndexOf("[")
37-
let endIdx = title.IndexOf("]")
36+
let startIdx = title.IndexOf '['
37+
let endIdx = title.IndexOf ']'
3838

3939
if startIdx <> -1 && endIdx > startIdx then
4040
title.Substring(startIdx + 1, endIdx - startIdx - 1)

src/app/Fake.Core.Environment/Environment.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ module Environment =
359359
/// </summary>
360360
let getNewestTool possibleToolPaths =
361361
possibleToolPaths
362-
|> Seq.sortBy (fun p -> p)
362+
|> Seq.sortBy id
363363
|> Array.ofSeq
364364
|> Array.rev
365365
|> Seq.ofArray

src/app/Fake.Core.Process/InternalStreams.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ module internal InternalStreams =
136136
(fun res -> endAction res),
137137
cancelAction =
138138
(fun () ->
139-
while asyncResult.Value = null do
139+
while isNull asyncResult.Value do
140140
Thread.Sleep 20
141141

142142
cancelAction (asyncResult.Value))
@@ -265,7 +265,7 @@ module internal InternalStreams =
265265
data <- resultData
266266
event.Set() |> ignore
267267

268-
if callback <> null then
268+
if not (isNull callback) then
269269
callback.Invoke(x :> IAsyncResult)
270270

271271
completed <- true)

src/app/Fake.Core.SemVer/SemVer.fs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,6 @@ open System.Text.RegularExpressions
1010
/// Contains active patterns which allow to deal with <a href="http://semver.org/">Semantic Versioning (SemVer)</a>.
1111
/// </summary>
1212
module SemVerActivePattern =
13-
let (|ParseRegex|_|) pattern input =
14-
let m = Regex.Match(input, pattern, RegexOptions.ExplicitCapture)
15-
16-
match m.Success with
17-
| true -> Some(List.tail [ for g in m.Groups -> g.Value ])
18-
| false -> None
1913

2014
[<Literal>]
2115
let Pattern =
@@ -25,10 +19,19 @@ module SemVerActivePattern =
2519
+ @"(\-(?<pre>[0-9A-Za-z\-\.]+))?"
2620
+ @"(\+(?<build>[0-9A-Za-z\-\.]+))?$"
2721

22+
let RegMatch = Regex(Pattern, RegexOptions.ExplicitCapture)
23+
24+
let (|ParseRegex|_|) input =
25+
let m = RegMatch.Match input
26+
27+
match m.Success with
28+
| true -> Some(List.tail [ for g in m.Groups -> g.Value ])
29+
| false -> None
30+
2831
let (|SemVer|_|) version =
2932

3033
match version with
31-
| ParseRegex Pattern [ major; minor; patch; pre; build ] -> Some [ major; minor; patch; pre; build ]
34+
| ParseRegex [ major; minor; patch; pre; build ] -> Some [ major; minor; patch; pre; build ]
3235
| _ -> None
3336

3437
let (|ValidVersion|_|) =
@@ -273,18 +276,20 @@ module SemVer =
273276
/// <summary>
274277
/// Matches if str is convertible to Int and not less than zero, and returns the value as UInt.
275278
/// </summary>
279+
[<return: Struct>]
276280
let inline private (|Int|_|) (str: string) =
277281
match Int32.TryParse(str, NumberStyles.Integer, null) with
278-
| true, num when num > -1 -> Some num
279-
| _ -> None
282+
| true, num when num > -1 -> ValueSome num
283+
| _ -> ValueNone
280284

281285
/// <summary>
282286
/// Matches if str is convertible to big int and not less than zero, and returns the bigint value.
283287
/// </summary>
288+
[<return: Struct>]
284289
let inline private (|Big|_|) (str: string) =
285290
match BigInteger.TryParse(str, NumberStyles.Integer, null) with
286-
| true, big when big > -1I -> Some big
287-
| _ -> None
291+
| true, big when big > -1I -> ValueSome big
292+
| _ -> ValueNone
288293

289294
/// <summary>
290295
/// Splits the given version string by possible delimiters but keeps them as parts of resulting list.
@@ -340,7 +345,7 @@ module SemVer =
340345
if version.Contains("..") then
341346
failwithf "Empty version part found in %s" version
342347

343-
let plusIndex = version.IndexOf("+")
348+
let plusIndex = version.IndexOf '+'
344349

345350
let versionStr =
346351
match plusIndex with

src/app/Fake.Core.String/String.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ module String =
172172
/// Removes all trailing .0 from a version string
173173
/// </summary>
174174
let rec NormalizeVersion (version: string) =
175-
if version = null then
175+
if isNull version then
176176
""
177177
else
178178
let elements = version.Split [| '.' |]

src/app/Fake.Core.String/StringBuilder.fs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ module StringBuilder =
4848
/// </summary>
4949
let inline appendWithoutQuotesIfNotNull (value: Object) s =
5050
appendIfTrueWithoutQuotes
51-
(value <> null)
51+
(not (isNull value))
5252
(match value with
5353
| :? String as sv -> (sprintf "%s%s" s sv)
5454
| _ -> (sprintf "%s%A" s value))
@@ -58,7 +58,7 @@ module StringBuilder =
5858
/// </summary>
5959
let inline appendIfNotNull (value: Object) s =
6060
appendIfTrue
61-
(value <> null)
61+
(not (isNull value))
6262
(match value with
6363
| :? String as sv -> (sprintf "%s%s" s sv)
6464
| _ -> (sprintf "%s%A" s value))
@@ -67,7 +67,7 @@ module StringBuilder =
6767
/// Appends a quoted text if the value is not null.
6868
/// </summary>
6969
let inline appendQuotedIfNotNull (value: Object) s (builder: StringBuilder) =
70-
if (value = null) then
70+
if isNull value then
7171
builder
7272
else
7373
(match value with

src/app/Fake.Core.Target/Target.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -861,7 +861,7 @@ module Target =
861861
let isValidTarget name = targetLeftSet.Contains(name)
862862

863863
let canBeExecuted (t: Target) =
864-
t.Dependencies @ t.SoftDependencies |> Seq.filter isValidTarget |> Seq.isEmpty
864+
t.Dependencies @ t.SoftDependencies |> Seq.exists isValidTarget |> not
865865

866866
let map =
867867
targetLeft

0 commit comments

Comments
 (0)