diff --git a/src/Fantomas.Tests/Fantomas.Tests.fsproj b/src/Fantomas.Tests/Fantomas.Tests.fsproj index b52957f26e..9968034593 100644 --- a/src/Fantomas.Tests/Fantomas.Tests.fsproj +++ b/src/Fantomas.Tests/Fantomas.Tests.fsproj @@ -84,7 +84,7 @@ - + diff --git a/src/Fantomas.Tests/KeepIndentInBranch.fs b/src/Fantomas.Tests/KeepIndentInBranchTests.fs similarity index 81% rename from src/Fantomas.Tests/KeepIndentInBranch.fs rename to src/Fantomas.Tests/KeepIndentInBranchTests.fs index 7b89880f2d..a27af54371 100644 --- a/src/Fantomas.Tests/KeepIndentInBranch.fs +++ b/src/Fantomas.Tests/KeepIndentInBranchTests.fs @@ -1,4 +1,4 @@ -module Fantomas.Tests.KeepIndentInBranch +module Fantomas.Tests.KeepIndentInBranchTests open NUnit.Framework open FsUnit @@ -907,3 +907,159 @@ module Foo = Thing.execute bar baz (thing, instructions) 0 """ + +[] +let ``sequential, let bindings, keep indent match, 1621`` () = + formatSourceString + false + """ +let main (args : Options) = + log.LogDebug ("Command line options: {Options}", args.ToString()) + + let includes = + if ArgParser.defaultArg args.Flag then + Flag.Include + else + Flag.Exclude + + match dryRunMode with + | DryRunMode.Dry -> + log.LogInformation ("No changes made due to --dry-run.") + 0 + | DryRunMode.Wet -> + + match requested with + | None -> + log.LogWarning ("No changes required; no action taken.") + 0 + | Some branched -> + + branched + |> blah + |> fun i -> log.LogInformation ("Done:\n{It}", i) + + 0 +""" + { config with + MaxLineLength = 100 + SpaceBeforeUppercaseInvocation = true + SpaceBeforeClassConstructor = true + SpaceBeforeMember = true + SpaceBeforeColon = true + SpaceBeforeSemicolon = true + IndentOnTryWith = true + MultilineBlockBracketsOnSameColumn = true + NewlineBetweenTypeDefinitionAndMembers = true + AlignFunctionSignatureToIndentation = true + AlternativeLongMemberDefinitions = true + MultiLineLambdaClosingNewline = true + DisableElmishSyntax = true + KeepIndentInBranch = true } + |> prepend newline + |> should + equal + """ +let main (args : Options) = + log.LogDebug ("Command line options: {Options}", args.ToString ()) + + let includes = + if ArgParser.defaultArg args.Flag then + Flag.Include + else + Flag.Exclude + + match dryRunMode with + | DryRunMode.Dry -> + log.LogInformation ("No changes made due to --dry-run.") + 0 + | DryRunMode.Wet -> + + match requested with + | None -> + log.LogWarning ("No changes required; no action taken.") + 0 + | Some branched -> + + branched + |> blah + |> fun i -> log.LogInformation ("Done:\n{It}", i) + + 0 +""" + +[] +let ``sequential, let bindings, keep indent if`` () = + formatSourceString + false + """ +let main (args : Options) = + log.LogDebug ("Command line options: {Options}", args.ToString()) + + let includes = + if ArgParser.defaultArg args.Flag then + Flag.Include + else + Flag.Exclude + + if dryRunMode then + log.LogInformation ("No changes made due to --dry-run.") + 0 + else + + match requested with + | None -> + log.LogWarning ("No changes required; no action taken.") + 0 + | Some branched -> + + branched + |> blah + |> fun i -> log.LogInformation ("Done:\n{It}", i) + + 0 +""" + { config with + MaxLineLength = 100 + SpaceBeforeUppercaseInvocation = true + SpaceBeforeClassConstructor = true + SpaceBeforeMember = true + SpaceBeforeColon = true + SpaceBeforeSemicolon = true + IndentOnTryWith = true + MultilineBlockBracketsOnSameColumn = true + NewlineBetweenTypeDefinitionAndMembers = true + AlignFunctionSignatureToIndentation = true + AlternativeLongMemberDefinitions = true + MultiLineLambdaClosingNewline = true + DisableElmishSyntax = true + KeepIndentInBranch = true } + |> prepend newline + |> should + equal + """ +let main (args : Options) = + log.LogDebug ("Command line options: {Options}", args.ToString ()) + + let includes = + if ArgParser.defaultArg args.Flag then + Flag.Include + else + Flag.Exclude + + if dryRunMode then + log.LogInformation ("No changes made due to --dry-run.") + 0 + else + + match requested with + | None -> + log.LogWarning ("No changes required; no action taken.") + 0 + | Some branched -> + + branched + |> blah + |> fun i -> log.LogInformation ("Done:\n{It}", i) + + 0 +""" diff --git a/src/Fantomas/CodePrinter.fs b/src/Fantomas/CodePrinter.fs index ce571b0837..d366afe00a 100644 --- a/src/Fantomas/CodePrinter.fs +++ b/src/Fantomas/CodePrinter.fs @@ -5295,155 +5295,79 @@ and genParenTupleWithIndentAndNewlines ps astContext = and genExprKeepIndentInBranch (astContext: ASTContext) (e: SynExpr) : Context -> Context = let keepIndentExpr = - match e with - | Sequential (e1, (KeepIndentMatch (me, clauses, matchRange, matchTriviaType) as e2), true) -> - let items = - [ ColMultilineItem( - genExpr astContext e1, - (let t, r = synExprToFsAstType e1 in sepNlnConsideringTriviaContentBeforeForMainNode t r), - e1.Range - ) - ColMultilineItem( - genKeepIndentMatch astContext me clauses matchRange matchTriviaType, - sepNlnConsideringTriviaContentBeforeForMainNode matchTriviaType matchRange, - e2.Range - ) ] - - colWithNlnWhenItemIsMultilineUsingConfig items - | LetOrUses (bs, (KeepIndentMatch (me, clauses, matchRange, matchTriviaType) as em)) -> - let bs = - List.map - (fun (s, synBinding: SynBinding) -> - let range = synBinding.RangeOfBindingAndRhs - - let expr = - enterNodeFor (synBindingToFsAstType synBinding) range - +> genLetBinding astContext s synBinding - + let genOtherExprItem (e: SynExpr) : ColMultilineItem = + ColMultilineItem( + genExpr astContext e, + (let t, r = synExprToFsAstType e in sepNlnConsideringTriviaContentBeforeForMainNode t r), + e.Range + ) - let sepNln = - sepNlnConsideringTriviaContentBeforeForMainNode (synBindingToFsAstType synBinding) range + let genBindingItems (bs: (string * SynBinding) list) : ColMultilineItem list = + List.map + (fun (s, synBinding: SynBinding) -> + let range = synBinding.RangeOfBindingAndRhs - ColMultilineItem(expr, sepNln, range)) - bs + let expr = + enterNodeFor (synBindingToFsAstType synBinding) range + +> genLetBinding astContext s synBinding - let m = - ColMultilineItem( - genKeepIndentMatch astContext me clauses matchRange matchTriviaType, - sepNlnConsideringTriviaContentBeforeForMainNode matchTriviaType matchRange, - em.Range - ) - colWithNlnWhenItemIsMultilineUsingConfig [ yield! bs - yield m ] - | LetOrUses (bs, Sequential (e1, KeepIndentMatch (me, clauses, matchRange, matchTriviaType), true)) -> - let bs = - List.map - (fun (s, synBinding: SynBinding) -> - let range = synBinding.RangeOfBindingAndRhs + let sepNln = + sepNlnConsideringTriviaContentBeforeForMainNode (synBindingToFsAstType synBinding) range - let expr = - enterNodeFor (synBindingToFsAstType synBinding) range - +> genLetBinding astContext s synBinding + ColMultilineItem(expr, sepNln, range)) + bs - let sepNln = - sepNlnConsideringTriviaContentBeforeForMainNode (synBindingToFsAstType synBinding) range - - ColMultilineItem(expr, sepNln, range)) - bs - - let e1 = - ColMultilineItem( - genExpr astContext e1, - (let t, r = synExprToFsAstType e1 in sepNlnConsideringTriviaContentBeforeForMainNode t r), - e1.Range - ) + let genKeepIndentMatchItem + ((me, clauses, matchRange, matchTriviaType): SynExpr * SynMatchClause list * Range * FsAstType) + : ColMultilineItem = + ColMultilineItem( + genKeepIndentMatch astContext me clauses matchRange matchTriviaType, + sepNlnConsideringTriviaContentBeforeForMainNode matchTriviaType matchRange, + matchRange + ) - let m = - ColMultilineItem( - genKeepIndentMatch astContext me clauses matchRange matchTriviaType, - sepNlnConsideringTriviaContentBeforeForMainNode matchTriviaType matchRange, - matchRange - ) + let genKeepIndentIfThenElseItem + ((branches, elseBranch, ifElseRange): (SynExpr * SynExpr * Range * Range * SynExpr) list * SynExpr * Range) + : ColMultilineItem = + ColMultilineItem( + genKeepIdentIf astContext branches elseBranch ifElseRange, + sepNlnConsideringTriviaContentBeforeForMainNode SynExpr_IfThenElse ifElseRange, + ifElseRange + ) - colWithNlnWhenItemIsMultilineUsingConfig [ yield! bs - yield e1 - yield m ] + match e with + | Sequential (e1, (KeepIndentMatch kim), true) -> + colWithNlnWhenItemIsMultilineUsingConfig [ genOtherExprItem e1 + genKeepIndentMatchItem kim ] + | Sequential (e1, LetOrUses (bs, (KeepIndentMatch kim)), true) -> + colWithNlnWhenItemIsMultilineUsingConfig [ yield genOtherExprItem e1 + yield! genBindingItems bs + yield genKeepIndentMatchItem kim ] + | LetOrUses (bs, (KeepIndentMatch kim)) -> + colWithNlnWhenItemIsMultilineUsingConfig [ yield! genBindingItems bs + yield genKeepIndentMatchItem kim ] + | LetOrUses (bs, Sequential (e1, KeepIndentMatch kim, true)) -> + colWithNlnWhenItemIsMultilineUsingConfig [ yield! genBindingItems bs + yield genOtherExprItem e1 + yield genKeepIndentMatchItem kim ] | KeepIndentMatch (me, clauses, matchRange, matchTriviaType) -> genKeepIndentMatch astContext me clauses matchRange matchTriviaType - | Sequential (e1, (KeepIndentIfThenElse (branches, elseBranch, ifElseRange) as e2), true) -> - let items = - [ ColMultilineItem( - genExpr astContext e1, - (let t, r = synExprToFsAstType e1 in sepNlnConsideringTriviaContentBeforeForMainNode t r), - e1.Range - ) - ColMultilineItem( - genKeepIdentIf astContext branches elseBranch ifElseRange, - sepNlnConsideringTriviaContentBeforeForMainNode SynExpr_IfThenElse ifElseRange, - e2.Range - ) ] - - colWithNlnWhenItemIsMultilineUsingConfig items - | LetOrUses (bs, (KeepIndentIfThenElse (branches, elseBranch, ifElseRange))) -> - let bs = - List.map - (fun (s, synBinding: SynBinding) -> - let range = synBinding.RangeOfBindingAndRhs - - let expr = - enterNodeFor (synBindingToFsAstType synBinding) range - +> genLetBinding astContext s synBinding - - - let sepNln = - sepNlnConsideringTriviaContentBeforeForMainNode (synBindingToFsAstType synBinding) range - - ColMultilineItem(expr, sepNln, range)) - bs - - let ifElse = - ColMultilineItem( - genKeepIdentIf astContext branches elseBranch ifElseRange, - sepNlnConsideringTriviaContentBeforeForMainNode SynExpr_IfThenElse ifElseRange, - ifElseRange - ) - - colWithNlnWhenItemIsMultilineUsingConfig [ yield! bs - yield ifElse ] - | LetOrUses (bs, Sequential (e1, KeepIndentIfThenElse (branches, elseBranch, ifElseRange), true)) -> - let bs = - List.map - (fun (s, synBinding: SynBinding) -> - let range = synBinding.RangeOfBindingAndRhs - - let expr = - enterNodeFor (synBindingToFsAstType synBinding) range - +> genLetBinding astContext s synBinding - - let sepNln = - sepNlnConsideringTriviaContentBeforeForMainNode (synBindingToFsAstType synBinding) range - - ColMultilineItem(expr, sepNln, range)) - bs - - let e1 = - ColMultilineItem( - genExpr astContext e1, - (let t, r = synExprToFsAstType e1 in sepNlnConsideringTriviaContentBeforeForMainNode t r), - e1.Range - ) - - let ifElse = - ColMultilineItem( - genKeepIdentIf astContext branches elseBranch ifElseRange, - sepNlnConsideringTriviaContentBeforeForMainNode SynExpr_IfThenElse ifElseRange, - ifElseRange - ) - - colWithNlnWhenItemIsMultilineUsingConfig [ yield! bs - yield e1 - yield ifElse ] + | Sequential (e1, (KeepIndentIfThenElse kii), true) -> + colWithNlnWhenItemIsMultilineUsingConfig [ genOtherExprItem e1 + genKeepIndentIfThenElseItem kii ] + | Sequential (e1, LetOrUses (bs, (KeepIndentIfThenElse kii)), true) -> + colWithNlnWhenItemIsMultilineUsingConfig [ yield genOtherExprItem e1 + yield! genBindingItems bs + yield genKeepIndentIfThenElseItem kii ] + | LetOrUses (bs, (KeepIndentIfThenElse kii)) -> + colWithNlnWhenItemIsMultilineUsingConfig [ yield! genBindingItems bs + yield genKeepIndentIfThenElseItem kii ] + | LetOrUses (bs, Sequential (e1, KeepIndentIfThenElse kii, true)) -> + + colWithNlnWhenItemIsMultilineUsingConfig [ yield! genBindingItems bs + yield genOtherExprItem e1 + yield genKeepIndentIfThenElseItem kii ] | KeepIndentIfThenElse (branches, elseBranch, ifElseRange) -> genKeepIdentIf astContext branches elseBranch ifElseRange | _ -> genExpr astContext e