From 7b52594dea8a82ad260fd060bb1561e325139d4d Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Sat, 23 Mar 2019 21:40:50 +0300 Subject: [PATCH] Support anon record expressions --- src/Fantomas.Tests/RecordTests.fs | 30 +++++++++++++++++++++++++++++- src/Fantomas/CodePrinter.fs | 14 ++++++++++++++ src/Fantomas/Context.fs | 12 ++++++++++-- src/Fantomas/SourceParser.fs | 7 +++++++ 4 files changed, 60 insertions(+), 3 deletions(-) diff --git a/src/Fantomas.Tests/RecordTests.fs b/src/Fantomas.Tests/RecordTests.fs index 4c60f9987c..f433f9657c 100644 --- a/src/Fantomas.Tests/RecordTests.fs +++ b/src/Fantomas.Tests/RecordTests.fs @@ -259,4 +259,32 @@ type MyExc = { inherit Exception(msg) X = 1 Y = 2 } -""" \ No newline at end of file +""" + +[] +let ``anon record expression``() = + formatSourceString false """ +let r = + {| Foo = 123 + Bar = "" |} +""" config + |> prepend newline + |> should equal """ +let r = + {| Foo = 123 + Bar = "" |} +""" + +[] +let `` anon record struct expression``() = + formatSourceString false """ +let r = + struct {| Foo = 123 + Bar = "" |} +""" config + |> prepend newline + |> should equal """ +let r = + struct {| Foo = 123 + Bar = "" |} +""" diff --git a/src/Fantomas/CodePrinter.fs b/src/Fantomas/CodePrinter.fs index 33b9c72eb9..587ec20972 100644 --- a/src/Fantomas/CodePrinter.fs +++ b/src/Fantomas/CodePrinter.fs @@ -473,6 +473,9 @@ and genVal astContext (Val(ats, px, ao, s, t, vi, _)) = and genRecordFieldName astContext (RecordFieldName(s, eo)) = opt sepNone eo (fun e -> !- s +> sepEq +> preserveBreakNlnOrAddSpace astContext e) +and genAnonRecordFieldName astContext (AnonRecordFieldName(s, e)) = + !- s +> sepEq +> preserveBreakNlnOrAddSpace astContext e + and genTuple astContext es = atCurrentColumn (coli sepComma es (fun i -> if i = 0 then genExpr astContext else noIndentBreakNln astContext @@ -539,6 +542,17 @@ and genExpr astContext synExpr = (fun (typ, expr) -> !- "inherit " +> genType astContext false typ +> genExpr astContext expr) +> recordExpr) +> sepCloseS + | AnonRecord(isStruct, fields, copyInfo) -> + let recordExpr = + let fieldsExpr = col sepSemiNln fields (genAnonRecordFieldName astContext) + copyInfo |> Option.map (fun e -> + genExpr astContext e +> ifElseCtx (futureNlnCheck fieldsExpr) (!- " with" +> indent +> sepNln +> fieldsExpr +> unindent) (!- " with " +> fieldsExpr)) + |> Option.defaultValue fieldsExpr + ifElse isStruct !- "struct " sepNone + +> sepOpenAnonRecd + +> atCurrentColumnIndent recordExpr + +> sepCloseAnonRecd + | ObjExpr(t, eio, bd, ims, range) -> // Check the role of the second part of eio let param = opt sepNone (Option.map fst eio) (genExpr astContext) diff --git a/src/Fantomas/Context.fs b/src/Fantomas/Context.fs index 10d61647bb..fbfde4330e 100644 --- a/src/Fantomas/Context.fs +++ b/src/Fantomas/Context.fs @@ -295,14 +295,22 @@ let internal sepOpenAFixed = !- "[|" /// closing token of list let internal sepCloseAFixed = !- "|]" -/// opening token of sequence +/// opening token of sequence or record let internal sepOpenS (ctx : Context) = if ctx.Config.SpaceAroundDelimiter then str "{ " ctx else str "{" ctx -/// closing token of sequence +/// closing token of sequence or record let internal sepCloseS (ctx : Context) = if ctx.Config.SpaceAroundDelimiter then str " }" ctx else str "}" ctx +/// opening token of anon record +let internal sepOpenAnonRecd (ctx : Context) = + if ctx.Config.SpaceAroundDelimiter then str "{| " ctx else str "{|" ctx + +/// closing token of anon record +let internal sepCloseAnonRecd (ctx : Context) = + if ctx.Config.SpaceAroundDelimiter then str " |}" ctx else str "|}" ctx + /// opening token of sequence let internal sepOpenSFixed = !- "{" diff --git a/src/Fantomas/SourceParser.fs b/src/Fantomas/SourceParser.fs index 8b1c12c758..5780bf604f 100644 --- a/src/Fantomas/SourceParser.fs +++ b/src/Fantomas/SourceParser.fs @@ -808,6 +808,11 @@ let (|Record|_|) = function Some(inheritOpt, xs, Option.map fst eo) | _ -> None +let (|AnonRecord|_|) = function + | SynExpr.AnonRecd(isStruct, copyInfo, fields, _) -> + Some(isStruct, fields, Option.map fst copyInfo) + | _ -> None + let (|ObjExpr|_|) = function | SynExpr.ObjExpr(t, eio, bd, ims, _, range) -> Some (t, eio, bd, ims, range) @@ -1207,6 +1212,8 @@ let (|Val|) (ValSpfn(ats, IdentOrKeyword(OpNameFull s), tds, t, vi, _, _, px, ao let (|RecordFieldName|) ((LongIdentWithDots s, _) : RecordFieldName, eo : SynExpr option, _) = (s, eo) +let (|AnonRecordFieldName|) ((Ident s): Ident, e: SynExpr) = (s, e) + let (|PatRecordFieldName|) ((LongIdent s1, Ident s2), p) = (s1, s2, p) let (|ValInfo|) (SynValInfo(aiss, ai)) = (aiss, ai)