Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Rework documentation parser #1259

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions release/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1384,6 +1384,15 @@
"description": "The prefix displayed before the signature",
"default": " // "
},
"FSharp.tooltipMode": {
"type": "string",
"description": "Control if tooltip should show only the summary or all the information",
"enum": [
"summary",
"full"
],
"default": "full"
},
"FSharp.disableFailedProjectNotifications": {
"type": "boolean",
"default": false,
Expand Down
7 changes: 4 additions & 3 deletions src/Components/InfoPanel.fs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ module InfoPanel =

module Panel =

let showdown = Fable.Import.Showdown.showdown.Converter.Create()
let showdownOptions = Fable.Import.Showdown.showdown.getDefaultOptions() :?> Fable.Import.Showdown.Showdown.ConverterOptions
showdownOptions.tables <- Some true

let showdown = Fable.Import.Showdown.showdown.Converter.Create(showdownOptions)

let mutable panel : WebviewPanel option = None

Expand All @@ -31,7 +34,6 @@ module InfoPanel =
else
false


let setContent str =
panel |> Option.iter (fun p ->
let str = showdown.makeHtml str
Expand Down Expand Up @@ -79,7 +81,6 @@ module InfoPanel =

let commentContent =
res.Comment
|> Markdown.createCommentString

let footerContent =
res.Footer
Expand Down
25 changes: 22 additions & 3 deletions src/Components/SignatureData.fs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,29 @@ module SignatureData =
p.Data.Parameters
|> Seq.concat
|> Seq.where (fun prm -> String.IsNullOrWhiteSpace prm.Name |> not)
|> Seq.map (fun prm -> sprintf "/// * `%s` - parameter of type `%s`" prm.Name prm.Type)
|> Seq.map (fun prm -> sprintf """/// <param name="%s"></param>""" prm.Name)
|> String.concat "\n"
let pms = if pms = "" then "///" else pms
let comment = sprintf "\n/// **Description**\n///\n/// **Parameters**\n%s\n///\n/// **Output Type**\n/// * `%s`\n///\n/// **Exceptions**\n///" pms p.Data.OutputType

let generics =
p.Data.Generics
|> Seq.map (fun generic ->
sprintf """/// <typeparam name="'%s"></typeparam>""" generic
)
|> String.concat "\n"

let comment =
[
yield "/// <summary>"
yield "/// "
yield "/// </summary>"
if pms <> "" then
yield pms
if generics <> "" then
yield generics
yield "/// <returns></returns>"
]
|> String.concat "\n"

let x = window.activeTextEditor.selection.active.line
let t = window.activeTextEditor.document.getText(Range(x, 0., x, 1000.))
let t' = t.TrimStart(' ')
Expand Down
3 changes: 2 additions & 1 deletion src/Core/DTO.fs
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,8 @@ module DTO =

type SignatureData =
{ OutputType : string
Parameters : Parameter list list }
Parameters : Parameter list list
Generics : string list }

type RangesAtPosition = {Ranges: Range list list}

Expand Down
114 changes: 0 additions & 114 deletions src/Core/Utils.fs
Original file line number Diff line number Diff line change
Expand Up @@ -200,120 +200,6 @@ module Array =
| _ when n >= xs.Length || n < 0 -> xs, [||]
| _ -> xs.[0..n-1], xs.[n..]

module Markdown =

open System.Text.RegularExpressions

let private stringReplacePatterns =
[ "&lt;", "<"
"&gt;", ">"
"&quot;", "\""
"&apos;", "'"
"&amp;", "&"
"<summary>", "**Description**\n\n"
"</summary>", "\n"
"<para>", "\n"
"</para>", "\n"
"<remarks>", ""
"</remarks>", "\n" ]

let private regexReplacePatterns =
let r pat = Regex(pat, RegexOptions.IgnoreCase)

let code (strings : string array) =
let str = strings.[0]
if str.Contains("\n") then
"```forceNoHighlight" + str + "```"
else
"`" + str + "`"
let returns = Array.item 0 >> sprintf "\n**Returns**\n\n%s"

let param (s : string[]) = sprintf "* `%s`: %s"(s.[0].Substring(1, s.[0].Length - 2)) s.[1]

[ r"<c>((?:(?!<c>)(?!<\/c>)[\s\S])*)<\/c>", code
r"""<see\s+cref=(?:'[^']*'|"[^"]*")>((?:(?!<\/see>)[\s\S])*)<\/see>""", code
r"""<param\s+name=('[^']*'|"[^"]*")>((?:(?!<\/param>)[\s\S])*)<\/param>""", param
r"""<typeparam\s+name=('[^']*'|"[^"]*")>((?:(?!<\/typeparam>)[\s\S])*)<\/typeparam>""", param
r"""<exception\s+cref=('[^']*'|"[^"]*")>((?:(?!<\/exception>)[\s\S])*)<\/exception>""", param
r"""<a\s+href=('[^']*'|"[^"]*")>((?:(?!<\/a>)[\s\S])*)<\/a>""", fun s -> (s.[0].Substring(1, s.[0].Length - 2))
r"<returns>((?:(?!<\/returns>)[\s\S])*)<\/returns>", returns ]

/// Helpers to create a new section in the markdown comment
let private suffixXmlKey (tag : string) (value : string) (str : string) =
match str.IndexOf(tag) with
| x when x <> -1 ->
let insertAt =
if str.Chars(x - 1) = ' ' then
x - 1
else
x
str.Insert(insertAt, value)
| _ -> str

let private suffixTypeparam = suffixXmlKey "<typeparam" "\n**Type parameters**\n\n"

let private suffixException = suffixXmlKey "<exception" "\n**Exceptions**\n\n"

let private suffixParam = suffixXmlKey "<param" "\n**Parameters**\n\n"

/// Replaces XML tags with Markdown equivalents.
/// List of standard tags: https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/xml-documentation
let private replaceXml (str : string) : string =
let str =
str
|> suffixTypeparam
|> suffixException
|> suffixParam

let res =
regexReplacePatterns
|> List.fold (fun res (regex : Regex, formatter : string[] -> string) ->
// repeat replacing with same pattern to handle nested tags, like `<c>..<c>..</c>..</c>`
let rec loop res : string =
match regex.Match res with
| m when m.Success ->
let splitted =
m.Groups
|> Seq.cast<Group>
|> Seq.map (fun g -> g.Value)
|> Seq.toArray
|> Array.splitAt 1
match splitted with
| [| firstGroup |], otherGroups ->
loop <| res.Replace(firstGroup, formatter otherGroups)
| _ -> failwithf "Error in regex pattern for nested xml tags with %s" res
| _ -> res
loop res
) str

stringReplacePatterns
|> List.fold (fun (res : string) (oldValue, newValue) ->
res.Replace(oldValue, newValue)
) res

let private normalizeLeadingSpace (content : string) =
content
.Replace("\r\n", "\n")
.Split('\n')
|> Array.map(fun line ->
if line.Length > 1 && line.[0] = ' ' then
line.[1..]
else
line
)
|> String.concat "\n"

let createCommentBlock (comment : string) : MarkdownString =
comment
|> replaceXml
|> normalizeLeadingSpace
|> (fun v -> MarkdownString v)

let createCommentString (comment : string) : string =
comment
|> replaceXml
|> normalizeLeadingSpace

module Promise =

open Fable.Import.JS
Expand Down