From 7e74c84d9b880b8d5a11aa0a2cd11b04ac029e44 Mon Sep 17 00:00:00 2001 From: 1eyewonder Date: Thu, 13 Jun 2024 09:05:22 -0500 Subject: [PATCH 1/4] Update Seq.filter + maps into Seq.choose --- src/Common/StringParsing.fs | 7 +++++-- src/FSharp.Formatting.ApiDocs/GenerateModel.fs | 7 +++++-- src/FSharp.Formatting.Common/Templating.fs | 13 +++++++++---- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/Common/StringParsing.fs b/src/Common/StringParsing.fs index 9ce65ee7..f02edb25 100644 --- a/src/Common/StringParsing.fs +++ b/src/Common/StringParsing.fs @@ -108,8 +108,11 @@ module String = let removeSpaces (lines: string list) = let spaces = lines - |> Seq.filter (String.IsNullOrWhiteSpace >> not) - |> Seq.map (fun line -> line |> Seq.takeWhile Char.IsWhiteSpace |> Seq.length) + |> Seq.choose (fun line -> + if not <| String.IsNullOrWhiteSpace line then + line |> Seq.takeWhile Char.IsWhiteSpace |> Seq.length |> Some + else + None) |> fun xs -> if Seq.isEmpty xs then 0 else Seq.min xs lines diff --git a/src/FSharp.Formatting.ApiDocs/GenerateModel.fs b/src/FSharp.Formatting.ApiDocs/GenerateModel.fs index 04cd96a9..e0d222dd 100644 --- a/src/FSharp.Formatting.ApiDocs/GenerateModel.fs +++ b/src/FSharp.Formatting.ApiDocs/GenerateModel.fs @@ -2264,8 +2264,11 @@ module internal SymbolReader = do replacedParagraphs |> Seq.collect collectParagraphIndirectLinks - |> Seq.filter (linkNotDefined doc) - |> Seq.map (getTypeLink ctx) + |> Seq.choose (fun line -> + if linkNotDefined doc line then + getTypeLink ctx line |> Some + else + None) |> Seq.iter (addLinkToType doc) doc.With(paragraphs = replacedParagraphs) diff --git a/src/FSharp.Formatting.Common/Templating.fs b/src/FSharp.Formatting.Common/Templating.fs index 043543b3..8d05ce51 100644 --- a/src/FSharp.Formatting.Common/Templating.fs +++ b/src/FSharp.Formatting.Common/Templating.fs @@ -48,10 +48,15 @@ type FrontMatterFile = // Allow empty lines in frontmatter let isBlankLine = String.IsNullOrWhiteSpace line isBlankLine || line.Contains(":")) - |> Seq.filter (String.IsNullOrWhiteSpace >> not) - |> Seq.map (fun line -> - let parts = line.Split(":") - parts.[0].ToLowerInvariant(), parts.[1]) + |> Seq.choose (fun line -> + let parts = line.Split(":") |> Array.toList + + if not <| String.IsNullOrWhiteSpace line then + match parts with + | first :: second :: _ -> Some(first.ToLowerInvariant(), second) + | _ -> None + else + None) |> Map.ofSeq match From 82f7cbeebd1b1f836c590b042be2896b3a9974a8 Mon Sep 17 00:00:00 2001 From: 1eyewonder Date: Wed, 19 Jun 2024 17:17:55 -0500 Subject: [PATCH 2/4] Updated analyzers --- .config/dotnet-tools.json | 2 +- Directory.Packages.props | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 3027b3ad..b902040d 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -9,7 +9,7 @@ ] }, "fsharp-analyzers": { - "version": "0.24.0", + "version": "0.26.0", "commands": [ "fsharp-analyzers" ] diff --git a/Directory.Packages.props b/Directory.Packages.props index facf2013..e699315b 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -27,7 +27,7 @@ - - + + \ No newline at end of file From c3cef1b121d8e5ce350d5ed172af8120107e0be4 Mon Sep 17 00:00:00 2001 From: 1eyewonder Date: Wed, 19 Jun 2024 17:23:25 -0500 Subject: [PATCH 3/4] Updated per review comments --- src/Common/StringParsing.fs | 2 +- src/FSharp.Formatting.ApiDocs/GenerateModel.fs | 6 ++---- src/FSharp.Formatting.Common/Templating.fs | 4 ++-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Common/StringParsing.fs b/src/Common/StringParsing.fs index f02edb25..1136bd4c 100644 --- a/src/Common/StringParsing.fs +++ b/src/Common/StringParsing.fs @@ -109,7 +109,7 @@ module String = let spaces = lines |> Seq.choose (fun line -> - if not <| String.IsNullOrWhiteSpace line then + if String.IsNullOrWhiteSpace line |> not then line |> Seq.takeWhile Char.IsWhiteSpace |> Seq.length |> Some else None) diff --git a/src/FSharp.Formatting.ApiDocs/GenerateModel.fs b/src/FSharp.Formatting.ApiDocs/GenerateModel.fs index e0d222dd..dfed5f30 100644 --- a/src/FSharp.Formatting.ApiDocs/GenerateModel.fs +++ b/src/FSharp.Formatting.ApiDocs/GenerateModel.fs @@ -2265,10 +2265,8 @@ module internal SymbolReader = replacedParagraphs |> Seq.collect collectParagraphIndirectLinks |> Seq.choose (fun line -> - if linkNotDefined doc line then - getTypeLink ctx line |> Some - else - None) + let linkIsDefined = linkNotDefined doc line |> not + if linkIsDefined then None else getTypeLink ctx line |> Some) |> Seq.iter (addLinkToType doc) doc.With(paragraphs = replacedParagraphs) diff --git a/src/FSharp.Formatting.Common/Templating.fs b/src/FSharp.Formatting.Common/Templating.fs index 8d05ce51..d17684ed 100644 --- a/src/FSharp.Formatting.Common/Templating.fs +++ b/src/FSharp.Formatting.Common/Templating.fs @@ -49,9 +49,9 @@ type FrontMatterFile = let isBlankLine = String.IsNullOrWhiteSpace line isBlankLine || line.Contains(":")) |> Seq.choose (fun line -> - let parts = line.Split(":") |> Array.toList + if String.IsNullOrWhiteSpace line |> not then + let parts = line.Split(":") |> Array.toList - if not <| String.IsNullOrWhiteSpace line then match parts with | first :: second :: _ -> Some(first.ToLowerInvariant(), second) | _ -> None From 6b8d5c98f9e1fccfef342fa4f246f04b61404e0a Mon Sep 17 00:00:00 2001 From: 1eyewonder Date: Thu, 20 Jun 2024 12:07:31 -0500 Subject: [PATCH 4/4] Additional collection optimizations --- .../GenerateModel.fs | 148 +++++++++--------- .../YaafFSharpScripting.fs | 10 +- src/fsdocs-tool/BuildCommand.fs | 9 +- 3 files changed, 87 insertions(+), 80 deletions(-) diff --git a/src/FSharp.Formatting.ApiDocs/GenerateModel.fs b/src/FSharp.Formatting.ApiDocs/GenerateModel.fs index dfed5f30..9b406e67 100644 --- a/src/FSharp.Formatting.ApiDocs/GenerateModel.fs +++ b/src/FSharp.Formatting.ApiDocs/GenerateModel.fs @@ -1282,8 +1282,9 @@ module internal TypeFormatter = n curriedArgs - |> List.map (List.map (fun x -> formatArgNameAndType (counter ()) x |> fst)) - |> List.map (fun argTuple -> + |> List.map (fun args -> + let argTuple = args |> List.map (formatArgNameAndType (counter ()) >> fst) + match argTuple with | [] -> !! "()" | [ argName ] when argName = "()" -> !! "()" @@ -2217,10 +2218,9 @@ module internal SymbolReader = } /// Returns whether the link is not included in the document defined links - let linkNotDefined (doc: LiterateDocument) (link: string) = + let linkDefined (doc: LiterateDocument) (link: string) = [ link; link.Replace("\r\n", ""); link.Replace("\r\n", " "); link.Replace("\n", ""); link.Replace("\n", " ") ] - |> Seq.map (fun key -> not (doc.DefinedLinks.ContainsKey(key))) - |> Seq.reduce (fun a c -> a && c) + |> List.exists (fun key -> doc.DefinedLinks.ContainsKey(key)) /// Returns a tuple of the undefined link and its Cref if it exists let getTypeLink (ctx: ReadingContext) undefinedLink = @@ -2265,8 +2265,10 @@ module internal SymbolReader = replacedParagraphs |> Seq.collect collectParagraphIndirectLinks |> Seq.choose (fun line -> - let linkIsDefined = linkNotDefined doc line |> not - if linkIsDefined then None else getTypeLink ctx line |> Some) + if linkDefined doc line then + None + else + getTypeLink ctx line |> Some) |> Seq.iter (addLinkToType doc) doc.With(paragraphs = replacedParagraphs) @@ -2276,15 +2278,12 @@ module internal SymbolReader = let text = lines - |> List.filter ( - findCommand - >> (function + |> List.choose (fun line -> + match findCommand line with | Some(k, v) -> cmds.[k] <- v - false - | _ -> true) - ) - |> List.map fst + None + | _ -> fst line |> Some) |> String.concat "\n" let doc = @@ -2422,8 +2421,7 @@ module internal SymbolReader = let readChildren ctx (entities: FSharpEntity seq) reader cond = entities - |> Seq.filter (fun v -> checkAccess ctx v.Accessibility) - |> Seq.filter cond + |> Seq.filter (fun v -> checkAccess ctx v.Accessibility && cond v) |> Seq.sortBy (fun (c: FSharpEntity) -> c.DisplayName) |> Seq.choose (reader ctx) |> List.ofSeq @@ -2449,23 +2447,28 @@ module internal SymbolReader = let readAllMembers ctx entityUrl kind (members: FSharpMemberOrFunctionOrValue seq) = members - |> Seq.filter (fun v -> checkAccess ctx v.Accessibility) - |> Seq.filter (fun v -> - not v.IsCompilerGenerated - && not v.IsPropertyGetterMethod - && not v.IsPropertySetterMethod - && not v.IsEventAddMethod - && not v.IsEventRemoveMethod) - |> Seq.choose (tryReadMember ctx entityUrl kind) + |> Seq.choose (fun v -> + if + checkAccess ctx v.Accessibility + && not v.IsCompilerGenerated + && not v.IsPropertyGetterMethod + && not v.IsPropertySetterMethod + && not v.IsEventAddMethod + && not v.IsEventRemoveMethod + then + tryReadMember ctx entityUrl kind v + else + None) |> List.ofSeq |> collectNamespaceDocs let readMembers ctx entityUrl kind (entity: FSharpEntity) cond = entity.MembersFunctionsAndValues - |> Seq.filter (fun v -> checkAccess ctx v.Accessibility) - |> Seq.filter (fun v -> not v.IsCompilerGenerated) - |> Seq.filter cond - |> Seq.choose (tryReadMember ctx entityUrl kind) + |> Seq.choose (fun v -> + if checkAccess ctx v.Accessibility && not v.IsCompilerGenerated && cond v then + tryReadMember ctx entityUrl kind v + else + None) |> List.ofSeq |> collectNamespaceDocs @@ -2486,47 +2489,51 @@ module internal SymbolReader = let readUnionCases ctx entityUrl (typ: FSharpEntity) = typ.UnionCases |> List.ofSeq - |> List.filter (fun v -> checkAccess ctx v.Accessibility) |> List.choose (fun case -> - readCommentsInto case ctx case.XmlDocSig (fun cat catidx exclude _ comment -> - let details = readUnionCase ctx typ case - - ApiDocMember( - case.Name, - readAttributes case.Attributes, - entityUrl, - ApiDocMemberKind.UnionCase, - cat, - catidx, - exclude, - details, - comment, - case, - ctx.WarnOnMissingDocs - ))) + if checkAccess ctx case.Accessibility |> not then + None + else + readCommentsInto case ctx case.XmlDocSig (fun cat catidx exclude _ comment -> + let details = readUnionCase ctx typ case + + ApiDocMember( + case.Name, + readAttributes case.Attributes, + entityUrl, + ApiDocMemberKind.UnionCase, + cat, + catidx, + exclude, + details, + comment, + case, + ctx.WarnOnMissingDocs + ))) |> collectNamespaceDocs let readRecordFields ctx entityUrl (typ: FSharpEntity) = typ.FSharpFields |> List.ofSeq - |> List.filter (fun field -> not field.IsCompilerGenerated) |> List.choose (fun field -> - readCommentsInto field ctx field.XmlDocSig (fun cat catidx exclude _ comment -> - let details = readFSharpField ctx field - - ApiDocMember( - field.Name, - readAttributes (Seq.append field.FieldAttributes field.PropertyAttributes), - entityUrl, - ApiDocMemberKind.RecordField, - cat, - catidx, - exclude, - details, - comment, - field, - ctx.WarnOnMissingDocs - ))) + if field.IsCompilerGenerated then + None + else + readCommentsInto field ctx field.XmlDocSig (fun cat catidx exclude _ comment -> + let details = readFSharpField ctx field + + ApiDocMember( + field.Name, + readAttributes (Seq.append field.FieldAttributes field.PropertyAttributes), + entityUrl, + ApiDocMemberKind.RecordField, + cat, + catidx, + exclude, + details, + comment, + field, + ctx.WarnOnMissingDocs + ))) |> collectNamespaceDocs let readStaticParams ctx entityUrl (typ: FSharpEntity) = @@ -2586,11 +2593,12 @@ module internal SymbolReader = if isNull nameAttr then None else - Some(nameAttr.Value, p.Value)) - |> Seq.iter (fun (name, xmlDoc) -> - let xmlDocSig = getFSharpStaticParamXmlSig typ name + let xmlDocSig = getFSharpStaticParamXmlSig typ nameAttr.Value - registerXmlDoc ctx xmlDocSig (Security.SecurityElement.Escape xmlDoc) |> ignore) + registerXmlDoc ctx xmlDocSig (Security.SecurityElement.Escape p.Value) + |> ignore + |> Some) + |> ignore let rec readType (ctx: ReadingContext) (typ: FSharpEntity) = if typ.IsProvided && typ.XmlDoc <> FSharpXmlDoc.None then @@ -2618,17 +2626,15 @@ module internal SymbolReader = let ivals, svals = getMembers typ - |> List.ofSeq - |> List.filter (fun v -> + |> Seq.filter (fun v -> checkAccess ctx v.Accessibility && not v.IsCompilerGenerated - && not v.IsOverrideOrExplicitInterfaceImplementation) - |> List.filter (fun v -> - not v.IsCompilerGenerated + && not v.IsOverrideOrExplicitInterfaceImplementation && not v.IsEventAddMethod && not v.IsEventRemoveMethod && not v.IsPropertyGetterMethod && not v.IsPropertySetterMethod) + |> List.ofSeq |> List.partition (fun v -> v.IsInstanceMember) let cvals, svals = svals |> List.partition (fun v -> v.CompiledName = ".ctor") diff --git a/src/FSharp.Formatting.Common/YaafFSharpScripting.fs b/src/FSharp.Formatting.Common/YaafFSharpScripting.fs index a8a344d2..6e32a331 100644 --- a/src/FSharp.Formatting.Common/YaafFSharpScripting.fs +++ b/src/FSharp.Formatting.Common/YaafFSharpScripting.fs @@ -83,7 +83,6 @@ module internal CompilerServiceExtensions = options.OtherOptions |> Array.filter (fun path -> path.StartsWith("-r:", StringComparison.Ordinal)) - |> Array.filter (fun path -> path.StartsWith("-r:", StringComparison.Ordinal)) //|> Seq.choose (fun path -> if path.StartsWith "-r:" then path.Substring 3 |> Some else None) //|> Seq.map (fun path -> path.Replace("\\\\", "\\")) |> Array.toList) @@ -180,11 +179,11 @@ module internal CompilerServiceExtensions = || libDirs |> List.exists (fun lib -> Directory.EnumerateFiles(lib) - |> Seq.filter (fun file -> Path.GetExtension file =? ".dll") |> Seq.filter (fun file -> // If we find a FSharp.Core in a lib path, we check if is suited for us... - Path.GetFileNameWithoutExtension file <>? "FSharp.Core" - || (tryCheckFsCore file |> Option.isSome)) + Path.GetExtension file =? ".dll" + && (Path.GetFileNameWithoutExtension file <>? "FSharp.Core" + || (tryCheckFsCore file |> Option.isSome))) |> Seq.toList |> isAssembly asm) @@ -279,10 +278,9 @@ module internal CompilerServiceExtensions = let findReferences libDir = Directory.EnumerateFiles(libDir, "*.dll") - |> Seq.map Path.GetFullPath // Filter files already referenced directly |> Seq.filter (fun file -> - let fileName = Path.GetFileName file + let fileName = Path.GetFullPath file |> Path.GetFileName dllFiles |> List.exists (fun (dllFile: string) -> Path.GetFileName dllFile =? fileName) diff --git a/src/fsdocs-tool/BuildCommand.fs b/src/fsdocs-tool/BuildCommand.fs index 5619e605..e00d4837 100644 --- a/src/fsdocs-tool/BuildCommand.fs +++ b/src/fsdocs-tool/BuildCommand.fs @@ -95,9 +95,12 @@ type internal DocContent (subFolderFullPath = rootOutputFolderFullPath) let allCultures = - System.Globalization.CultureInfo.GetCultures(System.Globalization.CultureTypes.AllCultures) - |> Array.map (fun x -> x.TwoLetterISOLanguageName) - |> Array.filter (fun x -> x.Length = 2) + CultureInfo.GetCultures(CultureTypes.AllCultures) + |> Array.choose (fun x -> + if x.TwoLetterISOLanguageName.Length <> 2 then + None + else + Some x.TwoLetterISOLanguageName) |> Array.distinct let makeMarkdownLinkResolver