From 6c76456370f4351770ec229b47828e0af9403fca Mon Sep 17 00:00:00 2001 From: nojaf Date: Thu, 23 Nov 2023 15:01:57 +0100 Subject: [PATCH] Update F# analyzers --- Directory.Packages.props | 4 +- src/FSharp.Formatting.ApiDocs/GenerateHtml.fs | 33 ++++---- .../GenerateMarkdown.fs | 26 ++++--- .../GenerateModel.fs | 77 +++++++++++-------- src/FSharp.Formatting.CodeFormat/Pervasive.fs | 2 +- .../SourceCode.fs | 2 +- .../ToolTipReader.fs | 4 +- src/FSharp.Formatting.Common/HtmlModel.fs | 4 +- .../PageContentList.fs | 2 +- src/FSharp.Formatting.Common/PynbModel.fs | 8 +- src/FSharp.Formatting.Common/Templating.fs | 6 +- .../YaafFSharpScripting.fs | 32 ++++---- src/FSharp.Formatting.Literate/Document.fs | 2 +- src/FSharp.Formatting.Literate/Evaluator.fs | 8 +- src/FSharp.Formatting.Literate/Formatting.fs | 2 +- src/FSharp.Formatting.Literate/ParseScript.fs | 67 ++++++++-------- .../Transformations.fs | 17 ++-- .../HtmlFormatting.fs | 16 ++-- .../LatexFormatting.fs | 2 +- src/FSharp.Formatting.Markdown/Markdown.fs | 2 +- .../MarkdownModel.fs | 14 ++-- .../MarkdownParser.fs | 28 +++---- .../MarkdownUtils.fs | 4 +- src/fsdocs-tool/BuildCommand.fs | 8 +- src/fsdocs-tool/ProjectCracker.fs | 40 ++++++---- 25 files changed, 221 insertions(+), 189 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index dd72d1cd3..c4b67d266 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -27,7 +27,7 @@ - - + + \ No newline at end of file diff --git a/src/FSharp.Formatting.ApiDocs/GenerateHtml.fs b/src/FSharp.Formatting.ApiDocs/GenerateHtml.fs index 7ef3216a3..f6176fb68 100644 --- a/src/FSharp.Formatting.ApiDocs/GenerateHtml.fs +++ b/src/FSharp.Formatting.ApiDocs/GenerateHtml.fs @@ -256,9 +256,10 @@ type HtmlRender(model: ApiDocModel, ?menuTemplateFolder: string) = h5 [ Class "fsdocs-example-header" ] [ !! "Example" ] p [ - Class "fsdocs-example" - if e.Id.IsSome then - Id e.Id.Value + yield Class "fsdocs-example" + match e.Id with + | None -> () + | Some id -> yield Id id ] [ embed e ] //if m.IsObsolete then // obsoleteMessage m.ObsoleteMessage @@ -610,13 +611,19 @@ type HtmlRender(model: ApiDocModel, ?menuTemplateFolder: string) = | _ -> () ] let listOfNamespacesNav otherDocs (nsOpt: ApiDocNamespace option) = - let isTemplatingAvailable = - match menuTemplateFolder with - | None -> false - | Some input -> Menu.isTemplatingAvailable input + let noTemplatingFallback () = + listOfNamespacesNavAux otherDocs nsOpt + |> List.map (fun html -> html.ToString()) + |> String.concat " \n" + + match menuTemplateFolder with + | None -> noTemplatingFallback () + | Some menuTemplateFolder -> + let isTemplatingAvailable = Menu.isTemplatingAvailable menuTemplateFolder - if isTemplatingAvailable then - if otherDocs && model.Collection.CollectionName <> "FSharp.Core" then + if not isTemplatingAvailable then + noTemplatingFallback () + else if otherDocs && model.Collection.CollectionName <> "FSharp.Core" then let menuItems = let title = "All Namespaces" let link = model.IndexFileUrl(root, collectionName, qualify, model.FileExtensions.InUrl) @@ -625,7 +632,7 @@ type HtmlRender(model: ApiDocModel, ?menuTemplateFolder: string) = Menu.MenuItem.Content = title Menu.MenuItem.IsActive = true } ] - Menu.createMenu menuTemplateFolder.Value false "API Reference" menuItems + Menu.createMenu menuTemplateFolder false "API Reference" menuItems else let categorise = Categorise.model model @@ -643,11 +650,7 @@ type HtmlRender(model: ApiDocModel, ?menuTemplateFolder: string) = Menu.MenuItem.Content = name Menu.MenuItem.IsActive = false }) - Menu.createMenu menuTemplateFolder.Value false "Namespaces" menuItems - else - listOfNamespacesNavAux otherDocs nsOpt - |> List.map (fun html -> html.ToString()) - |> String.concat " \n" + Menu.createMenu menuTemplateFolder false "Namespaces" menuItems /// Get the substitutions relevant to all member _.GlobalSubstitutions: Substitutions = diff --git a/src/FSharp.Formatting.ApiDocs/GenerateMarkdown.fs b/src/FSharp.Formatting.ApiDocs/GenerateMarkdown.fs index 12b940795..545c0aac4 100644 --- a/src/FSharp.Formatting.ApiDocs/GenerateMarkdown.fs +++ b/src/FSharp.Formatting.ApiDocs/GenerateMarkdown.fs @@ -355,13 +355,19 @@ type MarkdownRender(model: ApiDocModel, ?menuTemplateFolder: string) = | _ -> () ] let listOfNamespaces otherDocs nav (nsOpt: ApiDocNamespace option) = - let isTemplatingAvailable = - match menuTemplateFolder with - | None -> false - | Some input -> Menu.isTemplatingAvailable input + let noTemplatingFallback () = + listOfNamespacesAux otherDocs nav nsOpt + |> List.map (fun html -> html.ToString()) + |> String.concat " \n" + + match menuTemplateFolder with + | None -> noTemplatingFallback () + | Some menuTemplateFolder -> + let isTemplatingAvailable = Menu.isTemplatingAvailable menuTemplateFolder - if isTemplatingAvailable then - if otherDocs && nav && model.Collection.CollectionName <> "FSharp.Core" then + if not isTemplatingAvailable then + noTemplatingFallback () + else if otherDocs && nav && model.Collection.CollectionName <> "FSharp.Core" then let menuItems = let title = "All Namespaces" let link = model.IndexFileUrl(root, collectionName, qualify, model.FileExtensions.InUrl) @@ -370,7 +376,7 @@ type MarkdownRender(model: ApiDocModel, ?menuTemplateFolder: string) = Menu.MenuItem.Content = title Menu.MenuItem.IsActive = false } ] - Menu.createMenu menuTemplateFolder.Value false "API Reference" menuItems + Menu.createMenu menuTemplateFolder false "API Reference" menuItems else let categorise = Categorise.model model @@ -388,11 +394,7 @@ type MarkdownRender(model: ApiDocModel, ?menuTemplateFolder: string) = Menu.MenuItem.Content = name Menu.MenuItem.IsActive = false }) - Menu.createMenu menuTemplateFolder.Value false "Namespaces" menuItems - else - listOfNamespacesAux otherDocs nav nsOpt - |> List.map (fun html -> html.ToString()) - |> String.concat " \n" + Menu.createMenu menuTemplateFolder false "Namespaces" menuItems /// Get the substitutions relevant to all member _.GlobalSubstitutions: Substitutions = diff --git a/src/FSharp.Formatting.ApiDocs/GenerateModel.fs b/src/FSharp.Formatting.ApiDocs/GenerateModel.fs index aea3077a2..a544ce352 100644 --- a/src/FSharp.Formatting.ApiDocs/GenerateModel.fs +++ b/src/FSharp.Formatting.ApiDocs/GenerateModel.fs @@ -173,8 +173,10 @@ type ApiDocAttribute(name, fullName, constructorArguments, namedConstructorArgum member x.ObsoleteMessage = let tryFindObsoleteMessage = x.ConstructorArguments - |> List.tryFind (fun x -> x :? string) - |> Option.map string + |> List.tryPick (fun x -> + match x with + | :? string as s -> Some s + | _ -> None) |> Option.defaultValue "" if x.IsObsoleteAttribute then tryFindObsoleteMessage else "" @@ -186,8 +188,10 @@ type ApiDocAttribute(name, fullName, constructorArguments, namedConstructorArgum member x.CustomOperationName = let tryFindCustomOperation = x.ConstructorArguments - |> List.tryFind (fun x -> x :? string) - |> Option.map string + |> List.tryPick (fun x -> + match x with + | :? string as s -> Some s + | _ -> None) |> Option.defaultValue "" if x.IsCustomOperationAttribute then @@ -215,9 +219,9 @@ type ApiDocAttribute(name, fullName, constructorArguments, namedConstructorArgum let rec formatValue (v: obj) = match v with | :? string as s -> sprintf "\"%s\"" s - | :? array as a -> a |> Seq.map formatValue |> join "; " |> sprintf "[|%s|]" + | :? (obj array) as a -> a |> Seq.map formatValue |> join "; " |> sprintf "[|%s|]" | :? bool as b -> if b then "true" else "false" - | _ -> string v + | _ -> string v let formatedConstructorArguments = x.ConstructorArguments |> Seq.map formatValue |> join ", " @@ -239,7 +243,7 @@ type ApiDocAttribute(name, fullName, constructorArguments, namedConstructorArgum |> append formatedNamedConstructorArguments |> appendIfTrue needsBraces ")" |> append ">]" - |> string + |> string /// Formats the attribute using the Name. Removes the "Attribute"-suffix. E.g Obsolete member x.Format() = x.Format(x.Name, true) @@ -254,14 +258,14 @@ type ApiDocAttribute(name, fullName, constructorArguments, namedConstructorArgum member x.FormatFullNameLongForm() = x.Format(x.FullName, false) /// Tries to find the System.ObsoleteAttribute and return its obsolete message - static member internal TryGetObsoleteMessage(attributes: seq) = + static member internal TryGetObsoleteMessage(attributes: ApiDocAttribute seq) = attributes |> Seq.tryFind (fun a -> a.IsObsoleteAttribute) |> Option.map (fun a -> a.ObsoleteMessage) |> Option.defaultValue "" /// Tries to find the CustomOperationAttribute and return its obsolete message - static member internal TryGetCustomOperationName(attributes: seq) = + static member internal TryGetCustomOperationName(attributes: ApiDocAttribute seq) = attributes |> Seq.tryFind (fun a -> a.IsCustomOperationAttribute) |> Option.map (fun a -> a.CustomOperationName) @@ -715,8 +719,11 @@ module internal CrossReferences = let name = memb.CompiledName.Replace(".ctor", "#ctor") let typeGenericParameters = - memb.DeclaringEntity.Value.GenericParameters - |> Seq.mapi (fun num par -> par.Name, sprintf "`%d" num) + match memb.DeclaringEntity with + | None -> Seq.empty + | Some declaringEntity -> + declaringEntity.GenericParameters + |> Seq.mapi (fun num par -> par.Name, sprintf "`%d" num) let methodGenericParameters = memb.GenericParameters |> Seq.mapi (fun num par -> par.Name, sprintf "``%d" num) @@ -758,9 +765,12 @@ module internal CrossReferences = Log.verbf "Full Exception details of previous message: %O" exn memb.CompiledName - match (memb.DeclaringEntity.Value.TryFullName) with + match + memb.DeclaringEntity + |> Option.bind (fun declaringEntity -> declaringEntity.TryFullName) + with | None -> "" - | Some(n) -> sprintf "%s:%s.%s" (getMemberXmlDocsSigPrefix memb) n memberName + | Some fullName -> sprintf "%s:%s.%s" (getMemberXmlDocsSigPrefix memb) fullName memberName type internal CrefReference = { IsInternal: bool @@ -1004,11 +1014,14 @@ type internal CrossReferenceResolver(root, collectionName, qualify, extensions) externalDocsLink false simple typeName typeName let mfvToCref (mfv: FSharpMemberOrFunctionOrValue) = - let entityUrlBaseName = getUrlBaseNameForRegisteredEntity mfv.DeclaringEntity.Value + match mfv.DeclaringEntity with + | None -> failwith $"%s{mfv.DisplayName} does not have a DeclaringEntity" + | Some declaringEntity -> + let entityUrlBaseName = getUrlBaseNameForRegisteredEntity declaringEntity - { IsInternal = true - ReferenceLink = internalCrossReferenceForMember entityUrlBaseName mfv - NiceName = mfv.DeclaringEntity.Value.DisplayName + "." + mfv.DisplayName } + { IsInternal = true + ReferenceLink = internalCrossReferenceForMember entityUrlBaseName mfv + NiceName = declaringEntity.DisplayName + "." + mfv.DisplayName } let tryResolveCrossReferenceForMemberByXmlSig (memberXmlSig: string) = assert @@ -1225,7 +1238,7 @@ module internal TypeFormatter = let formatArgNameAndTypePair i (argName, argType) = let argName = match argName with - | None -> if isUnitType argType then "()" else "arg" + string i + | None -> if isUnitType argType then "()" else "arg" + string i | Some nm -> nm argName, argType @@ -1356,7 +1369,7 @@ module internal SymbolReader = ApiDocAttribute(name, fullName, constructorArguments, namedArguments) - let readAttributes (attributes: seq) = + let readAttributes (attributes: FSharpAttribute seq) = attributes |> Seq.map readAttribute |> Seq.toList let readMemberOrVal (ctx: ReadingContext) (v: FSharpMemberOrFunctionOrValue) = @@ -1374,8 +1387,10 @@ module internal SymbolReader = | Some v -> v.ConstructorArguments |> Seq.map snd - |> Seq.tryFind (fun x -> x :? string) - |> Option.map string + |> Seq.tryPick (fun x -> + match x with + | :? string as s -> Some s + | _ -> None) // This module doesn't have RequireQualifiedAccessAttribute and anyway we want the name to show // usage of its members as Array.Parallel.map @@ -1963,7 +1978,7 @@ module internal SymbolReader = let html = new StringBuilder() for (id, e) in List.indexed summaries do - let n = if id = 0 then "summary" else "summary-" + string id + let n = if id = 0 then "summary" else "summary-" + string id rawData.[n] <- e.Value readXmlElementAsHtml true urlMap cmds html e @@ -2004,7 +2019,7 @@ module internal SymbolReader = let html = new StringBuilder() for (id, e) in List.indexed remarkNodes do - let n = if id = 0 then "remarks" else "remarks-" + string id + let n = if id = 0 then "remarks" else "remarks-" + string id rawData.[n] <- e.Value readXmlElementAsHtml true urlMap cmds html e @@ -2020,7 +2035,7 @@ module internal SymbolReader = if returnNodes.Length > 0 then for (id, e) in List.indexed returnNodes do - let n = if id = 0 then "returns" else "returns-" + string id + let n = if id = 0 then "returns" else "returns-" + string id rawData.[n] <- e.Value readXmlElementAsHtml true urlMap cmds html e @@ -2069,7 +2084,7 @@ module internal SymbolReader = let exampleId = match e.TryAttr "id" with - | None -> if id = 0 then "example" else "example-" + string id + | None -> if id = 0 then "example" else "example-" + string id | Some attrId -> attrId rawData.[exampleId] <- e.Value @@ -2082,7 +2097,7 @@ module internal SymbolReader = [ for (id, e) in List.indexed noteNodes do let html = new StringBuilder() - let n = if id = 0 then "note" else "note-" + string id + let n = if id = 0 then "note" else "note-" + string id rawData.[n] <- e.Value readXmlElementAsHtml true urlMap cmds html e @@ -2106,7 +2121,7 @@ module internal SymbolReader = match lst with | [ x ] -> rawData.[n] <- x.Value - | lst -> lst |> List.iteri (fun id el -> rawData.[n + "-" + string id] <- el.Value)) + | lst -> lst |> List.iteri (fun id el -> rawData.[n + "-" + string id] <- el.Value)) let rawData = rawData |> Seq.toList @@ -2400,7 +2415,7 @@ module internal SymbolReader = |> function | (results, nspDocs) -> (results, combineNamespaceDocs nspDocs) - let readChildren ctx (entities: seq) reader cond = + let readChildren ctx (entities: FSharpEntity seq) reader cond = entities |> Seq.filter (fun v -> checkAccess ctx v.Accessibility) |> Seq.filter cond @@ -2427,7 +2442,7 @@ module internal SymbolReader = ctx.WarnOnMissingDocs )) - let readAllMembers ctx entityUrl kind (members: seq) = + let readAllMembers ctx entityUrl kind (members: FSharpMemberOrFunctionOrValue seq) = members |> Seq.filter (fun v -> checkAccess ctx v.Accessibility) |> Seq.filter (fun v -> @@ -2755,7 +2770,7 @@ module internal SymbolReader = ctx.Substitutions )) - and readEntities ctx (entities: seq<_>) = + and readEntities ctx (entities: _ seq) = let modifiers, nsdocs1 = readChildren ctx entities readModule (fun x -> x.IsFSharpModule) let typs, nsdocs2 = readChildren ctx entities readType (fun x -> not x.IsFSharpModule) @@ -2774,7 +2789,7 @@ module internal SymbolReader = else str - let readNamespace ctx (ns, entities: seq) = + let readNamespace ctx (ns, entities: FSharpEntity seq) = let entities, nsdocs = readEntities ctx entities ApiDocNamespace(stripMicrosoft ns, entities, ctx.Substitutions, nsdocs) diff --git a/src/FSharp.Formatting.CodeFormat/Pervasive.fs b/src/FSharp.Formatting.CodeFormat/Pervasive.fs index 79c62589f..524cd2bae 100644 --- a/src/FSharp.Formatting.CodeFormat/Pervasive.fs +++ b/src/FSharp.Formatting.CodeFormat/Pervasive.fs @@ -80,7 +80,7 @@ type AsyncMaybeBuilder() = x.Zero() [] - member x.For(sequence: seq<_>, body: 'T -> Async) : Async<_ option> = + member x.For(sequence: _ seq, body: 'T -> Async) : Async<_ option> = x.Using(sequence.GetEnumerator(), (fun enum -> x.While(enum.MoveNext, x.Delay(fun () -> body enum.Current)))) [] diff --git a/src/FSharp.Formatting.CodeFormat/SourceCode.fs b/src/FSharp.Formatting.CodeFormat/SourceCode.fs index 8a6e4be27..9db2c7b22 100644 --- a/src/FSharp.Formatting.CodeFormat/SourceCode.fs +++ b/src/FSharp.Formatting.CodeFormat/SourceCode.fs @@ -11,7 +11,7 @@ open FSharp.Formatting.CodeFormat.Constants // -------------------------------------------------------------------------------------- /// A tool tip consists of a list of items reported from the compiler -type ToolTipSpans = list +type ToolTipSpans = ToolTipSpan list /// A tool tip span can be emphasized text, plain text Literal or a line brak type ToolTipSpan = diff --git a/src/FSharp.Formatting.CodeFormat/ToolTipReader.fs b/src/FSharp.Formatting.CodeFormat/ToolTipReader.fs index 8f8727419..b0826ea76 100644 --- a/src/FSharp.Formatting.CodeFormat/ToolTipReader.fs +++ b/src/FSharp.Formatting.CodeFormat/ToolTipReader.fs @@ -20,13 +20,13 @@ let linesFromTaggedText (tags: TaggedText array) = for tag in tags do if tag.Tag = TextTag.Space && tag.Text.Contains "\n" then - yield string content + yield string content content.Clear() |> ignore else content.Append tag.Text |> ignore // yield any remaining text if content.Length <> 0 then - yield string content + yield string content } /// Turn string into a sequence of lines interleaved with line breaks diff --git a/src/FSharp.Formatting.Common/HtmlModel.fs b/src/FSharp.Formatting.Common/HtmlModel.fs index 82a2eff4d..0ffea8520 100644 --- a/src/FSharp.Formatting.Common/HtmlModel.fs +++ b/src/FSharp.Formatting.Common/HtmlModel.fs @@ -450,7 +450,7 @@ type internal HtmlElement = let attrs = if props.Length > 0 then - " " + (props |> List.map string |> String.concat " ") + " " + (props |> List.map string |> String.concat " ") else "" @@ -460,7 +460,7 @@ type internal HtmlElement = and formatVoid tag (props: HtmlProperties list) _level = let attrs = if props.Length > 0 then - " " + (props |> List.map string |> String.concat " ") + " " + (props |> List.map string |> String.concat " ") else "" diff --git a/src/FSharp.Formatting.Common/PageContentList.fs b/src/FSharp.Formatting.Common/PageContentList.fs index 8dc803548..5e9d23803 100644 --- a/src/FSharp.Formatting.Common/PageContentList.fs +++ b/src/FSharp.Formatting.Common/PageContentList.fs @@ -31,4 +31,4 @@ let mkPageContentMenu (html: string) = match listItems with | [] -> List.empty, EmptyContent - | items -> headingTexts, string (ul [] items) + | items -> headingTexts, string (ul [] items) diff --git a/src/FSharp.Formatting.Common/PynbModel.fs b/src/FSharp.Formatting.Common/PynbModel.fs index f2e6d0ad3..3afd8cefb 100644 --- a/src/FSharp.Formatting.Common/PynbModel.fs +++ b/src/FSharp.Formatting.Common/PynbModel.fs @@ -38,7 +38,7 @@ type Output = (this.data.ToString()) (match this.execution_count with | None -> "null" - | Some(x) -> string x) + | Some(x) -> string x) this.metadata this.output_type @@ -85,8 +85,8 @@ type Cell = """"execution_count": %s, "outputs": [%s],""" (match this.execution_count with | None -> "null" - | Some(x) -> string x) - (this.outputs |> Array.map string |> String.concat ",\n"))) + | Some(x) -> string x) + (this.outputs |> Array.map string |> String.concat ",\n"))) (this.source |> Array.map addLineEnd |> Array.map escapeAndQuote @@ -209,7 +209,7 @@ type Notebook = "nbformat": %i, "nbformat_minor": %i }""" - (this.cells |> Array.map string |> String.concat "\n,") + (this.cells |> Array.map string |> String.concat "\n,") this.metadata this.nbformat this.nbformat_minor diff --git a/src/FSharp.Formatting.Common/Templating.fs b/src/FSharp.Formatting.Common/Templating.fs index af7243f98..2656c7b40 100644 --- a/src/FSharp.Formatting.Common/Templating.fs +++ b/src/FSharp.Formatting.Common/Templating.fs @@ -213,7 +213,7 @@ module internal SimpleTemplating = #endif // Replace '{{xyz}}' in template text - let ApplySubstitutionsInText (substitutions: seq) (text: string) = + let ApplySubstitutionsInText (substitutions: (ParamKey * string) seq) (text: string) = if not (text.Contains "{{") then text else @@ -258,8 +258,8 @@ module internal SimpleTemplating = sb.ToString() - // Replace '{{xyz}}' in text - let ApplySubstitutions (substitutions: seq) (templateTextOpt: string option) = + /// Replace '{{xyz}}' in text + let ApplySubstitutions (substitutions: (ParamKey * string) seq) (templateTextOpt: string option) = let opt = templateTextOpt |> Option.bind (fun s -> diff --git a/src/FSharp.Formatting.Common/YaafFSharpScripting.fs b/src/FSharp.Formatting.Common/YaafFSharpScripting.fs index 8ed8cab9d..a5e072217 100644 --- a/src/FSharp.Formatting.Common/YaafFSharpScripting.fs +++ b/src/FSharp.Formatting.Common/YaafFSharpScripting.fs @@ -161,8 +161,9 @@ module internal CompilerServiceExtensions = yield "-r:" + dllFile for libDir in libDirs do yield "-I:" + libDir - if fsCoreLib.IsSome then - yield sprintf "-r:%s" fsCoreLib.Value + match fsCoreLib with + | None -> () + | Some fsCoreLib -> yield $"-r:%s{fsCoreLib}" yield! otherFlags yield fileName1 |] @@ -753,7 +754,7 @@ type internal FsiOptions = yield! (match x.NoWarns with | [] -> None - | l -> l |> Seq.map string |> String.concat "," |> sprintf "--nowarn:%s" |> Some) + | l -> l |> Seq.map string |> String.concat "," |> sprintf "--nowarn:%s" |> Some) |> maybeArg yield! match x.Optimize with @@ -799,7 +800,7 @@ type internal FsiOptions = x.WarnAsErrorList |> Seq.map (fun (enable, warnNums) -> warnNums - |> Seq.map string + |> Seq.map string |> String.concat "," |> sprintf "--warnaserror%s:%s" (getMinusPlus enable)) @@ -815,7 +816,7 @@ module internal Helper = type ForwardTextWriter(f) = inherit TextWriter() override __.Flush() = () - override __.Write(c: char) = f (string c) + override __.Write(c: char) = f (string c) override __.Write(c: string) = if isNull c |> not then @@ -875,15 +876,17 @@ module internal Helper = CombineTextWriter.Create [ yield fsiOutStream yield mergedOutStream - if liveFsiWriter.IsSome then - yield liveFsiWriter.Value ] + match liveFsiWriter with + | None -> () + | Some liveFsiWriter -> yield liveFsiWriter ] let stdOutWriter = CombineTextWriter.Create [ yield stdOutStream yield mergedOutStream - if liveOutWriter.IsSome then - yield liveOutWriter.Value ] + match liveOutWriter with + | None -> () + | Some liveFsiWriter -> yield liveFsiWriter ] let all = [ globalFsiOut, fsiOut; globalStdOut, stdOut; globalMergedOut, mergedOut ] @@ -891,7 +894,7 @@ module internal Helper = member _.StdOutWriter = stdOutWriter member _.GetOutputAndResetLocal() = - let [ fsi; std; merged ] = + let mapped = all |> List.map (fun (global', local) -> let data = local.ToString() @@ -902,9 +905,12 @@ module internal Helper = local.Clear() |> ignore data) - { FsiOutput = fsi - ScriptOutput = std - Merged = merged } + match mapped with + | [ fsi; std; merged ] -> + { FsiOutput = fsi + ScriptOutput = std + Merged = merged } + | _ -> failwith $"Expected three StringBuilders, got %A{mapped}" let consoleCapture out err f = let defOut = Console.Out diff --git a/src/FSharp.Formatting.Literate/Document.fs b/src/FSharp.Formatting.Literate/Document.fs index 65484090e..13e9e980a 100644 --- a/src/FSharp.Formatting.Literate/Document.fs +++ b/src/FSharp.Formatting.Literate/Document.fs @@ -128,7 +128,7 @@ type LiterateDocument(paragraphs, formattedTips, links, source, sourceFile, root member _.Paragraphs: MarkdownParagraphs = paragraphs /// Returns a dictionary containing explicitly defined links - member _.DefinedLinks: IDictionary> = links + member _.DefinedLinks: IDictionary = links /// Errors member _.Diagnostics: SourceError array = diagnostics diff --git a/src/FSharp.Formatting.Literate/Evaluator.fs b/src/FSharp.Formatting.Literate/Evaluator.fs index 20fbdd40a..cb0bba19d 100644 --- a/src/FSharp.Formatting.Literate/Evaluator.fs +++ b/src/FSharp.Formatting.Literate/Evaluator.fs @@ -94,7 +94,7 @@ type private NoOpFsiObject() = let mutable printSize = 10000 let mutable showIEnumerable = true let mutable showProperties = true - let mutable addedPrinters: list string), System.Type * (obj -> obj)>> = [] + let mutable addedPrinters: Choice string), System.Type * (obj -> obj)> list = [] member self.FloatingPointFormat with get () = fpfmt @@ -193,7 +193,7 @@ type FsiEvaluator let fsiSession = ScriptHost.Create(fsiOptions, discardStdOut = discardStdOut, fsiObj = fsiObj) let mutable plainTextPrinters: Choice<(obj -> string option), (obj -> obj option)> list = [] - let mutable htmlPrinters: Choice<(obj -> (seq * string) option), (obj -> obj option)> list = [] + let mutable htmlPrinters: Choice<(obj -> ((string * string) seq * string) option), (obj -> obj option)> list = [] //---------------------------------------------------- // Inject the standard 'fsi' script control model into the evaluation session @@ -247,7 +247,7 @@ type FsiEvaluator | _ -> if ty.IsAssignableFrom(value.GetType()) then match f with - | :? (obj -> seq * string) as f2 -> Some(f2 value) + | :? (obj -> (string * string) seq * string) as f2 -> Some(f2 value) | _ -> None else None @@ -444,7 +444,7 @@ module __FsiSettings = Unchecked.defaultof<_> with get, set /// Temporarily holds the function value injected into the F# evaluation session - static member val internal InjectedAddHtmlPrinter: ((obj -> seq * string) * Type -> unit) = + static member val internal InjectedAddHtmlPrinter: ((obj -> (string * string) seq * string) * Type -> unit) = Unchecked.defaultof<_> with get, set /// Temporarily holds the object value injected into the F# evaluation session diff --git a/src/FSharp.Formatting.Literate/Formatting.fs b/src/FSharp.Formatting.Literate/Formatting.fs index c296547c5..bb7083467 100644 --- a/src/FSharp.Formatting.Literate/Formatting.fs +++ b/src/FSharp.Formatting.Literate/Formatting.fs @@ -88,7 +88,7 @@ module internal Formatting = let id = count <- count + 1 - "cell" + string count + "cell" + string count let opts = { Evaluate = true diff --git a/src/FSharp.Formatting.Literate/ParseScript.fs b/src/FSharp.Formatting.Literate/ParseScript.fs index e81898f0d..2b2f39d4e 100644 --- a/src/FSharp.Formatting.Literate/ParseScript.fs +++ b/src/FSharp.Formatting.Literate/ParseScript.fs @@ -168,12 +168,13 @@ type internal ParseScript(parseOptions, ctx: CompilerContext) = /// Transform list of code blocks (snippet/comment/command) /// into a formatted Markdown document, with link definitions let rec transformBlocks isFirst prevCodeId count noEval acc defs blocks = - match blocks with + match blocks, prevCodeId with // Disable evaluation for the rest of the file - | BlockCommand(Command "do-not-eval-file" _) :: blocks -> transformBlocks false None count true acc defs blocks + | BlockCommand(Command "do-not-eval-file" _) :: blocks, _ -> + transformBlocks false None count true acc defs blocks // Reference to code snippet defined later - | BlockCommand((Command "include" ref) as cmds) :: blocks -> + | BlockCommand((Command "include" ref) as cmds) :: blocks, _ -> let popts = getParaOptions cmds let p = EmbedParagraphs(CodeReference(ref, popts), None) @@ -181,15 +182,15 @@ type internal ParseScript(parseOptions, ctx: CompilerContext) = transformBlocks false None count noEval (p :: acc) defs blocks // Include console output (stdout) of previous block - | BlockCommand(Command "include-output" EmptyString as cmds) :: blocks when prevCodeId.IsSome -> + | BlockCommand(Command "include-output" EmptyString as cmds) :: blocks, Some prevCodeId -> let popts = getParaOptions cmds - let p1 = EmbedParagraphs(OutputReference(prevCodeId.Value, popts), None) + let p1 = EmbedParagraphs(OutputReference(prevCodeId, popts), None) - transformBlocks false prevCodeId count noEval (p1 :: acc) defs blocks + transformBlocks false (Some prevCodeId) count noEval (p1 :: acc) defs blocks // Include console output (stdout) of a named block - | BlockCommand(Command "include-output" ref as cmds) :: blocks -> + | BlockCommand(Command "include-output" ref as cmds) :: blocks, _ -> let popts = getParaOptions cmds let p = EmbedParagraphs(OutputReference(ref, popts), None) @@ -197,15 +198,15 @@ type internal ParseScript(parseOptions, ctx: CompilerContext) = transformBlocks false prevCodeId count noEval (p :: acc) defs blocks // Include FSI output (stdout) of previous block - | BlockCommand(Command "include-fsi-output" EmptyString as cmds) :: blocks when prevCodeId.IsSome -> + | BlockCommand(Command "include-fsi-output" EmptyString as cmds) :: blocks, Some prevCodeId -> let popts = getParaOptions cmds - let p1 = EmbedParagraphs(FsiOutputReference(prevCodeId.Value, popts), None) + let p1 = EmbedParagraphs(FsiOutputReference(prevCodeId, popts), None) - transformBlocks false prevCodeId count noEval (p1 :: acc) defs blocks + transformBlocks false (Some prevCodeId) count noEval (p1 :: acc) defs blocks // Include FSI output (stdout) of a named block - | BlockCommand(Command "include-fsi-output" ref as cmds) :: blocks -> + | BlockCommand(Command "include-fsi-output" ref as cmds) :: blocks, _ -> let popts = getParaOptions cmds let p = EmbedParagraphs(FsiOutputReference(ref, popts), None) @@ -213,15 +214,15 @@ type internal ParseScript(parseOptions, ctx: CompilerContext) = transformBlocks false prevCodeId count noEval (p :: acc) defs blocks // Include the merge of the console and FSI output (stdout) of previous block - | BlockCommand(Command "include-fsi-merged-output" EmptyString as cmds) :: blocks when prevCodeId.IsSome -> + | BlockCommand(Command "include-fsi-merged-output" EmptyString as cmds) :: blocks, Some prevCodeId -> let popts = getParaOptions cmds - let p1 = EmbedParagraphs(FsiMergedOutputReference(prevCodeId.Value, popts), None) + let p1 = EmbedParagraphs(FsiMergedOutputReference(prevCodeId, popts), None) - transformBlocks false prevCodeId count noEval (p1 :: acc) defs blocks + transformBlocks false (Some prevCodeId) count noEval (p1 :: acc) defs blocks // Include the merge of the console and FSI output (stdout) of a named block - | BlockCommand(Command "include-fsi-merged-output" ref as cmds) :: blocks -> + | BlockCommand(Command "include-fsi-merged-output" ref as cmds) :: blocks, _ -> let popts = getParaOptions cmds let p = EmbedParagraphs(FsiMergedOutputReference(ref, popts), None) @@ -229,15 +230,15 @@ type internal ParseScript(parseOptions, ctx: CompilerContext) = transformBlocks false prevCodeId count noEval (p :: acc) defs blocks // Include formatted 'it' of previous block - | BlockCommand((Command "include-it" EmptyString) as cmds) :: blocks when prevCodeId.IsSome -> + | BlockCommand((Command "include-it" EmptyString) as cmds) :: blocks, Some prevCodeId -> let popts = getParaOptions cmds - let p1 = EmbedParagraphs(ItValueReference(prevCodeId.Value, popts), None) + let p1 = EmbedParagraphs(ItValueReference(prevCodeId, popts), None) - transformBlocks false prevCodeId count noEval (p1 :: acc) defs blocks + transformBlocks false (Some prevCodeId) count noEval (p1 :: acc) defs blocks // Include formatted 'it' of a named block - | BlockCommand(Command "include-it" ref as cmds) :: blocks -> + | BlockCommand(Command "include-it" ref as cmds) :: blocks, _ -> let popts = getParaOptions cmds let p = EmbedParagraphs(ItValueReference(ref, popts), None) @@ -245,15 +246,15 @@ type internal ParseScript(parseOptions, ctx: CompilerContext) = transformBlocks false None count noEval (p :: acc) defs blocks // Include unformatted 'it' of previous block - | BlockCommand((Command "include-it-raw" EmptyString) as cmds) :: blocks when prevCodeId.IsSome -> + | BlockCommand((Command "include-it-raw" EmptyString) as cmds) :: blocks, Some prevCodeId -> let popts = getParaOptions cmds - let p1 = EmbedParagraphs(ItRawReference(prevCodeId.Value, popts), None) + let p1 = EmbedParagraphs(ItRawReference(prevCodeId, popts), None) - transformBlocks false prevCodeId count noEval (p1 :: acc) defs blocks + transformBlocks false (Some prevCodeId) count noEval (p1 :: acc) defs blocks // Include unformatted 'it' of a named block - | BlockCommand(Command "include-it-raw" ref as cmds) :: blocks -> + | BlockCommand(Command "include-it-raw" ref as cmds) :: blocks, _ -> let popts = getParaOptions cmds let p = EmbedParagraphs(ItRawReference(ref, popts), None) @@ -261,7 +262,7 @@ type internal ParseScript(parseOptions, ctx: CompilerContext) = transformBlocks false None count noEval (p :: acc) defs blocks // Include formatted named value - | BlockCommand(Command "include-value" ref as cmds) :: blocks -> + | BlockCommand(Command "include-value" ref as cmds) :: blocks, _ -> let popts = getParaOptions cmds let p = EmbedParagraphs(ValueReference(ref, popts), None) @@ -269,7 +270,7 @@ type internal ParseScript(parseOptions, ctx: CompilerContext) = transformBlocks false None count noEval (p :: acc) defs blocks // Include code without evaluation - | BlockCommand(Command "raw" _ as cmds) :: BlockSnippet(snip) :: blocks -> + | BlockCommand(Command "raw" _ as cmds) :: BlockSnippet(snip) :: blocks, _ -> let popts = getParaOptions cmds let p = EmbedParagraphs(RawBlock(snip, popts), None) @@ -281,13 +282,13 @@ type internal ParseScript(parseOptions, ctx: CompilerContext) = // * do-not-eval - the snippet will not be evaluated // * define:foo - specifies the name of this snippet (for inclusion later) // * define-output - defines the name for the snippet's output - | BlockCommand(cmds) :: BlockSnippet(snip) :: blocks -> + | BlockCommand(cmds) :: BlockSnippet(snip) :: blocks, _ -> let outputName = match cmds with | Command "define-output" name -> name | _ -> incr count - "cell" + string count.Value + "cell" + string count.Value let opts = { Evaluate = getEvaluate noEval cmds @@ -302,17 +303,17 @@ type internal ParseScript(parseOptions, ctx: CompilerContext) = transformBlocks false (Some outputName) count noEval (code :: acc) defs blocks // Unknown command - | BlockCommand(cmds) :: _ -> + | BlockCommand(cmds) :: _, _ -> failwithf "Unknown command: %A" [ for (KeyValue(k, v)) in cmds -> sprintf "%s:%s" k v ] // Skip snippets with no content - | BlockSnippet([]) :: blocks -> transformBlocks isFirst prevCodeId count noEval acc defs blocks + | BlockSnippet([]) :: blocks, _ -> transformBlocks isFirst prevCodeId count noEval acc defs blocks // Ordinary F# code snippet - | BlockSnippet(snip) :: blocks -> + | BlockSnippet(snip) :: blocks, _ -> let id = incr count - "cell" + string count.Value + "cell" + string count.Value let opts = { Evaluate = not noEval @@ -327,7 +328,7 @@ type internal ParseScript(parseOptions, ctx: CompilerContext) = transformBlocks false (Some id) count noEval (p :: acc) defs blocks // Markdown documentation block - | BlockComment(text) :: blocks -> + | BlockComment(text) :: blocks, _ -> // yaml frontmatter let parseOptions = if isFirst then @@ -343,7 +344,7 @@ type internal ParseScript(parseOptions, ctx: CompilerContext) = let acc = (List.rev doc.Paragraphs) @ acc transformBlocks false None count noEval acc defs blocks - | [] -> + | [], _ -> // Union all link definitions & return Markdown doc let allDefs = [ for def in defs do diff --git a/src/FSharp.Formatting.Literate/Transformations.fs b/src/FSharp.Formatting.Literate/Transformations.fs index 41c2c904c..73783181d 100644 --- a/src/FSharp.Formatting.Literate/Transformations.fs +++ b/src/FSharp.Formatting.Literate/Transformations.fs @@ -131,13 +131,13 @@ module internal Transformations = + modul + " =\n" + "// [snippet:" - + (string index) + + (string index) + "]\n" + " " + code.Replace("\n", "\n ") + "\n" + "// [/snippet]" - | None, code -> "// [snippet:" + (string index) + "]\n" + code + "\n" + "// [/snippet]") + | None, code -> "// [snippet:" + (string index) + "]\n" + code + "\n" + "// [/snippet]") let modul = "module " + (new String(name |> Seq.filter Char.IsLetter |> Seq.toArray)) @@ -213,7 +213,10 @@ module internal Transformations = match refIndex.TryGetValue(key) with | true, i -> yield Literal(" [", r) - yield DirectLink([ Literal(string i, r) ], "#rf" + DateTime.Now.ToString("yyMMddhh"), None, r) + + yield + DirectLink([ Literal(string i, r) ], "#rf" + DateTime.Now.ToString("yyMMddhh"), None, r) + yield Literal("]", r) | _ -> () ] | MarkdownPatterns.SpanLeaf(sl) -> [ MarkdownPatterns.SpanLeaf(sl) ] @@ -386,8 +389,8 @@ module internal Transformations = | ValueReference _ -> ValueRef ref | _ -> OutputRef ref) - match results.TryFind(key) with - | Some(result, executionCount) -> + match results.TryFind(key), ctx.Evaluator with + | Some(result, executionCount), Some evaluator -> let kind = match special with | FsiMergedOutputReference _ -> FsiEmbedKind.FsiMergedOutput @@ -398,8 +401,8 @@ module internal Transformations = | ValueReference _ -> FsiEmbedKind.Value | _ -> failwith "unreachable" - ctx.Evaluator.Value.Format(result, kind, executionCount) - | None -> + evaluator.Format(result, kind, executionCount) + | _ -> let output = "Could not find reference '" + ref + "'" [ OutputBlock(output, "text/plain", None) ] diff --git a/src/FSharp.Formatting.Markdown/HtmlFormatting.fs b/src/FSharp.Formatting.Markdown/HtmlFormatting.fs index ce6a76b47..600bd742d 100644 --- a/src/FSharp.Formatting.Markdown/HtmlFormatting.fs +++ b/src/FSharp.Formatting.Markdown/HtmlFormatting.fs @@ -53,7 +53,7 @@ type internal FormattingContext = { LineBreak: unit -> unit Newline: string Writer: TextWriter - Links: IDictionary> + Links: IDictionary WrapCodeSnippets: bool GenerateHeaderAnchors: bool UniqueNameGenerator: UniqueNameGenerator @@ -142,7 +142,7 @@ let internal formatAnchor (ctx: FormattingContext) (spans: MarkdownSpans) = let extractWords (text: string) = Regex.Matches(text, @"\w+") |> Seq.cast |> Seq.map (fun m -> m.Value) - let rec gather (span: MarkdownSpan) : seq = + let rec gather (span: MarkdownSpan) : string seq = seq { match span with | Literal(str, _) -> yield! extractWords str @@ -177,7 +177,7 @@ let rec internal formatParagraph (ctx: FormattingContext) paragraph = | EmbedParagraphs(cmd, _) -> formatParagraphs ctx (cmd.Render()) | Heading(n, spans, _) -> - ctx.Writer.Write("") + ctx.Writer.Write(" n + ">") if ctx.GenerateHeaderAnchors then let anchorName = formatAnchor ctx spans @@ -187,7 +187,7 @@ let rec internal formatParagraph (ctx: FormattingContext) paragraph = else formatSpans ctx spans - ctx.Writer.Write("") + ctx.Writer.Write(" n + ">") | Paragraph(spans, _) -> ctx.ParagraphIndent() ctx.Writer.Write("

") @@ -196,7 +196,7 @@ let rec internal formatParagraph (ctx: FormattingContext) paragraph = formatSpan ctx span ctx.Writer.Write("

") - | HorizontalRule(_, _) -> ctx.Writer.Write("
") + | HorizontalRule _ -> ctx.Writer.Write("
") | CodeBlock(code, _, _fence, language, _, _) -> let code = if language = "fsharp" then @@ -241,10 +241,12 @@ let rec internal formatParagraph (ctx: FormattingContext) paragraph = ctx.Writer.Write("") ctx.Writer.Write(ctx.Newline) - if headers.IsSome then + match headers with + | None -> () + | Some headers -> ctx.Writer.Write("" + ctx.Newline + "" + ctx.Newline) - for cell, align in Seq.zip headers.Value aligns do + for cell, align in Seq.zip headers aligns do ctx.Writer.Write("") for paragraph in cell do diff --git a/src/FSharp.Formatting.Markdown/LatexFormatting.fs b/src/FSharp.Formatting.Markdown/LatexFormatting.fs index ddb8b1cda..28f8f07f1 100644 --- a/src/FSharp.Formatting.Markdown/LatexFormatting.fs +++ b/src/FSharp.Formatting.Markdown/LatexFormatting.fs @@ -47,7 +47,7 @@ type FormattingContext = { LineBreak: unit -> unit Newline: string Writer: TextWriter - Links: IDictionary> + Links: IDictionary GenerateLineNumbers: bool DefineSymbol: string } diff --git a/src/FSharp.Formatting.Markdown/Markdown.fs b/src/FSharp.Formatting.Markdown/Markdown.fs index c08928d3c..408fcb935 100644 --- a/src/FSharp.Formatting.Markdown/Markdown.fs +++ b/src/FSharp.Formatting.Markdown/Markdown.fs @@ -26,7 +26,7 @@ type MarkdownDocument(paragraphs, links) = member x.Paragraphs: MarkdownParagraphs = paragraphs /// Returns a dictionary containing explicitly defined links - member x.DefinedLinks: IDictionary> = links + member x.DefinedLinks: IDictionary = links /// Static class that provides methods for formatting /// and transforming Markdown documents. diff --git a/src/FSharp.Formatting.Markdown/MarkdownModel.fs b/src/FSharp.Formatting.Markdown/MarkdownModel.fs index dceaa90dc..635a886c5 100644 --- a/src/FSharp.Formatting.Markdown/MarkdownModel.fs +++ b/src/FSharp.Formatting.Markdown/MarkdownModel.fs @@ -70,7 +70,7 @@ type MarkdownParagraph = | InlineHtmlBlock of code: string * executionCount: int option * range: MarkdownRange option /// A Markdown List block - | ListBlock of kind: MarkdownListKind * items: list * range: MarkdownRange option + | ListBlock of kind: MarkdownListKind * items: MarkdownParagraphs list * range: MarkdownRange option /// A Markdown Quote block | QuotedBlock of paragraphs: MarkdownParagraphs * range: MarkdownRange option @@ -79,16 +79,16 @@ type MarkdownParagraph = | Span of body: MarkdownSpans * range: MarkdownRange option /// A Markdown Latex block - | LatexBlock of env: string * body: list * range: MarkdownRange option + | LatexBlock of env: string * body: string list * range: MarkdownRange option /// A Markdown Horizontal rule | HorizontalRule of character: char * range: MarkdownRange option /// A Markdown Table | TableBlock of - headers: option * - alignments: list * - rows: list * + headers: MarkdownTableRow option * + alignments: MarkdownColumnAlignment list * + rows: MarkdownTableRow list * range: MarkdownRange option /// Represents a block of markdown produced when parsing of code or tables or quoted blocks is suppressed @@ -104,10 +104,10 @@ type MarkdownParagraph = | OutputBlock of output: string * kind: string * executionCount: int option /// A type alias for a list of paragraphs -type MarkdownParagraphs = list +type MarkdownParagraphs = MarkdownParagraph list /// A type alias representing table row as a list of paragraphs -type MarkdownTableRow = list +type MarkdownTableRow = MarkdownParagraphs list /// Provides an extensibility point for adding custom kinds of paragraphs into a document /// (MarkdownEmbedParagraphs values can be embedded using MarkdownParagraph.EmbedParagraphs) diff --git a/src/FSharp.Formatting.Markdown/MarkdownParser.fs b/src/FSharp.Formatting.Markdown/MarkdownParser.fs index 4c1ff8a9c..739e95674 100644 --- a/src/FSharp.Formatting.Markdown/MarkdownParser.fs +++ b/src/FSharp.Formatting.Markdown/MarkdownParser.fs @@ -73,14 +73,10 @@ let (|NotPunctuation|_|) input = | _ -> Some input module Char = - let (|WhiteSpace|_|) input = + let (|WhiteSpace|_|) (input: char list) = match input with | [] -> Some input - | x :: _xs -> - if String.IsNullOrWhiteSpace(string x) then - Some input - else - None + | x :: _xs -> if Char.IsWhiteSpace x then Some input else None let (|NotWhiteSpace|_|) input = match input with @@ -316,7 +312,7 @@ let (|HtmlEntity|_|) input = /// Defines a context for the main `parseParagraphs` function type ParsingContext = - { Links: Dictionary> + { Links: Dictionary Newline: string IsFirst: bool CurrentRange: MarkdownRange option @@ -872,7 +868,7 @@ let (|TableCellSeparator|_|) = /// Recognizes row of pipe table. /// The function takes number of expected columns and array of delimiters. /// Returns list of strings between delimiters. -let (|PipeTableRow|_|) (size: option) delimiters (line: string, n: MarkdownRange) = +let (|PipeTableRow|_|) (size: int option) delimiters (line: string, n: MarkdownRange) = let parts = pipeTableFindSplits delimiters (line.ToCharArray() |> Array.toList) |> List.toArray @@ -880,7 +876,7 @@ let (|PipeTableRow|_|) (size: option) delimiters (line: string, n: Markdown let n = parts.Length - let m = if size.IsNone then 1 else size.Value + let m = size |> Option.defaultValue 1 let x = if String.IsNullOrEmpty(fst parts.[0]) && n > m then @@ -943,16 +939,14 @@ let (|PipeTableBlock|_|) input = /// Passed function is used to check whether all parts within grid are valid. /// Retuns tuple (position of grid columns, text between grid columns). let (|EmacsTableLine|_|) - (grid: option) + (grid: int array option) (c: char) (check: string * MarkdownRange -> bool) (line: string, _n: MarkdownRange) = let p = - if grid.IsSome then - grid.Value - else - Array.FindAll([| 0 .. line.Length - 1 |], (fun i -> line.[i] = c)) + grid + |> Option.defaultValue (Array.FindAll([| 0 .. line.Length - 1 |], (fun i -> line.[i] = c))) let n = p.Length - 1 @@ -1247,10 +1241,8 @@ let rec parseParagraphs (ctx: ParsingContext) (lines: (string * MarkdownRange) l yield OtherBlock(takenLines @ takenLines2, ctx.CurrentRange) else let headParagraphs = - if headers.IsNone then - None - else - Some(headers.Value |> List.map (fun i -> parseParagraphs ctx i |> List.ofSeq)) + headers + |> Option.map (fun headers -> headers |> List.map (fun i -> parseParagraphs ctx i |> List.ofSeq)) let rows = rows |> List.map (List.map (fun i -> parseParagraphs ctx i |> List.ofSeq)) diff --git a/src/FSharp.Formatting.Markdown/MarkdownUtils.fs b/src/FSharp.Formatting.Markdown/MarkdownUtils.fs index 393e15fc8..a6f86905c 100644 --- a/src/FSharp.Formatting.Markdown/MarkdownUtils.fs +++ b/src/FSharp.Formatting.Markdown/MarkdownUtils.fs @@ -75,7 +75,7 @@ module internal MarkdownUtils = /// Context passed around while formatting type FormattingContext = { - Links: IDictionary> + Links: IDictionary Newline: string /// Additional replacements to be made in content Substitutions: Substitutions @@ -344,7 +344,7 @@ module internal MarkdownUtils = if attribute.Value.EndsWith(".md", StringComparison.Ordinal) then attribute.SetValue(fLink attribute.Value) - let html = element.Elements() |> Seq.map string |> String.concat "" |> fText + let html = element.Elements() |> Seq.map string |> String.concat "" |> fText InlineHtmlBlock(html, count, range) with ex -> InlineHtmlBlock(mapText f code, count, range) diff --git a/src/fsdocs-tool/BuildCommand.fs b/src/fsdocs-tool/BuildCommand.fs index c6da4d81c..acca2b3ae 100644 --- a/src/fsdocs-tool/BuildCommand.fs +++ b/src/fsdocs-tool/BuildCommand.fs @@ -455,9 +455,11 @@ type internal DocContent File.SetLastWriteTime(outputFileFullPath, DateTime.Now) with _ when watch -> ())) + //printfn "skipping unchanged file %s" inputFileFullPath else if mainRun && watch then - //printfn "skipping unchanged file %s" inputFileFullPath - yield (Some(inputFileFullPath, isOtherLang, haveModel.Value), (fun _ -> ())) ] + match haveModel with + | None -> () + | Some haveModel -> yield (Some(inputFileFullPath, isOtherLang, haveModel), (fun _ -> ())) ] let rec processFolder (htmlTemplate, texTemplate, pynbTemplate, fsxTemplate, mdTemplate, isOtherLang, rootInputFolder, fullPathFileMap) @@ -818,7 +820,7 @@ module Serve = """ - tag.Replace("{{PORT}}", string port) + tag.Replace("{{PORT}}", string port) let connectedClients = ConcurrentDictionary() diff --git a/src/fsdocs-tool/ProjectCracker.fs b/src/fsdocs-tool/ProjectCracker.fs index 142077012..df698acf3 100644 --- a/src/fsdocs-tool/ProjectCracker.fs +++ b/src/fsdocs-tool/ProjectCracker.fs @@ -354,7 +354,7 @@ module Crack = RepositoryCommit = msbuildPropString "RepositoryCommit" } Ok(targetFrameworks, projOptions2) - | Error err -> GetProjectOptionsErrors(string err, msgs) |> Result.Error + | Error err -> GetProjectOptionsErrors(err, msgs) |> Result.Error let private ensureProjectWasRestored (file: string) = let projDir = Path.GetDirectoryName(file) @@ -661,22 +661,28 @@ module Crack = let crackedProjects = projectInfos - |> List.map (fun info -> - let substitutions = parametersForProjectInfo info - - info.TargetPath.Value, - info.ProjectOptions.Value.OtherOptions, - info.RepositoryUrl, - info.RepositoryBranch, - info.RepositoryType, - info.UsesMarkdownComments, - info.FsDocsWarnOnMissingDocs, - info.FsDocsSourceFolder, - info.FsDocsSourceRepository, - substitutions) - - let paths = [ for info in projectInfos -> Path.GetDirectoryName info.TargetPath.Value ] + |> List.choose (fun info -> + match info.TargetPath, info.ProjectOptions with + | Some targetPath, Some projectOptions -> + let substitutions = parametersForProjectInfo info + + Some( + targetPath, + projectOptions.OtherOptions, + info.RepositoryUrl, + info.RepositoryBranch, + info.RepositoryType, + info.UsesMarkdownComments, + info.FsDocsWarnOnMissingDocs, + info.FsDocsSourceFolder, + info.FsDocsSourceRepository, + substitutions + ) + | _ -> None) + + let paths = + projectInfos + |> List.choose (fun projectInfo -> projectInfo.TargetPath |> Option.map Path.GetDirectoryName) let docsParameters = parametersForProjectInfo projectInfoForDocs - root, collectionName, crackedProjects, paths, docsParameters