From 86f6453a112358bb0ace137c6ca20decad1f5a77 Mon Sep 17 00:00:00 2001 From: Josh DeGraw <18509575+josh-degraw@users.noreply.github.com> Date: Thu, 22 Sep 2022 10:32:38 -0600 Subject: [PATCH] Prevent stroustrup formatting when trivia is present before (#2527) * Prevent stroustrup formatting when trivia is present before * Update CHANGELOG.md --- CHANGELOG.md | 4 +- .../SynBindingFunctionExpressionTests.fs | 61 +++++++++++++++++++ .../SynMatchClauseExpressionTests.fs | 39 ++++++++++++ src/Fantomas.Core/Context.fs | 31 +++++++++- src/Fantomas.Core/Fantomas.Core.fsproj | 2 +- src/Fantomas.Core/SourceTransformer.fs | 15 ----- 6 files changed, 133 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e48775ffa7..f1d7b5a68a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,11 @@ # Changelog -## Unreleased +## [5.0.2] - 2022-09-22 ### Fixed * Wrong generic constraint placement in ML-style generic definitions with multiple type parameters. [#1868](https://github.com/fsprojects/fantomas/issues/1868) +* Incorrect async indentation when inside of a match. [#2501](https://github.com/fsprojects/fantomas/issues/2501) +* Conditional directives before expression leads to invalid code with Stroustrup. [#2517](https://github.com/fsprojects/fantomas/issues/2517) ### Documented * Building Fantomas in Visual Studio for dev errors. [#2447](https://github.com/fsprojects/fantomas/issues/2447) diff --git a/src/Fantomas.Core.Tests/Stroustrup/SynBindingFunctionExpressionTests.fs b/src/Fantomas.Core.Tests/Stroustrup/SynBindingFunctionExpressionTests.fs index eed7867a3a..f999e3e707 100644 --- a/src/Fantomas.Core.Tests/Stroustrup/SynBindingFunctionExpressionTests.fs +++ b/src/Fantomas.Core.Tests/Stroustrup/SynBindingFunctionExpressionTests.fs @@ -319,3 +319,64 @@ type Foo() = itemFive |] """ + +[] +let ``doesn't trigger stroustrup styling when an expression has trivia before it`` () = + formatSourceString + false + """ +let inline skipNoFail count (source: seq<_>) = +//if FABLE_COMPILER + seq { + yield "Hello" + } +""" + config + |> prepend newline + |> should + equal + """ +let inline skipNoFail count (source: seq<_>) = + //if FABLE_COMPILER + seq { yield "Hello" } +""" + +[] +let ``conditional directives before expression, 2517`` () = + formatSourceString + false + """ + let inline skipNoFail count (source: seq<_>) = +#if FABLE_COMPILER + seq { + let mutable i = 0 + let e = source.GetEnumerator () + while e.MoveNext () do + if i < count + then + i <- i + 1 + else + yield e.Current + } +#else + Enumerable.Skip(source, count) +#endif +""" + config + |> prepend newline + |> should + equal + """ +let inline skipNoFail count (source: seq<_>) = +#if FABLE_COMPILER + seq { + let mutable i = 0 + let e = source.GetEnumerator() + + while e.MoveNext() do + if i < count then i <- i + 1 else yield e.Current + } +#else + Enumerable.Skip(source, count) +#endif +""" diff --git a/src/Fantomas.Core.Tests/Stroustrup/SynMatchClauseExpressionTests.fs b/src/Fantomas.Core.Tests/Stroustrup/SynMatchClauseExpressionTests.fs index 3c54bff402..eafd6f3b32 100644 --- a/src/Fantomas.Core.Tests/Stroustrup/SynMatchClauseExpressionTests.fs +++ b/src/Fantomas.Core.Tests/Stroustrup/SynMatchClauseExpressionTests.fs @@ -445,3 +445,42 @@ match x with yield! visitSynExpr inheritArgs ] """ + +[] +let ``async indentation when inside of a match, 2501`` () = + formatSourceString + false + """ +let x = + match packageRegistrationUrl with + | Some packageRegistrationUrl -> + + async { + + let response = "" + + return "" + + } + + | None -> failwith "Package registration url not found" +""" + config + |> prepend newline + |> should + equal + """ +let x = + match packageRegistrationUrl with + | Some packageRegistrationUrl -> + + async { + + let response = "" + + return "" + + } + + | None -> failwith "Package registration url not found" +""" diff --git a/src/Fantomas.Core/Context.fs b/src/Fantomas.Core/Context.fs index d6b4c233e3..54956fea2d 100644 --- a/src/Fantomas.Core/Context.fs +++ b/src/Fantomas.Core/Context.fs @@ -7,6 +7,7 @@ open Fantomas.Core open Fantomas.Core.ISourceTextExtensions open Fantomas.Core.FormatConfig open Fantomas.Core.TriviaTypes +open Fantomas.Core.SourceTransformer type WriterEvent = | Write of string @@ -1176,9 +1177,32 @@ let addExtraNewlineIfLeadingWasMultiline leading sepNlnConsideringTriviaContentB leadingExpressionIsMultiline leading (fun ml -> sepNln +> onlyIf ml sepNlnConsideringTriviaContentBefore +> continuation) +let addParenIfAutoNln synExpr f = + let expr = f synExpr + expressionFitsOnRestOfLine expr (ifElse (hasParenthesis synExpr) (sepOpenT +> expr +> sepCloseT) expr) + +let addParenForTupleWhen f synExpr ctx = + let condition e = + match e with + | SourceParser.ElIf _ + | SynExpr.Lambda _ -> true + | _ -> false // "if .. then .. else" have precedence over "," + + let expr = f synExpr + ifElse (condition synExpr) (sepOpenT +> expr +> sepCloseT) expr ctx + +let private hasTriviaBeforeExpression ctx e = + let astType, range = synExprToFsAstType e + + Map.tryFindOrEmptyList astType ctx.TriviaBefore + |> List.exists (fun ti -> RangeHelpers.rangeEq range ti.Range) + let autoIndentAndNlnExpressUnlessStroustrup (f: SynExpr -> Context -> Context) (e: SynExpr) (ctx: Context) = match e with - | SourceParser.StroustrupStyleExpr ctx.Config.ExperimentalStroustrupStyle e -> f e ctx + | SourceParser.StroustrupStyleExpr ctx.Config.ExperimentalStroustrupStyle e when + (not (hasTriviaBeforeExpression ctx e)) + -> + f e ctx | _ -> indentSepNlnUnindent (f e) ctx let autoIndentAndNlnIfExpressionExceedsPageWidthUnlessStroustrup @@ -1187,7 +1211,10 @@ let autoIndentAndNlnIfExpressionExceedsPageWidthUnlessStroustrup (ctx: Context) = match e with - | SourceParser.StroustrupStyleExpr ctx.Config.ExperimentalStroustrupStyle e -> f e ctx + | SourceParser.StroustrupStyleExpr ctx.Config.ExperimentalStroustrupStyle e when + (not (hasTriviaBeforeExpression ctx e)) + -> + f e ctx | _ -> autoIndentAndNlnIfExpressionExceedsPageWidth (f e) ctx type internal ColMultilineItem = diff --git a/src/Fantomas.Core/Fantomas.Core.fsproj b/src/Fantomas.Core/Fantomas.Core.fsproj index a1752f5ca3..3882deff68 100644 --- a/src/Fantomas.Core/Fantomas.Core.fsproj +++ b/src/Fantomas.Core/Fantomas.Core.fsproj @@ -25,8 +25,8 @@ - + diff --git a/src/Fantomas.Core/SourceTransformer.fs b/src/Fantomas.Core/SourceTransformer.fs index 84a894d1d7..068f74f1fd 100644 --- a/src/Fantomas.Core/SourceTransformer.fs +++ b/src/Fantomas.Core/SourceTransformer.fs @@ -2,7 +2,6 @@ module internal Fantomas.Core.SourceTransformer open FSharp.Compiler.Syntax open FSharp.Compiler.Text -open Fantomas.Core.Context open Fantomas.Core.SourceParser open Fantomas.Core.TriviaTypes @@ -125,20 +124,6 @@ let (|LongGetMember|_|) = Some(SynBinding(ao, kind, isInline, isMutable, ats, px, valData, pat, ri, e, bindingRange, dp, trivia)) | _ -> None -let addParenIfAutoNln synExpr f = - let expr = f synExpr - expressionFitsOnRestOfLine expr (ifElse (hasParenthesis synExpr) (sepOpenT +> expr +> sepCloseT) expr) - -let addParenForTupleWhen f synExpr ctx = - let condition e = - match e with - | ElIf _ - | SynExpr.Lambda _ -> true - | _ -> false // "if .. then .. else" have precedence over "," - - let expr = f synExpr - ifElse (condition synExpr) (sepOpenT +> expr +> sepCloseT) expr ctx - let synModuleDeclToFsAstType = function | SynModuleDecl.Expr _ -> SynModuleDecl_Expr