From 3de2704b0f9ec6dc0e67c6b0c9a8f61cc6d83f1c Mon Sep 17 00:00:00 2001 From: Florian Verdonck Date: Wed, 15 Nov 2023 13:50:44 +0100 Subject: [PATCH] Add support for intersectionConstraints in SynTyparDecl. (#2986) --- CHANGELOG.md | 5 ++++ .../TypeDeclarationTests.fs | 30 +++++++++++++++++++ src/Fantomas.Core/ASTTransformer.fs | 15 ++++++++-- src/Fantomas.Core/CodePrinter.fs | 3 ++ src/Fantomas.Core/SyntaxOak.fs | 21 +++++++++++-- 5 files changed, 70 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e7aef780d..948ba60cdd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 6.3.0-alpha-003 - 2023-11-15 + +### Fixed +* Reformatting code with flexible type syntax remove hash symbol. [#2984](https://github.com/fsprojects/fantomas/issues/2984) + ## 6.3.0-alpha-002 - 2023-11-07 ### Changed diff --git a/src/Fantomas.Core.Tests/TypeDeclarationTests.fs b/src/Fantomas.Core.Tests/TypeDeclarationTests.fs index ecaae41409..90faea4c41 100644 --- a/src/Fantomas.Core.Tests/TypeDeclarationTests.fs +++ b/src/Fantomas.Core.Tests/TypeDeclarationTests.fs @@ -3631,3 +3631,33 @@ type MyArray3() = with get (x: int, y: int, z: int) = () and set (x: int, y: int, z: int) v = () """ + +[] +let ``intersection constraint, 2984`` () = + formatSourceString + false + """ +let typographyLabel<'msg, 'marker & #IFabLabel>() = () +""" + config + |> prepend newline + |> should + equal + """ +let typographyLabel<'msg, 'marker & #IFabLabel> () = () +""" + +[] +let ``multiple intersection constraint, 2984`` () = + formatSourceString + false + """ +let typographyLabel<'msg, 'marker & #IFabLabel & #IFoo & #Bar>() = () +""" + config + |> prepend newline + |> should + equal + """ +let typographyLabel<'msg, 'marker & #IFabLabel & #IFoo & #Bar> () = () +""" diff --git a/src/Fantomas.Core/ASTTransformer.fs b/src/Fantomas.Core/ASTTransformer.fs index 7082cb47b4..c2cef3c8dc 100644 --- a/src/Fantomas.Core/ASTTransformer.fs +++ b/src/Fantomas.Core/ASTTransformer.fs @@ -1997,13 +1997,24 @@ let mkModuleDecl (creationAide: CreationAide) (decl: SynModuleDecl) = |> ModuleDecl.NestedModule | decl -> failwithf $"Failed to create ModuleDecl for %A{decl}" -let mkSynTyparDecl (creationAide: CreationAide) (SynTyparDecl(attributes = attrs; typar = typar)) = +let mkSynTyparDecl + (creationAide: CreationAide) + (SynTyparDecl(attributes = attrs; typar = typar; intersectionConstraints = intersectionConstraints; trivia = trivia)) + = let m = match List.tryHead attrs with | None -> typar.Range | Some a -> unionRanges a.Range typar.Range - TyparDeclNode(mkAttributes creationAide attrs, mkSynTypar typar, m) + let intersectionConstraintNodes = + if intersectionConstraints.Length <> trivia.AmpersandRanges.Length then + failwith "Unexpected mismatch in SynTyparDecl between intersectionConstraints and AmpersandRanges" + else + (trivia.AmpersandRanges, intersectionConstraints) + ||> List.zip + |> List.collect (fun (amp, t) -> [ Choice2Of2(stn "&" amp); Choice1Of2(mkType creationAide t) ]) + + TyparDeclNode(mkAttributes creationAide attrs, mkSynTypar typar, intersectionConstraintNodes, m) let mkSynTyparDecls (creationAide: CreationAide) (tds: SynTyparDecls) : TyparDecls = match tds with diff --git a/src/Fantomas.Core/CodePrinter.fs b/src/Fantomas.Core/CodePrinter.fs index c97820350b..2f824c37fe 100644 --- a/src/Fantomas.Core/CodePrinter.fs +++ b/src/Fantomas.Core/CodePrinter.fs @@ -2538,6 +2538,9 @@ let genTyparDecl (isFirstTypeParam: bool) (td: TyparDeclNode) = genOnelinerAttributes td.Attributes +> onlyIf (isFirstTypeParam && String.startsWithOrdinal "^" td.TypeParameter.Text) sepSpace +> genSingleTextNode td.TypeParameter + +> colPre sepSpace sepSpace td.IntersectionConstraints (function + | Choice1Of2 t -> genType t + | Choice2Of2 amp -> genSingleTextNode amp) |> genNode td let genTyparDecls (td: TyparDecls) = diff --git a/src/Fantomas.Core/SyntaxOak.fs b/src/Fantomas.Core/SyntaxOak.fs index 6a962202ad..c9e4c066ab 100644 --- a/src/Fantomas.Core/SyntaxOak.fs +++ b/src/Fantomas.Core/SyntaxOak.fs @@ -2680,11 +2680,28 @@ type Constant = | Unit n -> n | Measure n -> n -type TyparDeclNode(attributes: MultipleAttributeListNode option, typar: SingleTextNode, range) = +type TyparDeclNode + ( + attributes: MultipleAttributeListNode option, + typar: SingleTextNode, + intersectionConstraints: Choice list, + range + ) = inherit NodeBase(range) - override val Children: Node array = [| yield! noa attributes; yield typar |] + + override val Children: Node array = + [| yield! noa attributes + yield typar + yield! + List.map + (function + | Choice1Of2 t -> Type.Node t + | Choice2Of2 amp -> amp :> Node) + intersectionConstraints |] + member val Attributes = attributes member val TypeParameter = typar + member val IntersectionConstraints = intersectionConstraints type TyparDeclsPostfixListNode (