diff --git a/CHANGELOG.md b/CHANGELOG.md index 35dfdad888..f0005055f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## [Unreleased] + +### Fixed +* Idempotency problem with ParsedHashDirective in signature file. [#2258](https://github.com/fsprojects/fantomas/issues/2258) + ## [5.0.0-alpha-007] - 2022-05-16 ### Changed diff --git a/src/Fantomas.Core.Tests/HashDirectiveTests.fs b/src/Fantomas.Core.Tests/HashDirectiveTests.fs index 7c250d6912..8c17382f31 100644 --- a/src/Fantomas.Core.Tests/HashDirectiveTests.fs +++ b/src/Fantomas.Core.Tests/HashDirectiveTests.fs @@ -139,3 +139,90 @@ let ``don't print trivia of other hash directive, 1464`` () = #r "nuget: Giraffe" """ + +[] +let ``trivia before hash directive in signature file, 2258`` () = + formatSourceString + true + """ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.Tokenization + +open System +open System.Threading +open FSharp.Compiler +open FSharp.Compiler.Text + +#nowarn "57" + +/// Represents encoded information for the end-of-line continuation of lexing +[] +type FSharpTokenizerLexState = + { PosBits: int64 + OtherBits: int64 } + + static member Initial: FSharpTokenizerLexState + + member Equals: FSharpTokenizerLexState -> bool + +/// Represents stable information for the state of the lexing engine at the end of a line +type FSharpTokenizerColorState = + | Token = 1 + | IfDefSkip = 3 + | String = 4 + | Comment = 5 + | StringInComment = 6 + | VerbatimStringInComment = 7 + | CamlOnly = 8 + | VerbatimString = 9 + | SingleLineComment = 10 + | EndLineThenSkip = 11 + | EndLineThenToken = 12 + | TripleQuoteString = 13 + | TripleQuoteStringInComment = 14 + | InitialState = 0 +""" + config + |> prepend newline + |> should + equal + """ +// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information. + +namespace FSharp.Compiler.Tokenization + +open System +open System.Threading +open FSharp.Compiler +open FSharp.Compiler.Text + +#nowarn "57" + +/// Represents encoded information for the end-of-line continuation of lexing +[] +type FSharpTokenizerLexState = + { PosBits: int64 + OtherBits: int64 } + + static member Initial: FSharpTokenizerLexState + + member Equals: FSharpTokenizerLexState -> bool + +/// Represents stable information for the state of the lexing engine at the end of a line +type FSharpTokenizerColorState = + | Token = 1 + | IfDefSkip = 3 + | String = 4 + | Comment = 5 + | StringInComment = 6 + | VerbatimStringInComment = 7 + | CamlOnly = 8 + | VerbatimString = 9 + | SingleLineComment = 10 + | EndLineThenSkip = 11 + | EndLineThenToken = 12 + | TripleQuoteString = 13 + | TripleQuoteStringInComment = 14 + | InitialState = 0 +""" diff --git a/src/Fantomas.Core/AstTransformer.fs b/src/Fantomas.Core/AstTransformer.fs index f12e3b8a70..ba862956ae 100644 --- a/src/Fantomas.Core/AstTransformer.fs +++ b/src/Fantomas.Core/AstTransformer.fs @@ -1498,7 +1498,10 @@ module private Ast = |> finalContinuation Continuation.sequence continuations finalContinuation - | SynModuleSigDecl.Val (SynValSig.SynValSig _ as node, _) -> visitSynValSig node |> finalContinuation + | SynModuleSigDecl.Val (SynValSig.SynValSig _ as node, range) -> + [ yield mkNode SynModuleSigDecl_Val range + yield! visitSynValSig node ] + |> finalContinuation | SynModuleSigDecl.Types (typeDefs, range) -> mkNode SynModuleSigDecl_Types range :: (List.collect visitSynTypeDefnSig typeDefs) diff --git a/src/Fantomas.Core/CodePrinter.fs b/src/Fantomas.Core/CodePrinter.fs index 50e38ba677..fae919bfe2 100644 --- a/src/Fantomas.Core/CodePrinter.fs +++ b/src/Fantomas.Core/CodePrinter.fs @@ -179,7 +179,7 @@ and genSigModuleOrNamespace match mdl with | SynModuleSigDecl.Types _ -> sepNlnConsideringTriviaContentBeforeForMainNode SynModuleSigDecl_Types mdl.Range - | SynModuleSigDecl.Val _ -> sepNlnConsideringTriviaContentBeforeForMainNode SynValSig_ mdl.Range + | SynModuleSigDecl.Val _ -> sepNlnConsideringTriviaContentBeforeForMainNode SynModuleSigDecl_Val mdl.Range | _ -> sepNone +> sepNln @@ -210,9 +210,11 @@ and genModuleDeclList astContext e = | OpenL (xs, ys) -> let expr = col sepNln xs (genModuleDecl astContext) - let r = List.head xs |> fun mdl -> mdl.Range + let r, triviaType = + List.head xs + |> fun mdl -> mdl.Range, synModuleDeclToFsAstType mdl // SynModuleDecl.Open cannot have attributes - let sepNln = sepNlnConsideringTriviaContentBeforeForMainNode SynModuleDecl_Open r + let sepNln = sepNlnConsideringTriviaContentBeforeForMainNode triviaType r collectItems ys (fun ysItems -> ColMultilineItem(expr, sepNln) :: ysItems @@ -267,13 +269,28 @@ and genSigModuleDeclList astContext (e: SynModuleSigDecl list) = | SigOpenL (xs, ys) -> let expr = col sepNln xs (genSigModuleDecl astContext) - let r = List.head xs |> fun mdl -> mdl.Range + let r, triviaType = + List.head xs + |> fun mdl -> mdl.Range, synModuleSigDeclToFsAstType mdl // SynModuleSigDecl.Open cannot have attributes - let sepNln = sepNlnConsideringTriviaContentBeforeForMainNode SynModuleSigDecl_Open r + let sepNln = sepNlnConsideringTriviaContentBeforeForMainNode triviaType r + + collectItems ys (fun ysItems -> + ColMultilineItem(expr, sepNln) :: ysItems + |> finalContinuation) + + | SigHashDirectiveL (xs, ys) -> + let expr = col sepNln xs (genSigModuleDecl astContext) + + let r = List.head xs |> fun mdl -> mdl.Range + + let sepNln = + sepNlnConsideringTriviaContentBeforeForMainNode SynModuleSigDecl_HashDirective r collectItems ys (fun ysItems -> ColMultilineItem(expr, sepNln) :: ysItems |> finalContinuation) + | s :: rest -> let sepNln = sepNlnConsideringTriviaContentBeforeForMainNode (synModuleSigDeclToFsAstType s) s.Range @@ -434,14 +451,7 @@ and genSigModuleDecl astContext node = colWithNlnWhenItemIsMultilineUsingConfig items | md -> failwithf "Unexpected module signature declaration: %O" md - |> (match node with - | SynModuleSigDecl.Types _ -> genTriviaFor SynModuleSigDecl_Types node.Range - | SynModuleSigDecl.NestedModule _ -> genTriviaFor SynModuleSigDecl_NestedModule node.Range - | SynModuleSigDecl.Open (SynOpenDeclTarget.ModuleOrNamespace _, _) -> - genTriviaFor SynModuleSigDecl_Open node.Range - | SynModuleSigDecl.Open (SynOpenDeclTarget.Type _, _) -> genTriviaFor SynModuleSigDecl_OpenType node.Range - | SynModuleSigDecl.Exception _ -> genTriviaFor SynModuleSigDecl_Exception node.Range - | _ -> id) + |> genTriviaFor (synModuleSigDeclToFsAstType node) node.Range and genIdent (ident: Ident) = let width = diff --git a/src/Fantomas.Core/SourceTransformer.fs b/src/Fantomas.Core/SourceTransformer.fs index f9a9d89de7..6a71e375ed 100644 --- a/src/Fantomas.Core/SourceTransformer.fs +++ b/src/Fantomas.Core/SourceTransformer.fs @@ -293,11 +293,12 @@ let rec synExprToFsAstType (expr: SynExpr) : FsAstType * Range = let synModuleSigDeclToFsAstType = function - | SynModuleSigDecl.Val _ -> SynValSig_ + | SynModuleSigDecl.Val _ -> SynModuleSigDecl_Val | SynModuleSigDecl.Exception _ -> SynModuleSigDecl_Exception | SynModuleSigDecl.NestedModule _ -> SynModuleSigDecl_NestedModule | SynModuleSigDecl.Types _ -> SynModuleSigDecl_Types - | SynModuleSigDecl.Open _ -> SynModuleSigDecl_Open + | SynModuleSigDecl.Open (SynOpenDeclTarget.ModuleOrNamespace _, _) -> SynModuleSigDecl_Open + | SynModuleSigDecl.Open (SynOpenDeclTarget.Type _, _) -> SynModuleSigDecl_OpenType | SynModuleSigDecl.HashDirective _ -> SynModuleSigDecl_HashDirective | SynModuleSigDecl.NamespaceFragment _ -> SynModuleSigDecl_NamespaceFragment | SynModuleSigDecl.ModuleAbbrev _ -> SynModuleSigDecl_ModuleAbbrev diff --git a/src/Fantomas.Core/TriviaTypes.fs b/src/Fantomas.Core/TriviaTypes.fs index 3e8e632c57..87702739eb 100644 --- a/src/Fantomas.Core/TriviaTypes.fs +++ b/src/Fantomas.Core/TriviaTypes.fs @@ -360,6 +360,7 @@ type FsAstType = | SynModuleOrNamespaceSig_DeclaredNamespace | SynModuleOrNamespaceSig_GlobalNamespace | SynModuleOrNamespaceSig_NamedModule + | SynModuleSigDecl_Val | SynModuleSigDecl_ModuleAbbrev | SynModuleSigDecl_NestedModule | SynModuleSigDecl_NestedModule_Module