Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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)

Expand Down
42 changes: 42 additions & 0 deletions src/Fantomas.Core.Tests/IndexSyntaxTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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
"""

[<Test>]
let ``index without dot followed by application argument`` () =
formatSourceString
"""
prepConfigs[1] host
"""
config
|> prepend newline
|> should
equal
"""
prepConfigs[1] host
"""

[<Test>]
let ``index without dot followed by multiple application arguments`` () =
formatSourceString
"""
prepConfigs[1] host port
"""
config
|> prepend newline
|> should
equal
"""
prepConfigs[1] host port
"""

[<Test>]
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
"""
33 changes: 1 addition & 32 deletions src/Fantomas.Core/ASTTransformer.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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<SynExpr>) ->
xs.Enqueue(argExpr)
Expand Down Expand Up @@ -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)
Expand Down
8 changes: 8 additions & 0 deletions src/Fantomas.Core/CodePrinter.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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) =
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down