diff --git a/CHANGELOG.md b/CHANGELOG.md index 089b9329f..f0443d1fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [8.0.0-alpha-005] - 2026-03-09 + +### Fixed + +- Closing `>` in nested multiline generic type applications violates offside rule. [#3243](https://github.com/fsprojects/fantomas/issues/3243) +- Index-without-dot syntax followed by application arguments was inconsistently formatted. [#3259](https://github.com/fsprojects/fantomas/pull/3259) + ## [8.0.0-alpha-004] - 2026-03-07 ### Changed @@ -8,7 +15,6 @@ ### Fixed -- Closing `>` in nested multiline generic type applications violates offside rule. [#3243](https://github.com/fsprojects/fantomas/issues/3243) - Lambda in non-last record field is now parenthesized when record is collapsed to single line to avoid producing invalid code. [#3246](https://github.com/fsprojects/fantomas/issues/3246) - `fsharp_newline_before_multiline_computation_expression = false` no longer produces invalid code when the CE builder's argument list wraps to multiple lines. [#3155](https://github.com/fsprojects/fantomas/issues/3155) diff --git a/src/Fantomas.Core.Tests/IndexSyntaxTests.fs b/src/Fantomas.Core.Tests/IndexSyntaxTests.fs index adfba5dbd..872892f77 100644 --- a/src/Fantomas.Core.Tests/IndexSyntaxTests.fs +++ b/src/Fantomas.Core.Tests/IndexSyntaxTests.fs @@ -273,3 +273,45 @@ inventory["Oranges"] // raises an exception if not found inventory.["Apples"] // raises an exception if not found nestedInventory["Oranges"][23] // raises an exception if not found """ + +[] +let ``index without dot followed by application argument`` () = + formatSourceString + """ +prepConfigs[1] host +""" + config + |> prepend newline + |> should + equal + """ +prepConfigs[1] host +""" + +[] +let ``index without dot followed by multiple application arguments`` () = + formatSourceString + """ +prepConfigs[1] host port +""" + config + |> prepend newline + |> should + equal + """ +prepConfigs[1] host port +""" + +[] +let ``index without dot with spaces followed by multiple application arguments`` () = + formatSourceString + """ +prepConfigs[ 1 ] host days +""" + config + |> prepend newline + |> should + equal + """ +prepConfigs[1] host days +""" diff --git a/src/Fantomas.Core/ASTTransformer.fs b/src/Fantomas.Core/ASTTransformer.fs index 5d36d6162..f6b536852 100644 --- a/src/Fantomas.Core/ASTTransformer.fs +++ b/src/Fantomas.Core/ASTTransformer.fs @@ -631,6 +631,7 @@ let (|ConstNumberExpr|_|) = let (|App|_|) e = let rec visit expr continuation = match expr with + | IndexWithoutDot _ -> continuation (expr, Queue()) | SynExpr.App(funcExpr = funcExpr; argExpr = argExpr) -> visit funcExpr (fun (head, xs: Queue) -> xs.Enqueue(argExpr) @@ -1362,38 +1363,6 @@ let mkExpr (creationAide: CreationAide) (e: SynExpr) : Expr = ExprAppWithLambdaNode(mkExpr creationAide fe, [], stn "(" lpr, Choice2Of2 lambdaNode, stn ")" rpr, exprRange) |> Expr.AppWithLambda - | SynExpr.App(ExprAtomicFlag.NonAtomic, - false, - SynExpr.App(ExprAtomicFlag.Atomic, - false, - identifierExpr, - SynExpr.ArrayOrListComputed(false, indexExpr, _), - _), - argExpr, - _) -> - ExprNestedIndexWithoutDotNode( - mkExpr creationAide identifierExpr, - mkExpr creationAide indexExpr, - mkExpr creationAide argExpr, - exprRange - ) - |> Expr.NestedIndexWithoutDot - | SynExpr.App(ExprAtomicFlag.NonAtomic, - false, - SynExpr.App(ExprAtomicFlag.NonAtomic, - false, - identifierExpr, - (SynExpr.ArrayOrListComputed(isArray = false; expr = indexExpr) as indexArgExpr), - _), - argExpr, - _) when (RangeHelpers.isAdjacentTo identifierExpr.Range indexArgExpr.Range) -> - ExprNestedIndexWithoutDotNode( - mkExpr creationAide identifierExpr, - mkExpr creationAide indexExpr, - mkExpr creationAide argExpr, - exprRange - ) - |> Expr.NestedIndexWithoutDot | App(fe, args) -> ExprAppNode(mkExpr creationAide fe, List.map (mkExpr creationAide) args, exprRange) diff --git a/src/Fantomas.Core/CodePrinter.fs b/src/Fantomas.Core/CodePrinter.fs index fa9da0db8..432a7eef4 100644 --- a/src/Fantomas.Core/CodePrinter.fs +++ b/src/Fantomas.Core/CodePrinter.fs @@ -61,6 +61,7 @@ let rec (|UppercaseExpr|LowercaseExpr|) (expr: Expr) = | Expr.AppSingleParenArg node -> (|UppercaseExpr|LowercaseExpr|) node.FunctionExpr | Expr.Paren node -> (|UppercaseExpr|LowercaseExpr|) node.Expr | Expr.App node -> (|UppercaseExpr|LowercaseExpr|) node.FunctionExpr + | Expr.IndexWithoutDot node -> (|UppercaseExpr|LowercaseExpr|) node.Identifier | _ -> failwithf "cannot determine if Expr %A is uppercase or lowercase" expr let (|ParenExpr|_|) (e: Expr) = @@ -1034,6 +1035,12 @@ let genExpr (e: Expr) = genAppLongIdentAndSingleParenArgExpr addSpace node // fn (a, b, c) + | Expr.AppSingleParenArg node when + (match node.FunctionExpr with + | Expr.IndexWithoutDot _ -> true + | _ -> false) + -> + (genExpr node.FunctionExpr +> genExpr node.ArgExpr) |> genNode node | Expr.AppSingleParenArg node -> let addSpace = sepSpaceBeforeParenInFuncInvocation node.FunctionExpr node.ArgExpr genAppSingleParenArgExpr addSpace node @@ -2600,6 +2607,7 @@ let genAppWithLambda sep (node: ExprAppWithLambdaNode) = let sepSpaceBeforeParenInFuncInvocation (functionExpr: Expr) (argExpr: Expr) ctx = match functionExpr, argExpr with | Expr.DotLambda _, _ -> ctx + | Expr.IndexWithoutDot _, ParenExpr _ -> ctx | Expr.Constant _, _ -> sepSpace ctx | ParenExpr _, _ -> sepSpace ctx | UppercaseExpr, ParenExpr _ -> onlyIf ctx.Config.SpaceBeforeUppercaseInvocation sepSpace ctx