Skip to content

Commit

Permalink
Preserve ident names between ticks. Fixes #406
Browse files Browse the repository at this point in the history
  • Loading branch information
nojaf committed Jul 17, 2019
1 parent 26db836 commit 163d4bb
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 32 deletions.
6 changes: 6 additions & 0 deletions src/Fantomas.Tests/LetBindingTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -124,4 +124,10 @@ let b = "meh"
let b = "meh"
"""

[<Test>]
let ``Raw method names with `/` `` () =
formatSourceString false "let ``/ operator combines paths`` = x" config
|> should equal """let ``/ operator combines paths`` = x
"""
10 changes: 10 additions & 0 deletions src/Fantomas.Tests/TokenParserTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -381,3 +381,13 @@ let ``infix operator in full words inside an ident`` () =
|> List.filter (fun { Item = item } -> match item with | IdentOperatorAsWord "op_LessThan" -> true | _ -> false)

List.length triviaNodes == 1

[<Test>]
let ``ident between tickets `` () =
let source = "let ``/ operator combines paths`` = ()"
let (tokens,lineCount) = tokenize [] source
let triviaNodes = getTriviaFromTokens tokens lineCount
match triviaNodes with
| [{ Item = IdentBetweenTicks("``/ operator combines paths``") }] ->
pass()
| _ -> fail()
18 changes: 9 additions & 9 deletions src/Fantomas.Tests/TriviaTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ let a = 9

match triviaNodes with
| [{ ContentBefore = [Comment(LineCommentOnSingleLine(lineComment))]; }
{ContentBefore = [Number("9")]}] ->
{ ContentItself = Some(Number("9"))}] ->
lineComment == "// meh"
| _ ->
failwith "Expected line comment"
Expand Down Expand Up @@ -66,7 +66,7 @@ let ``Line comment on same line, is after last AST item`` () =
|> List.head

match triviaNodes with
| [{Type = MainNode("SynModuleOrNamespace.AnonModule") ;ContentAfter = [Comment(LineCommentAfterSourceCode(lineComment))]}; {Type = MainNode("SynExpr.Const"); ContentBefore =[Number("7")]}] ->
| [{Type = MainNode("SynModuleOrNamespace.AnonModule") ;ContentAfter = [Comment(LineCommentAfterSourceCode(lineComment))]}; {Type = MainNode("SynExpr.Const"); ContentItself =Some(Number("7"))}] ->
lineComment == "// should be 8"
| _ ->
fail()
Expand All @@ -81,9 +81,9 @@ let b = 9"""
|> List.head

match triviaNodes with
| [{ContentBefore = [Number("7")]}
| [{ContentItself = Some(Number("7"))}
{ContentBefore = [Newline]}
{ContentBefore = [Number("9")]}] ->
{ContentItself = Some(Number("9"))}] ->
pass()
| _ ->
fail()
Expand All @@ -101,7 +101,7 @@ let a = 7

match triviaNodes with
| [{ContentBefore = [Comment(LineCommentOnSingleLine(fooComment));Comment(LineCommentOnSingleLine(barComment))]}
{ContentBefore = [Number("7")]}] ->
{ContentItself = Some(Number("7"))}] ->
fooComment == "// foo"
barComment == "// bar"
| _ ->
Expand All @@ -120,7 +120,7 @@ let ``Comments inside record`` () =

match triviaNodes with
| [{ Type = TriviaNodeType.Token(t); ContentAfter = [Comment(LineCommentAfterSourceCode("// foo"))] }
{ ContentBefore = [Number("7")] }] ->
{ ContentItself = Some(Number("7")) }] ->
t.Content == "{"
| _ ->
fail()
Expand All @@ -138,7 +138,7 @@ let ``Comment after all source code`` () =

match triviaNodes with
| [ { Type = MainNode(mn); ContentAfter = [Comment(LineCommentOnSingleLine(lineComment))] }
{ ContentBefore = [Number("123")] } ] ->
{ ContentItself = Some(Number("123")) } ] ->
mn == "SynModuleDecl.Types"
lineComment == (sprintf "%s// override private x.ToString() = \"\"" Environment.NewLine)
pass()
Expand All @@ -155,7 +155,7 @@ let ``Block comment added to trivia`` () =

match triviaNodes with
| [{ ContentAfter = [Comment(BlockComment(comment))]
Type = Token { Content = "=" } }; {ContentBefore = [Number("9")]}] ->
Type = Token { Content = "=" } }; {ContentItself = Some(Number("9"))}] ->
comment == "(* meh *)"
| _ ->
failwith "Expected block comment"
Expand Down Expand Up @@ -234,7 +234,7 @@ let a = 9

match triviaNodes with
| [{ ContentBefore = [Comment(BlockComment(comment)); Newline] }
{ ContentBefore = [Number("9")] }] ->
{ ContentItself = Some(Number("9")) }] ->
comment == "(* // meh *)"
| _ ->
failwith "Expected block comment"
Expand Down
30 changes: 12 additions & 18 deletions src/Fantomas/CodePrinter.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1808,12 +1808,9 @@ and genConst (c:SynConst) (r:range) =
let triviaStringContent =
trivia
|> Option.bind(fun tv ->
tv.ContentBefore
|> List.choose (fun tv ->
match tv with
| StringContent(sc) -> Some sc
| _ -> None )
|> List.tryExactlyOne
match tv.ContentItself with
| Some(StringContent(sc)) -> Some sc
| _ -> None
)

match triviaStringContent, trivia with
Expand Down Expand Up @@ -1843,9 +1840,7 @@ and genConstNumber (c:SynConst) (r: range) =
ctx.Trivia
|> List.tryFind (fun t -> t.Range = r)
|> Option.bind(fun tn ->
tn.ContentBefore
|> List.choose (fun tv -> match tv with | Number(n) -> Some n | _ -> None)
|> List.tryExactlyOne
match tn.ContentItself with | Some(Number(n)) -> Some n | _ -> None
)
|> fun n ->
match n with
Expand Down Expand Up @@ -1876,12 +1871,10 @@ and genConstBytes (bytes: byte []) (r: range) =
ctx.Trivia
|> List.tryFind(fun t -> t.Range = r)
|> Option.bind (fun tv ->
tv.ContentBefore
|> List.choose (fun sc ->
match sc with
| StringContent(content) -> Some content
| _ -> None)
|> List.tryExactlyOne)
match tv.ContentItself with
| Some(StringContent(content)) -> Some content
| _ -> None
)

match trivia with
| Some t -> !- t
Expand All @@ -1899,9 +1892,10 @@ and infixOperatorFromTrivia range fallback (ctx: Context) =
|> List.choose(fun t ->
match t.Range = range with
| true ->
t.ContentBefore
|> List.choose (fun tc -> match tc with | IdentOperatorAsWord(iiw) -> Some iiw | _ -> None)
|> List.tryHead
match t.ContentItself with
| Some(IdentOperatorAsWord(iiw)) -> Some iiw
| Some(IdentBetweenTicks(iiw)) -> Some iiw // Used when value between ``...``
| _ -> None
| _ -> None)
|> List.tryHead
|> fun iiw ->
Expand Down
1 change: 1 addition & 0 deletions src/Fantomas/Context.fs
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,7 @@ let internal printTriviaContent (c: TriviaContent) =
| Number _
| StringContent _
| IdentOperatorAsWord _
| IdentBetweenTicks _
-> sepNone // don't print here but somewhere in CodePrinter
| Directive(content, addNewline) ->
(ifElse addNewline sepNln sepNone) +> !- content +> sepNln
Expand Down
2 changes: 1 addition & 1 deletion src/Fantomas/SourceParser.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1255,7 +1255,7 @@ let getRangesFromAttributes (mdl: SynModuleDecl) =
types
|> Seq.collect(fun t ->
match t with
| SynTypeDefn.TypeDefn((SynComponentInfo.ComponentInfo(attrs, _,_,_,_,_,_,_)),stdr,_,_) -> collectAttributesRanges attrs
| SynTypeDefn.TypeDefn((SynComponentInfo.ComponentInfo(attrs, _,_,_,_,_,_,_)),_,_,_) -> collectAttributesRanges attrs
)
| _ -> Seq.empty
|> Seq.toList
8 changes: 8 additions & 0 deletions src/Fantomas/TokenParser.fs
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,13 @@ let rec private getTriviaFromTokensThemSelves (allTokens: Token list) (tokens: T
|> List.prependItem foundTrivia
getTriviaFromTokensThemSelves allTokens rest info

| head::rest when (head.TokenInfo.TokenName = "IDENT" && head.Content.StartsWith("``") && head.Content.EndsWith("``")) ->
let range = getRangeBetween "ident between ``" head head
let info =
Trivia.Create(IdentBetweenTicks(head.Content)) range
|> List.prependItem foundTrivia
getTriviaFromTokensThemSelves allTokens rest info

| (_)::rest -> getTriviaFromTokensThemSelves allTokens rest foundTrivia

| [] -> foundTrivia
Expand Down Expand Up @@ -391,6 +398,7 @@ let getTriviaNodesFromTokens (tokens: Token list) : TriviaNode list =
|> List.map (fun t ->
{ Type = TriviaNodeType.Token(t)
ContentBefore = []
ContentItself = None
ContentAfter = []
Range = getRangeBetween t.TokenInfo.TokenName t t }
)
21 changes: 17 additions & 4 deletions src/Fantomas/Trivia.fs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ let private mapNodeToTriviaNode (node: Node) =
|> Option.map (fun range ->
{ Type = MainNode(node.Type)
ContentAfter = []
ContentItself = None
ContentBefore = []
Range = range }
)
Expand Down Expand Up @@ -259,21 +260,33 @@ let private addTriviaToTriviaNode (triviaNodes: TriviaNode list) trivia =

| { Item = StringContent(_) as siNode; Range = range } ->
findNodeOnLineAndColumn triviaNodes range.StartLine range.StartColumn
|> updateTriviaNode (fun tn -> { tn with ContentBefore = List.appendItem tn.ContentBefore (siNode) }) triviaNodes
|> updateTriviaNode (fun tn -> { tn with ContentItself = Some siNode }) triviaNodes

| { Item = Number(_) as number; Range = range } ->
findNodeOnLineAndColumn triviaNodes range.StartLine range.StartColumn
|> updateTriviaNode (fun tn -> { tn with ContentBefore = List.appendItem tn.ContentBefore number }) triviaNodes
|> updateTriviaNode (fun tn -> { tn with ContentItself = Some number }) triviaNodes

| { Item = IdentOperatorAsWord(_) as ifw; Range = range } ->
findBindingThatStartsWith triviaNodes range.StartColumn range.StartLine
|> updateTriviaNode (fun tn -> { tn with ContentBefore = List.appendItem tn.ContentBefore ifw }) triviaNodes
|> updateTriviaNode (fun tn -> { tn with ContentItself = Some ifw }) triviaNodes

| { Item = IdentBetweenTicks(_) as iNode; Range = range } ->
triviaNodes
|> List.tryFind (fun t ->
let isIdent =
match t.Type with
| MainNode("SynExpr.Ident")
| MainNode("SynPat.Named") -> true
| _ -> false
isIdent && (t.Range.StartColumn = range.StartColumn || t.Range.StartColumn = range.StartColumn + 1) && t.Range.StartLine = range.StartLine
)
|> updateTriviaNode (fun tn -> { tn with ContentItself = Some iNode }) triviaNodes

| _ ->
triviaNodes

let private triviaNodeIsNotEmpty triviaNode =
not(List.isEmpty triviaNode.ContentAfter) || not(List.isEmpty triviaNode.ContentBefore)
not(List.isEmpty triviaNode.ContentAfter) || not(List.isEmpty triviaNode.ContentBefore) || Option.isSome triviaNode.ContentItself

(*
1. Collect TriviaNode from tokens and AST
Expand Down
2 changes: 2 additions & 0 deletions src/Fantomas/TriviaTypes.fs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type TriviaContent =
| Number of string
| StringContent of string
| IdentOperatorAsWord of string
| IdentBetweenTicks of string
| Comment of Comment
| Newline
| Directive of directive:string * appendNewline:bool
Expand All @@ -51,5 +52,6 @@ type TriviaNodeType =
type TriviaNode =
{ Type: TriviaNodeType
ContentBefore: TriviaContent list
ContentItself: TriviaContent option
ContentAfter: TriviaContent list
Range: range }

0 comments on commit 163d4bb

Please sign in to comment.