From 61ef1edfde029a8c20b9a6c005a9087d1c6bbb51 Mon Sep 17 00:00:00 2001 From: nojaf Date: Thu, 1 Apr 2021 17:41:42 +0200 Subject: [PATCH] Print trivia of TypeDefnSig using FullRange extension. Fixes #1562. --- src/Fantomas.Tests/SignatureTests.fs | 57 ++++++++++++++++++++++++++++ src/Fantomas/AstExtensions.fs | 11 ++++++ src/Fantomas/AstTransformer.fs | 4 +- src/Fantomas/CodePrinter.fs | 34 +++++++++++++++-- src/Fantomas/Context.fs | 15 ++++---- src/Fantomas/Fantomas.fsproj | 1 + src/Fantomas/SourceParser.fs | 9 ++++- src/Fantomas/TriviaTypes.fs | 2 +- 8 files changed, 118 insertions(+), 15 deletions(-) create mode 100644 src/Fantomas/AstExtensions.fs diff --git a/src/Fantomas.Tests/SignatureTests.fs b/src/Fantomas.Tests/SignatureTests.fs index 17ff3e124e..15c49076bc 100644 --- a/src/Fantomas.Tests/SignatureTests.fs +++ b/src/Fantomas.Tests/SignatureTests.fs @@ -1325,3 +1325,60 @@ type 'a Bar = /// | Quux """ + +[] +let ``comment between recursive type, 1562`` () = + formatSourceString + true + """ +namespace Baz + +type Foo = | Foo of int + +/// +and [] Bar<'a> = + | Bar of int +""" + config + |> prepend newline + |> should + equal + """ +namespace Baz + +type Foo = Foo of int + +/// +and [] Bar<'a> = Bar of int +""" + +[] +let ``comments between multiple recursive types`` () = + formatSourceString + true + """ +namespace Baz + +type Foo = | Foo of int + +/// barry +and Bar = | Bar of string + +/// mehhy +and Meh = | Meh of DateTime +""" + config + |> prepend newline + |> should + equal + """ +namespace Baz + +type Foo = Foo of int + +/// barry +and Bar = Bar of string + +/// mehhy +and Meh = Meh of DateTime +""" diff --git a/src/Fantomas/AstExtensions.fs b/src/Fantomas/AstExtensions.fs new file mode 100644 index 0000000000..272c9f9c74 --- /dev/null +++ b/src/Fantomas/AstExtensions.fs @@ -0,0 +1,11 @@ +module Fantomas.AstExtensions + +open FSharp.Compiler.SyntaxTree +open FSharp.Compiler.Text +open FSharp.Compiler.Text.Range + +type SynTypeDefnSig with + /// Combines the range of type name and the body. + member this.FullRange : Range = + match this with + | SynTypeDefnSig.TypeDefnSig (comp, _, _, r) -> mkRange r.FileName comp.Range.Start r.End diff --git a/src/Fantomas/AstTransformer.fs b/src/Fantomas/AstTransformer.fs index 925b82c436..37d603bc3d 100644 --- a/src/Fantomas/AstTransformer.fs +++ b/src/Fantomas/AstTransformer.fs @@ -3,6 +3,7 @@ module Fantomas.AstTransformer open FSharp.Compiler.Text open FSharp.Compiler.SyntaxTree open Fantomas.TriviaTypes +open Fantomas.AstExtensions open Fantomas type Id = { Ident: string; Range: Range } @@ -645,7 +646,8 @@ module private Ast = and visitSynTypeDefnSig (typeDefSig: SynTypeDefnSig) : TriviaNodeAssigner list = match typeDefSig with | TypeDefnSig (sci, synTypeDefnSigReprs, memberSig, _) -> - [ yield! visitSynComponentInfo sci + [ yield mkNode TypeDefnSig_ typeDefSig.FullRange + yield! visitSynComponentInfo sci yield! visitSynTypeDefnSigRepr synTypeDefnSigReprs yield! (memberSig |> List.collect visitSynMemberSig) ] diff --git a/src/Fantomas/CodePrinter.fs b/src/Fantomas/CodePrinter.fs index e2597cc854..5b6fb7e042 100644 --- a/src/Fantomas/CodePrinter.fs +++ b/src/Fantomas/CodePrinter.fs @@ -12,6 +12,7 @@ open Fantomas.SourceTransformer open Fantomas.Context open Fantomas.TriviaTypes open Fantomas.TriviaContext +open Fantomas.AstExtensions /// This type consists of contextual information which is important for formatting type ASTContext = @@ -454,8 +455,24 @@ and genSigModuleDecl astContext node = | SigOpen (s) -> !-(sprintf "open %s" s) | SigOpenType (s) -> !-(sprintf "open type %s" s) | SigTypes (t :: ts) -> + let sepTs = + match List.tryHead ts with + | Some t -> + let attributeRanges = + getRangesFromAttributesFromSynTypeDefnSig t + + sepNln + +> sepNlnConsideringTriviaContentBeforeWithAttributesFor TypeDefnSig_ t.FullRange attributeRanges + | None -> rep 2 sepNln + genSigTypeDefn { astContext with IsFirstChild = true } t - +> colPre (rep 2 sepNln) (rep 2 sepNln) ts (genSigTypeDefn { astContext with IsFirstChild = false }) + +> colPreEx + sepTs + (fun (ty: SynTypeDefnSig) -> + sepNln + +> sepNlnConsideringTriviaContentBeforeForMainNode TypeDefnSig_ ty.FullRange) + ts + (genSigTypeDefn { astContext with IsFirstChild = false }) | md -> failwithf "Unexpected module signature declaration: %O" md |> (match node with | SynModuleSigDecl.Types _ -> genTriviaFor SynModuleSigDecl_Types node.Range @@ -3691,13 +3708,23 @@ and sepNlnBetweenSigTypeAndMembers (synTypeDefnRepr: SynTypeDefnSigRepr) (ms: Sy sepNlnTypeAndMembers synTypeDefnRepr.Range.End range mainNodeType | None -> sepNone -and genSigTypeDefn astContext (SigTypeDef (ats, px, ao, tds, tcs, tdr, ms, s, preferPostfix)) = +and genSigTypeDefn astContext (SigTypeDef (ats, px, ao, tds, tcs, tdr, ms, s, preferPostfix, fullRange)) = + let genTriviaForOnelinerAttributes f (ctx: Context) = + match ats with + | [] -> f ctx + | h :: _ -> + (enterNodeFor SynAttributeList_ h.Range + +> f + +> leaveNodeFor SynAttributeList_ h.Range) + ctx + let typeName = genPreXmlDoc px +> ifElse astContext.IsFirstChild (genAttributes astContext ats -- "type ") - (!- "and " +> genOnelinerAttributes astContext ats) + ((!- "and " +> genOnelinerAttributes astContext ats) + |> genTriviaForOnelinerAttributes) +> opt sepSpace ao genAccess +> genTypeAndParam astContext s tds tcs preferPostfix @@ -3855,6 +3882,7 @@ and genSigTypeDefn astContext (SigTypeDef (ats, px, ao, tds, tcs, tdr, ms, s, pr +> unindent | SigExceptionRepr (SigExceptionDefRepr (ats, px, ao, uc)) -> genExceptionBody astContext ats px ao uc + |> genTriviaFor TypeDefnSig_ fullRange and genSigSimpleRecord tdr ms ao' fs astContext = // the typeName is already printed diff --git a/src/Fantomas/Context.fs b/src/Fantomas/Context.fs index 0409759d6d..3e4d3dbf0d 100644 --- a/src/Fantomas/Context.fs +++ b/src/Fantomas/Context.fs @@ -1344,28 +1344,27 @@ let internal sepNlnConsideringTriviaContentBeforeWithAttributesFor (attributeRanges: Range seq) (ctx: Context) = - let triviaNode = + let triviaNodeBeforeMain = match Map.tryFind mainNode ctx.TriviaMainNodes with | Some triviaNodes -> - List.tryFind + List.exists (fun { Range = r; ContentBefore = cb } -> hasPrintableContent cb && RangeHelpers.rangeEq r ownRange) triviaNodes - | None -> None + | None -> false - let attributeNode = + let triviaNodeBeforeAttribute = match Map.tryFind SynAttributeList_ ctx.TriviaMainNodes with | Some attributeNodes -> - List.tryFind + List.exists (fun { Range = r; ContentBefore = cb } -> hasPrintableContent cb && Seq.exists (RangeHelpers.rangeEq r) attributeRanges) attributeNodes - | None -> None + | None -> false - if Option.isSome triviaNode - || Option.isSome attributeNode then + if triviaNodeBeforeMain || triviaNodeBeforeAttribute then ctx else sepNln ctx diff --git a/src/Fantomas/Fantomas.fsproj b/src/Fantomas/Fantomas.fsproj index 6530459e3b..5ec3384901 100644 --- a/src/Fantomas/Fantomas.fsproj +++ b/src/Fantomas/Fantomas.fsproj @@ -13,6 +13,7 @@ + diff --git a/src/Fantomas/SourceParser.fs b/src/Fantomas/SourceParser.fs index 3a859d05eb..4b6240c606 100644 --- a/src/Fantomas/SourceParser.fs +++ b/src/Fantomas/SourceParser.fs @@ -8,6 +8,7 @@ open FSharp.Compiler.SyntaxTree open FSharp.Compiler.XmlDoc open Fantomas open Fantomas.Context +open Fantomas.AstExtensions type Composite<'a, 'b> = | Pair of 'b * 'b @@ -1353,9 +1354,9 @@ let (|SigTypeDef|) (SynTypeDefnSig.TypeDefnSig (SynComponentInfo.ComponentInfo (ats, tds, tcs, LongIdent s, px, preferPostfix, ao, _), tdr, ms, - _)) + _) as node) = - (ats, px, ao, tds, tcs, tdr, ms, s, preferPostfix) + (ats, px, ao, tds, tcs, tdr, ms, s, preferPostfix, node.FullRange) let (|TyparDecl|) (SynTyparDecl.TyparDecl (ats, tp)) = (ats, tp) @@ -1586,6 +1587,10 @@ let getRangesFromAttributesFromSynModuleSigDeclaration (sdl: SynModuleSigDecl) = | _ -> Seq.empty |> Seq.toList +let getRangesFromAttributesFromSynTypeDefnSig (TypeDefnSig (comp, _, _, _)) = + match comp with + | SynComponentInfo.ComponentInfo (attrs, _, _, _, _, _, _, _) -> collectAttributesRanges attrs + let getRangesFromAttributesFromSynBinding (sb: SynBinding) = match sb with | SynBinding.Binding (_, _, _, _, attrs, _, _, _, _, _, _, _) -> attrs |> List.map (fun a -> a.Range) diff --git a/src/Fantomas/TriviaTypes.fs b/src/Fantomas/TriviaTypes.fs index c451da0412..638c8dce8f 100644 --- a/src/Fantomas/TriviaTypes.fs +++ b/src/Fantomas/TriviaTypes.fs @@ -193,7 +193,7 @@ type FsAstType = | ArgOptions_ | InterfaceImpl_ | TypeDefn_ - // | TypeDefnSig_ use first nested type + | TypeDefnSig_ // | SynTypeDefnSigRepr_ObjectModel use first nested node | SynTypeDefnSigRepr_Exception | SynMemberDefn_Open