Skip to content

Commit

Permalink
Capture then + expr in new node (#3075)
Browse files Browse the repository at this point in the history
* Update FCS to 050271d631956a4e0d0484a583d38236b727a46d, introduce new node to capture then + expr.

* Add changelog entry.
  • Loading branch information
nojaf committed Apr 12, 2024
1 parent fe0c0b7 commit 4d5e5e2
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 26 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 6.3.2 - 2024-04-12

### Changed
* Update FCS to 'Add SynExprSequentialTrivia', commit 050271d631956a4e0d0484a583d38236b727a46d [#3075](https://github.com/fsprojects/fantomas/pull/3075)

### Fixed
* Fantomas corrupts an explicit constructor with then clause. [#3074](https://github.com/fsprojects/fantomas/issues/3074)

## 6.3.1 - 2024-03-30

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Some common use cases include:

<!-- Versions -->
<PropertyGroup>
<FCSCommitHash>1da032a64321c77782e8d125afd3bf29863c3d9c</FCSCommitHash>
<FCSCommitHash>050271d631956a4e0d0484a583d38236b727a46d</FCSCommitHash>
</PropertyGroup>

<PropertyGroup>
Expand Down
3 changes: 2 additions & 1 deletion src/Fantomas.Core.Tests/ASTTransformerTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ let ``avoid stack-overflow in long array/list, 2485`` () =
true,
mkStringExpr (),
childExpr,
Range.Zero
Range.Zero,
SynExprSequentialTrivia.Zero
))

SynExpr.ArrayOrListComputed(true, mkArray 0 (mkStringExpr ()), Range.Zero)
Expand Down
37 changes: 37 additions & 0 deletions src/Fantomas.Core.Tests/ConstructorTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -165,3 +165,40 @@ type StateMachine
=
StateMachine()
"""

[<Test>]
let ``explicit constructor with then keyword, 3074`` () =
formatSourceString
"""
type CreateBuildingViewModel =
new (items) as vm
=
let p = ""
{
inherit ResizeArray(seq {
yield p
yield! items
})
}
then
vm.program <- p
"""
config
|> prepend newline
|> should
equal
"""
type CreateBuildingViewModel =
new(items) as vm =
let p = ""
{ inherit
ResizeArray(
seq {
yield p
yield! items
}
) }
then vm.program <- p
"""
33 changes: 23 additions & 10 deletions src/Fantomas.Core/ASTTransformer.fs
Original file line number Diff line number Diff line change
Expand Up @@ -213,14 +213,18 @@ let mkAttributes (creationAide: CreationAide) (al: SynAttributeList list) : Mult
let range = attributeLists |> List.map (fun al -> al.Range) |> combineRanges
Some(MultipleAttributeListNode(attributeLists, range))

/// Only used to get items of SynExpr.ArrayOrListComputed
/// We can safely assume the SequentialTrivia.SeparatorRange is not going to be `then`.
let (|Sequentials|_|) e =
let rec visit (e: SynExpr) (finalContinuation: SynExpr list -> SynExpr list) : SynExpr list =
match e with
| SynExpr.Sequential(_, _, e1, e2, _) -> visit e2 (fun xs -> e1 :: xs |> finalContinuation)
| SynExpr.Sequential(expr1 = e1; expr2 = e2) ->

visit e2 (fun xs -> e1 :: xs |> finalContinuation)
| e -> finalContinuation [ e ]

match e with
| SynExpr.Sequential(_, _, e1, e2, _) ->
| SynExpr.Sequential(expr1 = e1; expr2 = e2) ->
let xs = visit e2 id
Some(e1 :: xs)
| _ -> None
Expand Down Expand Up @@ -332,12 +336,25 @@ let rec collectComputationExpressionStatements

collectComputationExpressionStatements creationAide body (fun bodyStatements ->
[ letOrUseBang; yield! andBangs; yield! bodyStatements ] |> finalContinuation)
| SynExpr.Sequential(_, _, e1, e2, _) ->
| SynExpr.Sequential(expr1 = e1; expr2 = e2; trivia = trivia) ->
let continuations
: ((ComputationExpressionStatement list -> ComputationExpressionStatement list)
-> ComputationExpressionStatement list) list =
[ collectComputationExpressionStatements creationAide e1
collectComputationExpressionStatements creationAide e2 ]
let c2 =
match trivia.SeparatorRange with
// detect then keyword in explicit constructor
| Some mThen when mThen.StartColumn + 4 = mThen.EndColumn ->
let thenNode = stn "then" mThen
let expr = mkExpr creationAide e2
let m = unionRanges mThen e2.Range
let node = ExprExplicitConstructorThenExpr(thenNode, expr, m)

fun finalContinuation ->
finalContinuation
[ ComputationExpressionStatement.OtherStatement(Expr.ExplicitConstructorThenExpr node) ]
| _ -> collectComputationExpressionStatements creationAide e2

[ collectComputationExpressionStatements creationAide e1; c2 ]

let finalContinuation (nodes: ComputationExpressionStatement list list) : ComputationExpressionStatement list =
List.collect id nodes |> finalContinuation
Expand Down Expand Up @@ -2732,10 +2749,7 @@ let mkMemberDefn (creationAide: CreationAide) (md: SynMemberDefn) =
accessibility = ao)
expr = expr
trivia = { EqualsRange = Some mEq })) when (newIdent.idText = "new") ->
let exprNode, thenExprNode =
match expr with
| SynExpr.Sequential(_, false, e1, e2, _) -> mkExpr creationAide e1, Some(mkExpr creationAide e2)
| e -> mkExpr creationAide e, None
let exprNode = mkExpr creationAide expr

MemberDefnExplicitCtorNode(
mkXmlDoc px,
Expand All @@ -2746,7 +2760,6 @@ let mkMemberDefn (creationAide: CreationAide) (md: SynMemberDefn) =
Option.map mkIdent ido,
stn "=" mEq,
exprNode,
thenExprNode,
memberDefinitionRange
)
|> MemberDefn.ExplicitCtor
Expand Down
16 changes: 6 additions & 10 deletions src/Fantomas.Core/CodePrinter.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1572,6 +1572,10 @@ let genExpr (e: Expr) =
+> genSingleTextNode node.End

expressionFitsOnRestOfLine short long |> genNode node
| Expr.ExplicitConstructorThenExpr node ->
genSingleTextNode node.Then
+> sepSpaceOrIndentAndNlnIfExpressionExceedsPageWidth (genExpr node.Expr)
|> genNode node

let genQuoteExpr (node: ExprQuoteNode) =
genSingleTextNode node.OpenToken
Expand Down Expand Up @@ -3786,15 +3790,7 @@ let genMemberDefn (md: MemberDefn) =
+> autoIndentAndNlnIfExpressionExceedsPageWidth (genLongParenPatParameter node.Pattern)
+> optSingle (fun alias -> sepSpace +> !- "as" +> sepSpace +> genSingleTextNode alias) node.Alias)
(fun isMultiline ctx ->
let genExpr =
genExpr node.Expr
+> optSingle
(fun thenExpr ->
sepNln
+> !- "then"
+> sepSpaceOrIndentAndNlnIfExpressionExceedsPageWidth (genExpr thenExpr))
node.ThenExpr

let genExpr = genExpr node.Expr
let short = genSingleTextNode node.Equals +> sepSpace +> genExpr

let long ctx =
Expand All @@ -3810,7 +3806,7 @@ let genMemberDefn (md: MemberDefn) =

genXml node.XmlDoc
+> genAttributes node.Attributes
+> ifElse node.ThenExpr.IsSome long (expressionFitsOnRestOfLine short long)
+> expressionFitsOnRestOfLine short long
|> genNode (MemberDefn.Node md)
| MemberDefn.LetBinding node -> genBindings true node.Bindings |> genNode (MemberDefn.Node md)
| MemberDefn.Interface node ->
Expand Down
15 changes: 11 additions & 4 deletions src/Fantomas.Core/SyntaxOak.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1649,6 +1649,14 @@ type ExprBeginEndNode(beginNode: SingleTextNode, expr: Expr, endNode: SingleText
member val Expr = expr
member val End = endNode

/// then <expr>
/// Only valid in secondary constructors, original coming from SynExpr.Sequential(trivia = { SeparatorRange = Some mThen })
type ExprExplicitConstructorThenExpr(thenNode: SingleTextNode, expr: Expr, range) =
inherit NodeBase(range)
override val Children: Node array = [| yield thenNode; yield Expr.Node expr |]
member val Then = thenNode
member val Expr = expr

[<RequireQualifiedAccess; NoEquality; NoComparison>]
type Expr =
| Lazy of ExprLazyNode
Expand Down Expand Up @@ -1715,6 +1723,7 @@ type Expr =
| Chain of ExprChain
| DotLambda of ExprDotLambda
| BeginEnd of ExprBeginEndNode
| ExplicitConstructorThenExpr of ExprExplicitConstructorThenExpr

static member Node(x: Expr) : Node =
match x with
Expand Down Expand Up @@ -1782,6 +1791,7 @@ type Expr =
| Chain n -> n
| DotLambda n -> n
| BeginEnd n -> n
| ExplicitConstructorThenExpr n -> n

member e.HasParentheses: bool =
match e with
Expand Down Expand Up @@ -2399,7 +2409,6 @@ type MemberDefnExplicitCtorNode
alias: SingleTextNode option,
equals: SingleTextNode,
expr: Expr,
thenExpr: Expr option,
range
) =
inherit NodeBase(range)
Expand All @@ -2412,8 +2421,7 @@ type MemberDefnExplicitCtorNode
yield Pattern.Node pat
yield! noa alias
yield equals
yield Expr.Node expr
yield! noa (Option.map Expr.Node thenExpr) |]
yield Expr.Node expr |]

member val XmlDoc = xmlDoc
member val Attributes = attributes
Expand All @@ -2423,7 +2431,6 @@ type MemberDefnExplicitCtorNode
member val Alias = alias
member val Equals = equals
member val Expr = expr
member val ThenExpr = thenExpr

type MemberDefnInterfaceNode
(interfaceNode: SingleTextNode, t: Type, withNode: SingleTextNode option, members: MemberDefn list, range) =
Expand Down

0 comments on commit 4d5e5e2

Please sign in to comment.