Skip to content

Commit

Permalink
Print trivia around SynConst and correct line comment construction. F…
Browse files Browse the repository at this point in the history
…ixes #1518 (#1519)
  • Loading branch information
nojaf committed Mar 14, 2021
1 parent 75f0dfc commit ea53b70
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 65 deletions.
106 changes: 106 additions & 0 deletions src/Fantomas.Tests/SynConstTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -308,3 +308,109 @@ let controlEscapes = "\a \b \f \v"
"""let hexEscape = "\x00"
let controlEscapes = "\a \b \f \v"
"""

[<Test>]
let ``trivia after SynConst.Boolean, 1518`` () =
formatSourceString
false
"""
match ast with
| ParsedInput.SigFile _input ->
// There is not much to explore in signature files
true
| ParsedInput.ImplFile input -> validateImplFileInput input
match t with
| TTuple _ -> not node.IsEmpty
| TFun _ -> true // Fun is grouped by brackets inside 'genType astContext true t'
| _ -> false
let condition e =
match e with
| ElIf _
| SynExpr.Lambda _ -> true
| _ -> false // "if .. then .. else" have precedence over ","
let x = 9
"""
config
|> prepend newline
|> should
equal
"""
match ast with
| ParsedInput.SigFile _input ->
// There is not much to explore in signature files
true
| ParsedInput.ImplFile input -> validateImplFileInput input
match t with
| TTuple _ -> not node.IsEmpty
| TFun _ -> true // Fun is grouped by brackets inside 'genType astContext true t'
| _ -> false
let condition e =
match e with
| ElIf _
| SynExpr.Lambda _ -> true
| _ -> false // "if .. then .. else" have precedence over ","
let x = 9
"""

[<Test>]
let ``trivia after SynConst.Char`` () =
formatSourceString
false
"""
let c = 'r' // meh
let x = 1
"""
config
|> prepend newline
|> should
equal
"""
let c = 'r' // meh
let x = 1
"""

[<Test>]
let ``trivia after SynConst.Bytes`` () =
formatSourceString
false
"""
let bytes = "meh"B // meh
let x = 1
"""
config
|> prepend newline
|> should
equal
"""
let bytes = "meh"B // meh
let x = 1
"""

[<Test>]
let ``trivia after SynConst.String, 1518`` () =
formatSourceString
false
"
let source = \"\"\"printfn foo
printfn bar\"\"\" // difference is the 4 spaces on line 188
let x = 9
"
config
|> prepend newline
|> should
equal
"
let source = \"\"\"printfn foo
printfn bar\"\"\" // difference is the 4 spaces on line 188
let x = 9
"
25 changes: 19 additions & 6 deletions src/Fantomas/CodePrinter.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5173,7 +5173,9 @@ and genConst (c: SynConst) (r: Range) =
+> !- ")"
+> leaveNodeTokenByName r RPAREN
|> genTriviaFor SynConst_Unit r
| SynConst.Bool (b) -> !-(if b then "true" else "false")
| SynConst.Bool (b) ->
!-(if b then "true" else "false")
|> genTriviaFor SynConst_Bool r
| SynConst.Byte _
| SynConst.SByte _
| SynConst.Int16 _
Expand Down Expand Up @@ -5218,18 +5220,29 @@ and genConst (c: SynConst) (r: Range) =
<| ctx
| SynConst.Char (c) ->
fun (ctx: Context) ->
let charContentFromTrivia =
TriviaHelpers.``get CharContent`` r ctx.TriviaMainNodes
let tn =
Map.tryFindOrEmptyList SynConst_Char ctx.TriviaMainNodes
|> List.tryFind (fun t -> RangeHelpers.rangeEq t.Range r)

let expr =
match charContentFromTrivia with
| Some content -> !-content
match tn with
| Some ({ ContentItself = Some (CharContent (content)) } as tn) ->
printContentBefore tn -- content
+> printContentAfter tn
| Some tn ->
let escapedChar = Char.escape c

printContentBefore tn
-- (sprintf "\'%s\'" escapedChar)
+> printContentAfter tn
| None ->
let escapedChar = Char.escape c
!-(sprintf "\'%s\'" escapedChar)

expr ctx
| SynConst.Bytes (bytes, r) -> genConstBytes bytes r
| SynConst.Bytes (bytes, r) ->
genConstBytes bytes r
|> genTriviaFor SynConst_Bytes r
| SynConst.Measure (c, m) ->
let measure =
match m with
Expand Down
73 changes: 25 additions & 48 deletions src/Fantomas/TokenParser.fs
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,23 @@ let rec private tokenizeLine (tokenizer: FSharpLineTokenizer) sourceCodeLines st
let extraToken =
{ TokenInfo = extraTokenInfo
LineNumber = lineNumber
Content = getTokenText sourceCodeLines lineNumber extraTokenInfo }
Content = getTokenText sourceCodeLines lineNumber extraTokenInfo
Index = 0 }

let token =
{ TokenInfo = tok
LineNumber = lineNumber
Content = getTokenText sourceCodeLines lineNumber tok }
Content = getTokenText sourceCodeLines lineNumber tok
Index = 0 }

tokenizeLine tokenizer sourceCodeLines state lineNumber (token :: extraToken :: tokens)

| (Some tok, state), _ ->
let token : Token =
{ TokenInfo = tok
LineNumber = lineNumber
Content = getTokenText sourceCodeLines lineNumber tok }
Content = getTokenText sourceCodeLines lineNumber tok
Index = 0 }
// Tokenize the rest, in the new state
tokenizeLine tokenizer sourceCodeLines state lineNumber (token :: tokens)

Expand Down Expand Up @@ -83,6 +86,7 @@ let private createHashToken lineNumber content offset =

{ LineNumber = lineNumber
Content = content
Index = 0
TokenInfo =
{ TokenName = "HASH_IF"
LeftColumn = left
Expand Down Expand Up @@ -337,6 +341,7 @@ and tokenize defines (hashTokens: Token list) (content: string) : Token list =
tokens

combined
|> List.mapi (fun idx t -> { t with Index = idx })

let getDefinesWords (tokens: Token list) =
tokens
Expand Down Expand Up @@ -672,54 +677,26 @@ let rec private getTriviaFromTokensThemSelves
foundTrivia
=
match tokens with
| (NoCommentToken nct) :: WhiteSpaceToken _ :: (LineComments (commentTokens, nextTokens)) ->
let comment =
let commentText = collectComment commentTokens
let firstCommentToken = List.head commentTokens

(if nct.LineNumber < firstCommentToken.LineNumber then
LineCommentOnSingleLine commentText
else
LineCommentAfterSourceCode commentText)
|> Comment

let range =
let headToken = List.head commentTokens
let lastToken = List.tryLast commentTokens
getRangeBetween mkRange headToken (Option.defaultValue headToken lastToken)

let info =
Trivia.Create comment range
|> List.appendItem foundTrivia

getTriviaFromTokensThemSelves mkRange allTokens (nct :: nextTokens) info
| (NoCommentToken nct) :: (LineComments (commentTokens, nextTokens)) ->
let comment =
let commentText = collectComment commentTokens
let firstCommentToken = List.head commentTokens

(if nct.LineNumber < firstCommentToken.LineNumber
|| (nct.TokenInfo.Tag = whiteSpaceTag
&& firstCommentToken.LineNumber = nct.LineNumber) then
LineCommentOnSingleLine commentText
else
LineCommentAfterSourceCode commentText)
|> Comment

let range =
let headToken = List.head commentTokens
let lastToken = List.tryLast commentTokens
getRangeBetween mkRange headToken (Option.defaultValue headToken lastToken)

let info =
Trivia.Create comment range
|> List.appendItem foundTrivia
| LineComments (({ Index = headIndex
LineNumber = headLineNumber } :: _ as commentTokens),
nextTokens) ->
let prevToken = List.tryItem (headIndex - 1) allTokens
let prevButOneToken = List.tryItem (headIndex - 2) allTokens

let commentType =
match prevButOneToken, prevToken with
| Some ({ LineNumber = ncln }), Some (WhiteSpaceToken _) ->
if ncln = headLineNumber then
LineCommentAfterSourceCode
else
LineCommentOnSingleLine
| Some ({ LineNumber = l1 }), Some ({ LineNumber = l2 }) when (headLineNumber = l1 && headLineNumber = l2) ->
LineCommentAfterSourceCode
| _ -> LineCommentOnSingleLine

getTriviaFromTokensThemSelves mkRange allTokens (nct :: nextTokens) info
| LineComments (commentTokens, nextTokens) ->
let comment =
collectComment commentTokens
|> LineCommentOnSingleLine
|> commentType
|> Comment

let range =
Expand Down
10 changes: 0 additions & 10 deletions src/Fantomas/TriviaHelpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -125,15 +125,5 @@ module internal TriviaHelpers =
| Some (StringContent sc) -> String.isMultiline sc
| _ -> false


RangeHelpers.rangeEq tn.Range range
&& contentItSelfIsMultilineString ())

let ``get CharContent`` range (nodes: Map<FsAstType, TriviaNode list>) =
Map.tryFindOrEmptyList SynConst_Char nodes
|> List.tryFind (fun t -> RangeHelpers.rangeEq t.Range range)
|> Option.bind
(fun tv ->
match tv.ContentItself with
| Some (CharContent c) -> Some c
| _ -> None)
3 changes: 2 additions & 1 deletion src/Fantomas/TriviaTypes.fs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ type FsTokenType =
type Token =
{ TokenInfo: FSharpTokenInfo
LineNumber: int
Content: string }
Content: string
Index: int }

type Comment =
| LineCommentAfterSourceCode of comment: string
Expand Down

0 comments on commit ea53b70

Please sign in to comment.