Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Capture StartEndRange information in SynExpr.AnonRecd to fix #2566 #2591

Merged
merged 5 commits into from
Oct 24, 2022
Merged
Show file tree
Hide file tree
Changes from 3 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Fixed
* Idempotency problem with `struct end`. [#2592](https://github.com/fsprojects/fantomas/issues/2592)
* Idempotency problem when having a comment in an anonymous record and Stroustrup formatting. [#2566](https://github.com/fsprojects/fantomas/issues/2566)

## [5.1.0-beta-001] - 2022-10-19

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1395,3 +1395,60 @@ let f
=
x
"""

[<Test>]
let ``comment in bracket ranges of anonymous type, 2566`` () =
formatSourceString
false
"""
let x = {| // test1
Y = 42
Z = "string"
Foo = "Bar"
// test2
|}

let y = {|
Y = 42
// test
|}

let z = {|
Y = 42
|}

let a = {| // test1
foo with
Level = 7
Square = 9
// test2
|}
"""
config
|> prepend newline
|> should
equal
"""
let x =
{| // test1
Y = 42
Z = "string"
Foo = "Bar"
// test2
|}

let y =
{|
Y = 42
// test
|}

let z = {| Y = 42 |}

let a =
{| foo with// test1
Level = 7
Square = 9
// test2
|}
"""
56 changes: 56 additions & 0 deletions src/Fantomas.Core.Tests/RecordTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2179,3 +2179,59 @@ type ExprFolder<'State> =
-> Exp
-> 'State |}
"""

[<Test>]
let ``comment in bracket ranges of anonymous type`` () =
formatSourceString
false
"""
let x = {| // test1
Y = 42
Z = "string"
Foo = "Bar"
// test2
|}

let y = {|
Y = 42
// test
|}

let z = {|
Y = 42
|}

let a = {| // test1
foo with
Level = 7
Square = 9
// test2
|}
"""
config
|> prepend newline
|> should
equal
"""
let x =
{| Y = // test1
42
Z = "string"
Foo = "Bar"
// test2
|}

let y =
{| Y = 42
// test
|}

let z = {| Y = 42 |}

let a =
{| foo with// test1
Level = 7
Square = 9
// test2
|}
"""
7 changes: 5 additions & 2 deletions src/Fantomas.Core/AstTransformer.fs
Original file line number Diff line number Diff line change
Expand Up @@ -231,12 +231,15 @@ and visitSynExpr (synExpr: SynExpr) : TriviaNode list =
yield mkNode SynExpr_Record_ClosingBrace closingBrace |])
|> List.singleton
|> finalContinuation
| SynExpr.AnonRecd (_, _, recordFields, range) ->
| SynExpr.AnonRecd (_, _, recordFields, StartEndRange 2 (openingBrace, range, closingBrace)) ->
mkSynExprNode
SynExpr_AnonRecd
synExpr
range
(sortChildren [| yield! List.map visitAnonRecordField recordFields |])
(sortChildren
[| yield mkNode SynExpr_AnonRecd_OpeningBrace openingBrace
yield! List.map visitAnonRecordField recordFields
yield mkNode SynExpr_AnonRecd_ClosingBrace closingBrace |])
|> List.singleton
|> finalContinuation
| SynExpr.New (_, typeName, expr, range) ->
Expand Down
32 changes: 18 additions & 14 deletions src/Fantomas.Core/CodePrinter.fs
Original file line number Diff line number Diff line change
Expand Up @@ -915,18 +915,18 @@ and genExpr synExpr ctx =
let size = getRecordSize ctx xs
isSmallExpression size smallRecordExpr multilineRecordExpr ctx

| AnonRecord (isStruct, fields, copyInfo) ->
| AnonRecord (openingBrace, isStruct, fields, copyInfo, closingBrace) ->
let smallExpression =
onlyIf isStruct !- "struct "
+> sepOpenAnonRecd
+> genTriviaFor SynExpr_AnonRecd_OpeningBrace openingBrace sepOpenAnonRecd
+> optSingle (fun e -> genExpr e +> !- " with ") copyInfo
+> col sepSemi fields genAnonRecordFieldName
+> sepCloseAnonRecd
+> genTriviaFor SynExpr_AnonRecd_ClosingBrace closingBrace sepCloseAnonRecd

let longExpression =
ifAlignBrackets
(genMultilineAnonRecordAlignBrackets isStruct fields copyInfo)
(genMultilineAnonRecord isStruct fields copyInfo)
(genMultilineAnonRecordAlignBrackets openingBrace isStruct fields copyInfo closingBrace)
(genMultilineAnonRecord openingBrace isStruct fields copyInfo closingBrace)

fun (ctx: Context) ->
let size = getRecordSize ctx fields
Expand Down Expand Up @@ -2363,23 +2363,23 @@ and genInheritConstructor (inheritCtor: SynType * SynExpr) =
+> expressionFitsOnRestOfLine (genExpr px) (genMultilineFunctionApplicationArguments px)
| OtherInheritConstructor (t, e) -> genType t +> sepSpaceOrIndentAndNlnIfExpressionExceedsPageWidth (genExpr e)

and genMultilineAnonRecord (isStruct: bool) fields copyInfo =
and genMultilineAnonRecord openingBrace (isStruct: bool) fields copyInfo closingBrace =
let recordExpr =
match copyInfo with
| Some e ->
sepOpenAnonRecd
genTriviaFor SynExpr_AnonRecd_OpeningBrace openingBrace sepOpenAnonRecd
+> atCurrentColumn (
genExpr e
+> (!- " with" +> indentSepNlnUnindent (col sepNln fields genAnonRecordFieldName))
)
+> sepCloseAnonRecd
+> genTriviaFor SynExpr_AnonRecd_ClosingBrace closingBrace sepCloseAnonRecd
| None ->
fun ctx ->
// position after `{| ` or `{|`
let targetColumn = ctx.Column + (if ctx.Config.SpaceAroundDelimiter then 3 else 2)

atCurrentColumn
(sepOpenAnonRecd
(genTriviaFor SynExpr_AnonRecd_OpeningBrace openingBrace sepOpenAnonRecdFixed
+> col sepNln fields (fun (AnonRecordFieldName (ident, eq, e, range)) ->
let expr =
if ctx.Config.IndentSize < 3 then
Expand All @@ -2394,12 +2394,12 @@ and genMultilineAnonRecord (isStruct: bool) fields copyInfo =
+> genEq SynExpr_AnonRecd_Field_Equals eq
+> expr
+> leaveNodeFor SynExpr_AnonRecd_Field range)
+> sepCloseAnonRecd)
+> genTriviaFor SynExpr_AnonRecd_ClosingBrace closingBrace sepCloseAnonRecd)
ctx

onlyIf isStruct !- "struct " +> recordExpr

and genMultilineAnonRecordAlignBrackets (isStruct: bool) fields copyInfo =
and genMultilineAnonRecordAlignBrackets openingBrace (isStruct: bool) fields copyInfo closingBrace =
let fieldsExpr = col sepNln fields genAnonRecordFieldName

let copyExpr fieldsExpr e =
Expand All @@ -2414,12 +2414,16 @@ and genMultilineAnonRecordAlignBrackets (isStruct: bool) fields copyInfo =

let genAnonRecord =
match copyInfo with
| Some ci -> sepOpenAnonRecd +> copyExpr fieldsExpr ci +> sepNln +> sepCloseAnonRecdFixed
| Some ci ->
genTriviaFor SynExpr_AnonRecd_OpeningBrace openingBrace sepOpenAnonRecd
+> copyExpr fieldsExpr ci
+> sepNln
+> genTriviaFor SynExpr_AnonRecd_ClosingBrace closingBrace sepCloseAnonRecdFixed
| None ->
sepOpenAnonRecdFixed
genTriviaFor SynExpr_AnonRecd_OpeningBrace openingBrace sepOpenAnonRecd
+> indentSepNlnUnindent fieldsExpr
+> sepNln
+> sepCloseAnonRecdFixed
+> genTriviaFor SynExpr_AnonRecd_ClosingBrace closingBrace sepCloseAnonRecdFixed

ifElse isStruct !- "struct " sepNone +> genAnonRecord

Expand Down
3 changes: 2 additions & 1 deletion src/Fantomas.Core/SourceParser.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1071,7 +1071,8 @@ let (|Record|_|) =

let (|AnonRecord|_|) =
function
| SynExpr.AnonRecd (isStruct, copyInfo, fields, _) -> Some(isStruct, fields, Option.map fst copyInfo)
| SynExpr.AnonRecd (isStruct, copyInfo, fields, StartEndRange 2 (openingBrace, _, closingBrace)) ->
Some(openingBrace, isStruct, fields, Option.map fst copyInfo, closingBrace)
| _ -> None

let (|ObjExpr|_|) =
Expand Down
2 changes: 2 additions & 0 deletions src/Fantomas.Core/TriviaTypes.fs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ type FsAstType =
| SynExpr_Record_OpeningBrace
| SynExpr_Record_ClosingBrace
| SynExpr_AnonRecd
| SynExpr_AnonRecd_OpeningBrace
| SynExpr_AnonRecd_ClosingBrace
| SynExpr_AnonRecd_Field
| SynExpr_AnonRecd_Field_Equals
| SynExpr_New
Expand Down