From 23a0507325f26fe587175f867878160033af2699 Mon Sep 17 00:00:00 2001 From: Tuomas Hietanen Date: Tue, 6 Aug 2024 13:55:42 +0100 Subject: [PATCH] Some code clean-ups and performance improvements --- .../TeamCityInternal.fs | 110 ++++++++++-------- .../docopt.fs/Docopt/Docopt.fs | 4 +- src/app/Fake.Core.Environment/Environment.fs | 2 +- src/app/Fake.Core.Process/InternalStreams.fs | 4 +- src/app/Fake.Core.SemVer/SemVer.fs | 29 +++-- src/app/Fake.Core.String/String.fs | 2 +- src/app/Fake.Core.String/StringBuilder.fs | 6 +- src/app/Fake.Core.Target/Target.fs | 2 +- src/app/Fake.Core.Xml/Xml.fs | 12 +- .../Fake.DotNet.FSFormatting/FSFormatting.fs | 6 +- src/app/Fake.DotNet.NuGet/NuGet.fs | 8 +- src/app/Fake.DotNet.NuGet/NuGetVersion.fs | 2 +- src/app/Fake.DotNet.Paket/PaketTemplate.fs | 2 +- .../Fake.DotNet.Testing.DotCover/DotCover.fs | 2 +- src/app/Fake.DotNet.Testing.MSTest/MSTest.fs | 2 +- src/app/Fake.DotNet.Testing.NUnit/Xml.fs | 3 +- .../OpenCover.fs | 2 +- src/app/Fake.IO.FileSystem/Globbing.fs | 2 +- src/app/Fake.IO.Zip/Zip.fs | 3 +- src/app/Fake.Runtime/FakeRuntimeHints.fs | 2 +- src/app/Fake.Runtime/YaafFSharpScripting.fs | 16 ++- src/app/Fake.Tools.Git/Submodule.fs | 2 +- 22 files changed, 115 insertions(+), 108 deletions(-) diff --git a/src/app/Fake.BuildServer.TeamCity/TeamCityInternal.fs b/src/app/Fake.BuildServer.TeamCity/TeamCityInternal.fs index 68537128a5e..0d668446a3b 100644 --- a/src/app/Fake.BuildServer.TeamCity/TeamCityInternal.fs +++ b/src/app/Fake.BuildServer.TeamCity/TeamCityInternal.fs @@ -222,28 +222,34 @@ module private JavaPropertiesFile = | KeyValue of key: string * value: string module private Parser = - type CharReader = unit -> char option + type CharReader = unit -> char voption + [] let inline (|IsWhitespace|_|) c = match c with - | Some c -> if c = ' ' || c = '\t' || c = '\u00ff' then Some c else None - | None -> None + | ValueSome c -> + if c = ' ' || c = '\t' || c = '\u00ff' then + ValueSome c + else + ValueNone + | ValueNone -> ValueNone type IsEof = | Yes = 1y | No = 0y - let rec readToFirstChar (c: char option) (reader: CharReader) = + let rec readToFirstChar (c: char voption) (reader: CharReader) = match c with | IsWhitespace _ -> readToFirstChar (reader ()) reader - | Some '\r' - | Some '\n' -> None, IsEof.No - | Some _ -> c, IsEof.No - | None -> None, IsEof.Yes + | ValueSome '\r' + | ValueSome '\n' -> ValueNone, IsEof.No + | ValueSome _ -> c, IsEof.No + | ValueNone -> ValueNone, IsEof.Yes + [] let inline (|EscapeSequence|_|) c = match c with - | Some c -> + | ValueSome c -> if c = 'r' || c = 'n' @@ -254,10 +260,10 @@ module private JavaPropertiesFile = || c = ''' || c = '\\' then - Some c + ValueSome c else - None - | None -> None + ValueNone + | ValueNone -> ValueNone let inline isHex c = (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f') @@ -270,7 +276,9 @@ module private JavaPropertiesFile = | 't' -> '\t' | 'u' -> match reader (), reader (), reader (), reader () with - | Some c1, Some c2, Some c3, Some c4 when isHex c1 && isHex c2 && isHex c3 && isHex c4 -> + | ValueSome c1, ValueSome c2, ValueSome c3, ValueSome c4 when + isHex c1 && isHex c2 && isHex c3 && isHex c4 + -> let hex = String([| c1; c2; c3; c4 |]) let value = @@ -280,89 +288,89 @@ module private JavaPropertiesFile = | _ -> failwith "Invalid unicode escape" | _ -> c - let inline readKey (c: char option) (reader: CharReader) (buffer: StringBuilder) = + let inline readKey (c: char voption) (reader: CharReader) (buffer: StringBuilder) = let rec recurseEnd (result: string) = match reader () with - | Some ':' - | Some '=' + | ValueSome ':' + | ValueSome '=' | IsWhitespace _ -> recurseEnd result - | Some '\r' - | Some '\n' -> result, false, None, IsEof.No - | None -> result, false, None, IsEof.Yes - | Some c -> result, true, Some c, IsEof.No + | ValueSome '\r' + | ValueSome '\n' -> result, false, ValueNone, IsEof.No + | ValueNone -> result, false, ValueNone, IsEof.Yes + | ValueSome c -> result, true, ValueSome c, IsEof.No - let rec recurse (c: char option) (buffer: StringBuilder) (escaping: bool) = + let rec recurse (c: char voption) (buffer: StringBuilder) (escaping: bool) = match c with | EscapeSequence c when escaping -> let realChar = readEscapeSequence c reader recurse (reader ()) (buffer.Append(realChar)) false - | Some ' ' -> recurseEnd (buffer.ToString()) - | Some ':' - | Some '=' when not escaping -> recurseEnd (buffer.ToString()) - | Some '\r' - | Some '\n' -> buffer.ToString(), false, None, IsEof.No - | None -> buffer.ToString(), false, None, IsEof.Yes - | Some '\\' -> recurse (reader ()) buffer true - | Some c -> recurse (reader ()) (buffer.Append(c)) false + | ValueSome ' ' -> recurseEnd (buffer.ToString()) + | ValueSome ':' + | ValueSome '=' when not escaping -> recurseEnd (buffer.ToString()) + | ValueSome '\r' + | ValueSome '\n' -> buffer.ToString(), false, ValueNone, IsEof.No + | ValueNone -> buffer.ToString(), false, ValueNone, IsEof.Yes + | ValueSome '\\' -> recurse (reader ()) buffer true + | ValueSome c -> recurse (reader ()) (buffer.Append(c)) false recurse c buffer false let rec readComment (reader: CharReader) (buffer: StringBuilder) = match reader () with - | Some '\r' - | Some '\n' -> Some(Comment(buffer.ToString())), IsEof.No - | None -> Some(Comment(buffer.ToString())), IsEof.Yes - | Some c -> readComment reader (buffer.Append(c)) + | ValueSome '\r' + | ValueSome '\n' -> Some(Comment(buffer.ToString())), IsEof.No + | ValueNone -> Some(Comment(buffer.ToString())), IsEof.Yes + | ValueSome c -> readComment reader (buffer.Append(c)) - let inline readValue (c: char option) (reader: CharReader) (buffer: StringBuilder) = - let rec recurse (c: char option) (buffer: StringBuilder) (escaping: bool) (cr: bool) (lineStart: bool) = + let inline readValue (c: char voption) (reader: CharReader) (buffer: StringBuilder) = + let rec recurse (c: char voption) (buffer: StringBuilder) (escaping: bool) (cr: bool) (lineStart: bool) = match c with | EscapeSequence c when escaping -> let realChar = readEscapeSequence c reader recurse (reader ()) (buffer.Append(realChar)) false false false - | Some '\r' - | Some '\n' -> - if escaping || (cr && c = Some '\n') then - recurse (reader ()) buffer false (c = Some '\r') true + | ValueSome '\r' + | ValueSome '\n' -> + if escaping || (cr && c = ValueSome '\n') then + recurse (reader ()) buffer false (c = ValueSome '\r') true else buffer.ToString(), IsEof.No - | None -> buffer.ToString(), IsEof.Yes - | Some _ when lineStart -> + | ValueNone -> buffer.ToString(), IsEof.Yes + | ValueSome _ when lineStart -> let firstChar, _ = readToFirstChar c reader recurse firstChar buffer false false false - | Some '\\' -> recurse (reader ()) buffer true false false - | Some c -> recurse (reader ()) (buffer.Append(c)) false false false + | ValueSome '\\' -> recurse (reader ()) buffer true false false + | ValueSome c -> recurse (reader ()) (buffer.Append(c)) false false false recurse c buffer false false true let rec readLine (reader: CharReader) (buffer: StringBuilder) = match readToFirstChar (reader ()) reader with - | Some '#', _ - | Some '!', _ -> readComment reader (buffer.Clear()) - | Some firstChar, _ -> - let key, hasValue, c, isEof = readKey (Some firstChar) reader (buffer.Clear()) + | ValueSome '#', _ + | ValueSome '!', _ -> readComment reader (buffer.Clear()) + | ValueSome firstChar, _ -> + let key, hasValue, c, isEof = readKey (ValueSome firstChar) reader (buffer.Clear()) let value, isEof = if hasValue then // 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 let firstChar = match c with - | Some c -> Some c - | None -> reader () + | ValueSome c -> ValueSome c + | ValueNone -> reader () readValue firstChar reader (buffer.Clear()) else "", isEof Some(KeyValue(key, value)), isEof - | None, isEof -> None, isEof + | ValueNone, isEof -> None, isEof let inline textReaderToReader (reader: TextReader) = let buffer = [| '\u0000' |] fun () -> let eof = reader.Read(buffer, 0, 1) = 0 - if eof then None else Some(buffer[0]) + if eof then ValueNone else ValueSome(buffer[0]) let parseWithReader reader = let buffer = StringBuilder(255) diff --git a/src/app/Fake.Core.CommandLineParsing/docopt.fs/Docopt/Docopt.fs b/src/app/Fake.Core.CommandLineParsing/docopt.fs/Docopt/Docopt.fs index 8d9c27679ea..d787b3926df 100644 --- a/src/app/Fake.Core.CommandLineParsing/docopt.fs/Docopt/Docopt.fs +++ b/src/app/Fake.Core.CommandLineParsing/docopt.fs/Docopt/Docopt.fs @@ -33,8 +33,8 @@ module DocHelper = let title = line'.Substring(0, idxCol) let sectionName = - let startIdx = title.IndexOf("[") - let endIdx = title.IndexOf("]") + let startIdx = title.IndexOf '[' + let endIdx = title.IndexOf ']' if startIdx <> -1 && endIdx > startIdx then title.Substring(startIdx + 1, endIdx - startIdx - 1) diff --git a/src/app/Fake.Core.Environment/Environment.fs b/src/app/Fake.Core.Environment/Environment.fs index c8b06355606..d7876febab1 100644 --- a/src/app/Fake.Core.Environment/Environment.fs +++ b/src/app/Fake.Core.Environment/Environment.fs @@ -359,7 +359,7 @@ module Environment = /// let getNewestTool possibleToolPaths = possibleToolPaths - |> Seq.sortBy (fun p -> p) + |> Seq.sortBy id |> Array.ofSeq |> Array.rev |> Seq.ofArray diff --git a/src/app/Fake.Core.Process/InternalStreams.fs b/src/app/Fake.Core.Process/InternalStreams.fs index a5ca181c897..59896a564c7 100644 --- a/src/app/Fake.Core.Process/InternalStreams.fs +++ b/src/app/Fake.Core.Process/InternalStreams.fs @@ -136,7 +136,7 @@ module internal InternalStreams = (fun res -> endAction res), cancelAction = (fun () -> - while asyncResult.Value = null do + while isNull asyncResult.Value do Thread.Sleep 20 cancelAction (asyncResult.Value)) @@ -265,7 +265,7 @@ module internal InternalStreams = data <- resultData event.Set() |> ignore - if callback <> null then + if not (isNull callback) then callback.Invoke(x :> IAsyncResult) completed <- true) diff --git a/src/app/Fake.Core.SemVer/SemVer.fs b/src/app/Fake.Core.SemVer/SemVer.fs index 834ae8b903c..1889ee73dfd 100644 --- a/src/app/Fake.Core.SemVer/SemVer.fs +++ b/src/app/Fake.Core.SemVer/SemVer.fs @@ -10,12 +10,6 @@ open System.Text.RegularExpressions /// Contains active patterns which allow to deal with Semantic Versioning (SemVer). /// module SemVerActivePattern = - let (|ParseRegex|_|) pattern input = - let m = Regex.Match(input, pattern, RegexOptions.ExplicitCapture) - - match m.Success with - | true -> Some(List.tail [ for g in m.Groups -> g.Value ]) - | false -> None [] let Pattern = @@ -25,10 +19,19 @@ module SemVerActivePattern = + @"(\-(?
[0-9A-Za-z\-\.]+))?"
         + @"(\+(?[0-9A-Za-z\-\.]+))?$"
 
+    let RegMatch = Regex(Pattern, RegexOptions.ExplicitCapture)
+
+    let (|ParseRegex|_|) input =
+        let m = RegMatch.Match input
+
+        match m.Success with
+        | true -> Some(List.tail [ for g in m.Groups -> g.Value ])
+        | false -> None
+
     let (|SemVer|_|) version =
 
         match version with
-        | ParseRegex Pattern [ major; minor; patch; pre; build ] -> Some [ major; minor; patch; pre; build ]
+        | ParseRegex [ major; minor; patch; pre; build ] -> Some [ major; minor; patch; pre; build ]
         | _ -> None
 
     let (|ValidVersion|_|) =
@@ -273,18 +276,20 @@ module SemVer =
     /// 
     /// Matches if str is convertible to Int and not less than zero, and returns the value as UInt.
     /// 
+    []
     let inline private (|Int|_|) (str: string) =
         match Int32.TryParse(str, NumberStyles.Integer, null) with
-        | true, num when num > -1 -> Some num
-        | _ -> None
+        | true, num when num > -1 -> ValueSome num
+        | _ -> ValueNone
 
     /// 
     /// Matches if str is convertible to big int and not less than zero, and returns the bigint value.
     /// 
+    []
     let inline private (|Big|_|) (str: string) =
         match BigInteger.TryParse(str, NumberStyles.Integer, null) with
-        | true, big when big > -1I -> Some big
-        | _ -> None
+        | true, big when big > -1I -> ValueSome big
+        | _ -> ValueNone
 
     /// 
     /// Splits the given version string by possible delimiters but keeps them as parts of resulting list.
@@ -340,7 +345,7 @@ module SemVer =
             if version.Contains("..") then
                 failwithf "Empty version part found in %s" version
 
-            let plusIndex = version.IndexOf("+")
+            let plusIndex = version.IndexOf '+'
 
             let versionStr =
                 match plusIndex with
diff --git a/src/app/Fake.Core.String/String.fs b/src/app/Fake.Core.String/String.fs
index cea1f57d55c..e440db8212d 100644
--- a/src/app/Fake.Core.String/String.fs
+++ b/src/app/Fake.Core.String/String.fs
@@ -172,7 +172,7 @@ module String =
     /// Removes all trailing .0 from a version string
     /// 
     let rec NormalizeVersion (version: string) =
-        if version = null then
+        if isNull version then
             ""
         else
             let elements = version.Split [| '.' |]
diff --git a/src/app/Fake.Core.String/StringBuilder.fs b/src/app/Fake.Core.String/StringBuilder.fs
index dac4953202c..305a6b6f7df 100644
--- a/src/app/Fake.Core.String/StringBuilder.fs
+++ b/src/app/Fake.Core.String/StringBuilder.fs
@@ -48,7 +48,7 @@ module StringBuilder =
     /// 
     let inline appendWithoutQuotesIfNotNull (value: Object) s =
         appendIfTrueWithoutQuotes
-            (value <> null)
+            (not (isNull value))
             (match value with
              | :? String as sv -> (sprintf "%s%s" s sv)
              | _ -> (sprintf "%s%A" s value))
@@ -58,7 +58,7 @@ module StringBuilder =
     /// 
     let inline appendIfNotNull (value: Object) s =
         appendIfTrue
-            (value <> null)
+            (not (isNull value))
             (match value with
              | :? String as sv -> (sprintf "%s%s" s sv)
              | _ -> (sprintf "%s%A" s value))
@@ -67,7 +67,7 @@ module StringBuilder =
     /// Appends a quoted text if the value is not null.
     /// 
     let inline appendQuotedIfNotNull (value: Object) s (builder: StringBuilder) =
-        if (value = null) then
+        if isNull value then
             builder
         else
             (match value with
diff --git a/src/app/Fake.Core.Target/Target.fs b/src/app/Fake.Core.Target/Target.fs
index dde9652f7a5..faf1bc88750 100644
--- a/src/app/Fake.Core.Target/Target.fs
+++ b/src/app/Fake.Core.Target/Target.fs
@@ -861,7 +861,7 @@ module Target =
             let isValidTarget name = targetLeftSet.Contains(name)
 
             let canBeExecuted (t: Target) =
-                t.Dependencies @ t.SoftDependencies |> Seq.filter isValidTarget |> Seq.isEmpty
+                t.Dependencies @ t.SoftDependencies |> Seq.exists isValidTarget |> not
 
             let map =
                 targetLeft
diff --git a/src/app/Fake.Core.Xml/Xml.fs b/src/app/Fake.Core.Xml/Xml.fs
index 4e5164e0c48..813c7f946d7 100644
--- a/src/app/Fake.Core.Xml/Xml.fs
+++ b/src/app/Fake.Core.Xml/Xml.fs
@@ -216,7 +216,7 @@ module Xml =
     let replaceXPath xpath value (doc: XmlDocument) =
         let node = doc.SelectSingleNode xpath
 
-        if node = null then
+        if isNull node then
             failwithf "XML node '%s' not found" xpath
         else
             node.Value <- value
@@ -272,7 +272,7 @@ module Xml =
         namespaces |> Seq.iter nsmgr.AddNamespace
         let node = doc.DocumentElement.SelectSingleNode(xpath, nsmgr)
 
-        if node = null then
+        if isNull node then
             failwithf "XML node '%s' not found" xpath
         else
             node.InnerText
@@ -290,7 +290,7 @@ module Xml =
         namespaces |> Seq.iter nsmgr.AddNamespace
         let node = doc.DocumentElement.SelectSingleNode(xpath, nsmgr)
 
-        if node = null then
+        if isNull node then
             failwithf "XML node '%s' not found" xpath
         else
             let attributeValue = node.Attributes[attribute]
@@ -312,7 +312,7 @@ module Xml =
         namespaces |> Seq.iter nsmgr.AddNamespace
         let node = doc.DocumentElement.SelectSingleNode(xpath, nsmgr)
 
-        if node = null then
+        if isNull node then
             failwithf "XML node '%s' not found" xpath
         else
             node
@@ -396,7 +396,7 @@ module Xml =
         namespaces |> Seq.iter nsmgr.AddNamespace
         let node = doc.SelectSingleNode(xpath, nsmgr)
 
-        if node = null then
+        if isNull node then
             failwithf "XML node '%s' not found" xpath
         else
             node.Value <- value
@@ -416,7 +416,7 @@ module Xml =
         namespaces |> Seq.iter nsmgr.AddNamespace
         let node = doc.SelectSingleNode(xpath, nsmgr)
 
-        if node = null then
+        if isNull node then
             failwithf "XML node '%s' not found" xpath
         else
             node.InnerText <- innerTextValue
diff --git a/src/app/Fake.DotNet.FSFormatting/FSFormatting.fs b/src/app/Fake.DotNet.FSFormatting/FSFormatting.fs
index 0f45d4e421d..142ce29f7ab 100644
--- a/src/app/Fake.DotNet.FSFormatting/FSFormatting.fs
+++ b/src/app/Fake.DotNet.FSFormatting/FSFormatting.fs
@@ -77,8 +77,7 @@ let createDocs p =
 
     let command =
         arguments.ProjectParameters
-        |> Seq.map (fun (k, v) -> [ k; v ])
-        |> Seq.concat
+        |> Seq.collect (fun (k, v) -> [ k; v ])
         |> Seq.append (
             [ "literate"; "--processdirectory" ]
             @ layoutroots
@@ -143,8 +142,7 @@ let createDocsForDlls (p: MetadataFormatArguments -> MetadataFormatArguments) dl
 
 
     projectParameters
-    |> Seq.map (fun (k, v) -> [ k; v ])
-    |> Seq.concat
+    |> Seq.collect (fun (k, v) -> [ k; v ])
     |> Seq.append (
         [ "metadataformat"; "--generate"; "--outdir"; outputDir ]
         @ layoutroots
diff --git a/src/app/Fake.DotNet.NuGet/NuGet.fs b/src/app/Fake.DotNet.NuGet/NuGet.fs
index 7a391eaa177..3a4b148c0a0 100644
--- a/src/app/Fake.DotNet.NuGet/NuGet.fs
+++ b/src/app/Fake.DotNet.NuGet/NuGet.fs
@@ -307,7 +307,7 @@ module NuGet =
             |> String.toLines
 
         let getGroup items toTags =
-            if items = [] then
+            if List.isEmpty items then
                 ""
             else
                 sprintf "%s" (items |> toTags)
@@ -330,7 +330,7 @@ module NuGet =
         let getFrameworkAssemblyTags references =
             references
             |> Seq.map (fun x ->
-                if x.FrameworkVersions = [] then
+                if List.isEmpty x.FrameworkVersions then
                     sprintf "" x.AssemblyName
                 else
                     sprintf
@@ -340,7 +340,7 @@ module NuGet =
             |> String.toLines
 
         let frameworkAssembliesXml =
-            if parameters.FrameworkAssemblies = [] then
+            if List.isEmpty parameters.FrameworkAssemblies then
                 ""
             else
                 sprintf
@@ -417,7 +417,7 @@ module NuGet =
                 XText(notEncodedText).ToString().Replace("�", "ß")
 
         let toSingleLine (text: string) =
-            if text = null then
+            if isNull text then
                 null
             else
                 text.Replace("\r", "").Replace("\n", "").Replace("  ", " ")
diff --git a/src/app/Fake.DotNet.NuGet/NuGetVersion.fs b/src/app/Fake.DotNet.NuGet/NuGetVersion.fs
index d8483000dbb..8a6649bf01c 100644
--- a/src/app/Fake.DotNet.NuGet/NuGetVersion.fs
+++ b/src/app/Fake.DotNet.NuGet/NuGetVersion.fs
@@ -162,7 +162,7 @@ module Version =
                         Some <| SemVer.parse m.Identity.Version.OriginalVersion
                     with _ ->
                         None)
-                |> Seq.sortByDescending (fun v -> v)
+                |> Seq.sortByDescending id
                 |> Seq.tryHead
         }
         |> Async.RunSynchronously
diff --git a/src/app/Fake.DotNet.Paket/PaketTemplate.fs b/src/app/Fake.DotNet.Paket/PaketTemplate.fs
index b30a94f4310..0574dc4b26c 100644
--- a/src/app/Fake.DotNet.Paket/PaketTemplate.fs
+++ b/src/app/Fake.DotNet.Paket/PaketTemplate.fs
@@ -229,7 +229,7 @@ module internal Rendering =
     let inline appendListWithName name lines (sb: StringBuilder) =
         match lines with
         | [] -> sb
-        | singleLine :: [] -> sb |> appendWithName name singleLine
+        | [ singleLine ] -> sb |> appendWithName name singleLine
         | _ ->
             lines
             |> Seq.fold (fun s line -> s |> appendIndented line) (sb.Append(sprintf "%s\n" name))
diff --git a/src/app/Fake.DotNet.Testing.DotCover/DotCover.fs b/src/app/Fake.DotNet.Testing.DotCover/DotCover.fs
index 92124afbfa3..deaf756a697 100644
--- a/src/app/Fake.DotNet.Testing.DotCover/DotCover.fs
+++ b/src/app/Fake.DotNet.Testing.DotCover/DotCover.fs
@@ -341,7 +341,7 @@ module DotCover =
             assemblies |> Array.map (fun a -> "/testcontainer:" + a) |> String.concat " "
 
         let testResultsFile =
-            if parameters.ResultsDir <> null then
+            if not (isNull parameters.ResultsDir) then
                 sprintf @"%s\%s.trx" parameters.ResultsDir (DateTime.Now.ToString("yyyyMMdd-HHmmss.ff"))
             else
                 null
diff --git a/src/app/Fake.DotNet.Testing.MSTest/MSTest.fs b/src/app/Fake.DotNet.Testing.MSTest/MSTest.fs
index 7e4fd2ea63d..29f2613fc9b 100644
--- a/src/app/Fake.DotNet.Testing.MSTest/MSTest.fs
+++ b/src/app/Fake.DotNet.Testing.MSTest/MSTest.fs
@@ -98,7 +98,7 @@ module MSTest =
     /// 
     let buildArgs (parameters: MSTestParams) (assembly: string) =
         let testResultsFile =
-            if parameters.ResultsDir <> null then
+            if not (isNull parameters.ResultsDir) then
                 sprintf @"%s\%s.trx" parameters.ResultsDir (DateTime.Now.ToString("yyyyMMdd-HHmmss.ff"))
             else
                 null
diff --git a/src/app/Fake.DotNet.Testing.NUnit/Xml.fs b/src/app/Fake.DotNet.Testing.NUnit/Xml.fs
index d6a3dfa8126..0c8b0283caf 100644
--- a/src/app/Fake.DotNet.Testing.NUnit/Xml.fs
+++ b/src/app/Fake.DotNet.Testing.NUnit/Xml.fs
@@ -38,8 +38,7 @@ module Xml =
     /// A sequence of XML documents
     let AllSucceeded xDocs =
         xDocs
-        |> Seq.map GetTestAssemblies
-        |> Seq.concat
+        |> Seq.collect GetTestAssemblies
         |> Seq.map (fun assembly -> assembly.Attribute(imp "result").Value)
         |> Seq.map ((<>) "Failure")
         |> Seq.reduce (&&)
diff --git a/src/app/Fake.DotNet.Testing.OpenCover/OpenCover.fs b/src/app/Fake.DotNet.Testing.OpenCover/OpenCover.fs
index 640c76e8aac..a3eebdceef6 100644
--- a/src/app/Fake.DotNet.Testing.OpenCover/OpenCover.fs
+++ b/src/app/Fake.DotNet.Testing.OpenCover/OpenCover.fs
@@ -136,7 +136,7 @@ module OpenCover =
             printParamWithValue paramName (mergeListAsValues paramList valueModification)
 
         let printParamListAsValuesWithQuote paramName paramList =
-            printParamWithValue paramName (quote (mergeListAsValues paramList (fun v -> v)))
+            printParamWithValue paramName (quote (mergeListAsValues paramList id))
 
         let printParamListAsValues paramName paramList =
             printParamListAsValuesWithModification paramName paramList (fun v -> string v)
diff --git a/src/app/Fake.IO.FileSystem/Globbing.fs b/src/app/Fake.IO.FileSystem/Globbing.fs
index 8bf51c85b55..de00e460cc2 100644
--- a/src/app/Fake.IO.FileSystem/Globbing.fs
+++ b/src/app/Fake.IO.FileSystem/Globbing.fs
@@ -56,7 +56,7 @@ module Glob =
         | Drive name :: t ->
             let subDirs = List.collect (checkSubDirs true name) acc
             buildPaths subDirs t
-        | Recursive :: [] ->
+        | [ Recursive ] ->
             let dirs =
                 Seq.collect
                     (fun dir ->
diff --git a/src/app/Fake.IO.Zip/Zip.fs b/src/app/Fake.IO.Zip/Zip.fs
index b6be8e8e504..30e77176571 100644
--- a/src/app/Fake.IO.Zip/Zip.fs
+++ b/src/app/Fake.IO.Zip/Zip.fs
@@ -406,8 +406,7 @@ module Zip =
     /// A sequence of target folders and files to include relative to their base directory.
     let createZipOfIncludes fileName comment level (files: (string * IGlobbingPattern) seq) =
         files
-        |> Seq.map (fun (wd, glob) -> glob |> filesAsSpecs "" |> moveToFolder wd)
-        |> Seq.concat
+        |> Seq.collect (fun (wd, glob) -> glob |> filesAsSpecs "" |> moveToFolder wd)
         |> createZipSpec fileName comment level
     //let items = seq {
     //    for path, incl in files do
diff --git a/src/app/Fake.Runtime/FakeRuntimeHints.fs b/src/app/Fake.Runtime/FakeRuntimeHints.fs
index 51948cd6efd..af05eda2c60 100644
--- a/src/app/Fake.Runtime/FakeRuntimeHints.fs
+++ b/src/app/Fake.Runtime/FakeRuntimeHints.fs
@@ -159,7 +159,7 @@ let retrieveHints
         let buildVersionMetadataPrefix = "+build"
         let attribute = assembly.GetCustomAttribute()
 
-        match attribute.InformationalVersion <> null with
+        match not (isNull attribute.InformationalVersion) with
         | true ->
             let mutable value = attribute.InformationalVersion
             let index = value.IndexOf(buildVersionMetadataPrefix)
diff --git a/src/app/Fake.Runtime/YaafFSharpScripting.fs b/src/app/Fake.Runtime/YaafFSharpScripting.fs
index 509b3cbd338..90180935c2b 100644
--- a/src/app/Fake.Runtime/YaafFSharpScripting.fs
+++ b/src/app/Fake.Runtime/YaafFSharpScripting.fs
@@ -361,10 +361,9 @@ module internal CompilerServiceExtensions =
             dllFiles
             |> Seq.map (fun file ->
                 file,
-                if referenceMap.ContainsKey file then
-                    Some referenceMap.[file]
-                else
-                    None)
+                match referenceMap.TryGetValue file with
+                | true, foundFile -> Some foundFile
+                | false, _ -> None)
 
         let getProjectReferencesSimple frameworkVersion dllFiles =
             let dllFiles = dllFiles |> Seq.toList
@@ -382,9 +381,9 @@ module internal CompilerServiceExtensions =
         member x.NamespaceName =
             x.FullName.Substring(
                 0,
-                match x.FullName.IndexOf("[") with
+                match x.FullName.IndexOf '[' with
                 | -1 -> x.FullName.Length
-                | _ as i -> i
+                | i -> i
             )
 
     type FSharpAssembly with
@@ -533,7 +532,7 @@ module internal StringHelpers =
     []
     module Assert =
         let notNull argName arg =
-            if arg = null then
+            if isNull arg then
                 nullArg argName
 
         let notNullOrEmpty argName arg =
@@ -1319,7 +1318,7 @@ type internal FsiOptions =
                | [] -> Seq.empty
                | opts ->
                    opts
-                   |> Seq.map (fun (enable, types) ->
+                   |> Seq.collect (fun (enable, types) ->
                        seq {
                            yield sprintf "--optimize%s" (getMinusPlus enable)
 
@@ -1336,7 +1335,6 @@ type internal FsiOptions =
                                        | NoTailCalls -> "notailcalls")
                                    |> String.concat ","
                        })
-                   |> Seq.concat
 
            yield! getSimpleBoolArg "--quiet" x.Quiet
            yield! getSimpleBoolArg "--quotations-debug" x.QuotationsDebug
diff --git a/src/app/Fake.Tools.Git/Submodule.fs b/src/app/Fake.Tools.Git/Submodule.fs
index 8bd897d05aa..85f98b71d7e 100644
--- a/src/app/Fake.Tools.Git/Submodule.fs
+++ b/src/app/Fake.Tools.Git/Submodule.fs
@@ -55,7 +55,7 @@ module Submodule =
 
             let name, branch =
                 if n.Contains "(" then
-                    n.Substring(0, n.IndexOf "(") |> trimChars, n.Substring(n.IndexOf "(") |> trimChars
+                    n.Substring(0, n.IndexOf '(') |> trimChars, n.Substring(n.IndexOf '(') |> trimChars
                 else
                     n, null