From 636a09d9e32538edbf3e529b29089d3932602265 Mon Sep 17 00:00:00 2001 From: nojaf Date: Fri, 4 Sep 2020 11:27:05 +0200 Subject: [PATCH] Use ranges for parenthesis found in SynExpr.Paren to print trivia. Fixes #1084. --- src/Fantomas.Tests/LambdaTests.fs | 35 ++++++++++++++++++++++++ src/Fantomas/CodePrinter.fs | 44 ++++++++++++++++--------------- src/Fantomas/SourceParser.fs | 4 +-- 3 files changed, 60 insertions(+), 23 deletions(-) diff --git a/src/Fantomas.Tests/LambdaTests.fs b/src/Fantomas.Tests/LambdaTests.fs index 4b4ea93d28..e7acf4add1 100644 --- a/src/Fantomas.Tests/LambdaTests.fs +++ b/src/Fantomas.Tests/LambdaTests.fs @@ -394,4 +394,39 @@ let options = | Graph.HierarchicalUpDown -> createObj [ "hierarchical" ==> hierOpts "UD" ] o.layout <- Some layout) +""" + +[] +let ``don't print unrelated trivia after closing parenthesis of lambda, 1084`` () = + formatSourceString false """ +let private tokenizeLines (sourceTokenizer: FSharpSourceTokenizer) allLines state = + allLines + |> List.mapi (fun index line -> line, (index + 1)) // line number is needed in tokenizeLine + |> List.fold (fun (state, tokens) (line, lineNumber) -> + let tokenizer = sourceTokenizer.CreateLineTokenizer(line) + let nextState, tokensOfLine = + tokenizeLine tokenizer allLines state lineNumber [] + + let allTokens = List.append tokens (List.rev tokensOfLine) // tokens of line are add in reversed order + (nextState, allTokens) + ) (state, []) // empty tokens to start with + |> snd // ignore the state +""" config + |> prepend newline + |> should equal """ +let private tokenizeLines (sourceTokenizer: FSharpSourceTokenizer) allLines state = + allLines + |> List.mapi (fun index line -> line, (index + 1)) // line number is needed in tokenizeLine + |> List.fold (fun (state, tokens) (line, lineNumber) -> + let tokenizer = + sourceTokenizer.CreateLineTokenizer(line) + + let nextState, tokensOfLine = + tokenizeLine tokenizer allLines state lineNumber [] + + let allTokens = + List.append tokens (List.rev tokensOfLine) // tokens of line are add in reversed order + + (nextState, allTokens)) (state, []) // empty tokens to start with + |> snd // ignore the state """ \ No newline at end of file diff --git a/src/Fantomas/CodePrinter.fs b/src/Fantomas/CodePrinter.fs index d9d03be95f..e36b900407 100644 --- a/src/Fantomas/CodePrinter.fs +++ b/src/Fantomas/CodePrinter.fs @@ -958,13 +958,13 @@ and genExpr astContext synExpr = match e with | MultilineString _ | Lambda _ - | Paren (Lambda _) - | Paren (MatchLambda _) -> id + | Paren (_, Lambda _, _) + | Paren (_, MatchLambda _, _) -> id | _ -> autoNlnIfExpressionExceedsPageWidth let kw tokenName f = tokN synExpr.Range tokenName f - let sepOpenT = tokN synExpr.Range LPAREN sepOpenT - let sepCloseT = tokN synExpr.Range RPAREN sepCloseT + let sepOpenTFor r = tokN (Option.defaultValue synExpr.Range r) LPAREN sepOpenT + let sepCloseTFor r = tokN (Option.defaultValue synExpr.Range r) RPAREN sepCloseT match synExpr with | ElmishReactWithoutChildren(identifier, isArray, children) -> @@ -1309,7 +1309,7 @@ and genExpr astContext synExpr = fun ctx -> isShortExpression ctx.Config.MaxArrayOrListWidth shortExpression multilineExpression ctx | JoinIn(e1, e2) -> genExpr astContext e1 -- " in " +> genExpr astContext e2 - | Paren(DesugaredLambda(cps, e)) -> + | Paren(_, DesugaredLambda(cps, e), _) -> fun (ctx: Context) -> let lastLineOnlyContainsParenthesis = lastLineOnlyContains [| ' ';'('|] ctx @@ -1338,7 +1338,7 @@ and genExpr astContext synExpr = | DesugaredLambda(cps, e) -> !- "fun " +> col sepSpace cps (fst >> genComplexPats astContext) +> sepArrow +> autoIndentAndNlnIfExpressionExceedsPageWidth (genExpr astContext e) - | Paren(Lambda(e, sps)) -> + | Paren(lpr, Lambda(e, sps), rpr) -> fun (ctx: Context) -> let lastLineOnlyContainsParenthesis = lastLineOnlyContains [| ' ';'('|] ctx let hasLineCommentAfterArrow = @@ -1346,14 +1346,14 @@ and genExpr astContext synExpr = |> Option.isSome let expr = - sepOpenT + sepOpenTFor (Some lpr) -- "fun " +> col sepSpace sps (genSimplePats astContext) +> triviaAfterArrow synExpr.Range +> ifElse hasLineCommentAfterArrow (genExpr astContext e) (ifElse lastLineOnlyContainsParenthesis (autoIndentAndNlnIfExpressionExceedsPageWidth (genExpr astContext e)) (autoNlnIfExpressionExceedsPageWidth (genExpr astContext e))) - +> sepCloseT + +> sepCloseTFor rpr expr ctx @@ -1384,18 +1384,20 @@ and genExpr astContext synExpr = genTyparList astContext tps +> sepColon +> sepOpenT +> genMemberSig astContext msg +> sepCloseT +> sepSpace +> genExpr astContext e - | Paren (ILEmbedded r) -> + | Paren (_, ILEmbedded r, _) -> // Just write out original code inside (# ... #) fun ctx -> !- (defaultArg (lookup r ctx) "") ctx - | Paren e -> + | Paren (lpr ,e, rpr) -> match e with | MultilineString _ -> - sepOpenT + sepOpenTFor (Some lpr) +> atCurrentColumn (genExpr { astContext with IsInsideDotGet = false } e +> indentIfNeeded sepNone) - +> sepCloseT + +> sepCloseTFor rpr | _ -> // Parentheses nullify effects of no space inside DotGet - sepOpenT +> genExpr { astContext with IsInsideDotGet = false } e +> sepCloseT + sepOpenTFor (Some lpr) + +> genExpr { astContext with IsInsideDotGet = false } e + +> sepCloseTFor rpr | CompApp(s, e) -> !- s +> sepSpace +> sepOpenS +> genExpr { astContext with IsNakedRange = true } e +> sepCloseS // This supposes to be an infix function, but for some reason it isn't picked up by InfixApps @@ -1499,9 +1501,9 @@ and genExpr astContext synExpr = let genMultilineExpr = match e with - | Paren(Lambda(_)) -> atCurrentColumnIndent(genExpr astContext e) - | Paren(App(_)) - | Paren(Tuple(_)) -> + | Paren(_, Lambda(_), _) -> atCurrentColumnIndent(genExpr astContext e) + | Paren(_, App(_), _) + | Paren(_, Tuple(_), _) -> atCurrentColumn(genExpr astContext e) | _ -> ifElse hasParenthesis @@ -1542,8 +1544,8 @@ and genExpr astContext synExpr = +> (ifElse (not hasPar && addSpaceBefore) sepSpace sepNone) +> (fun ctx -> match e2 with - | Paren (App (_)) when astContext.IsInsideDotGet -> genExpr astContext e2 ctx - | Paren (DotGet (App(_), _)) when astContext.IsInsideDotGet -> genExpr astContext e2 ctx + | Paren (_, App (_), _) when astContext.IsInsideDotGet -> genExpr astContext e2 ctx + | Paren (_, DotGet (App(_), _), _) when astContext.IsInsideDotGet -> genExpr astContext e2 ctx | ConstExpr(SynConst.Unit, _) when astContext.IsInsideDotGet -> genExpr astContext e2 ctx | _ -> appNlnFun e2 (genExpr astContext e2) ctx) +> unindent) @@ -1579,7 +1581,7 @@ and genExpr astContext synExpr = let hasThreeOrMoreLambdas = List.filter (function - | Paren (Lambda (_)) -> true + | Paren (_, Lambda (_), _) -> true | _ -> false) es |> List.length |> fun l -> l >= 3 @@ -1587,8 +1589,8 @@ and genExpr astContext synExpr = if List.exists (function | Lambda _ | MatchLambda _ - | Paren (Lambda (_)) - | Paren (MatchLambda (_)) + | Paren (_, Lambda (_), _) + | Paren (_, MatchLambda (_), _) | MultilineString _ | CompExpr _ -> true | _ -> false) es && not hasThreeOrMoreLambdas then diff --git a/src/Fantomas/SourceParser.fs b/src/Fantomas/SourceParser.fs index f885327003..70defed6a3 100644 --- a/src/Fantomas/SourceParser.fs +++ b/src/Fantomas/SourceParser.fs @@ -496,8 +496,8 @@ let (|Quote|_|) = function | _ -> None let (|Paren|_|) = function - | SynExpr.Paren(e, _, _, _) -> - Some e + | SynExpr.Paren(e, lpr, rpr, _) -> + Some (lpr, e, rpr) | _ -> None type ExprKind =