diff --git a/paket.dependencies b/paket.dependencies index 1491b937aa..08dcfe79a9 100644 --- a/paket.dependencies +++ b/paket.dependencies @@ -3,8 +3,8 @@ source https://api.nuget.org/v3/index.json framework: netstandard2.0, net5.0, netcoreapp3.1 storage: none -nuget FSharp.Core -nuget FSharp.Compiler.Service ~> 39.0 +nuget FSharp.Core 5.0.3-beta.21352.5 +nuget FSharp.Compiler.Service 40.0.1-preview.21352.5 nuget FsUnit nuget FsCheck nuget Microsoft.NET.Test.Sdk 16.9.1 diff --git a/paket.lock b/paket.lock index 981557a49a..2e54219a9d 100644 --- a/paket.lock +++ b/paket.lock @@ -26,11 +26,11 @@ NUGET editorconfig (0.12.2) FsCheck (2.14.3) FSharp.Core (>= 4.2.3) - FSharp.Compiler.Service (39.0) - FSharp.Core (5.0.1) - Microsoft.Build.Framework (>= 16.6) - Microsoft.Build.Tasks.Core (>= 16.6) - Microsoft.Build.Utilities.Core (>= 16.6) + FSharp.Compiler.Service (40.0.1-preview.21352.5) + FSharp.Core (5.0.3-beta.21352.5) + Microsoft.Build.Framework (>= 16.9) + Microsoft.Build.Tasks.Core (>= 16.9) + Microsoft.Build.Utilities.Core (>= 16.9) System.Buffers (>= 4.5.1) System.Collections.Immutable (>= 5.0) System.Diagnostics.Process (>= 4.3) @@ -44,6 +44,7 @@ NUGET System.Reflection.Metadata (>= 5.0) System.Reflection.TypeExtensions (>= 4.3) System.Runtime (>= 4.3) + System.Runtime.CompilerServices.Unsafe (>= 5.0) System.Runtime.InteropServices (>= 4.3) System.Runtime.Loader (>= 4.3) System.Security.Claims (>= 4.3) @@ -52,7 +53,7 @@ NUGET System.Threading.Tasks.Parallel (>= 4.3) System.Threading.Thread (>= 4.3) System.Threading.ThreadPool (>= 4.3) - FSharp.Core (5.0.1) + FSharp.Core (5.0.3-beta.21352.5) FsUnit (4.0.2) FSharp.Core (>= 4.3.4) NETStandard.Library (>= 2.0.3) @@ -60,26 +61,27 @@ NUGET Iced (1.7) MAB.DotIgnore (3.0.2) NETStandard.Library (>= 1.6.1) - Microsoft.Build.Framework (16.8) + Microsoft.Build.Framework (16.10) System.Security.Permissions (>= 4.7) - Microsoft.Build.Tasks.Core (16.8) - Microsoft.Build.Framework (>= 16.8) - Microsoft.Build.Utilities.Core (>= 16.8) + Microsoft.Build.Tasks.Core (16.10) + Microsoft.Build.Framework (>= 16.10) + Microsoft.Build.Utilities.Core (>= 16.10) + Microsoft.NET.StringTools (>= 1.0) Microsoft.Win32.Registry (>= 4.3) System.CodeDom (>= 4.4) - System.Collections.Immutable (>= 1.5) + System.Collections.Immutable (>= 5.0) System.Reflection.Metadata (>= 1.6) - System.Reflection.TypeExtensions (>= 4.1) System.Resources.Extensions (>= 4.6) - System.Runtime.InteropServices (>= 4.3) System.Security.Cryptography.Pkcs (>= 4.7) System.Security.Cryptography.Xml (>= 4.7) System.Security.Permissions (>= 4.7) System.Threading.Tasks.Dataflow (>= 4.9) - Microsoft.Build.Utilities.Core (16.8) - Microsoft.Build.Framework (>= 16.8) + Microsoft.Build.Utilities.Core (16.10) + Microsoft.Build.Framework (>= 16.10) + Microsoft.NET.StringTools (>= 1.0) Microsoft.Win32.Registry (>= 4.3) - System.Collections.Immutable (>= 1.5) + System.Collections.Immutable (>= 5.0) + System.Configuration.ConfigurationManager (>= 4.7) System.Security.Permissions (>= 4.7) System.Text.Encoding.CodePages (>= 4.0.1) Microsoft.CodeAnalysis.Analyzers (3.0) @@ -99,6 +101,9 @@ NUGET Microsoft.Diagnostics.Tracing.TraceEvent (2.0.56) System.Runtime.CompilerServices.Unsafe (>= 4.5.2) Microsoft.DotNet.PlatformAbstractions (3.1.4) + Microsoft.NET.StringTools (1.0) + System.Memory (>= 4.5.4) + System.Runtime.CompilerServices.Unsafe (>= 5.0) Microsoft.NET.Test.Sdk (16.9.1) Microsoft.CodeCoverage (>= 16.9.1) - restriction: || (== net5.0) (== netcoreapp3.1) (&& (== netstandard2.0) (>= net45)) (&& (== netstandard2.0) (>= netcoreapp1.0)) Microsoft.TestPlatform.TestHost (>= 16.9.1) - restriction: || (== net5.0) (== netcoreapp3.1) (&& (== netstandard2.0) (>= netcoreapp1.0)) @@ -437,7 +442,7 @@ NUGET System.Runtime (4.3.1) Microsoft.NETCore.Platforms (>= 1.1.1) Microsoft.NETCore.Targets (>= 1.1.3) - System.Runtime.CompilerServices.Unsafe (4.7) + System.Runtime.CompilerServices.Unsafe (5.0) System.Runtime.Extensions (4.3.1) Microsoft.NETCore.Platforms (>= 1.1.1) Microsoft.NETCore.Targets (>= 1.1.3) diff --git a/src/Fantomas.Benchmarks/Runners.fs b/src/Fantomas.Benchmarks/Runners.fs index c25a9b214e..b7201dc0eb 100644 --- a/src/Fantomas.Benchmarks/Runners.fs +++ b/src/Fantomas.Benchmarks/Runners.fs @@ -1,8 +1,8 @@ module Fantomas.Benchmarks.Runners -open BenchmarkDotNet.Attributes open System.IO -open FSharp.Compiler.SourceCodeServices +open BenchmarkDotNet.Attributes +open FSharp.Compiler.CodeAnalysis open Fantomas open Fantomas.Extras diff --git a/src/Fantomas.Extras/FakeHelpers.fs b/src/Fantomas.Extras/FakeHelpers.fs index 8047f96c76..6a902eb831 100644 --- a/src/Fantomas.Extras/FakeHelpers.fs +++ b/src/Fantomas.Extras/FakeHelpers.fs @@ -2,7 +2,7 @@ module Fantomas.Extras.FakeHelpers open System open System.IO -open FSharp.Compiler.SourceCodeServices +open FSharp.Compiler.CodeAnalysis open Fantomas open Fantomas.FormatConfig open Fantomas.Extras diff --git a/src/Fantomas.Tests/AttributeTests.fs b/src/Fantomas.Tests/AttributeTests.fs index 5cbc9356c3..352358c69c 100644 --- a/src/Fantomas.Tests/AttributeTests.fs +++ b/src/Fantomas.Tests/AttributeTests.fs @@ -783,3 +783,45 @@ module Foo = [] extern bool GetFileInformationByHandleEx(IntPtr hFile, FILE_INFO_BY_HANDLE_CLASS infoClass, [] FILE_NAME_INFO& info, uint32 dwBufferSize) """ + +[] +let ``comment after attribute before let binding with return type`` () = + formatSourceString + false + """ +[] +// bar +let add (a: int) ( b : int) : int = a + b +""" + config + |> prepend newline + |> should + equal + """ +[] +// bar +let add (a: int) (b: int) : int = a + b +""" + +[] +let ``comment after attribute before value binding with return type`` () = + formatSourceString + false + """ +[] +// bar + +// bar again, cuz why not +let x: int = 99 +""" + config + |> prepend newline + |> should + equal + """ +[] +// bar + +// bar again, cuz why not +let x: int = 99 +""" diff --git a/src/Fantomas.Tests/TestHelpers.fs b/src/Fantomas.Tests/TestHelpers.fs index 09b63ea6a7..956bcc8e6b 100644 --- a/src/Fantomas.Tests/TestHelpers.fs +++ b/src/Fantomas.Tests/TestHelpers.fs @@ -1,17 +1,17 @@ module Fantomas.Tests.TestHelper -open FsUnit open System +open System.IO +open NUnit.Framework +open FsCheck +open FsUnit +open FSharp.Compiler.Text +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.Syntax +open FSharp.Compiler.Xml open Fantomas.FormatConfig open Fantomas open Fantomas.Extras -open FSharp.Compiler.Text -open FSharp.Compiler.SourceCodeServices -open FSharp.Compiler.SyntaxTree -open FSharp.Compiler.XmlDoc -open NUnit.Framework -open FsCheck -open System.IO [] do () @@ -41,7 +41,7 @@ let private isValidAndHasNoWarnings fileName source parsingOptions = let! untypedRes = sharedChecker.Value.ParseFile(fileName, sourceText, parsingOptionsWithDefines) let errors = - untypedRes.Errors + untypedRes.Diagnostics |> Array.filter (fun e -> not (List.contains e.Message safeToIgnoreWarnings)) // FSharpErrorInfo contains both Errors and Warnings // https://fsharp.github.io/FSharp.Compiler.Service/reference/fsharp-compiler-sourcecodeservices-fsharperrorinfo.html @@ -206,7 +206,7 @@ let toSynExprs (Input s) = [], [ SynModuleOrNamespace (_, false, - AnonModule, + SynModuleOrNamespaceKind.AnonModule, exprs, _, _, @@ -246,8 +246,8 @@ let fromSynExpr expr = [ SynModuleOrNamespace( [ ident ], false, - AnonModule, - [ SynModuleDecl.DoExpr(NoDebugPointAtDoBinding, expr, zero) ], + SynModuleOrNamespaceKind.AnonModule, + [ SynModuleDecl.DoExpr(DebugPointAtBinding.NoneAtDo, expr, zero) ], PreXmlDoc.Empty, [], None, diff --git a/src/Fantomas.Tests/TokenParserTests.fs b/src/Fantomas.Tests/TokenParserTests.fs index ace1ddf74d..f5c718e55a 100644 --- a/src/Fantomas.Tests/TokenParserTests.fs +++ b/src/Fantomas.Tests/TokenParserTests.fs @@ -23,8 +23,8 @@ let private mkRange: MkRange = fun (sl, sc) (el, ec) -> FSharp.Compiler.Text.Range.mkRange "TokenParserTests" - (FSharp.Compiler.Text.Pos.mkPos sl sc) - (FSharp.Compiler.Text.Pos.mkPos el ec) + (FSharp.Compiler.Text.Position.mkPos sl sc) + (FSharp.Compiler.Text.Position.mkPos el ec) let private getTriviaFromTokens = getTriviaFromTokens mkRange let private getTriviaNodesFromTokens = getTriviaNodesFromTokens mkRange diff --git a/src/Fantomas.Tests/TriviaTests.fs b/src/Fantomas.Tests/TriviaTests.fs index 8ef14d0f28..5ec4ad4ac3 100644 --- a/src/Fantomas.Tests/TriviaTests.fs +++ b/src/Fantomas.Tests/TriviaTests.fs @@ -10,8 +10,8 @@ let private collectTrivia = (fun (sl, sc) (el, ec) -> FSharp.Compiler.Text.Range.mkRange "TriviaTests" - (FSharp.Compiler.Text.Pos.mkPos sl sc) - (FSharp.Compiler.Text.Pos.mkPos el ec)) + (FSharp.Compiler.Text.Position.mkPos sl sc) + (FSharp.Compiler.Text.Position.mkPos el ec)) let private toTrivia source = let astWithDefines = parse false source |> Array.toList diff --git a/src/Fantomas/AstExtensions.fs b/src/Fantomas/AstExtensions.fs index b88b847228..606d9a85a6 100644 --- a/src/Fantomas/AstExtensions.fs +++ b/src/Fantomas/AstExtensions.fs @@ -1,16 +1,47 @@ module Fantomas.AstExtensions -open FSharp.Compiler.SyntaxTree +open FSharp.Compiler.Syntax 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 - let longIdentFullRange (li: LongIdent) : Range = match li with | [] -> range.Zero | h :: _ -> unionRanges h.idRange (List.last li).idRange + +let private hasLinesBetweenAttributesAndFirstNode (attributes: SynAttributes) (firstNodeRange: Range) : Range option = + let fileName = firstNodeRange.FileName + + List.tryLast attributes + |> Option.bind + (fun lastAttribute -> + if lastAttribute.Range.EndLine + 1 < firstNodeRange.StartLine + && firstNodeRange.Start.Column > 0 then + let pos = + Position.mkPos firstNodeRange.StartLine 0 + + mkRange fileName pos pos |> Some + else + None) + +type SynBinding with + /// Construct an artificial range after the attributes and before the head pattern. + /// This is to detect newline or comment trivia in that exact location. + member this.AfterAttributesBeforeHeadPattern: Range option = + match this with + | SynBinding(attributes = []) -> None + | SynBinding (attributes = attrs; headPat = pat) -> hasLinesBetweenAttributesAndFirstNode attrs pat.Range + +type SynTypeDefn with + member this.AfterAttributesBeforeComponentInfo: Range option = + match this with + | SynTypeDefn(typeInfo = SynComponentInfo(attributes = [])) -> None + | SynTypeDefn(typeInfo = SynComponentInfo (attributes = attrs; range = compRange)) -> + hasLinesBetweenAttributesAndFirstNode attrs compRange + +type SynField with + member this.AfterAttributesBeforeIdentifier: Range option = + match this with + | SynField(attributes = []) -> None + | SynField (attributes = _ :: _; idOpt = None) -> None + | SynField (attributes = attrs; idOpt = Some ident) -> hasLinesBetweenAttributesAndFirstNode attrs ident.idRange diff --git a/src/Fantomas/AstTransformer.fs b/src/Fantomas/AstTransformer.fs index 107ea3bd5a..12a00e4cab 100644 --- a/src/Fantomas/AstTransformer.fs +++ b/src/Fantomas/AstTransformer.fs @@ -1,7 +1,7 @@ module Fantomas.AstTransformer open FSharp.Compiler.Text -open FSharp.Compiler.SyntaxTree +open FSharp.Compiler.Syntax open Fantomas.TriviaTypes open Fantomas.AstExtensions open Fantomas @@ -16,14 +16,14 @@ module private Ast = let rec visitSynModuleOrNamespace (modOrNs: SynModuleOrNamespace) : TriviaNodeAssigner list = match modOrNs with - | SynModuleOrNamespace (longIdent, _, kind, decls, _, attrs, _, range) -> + | SynModuleOrNamespace (longIdent, _, kind, decls, _, attrs, _, _range) -> let longIdentNodes = match kind, decls with | SynModuleOrNamespaceKind.AnonModule, _ :: _ -> [] | _ -> visitLongIdentIncludingFullRange longIdent [ yield! longIdentNodes - yield! (visitSynAttributeLists range attrs) + yield! (visitSynAttributeLists attrs) yield! (decls |> List.collect visitSynModuleDecl) ] and visitSynModuleDecl (ast: SynModuleDecl) : TriviaNodeAssigner list = @@ -75,7 +75,7 @@ module private Ast = |> finalContinuation | SynModuleDecl.Attributes (attrs, range) -> mkNode SynModuleDecl_Attributes range - :: (visitSynAttributeLists range attrs) + :: (visitSynAttributeLists attrs) |> finalContinuation | SynModuleDecl.HashDirective (hash, range) -> [ mkNode SynModuleDecl_HashDirective range @@ -455,12 +455,11 @@ module private Ast = (fun nodes -> mkNode SynExpr_AddressOf range :: nodes |> finalContinuation) - | SynExpr.TraitCall (typars, sign, expr, range) -> + | SynExpr.TraitCall (_typars, sign, expr, range) -> visit expr (fun nodes -> [ yield mkNode SynExpr_TraitCall range - yield! typars |> List.collect visitSynTypar yield! visitSynMemberSig sign yield! nodes ] |> finalContinuation) @@ -568,7 +567,7 @@ module private Ast = (fun nodes -> mkNode SynExpr_Fixed range :: nodes |> finalContinuation) - | SynExpr.InterpolatedString (parts, range) -> + | SynExpr.InterpolatedString (parts, _, range) -> mkNode SynExpr_InterpolatedString range :: (List.collect visitSynInterpolatedStringPart parts) |> finalContinuation @@ -619,8 +618,8 @@ module private Ast = and visitSynMatchClause (mc: SynMatchClause) : TriviaNodeAssigner list = match mc with - | SynMatchClause.Clause (pat, e1, e2, _range, _) -> - mkNode SynMatchClause_Clause mc.Range // _range is the same range as pat, see https://github.com/dotnet/fsharp/issues/10877 + | SynMatchClause (pat, e1, e2, _range, _) -> + mkNode SynMatchClause_ mc.Range // _range is the same range as pat, see https://github.com/dotnet/fsharp/issues/10877 :: [ yield! visitSynPat pat if e1.IsSome then yield! visitSynExpr e1.Value @@ -630,23 +629,32 @@ module private Ast = and visitSynInterfaceImpl (ii: SynInterfaceImpl) : TriviaNodeAssigner list = match ii with - | InterfaceImpl (typ, bindings, range) -> - [ yield mkNode InterfaceImpl_ range + | SynInterfaceImpl (typ, bindings, range) -> + [ yield mkNode SynInterfaceImpl_ range yield! visitSynType typ yield! (bindings |> List.collect visitSynBinding) ] and visitSynTypeDefn (td: SynTypeDefn) = match td with - | TypeDefn (sci, stdr, members, range) -> - [ yield mkNode TypeDefn_ range + | SynTypeDefn (sci, stdr, members, implicitConstructor, range) -> + let afterAttributesBeforeRepr = + match td.AfterAttributesBeforeComponentInfo with + | None -> [] + | Some r -> + mkNode SynTypeDefn_AfterAttributesBeforeComponentInfo r + |> List.singleton + + // TODO process implicitConstructor ?? + [ yield mkNode SynTypeDefn_ range yield! visitSynComponentInfo sci + yield! afterAttributesBeforeRepr yield! visitSynTypeDefnRepr stdr yield! (members |> List.collect visitSynMemberDefn) ] and visitSynTypeDefnSig (typeDefSig: SynTypeDefnSig) : TriviaNodeAssigner list = match typeDefSig with - | TypeDefnSig (sci, synTypeDefnSigReprs, memberSig, _) -> - [ yield mkNode TypeDefnSig_ typeDefSig.FullRange + | SynTypeDefnSig (sci, synTypeDefnSigReprs, memberSig, _) -> + [ yield mkNode SynTypeDefnSig_ typeDefSig.Range yield! visitSynComponentInfo sci yield! visitSynTypeDefnSigRepr synTypeDefnSigReprs yield! (memberSig |> List.collect visitSynMemberSig) ] @@ -675,7 +683,7 @@ module private Ast = :: (visitSynBinding memberDefn) | SynMemberDefn.ImplicitCtor (_, attrs, ctorArgs, _, _xmlDoc, range) -> [ yield mkNode SynMemberDefn_ImplicitCtor range - yield! (visitSynAttributeLists range attrs) + yield! (visitSynAttributeLists attrs) yield! visitSynSimplePats ctorArgs ] | SynMemberDefn.ImplicitInherit (inheritType, inheritArgs, _, range) -> [ yield mkNode SynMemberDefn_ImplicitInherit range @@ -703,7 +711,7 @@ module private Ast = :: (visitSynTypeDefn typeDefn) | SynMemberDefn.AutoProperty (attrs, _, _, typeOpt, _, _, _, _, synExpr, _, range) -> [ yield mkNode SynMemberDefn_AutoProperty range - yield! (visitSynAttributeLists range attrs) + yield! (visitSynAttributeLists attrs) if typeOpt.IsSome then yield! visitSynType typeOpt.Value yield! visitSynExpr synExpr ] @@ -732,7 +740,7 @@ module private Ast = (fun nodes -> [ yield mkNode SynSimplePat_Attrib range yield! nodes - yield! (visitSynAttributeLists range attrs) ] + yield! (visitSynAttributeLists attrs) ] |> continuation) visit sp id @@ -757,15 +765,23 @@ module private Ast = and visitSynBinding (binding: SynBinding) : TriviaNodeAssigner list = match binding with - | Binding (_, kind, _, _, attrs, _, valData, headPat, returnInfo, expr, range, _) -> + | SynBinding (_, kind, _, _, attrs, _, valData, headPat, returnInfo, expr, _range, _) -> let t = match kind with - | SynBindingKind.StandaloneExpression -> StandaloneExpression_ - | SynBindingKind.NormalBinding -> NormalBinding_ - | SynBindingKind.DoBinding -> DoBinding_ + | SynBindingKind.StandaloneExpression -> SynBindingKind_StandaloneExpression + | SynBindingKind.Normal -> SynBindingKind_Normal + | SynBindingKind.Do -> SynBindingKind_Do + + let afterAttributesBeforeHeadPattern = + match binding.AfterAttributesBeforeHeadPattern with + | Some r -> + mkNode SynBinding_AfterAttributes_BeforeHeadPattern r + |> List.singleton + | None -> [] - [ yield mkNode t binding.RangeOfBindingAndRhs - yield! visitSynAttributeLists range attrs + [ yield mkNode t binding.RangeOfBindingWithRhs + yield! visitSynAttributeLists attrs + yield! afterAttributesBeforeHeadPattern yield! visitSynValData valData yield! visitSynPat headPat yield! @@ -780,10 +796,10 @@ module private Ast = and visitSynValSig (svs: SynValSig) : TriviaNodeAssigner list = match svs with - | ValSpfn (attrs, ident, explicitValDecls, synType, arity, _, _, _, _, expr, range) -> - [ yield mkNode ValSpfn_ range + | SynValSig (attrs, ident, explicitValDecls, synType, arity, _, _, _, _, expr, range) -> + [ yield mkNode SynValSig_ range yield visitIdent ident - yield! (visitSynAttributeLists range attrs) + yield! (visitSynAttributeLists attrs) yield! visitSynValTyparDecls explicitValDecls yield! visitSynType synType yield! visitSynValInfo arity @@ -792,29 +808,19 @@ module private Ast = and visitSynValTyparDecls (valTypeDecl: SynValTyparDecls) : TriviaNodeAssigner list = match valTypeDecl with - | SynValTyparDecls (typardecls, _, _) -> List.collect visitSynTyparDecl typardecls + | SynValTyparDecls (Some typardecl, _) -> visitSynTyparDecls typardecl + | _ -> [] and visitSynTyparDecl (std: SynTyparDecl) : TriviaNodeAssigner list = match std with - | TyparDecl (attrs, typar) -> - [ yield! (visitSynAttributeLists typar.Range attrs) - yield! visitSynTypar typar ] - - and visitSynTypar (typar: SynTypar) : TriviaNodeAssigner list = - match typar with - | Typar _ -> [] - - and visitTyparStaticReq (tsr: TyparStaticReq) = - match tsr with - | NoStaticReq -> "NoStaticReq" - | HeadTypeStaticReq -> "HeadTypeStaticReq" + | SynTyparDecl (attrs, _) -> [ yield! (visitSynAttributeLists attrs) ] and visitSynBindingReturnInfo (returnInfo: SynBindingReturnInfo) : TriviaNodeAssigner list = match returnInfo with | SynBindingReturnInfo (typeName, range, attrs) -> [ yield mkNode SynBindingReturnInfo_ range yield! visitSynType typeName - yield! (visitSynAttributeLists range attrs) ] + yield! (visitSynAttributeLists attrs) ] and visitSynPat (sp: SynPat) : TriviaNodeAssigner list = let rec visit @@ -829,12 +835,19 @@ module private Ast = mkNode SynPat_Wild range |> List.singleton |> finalContinuation - | SynPat.Named (synPat, _, _, _, range) -> - visit - synPat - (fun nodes -> - mkNode SynPat_Named range :: nodes - |> finalContinuation) + | SynPat.Named (ident, _, _, range) -> + [ mkNode SynPat_Named range + visitIdent ident ] + |> finalContinuation + | SynPat.As (synPat, synPat2, range) -> + let continuations: ((TriviaNodeAssigner list -> TriviaNodeAssigner list) -> TriviaNodeAssigner list) list = + [ visit synPat; visit synPat2 ] + + let finalContinuation (nodes: TriviaNodeAssigner list list) : TriviaNodeAssigner list = + mkNode SynPat_As range :: (List.collect id nodes) + |> finalContinuation + + Continuation.sequence continuations finalContinuation | SynPat.Typed (synPat, synType, range) -> visit synPat @@ -848,7 +861,7 @@ module private Ast = (fun nodes -> [ yield mkNode SynPat_Attrib range yield! nodes - yield! (visitSynAttributeLists range attrs) ] + yield! (visitSynAttributeLists attrs) ] |> finalContinuation) | SynPat.Or (synPat, synPat2, _range) -> let continuations: ((TriviaNodeAssigner list -> TriviaNodeAssigner list) -> TriviaNodeAssigner list) list = @@ -943,17 +956,31 @@ module private Ast = and visitSynConstructorArgs (ctorArgs: SynArgPats) : TriviaNodeAssigner list = match ctorArgs with - | Pats pats -> List.collect visitSynPat pats - | NamePatPairs (pats, range) -> - mkNode NamePatPairs_ range + | SynArgPats.Pats pats -> List.collect visitSynPat pats + | SynArgPats.NamePatPairs (pats, range) -> + mkNode SynArgPats_NamePatPairs range :: (List.collect (snd >> visitSynPat) pats) and visitSynComponentInfo (sci: SynComponentInfo) : TriviaNodeAssigner list = match sci with - | ComponentInfo (attribs, typeParams, _, _, _, _, _, range) -> - [ yield mkNode ComponentInfo_ range - yield! (visitSynAttributeLists range attribs) - yield! (typeParams |> List.collect visitSynTyparDecl) ] + | SynComponentInfo (attribs, typeParams, _, _, _, _, _, range) -> + [ yield mkNode SynComponentInfo_ range + yield! (visitSynAttributeLists attribs) + yield! + (Option.map visitSynTyparDecls typeParams + |> Option.defaultValue []) ] + + and visitSynTyparDecls (decls: SynTyparDecls) : TriviaNodeAssigner list = + match decls with + | SynTyparDecls.PostfixList (decls, _constraints, range) -> + [ yield mkNode SynTyparDecls_PostfixList range + yield! (List.collect visitSynTyparDecl decls) ] + | SynTyparDecls.PrefixList (decls, range) -> + [ yield mkNode SynTyparDecls_PrefixList range + yield! (List.collect visitSynTyparDecl decls) ] + | SynTyparDecls.SinglePrefix (decl, range) -> + [ yield mkNode SynTyparDecls_SinglePrefix range + yield! (visitSynTyparDecl decl) ] and visitSynTypeDefnRepr (stdr: SynTypeDefnRepr) : TriviaNodeAssigner list = match stdr with @@ -965,17 +992,17 @@ module private Ast = and visitSynTypeDefnKind (kind: SynTypeDefnKind) : TriviaNodeAssigner list = match kind with - | TyconUnspecified - | TyconClass - | TyconInterface - | TyconStruct - | TyconRecord - | TyconAbbrev - | TyconHiddenRepr - | TyconAugmentation - | TyconUnion - | TyconILAssemblyCode -> [] - | TyconDelegate (typ, valinfo) -> visitSynType typ @ visitSynValInfo valinfo + | SynTypeDefnKind.Unspecified + | SynTypeDefnKind.Class + | SynTypeDefnKind.Interface + | SynTypeDefnKind.Struct + | SynTypeDefnKind.Record + | SynTypeDefnKind.Abbrev + | SynTypeDefnKind.Opaque + | SynTypeDefnKind.Augmentation + | SynTypeDefnKind.Union + | SynTypeDefnKind.IL -> [] + | SynTypeDefnKind.Delegate (typ, valinfo) -> visitSynType typ @ visitSynValInfo valinfo and visitSynTypeDefnSimpleRepr (arg: SynTypeDefnSimpleRepr) = match arg with @@ -1013,59 +1040,64 @@ module private Ast = match sedr with | SynExceptionDefnRepr (attrs, unionCase, _, _, _, range) -> [ yield mkNode SynExceptionDefnRepr_ range - yield! (visitSynAttributeLists range attrs) + yield! (visitSynAttributeLists attrs) yield! visitSynUnionCase unionCase ] and visitSynAttribute (attr: SynAttribute) : TriviaNodeAssigner list = mkNode SynAttribute_ attr.Range :: (visitSynExpr attr.ArgExpr) - and visitSynAttributeLists (parentRange: Range) (attrs: SynAttributeList list) : TriviaNodeAssigner list = - match attrs with - | [ h ] -> visitSynAttributeList parentRange h - | _ :: tail -> - let aRanges = - tail - |> List.map (fun a -> a.Range) - |> fun r -> r @ [ parentRange ] - - List.zip attrs aRanges - |> List.collect (fun (a, r) -> visitSynAttributeList r a) - | [] -> [] - - and visitSynAttributeList (parentRange: Range) (attrs: SynAttributeList) : TriviaNodeAssigner list = - TriviaNodeAssigner(MainNode(SynAttributeList_), attrs.Range, parentRange.StartLine - attrs.Range.EndLine - 1) + and visitSynAttributeLists (attrs: SynAttributeList list) : TriviaNodeAssigner list = + List.collect visitSynAttributeList attrs + // match attrs with +// | [ h ] -> visitSynAttributeList h +// | _ :: tail -> +// let aRanges = +// tail +// |> List.map (fun a -> a.Range) +// |> fun r -> r @ [ parentRange ] +// +// List.zip attrs aRanges +// |> List.collect (fun (a, r) -> visitSynAttributeList r a) +// | [] -> [] + + and visitSynAttributeList (attrs: SynAttributeList) : TriviaNodeAssigner list = + TriviaNodeAssigner(MainNode(SynAttributeList_), attrs.Range) :: (List.collect visitSynAttribute attrs.Attributes) and visitSynUnionCase (uc: SynUnionCase) : TriviaNodeAssigner list = match uc with - | UnionCase (attrs, _, uct, _, _, range) -> - [ yield mkNode UnionCase_ range + | SynUnionCase (attrs, _, uct, _, _, range) -> + [ yield mkNode SynUnionCase_ range yield! visitSynUnionCaseType uct - yield! (visitSynAttributeLists range attrs) ] + yield! (visitSynAttributeLists attrs) ] - and visitSynUnionCaseType (uct: SynUnionCaseType) = + and visitSynUnionCaseType (uct: SynUnionCaseKind) = match uct with - | UnionCaseFields cases -> List.collect visitSynField cases - | UnionCaseFullType (stype, valInfo) -> visitSynType stype @ visitSynValInfo valInfo + | SynUnionCaseKind.Fields fields -> List.collect visitSynField fields + | SynUnionCaseKind.FullType (stype, valInfo) -> visitSynType stype @ visitSynValInfo valInfo and visitSynEnumCase (sec: SynEnumCase) : TriviaNodeAssigner list = match sec with - | EnumCase (attrs, ident, value, _, range) -> - [ yield mkNode EnumCase_ range - yield! (visitSynAttributeLists range attrs) + | SynEnumCase (attrs, ident, value, _, _, range) -> + [ yield mkNode SynEnumCase_ range + yield! (visitSynAttributeLists attrs) yield visitIdent ident yield visitSynConst range value ] and visitSynField (sfield: SynField) : TriviaNodeAssigner list = match sfield with - | Field (attrs, _, ident, typ, _, _, _, range) -> - let parentRange = - Option.map (fun (i: Ident) -> i.idRange) ident - |> Option.defaultValue range + | SynField (attrs, _, _ident, typ, _, _, _, range) -> + let afterAttributesBeforeIdentifier = + match sfield.AfterAttributesBeforeIdentifier with + | None -> [] + | Some r -> + mkNode SynField_AfterAttributesBeforeIdentifier r + |> List.singleton - [ yield mkNode Field_ range - yield! (visitSynAttributeLists parentRange attrs) + [ yield mkNode SynField_ range + yield! (visitSynAttributeLists attrs) + yield! afterAttributesBeforeIdentifier yield! visitSynType typ ] and visitSynType (st: SynType) = @@ -1123,9 +1155,9 @@ module private Ast = |> finalContinuation Continuation.sequence continuations finalContinuation - | SynType.Var (genericName, range) -> + | SynType.Var (_, range) -> mkNode SynType_Var range - :: (visitSynTypar genericName) + |> List.singleton |> finalContinuation | SynType.Anon range -> mkNode SynType_Anon range @@ -1216,12 +1248,11 @@ module private Ast = | SynConst.Bytes _ -> SynConst_Bytes | SynConst.UInt16s _ -> SynConst_UInt16s | SynConst.Measure _ -> SynConst_Measure + | SynConst.SourceIdentifier _ -> SynConst_SourceIdentifier match sc with - | SynConst.Measure (n, SynMeasure.Seq (_, mr)) -> - let numberRange = - Range.mkRange mr.FileName parentRange.Start (Pos.mkPos mr.StartLine (mr.StartColumn - 1)) - + | SynConst.Measure (n, numberRange, _) -> + // TODO: take constant range into account mkNode (t n) numberRange | _ -> mkNode (t sc) (sc.Range parentRange) @@ -1233,13 +1264,7 @@ module private Ast = and visitSynArgInfo (sai: SynArgInfo) : TriviaNodeAssigner list = match sai with - | SynArgInfo (attrs, _, ident) -> - let parentRange = - ident - |> Option.map (fun i -> i.idRange) - |> Option.defaultValue range.Zero - - visitSynAttributeLists parentRange attrs + | SynArgInfo (attrs, _, _ident) -> visitSynAttributeLists attrs and visitParsedHashDirective (hash: ParsedHashDirective) : TriviaNodeAssigner = match hash with @@ -1247,14 +1272,14 @@ module private Ast = and visitSynModuleOrNamespaceSig (modOrNs: SynModuleOrNamespaceSig) : TriviaNodeAssigner list = match modOrNs with - | SynModuleOrNamespaceSig (longIdent, _, kind, decls, _, attrs, _, range) -> + | SynModuleOrNamespaceSig (longIdent, _, kind, decls, _, attrs, _, _range) -> let longIdentNodes = match kind, decls with | SynModuleOrNamespaceKind.AnonModule, _ :: _ -> [] | _ -> visitLongIdentIncludingFullRange longIdent [ yield! longIdentNodes - yield! (visitSynAttributeLists range attrs) + yield! (visitSynAttributeLists attrs) yield! (decls |> List.collect visitSynModuleSigDecl) ] and visitSynModuleSigDecl (ast: SynModuleSigDecl) : TriviaNodeAssigner list = @@ -1278,7 +1303,7 @@ module private Ast = |> finalContinuation Continuation.sequence continuations finalContinuation - | SynModuleSigDecl.Val (SynValSig.ValSpfn _ as node, _) -> visitSynValSig node |> finalContinuation + | SynModuleSigDecl.Val (SynValSig.SynValSig _ as node, _) -> visitSynValSig node |> finalContinuation | SynModuleSigDecl.Types (typeDefs, range) -> mkNode SynModuleSigDecl_Types range :: (List.collect visitSynTypeDefnSig typeDefs) diff --git a/src/Fantomas/CodeFormatter.fsi b/src/Fantomas/CodeFormatter.fsi index d24750815c..26201ff885 100644 --- a/src/Fantomas/CodeFormatter.fsi +++ b/src/Fantomas/CodeFormatter.fsi @@ -3,8 +3,8 @@ namespace Fantomas open Fantomas.FormatConfig open Fantomas.SourceOrigin open FSharp.Compiler.Text -open FSharp.Compiler.SourceCodeServices -open FSharp.Compiler.SyntaxTree +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.Syntax [] type CodeFormatter = diff --git a/src/Fantomas/CodeFormatterImpl.fs b/src/Fantomas/CodeFormatterImpl.fs index 4ecb7f7d19..e339692dae 100644 --- a/src/Fantomas/CodeFormatterImpl.fs +++ b/src/Fantomas/CodeFormatterImpl.fs @@ -4,11 +4,13 @@ module Fantomas.CodeFormatterImpl open System open System.Diagnostics open System.Text.RegularExpressions -open FSharp.Compiler.Text.Range -open FSharp.Compiler.Text.Pos -open FSharp.Compiler.SourceCodeServices -open FSharp.Compiler.SyntaxTree +open FSharp.Compiler.CodeAnalysis +open FSharp.Compiler.Diagnostics +open FSharp.Compiler.Syntax open FSharp.Compiler.Text +open FSharp.Compiler.Text.Position +open FSharp.Compiler.Text.Range +open FSharp.Compiler.Tokenization open Fantomas open Fantomas.FormatConfig open Fantomas.SourceOrigin @@ -74,7 +76,7 @@ let parse (checker: FSharpChecker) (parsingOptions: FSharpParsingOptions) { File if untypedRes.ParseHadErrors then let errors = - untypedRes.Errors + untypedRes.Diagnostics |> Array.filter (fun e -> e.Severity = FSharpDiagnosticSeverity.Error) if not <| Array.isEmpty errors then @@ -83,14 +85,7 @@ let parse (checker: FSharpChecker) (parsingOptions: FSharpParsingOptions) { File sprintf "Parsing failed with errors: %A\nAnd options: %A" errors parsingOptionsWithDefines ) - let tree = - match untypedRes.ParseTree with - | Some tree -> tree - | None -> - raise - <| FormatException "Parsing failed. Please select a complete code fragment to format." - - return (tree, conditionalCompilationDefines, defineHashTokens) + return (untypedRes.ParseTree, conditionalCompilationDefines, defineHashTokens) }) |> Async.Parallel @@ -103,7 +98,7 @@ let isValidAST ast = let (|IndexerArgList|) xs = List.collect (|IndexerArg|) xs - let rec validateImplFileInput (ParsedImplFileInput (_, moduleOrNamespaceList)) = + let rec validateImplFileInput (SourceParser.ParsedImplFileInput (_, moduleOrNamespaceList)) = List.forall validateModuleOrNamespace moduleOrNamespaceList and validateModuleOrNamespace (SynModuleOrNamespace (decls = decls)) = List.forall validateModuleDecl decls @@ -123,7 +118,7 @@ let isValidAST ast = | SynModuleDecl.HashDirective _ | SynModuleDecl.Open _ -> true - and validateTypeDefn (TypeDefn (_componentInfo, representation, members, _range)) = + and validateTypeDefn (SynTypeDefn (_componentInfo, representation, members, _implicitConstructor, _range)) = validateTypeDefnRepr representation && List.forall validateMemberDefn members @@ -168,18 +163,18 @@ let isValidAST ast = | SynMemberDefn.ImplicitInherit (_, expr, _, _) -> validateExpr expr and validateBinding - (Binding (_access, - _bindingKind, - _isInline, - _isMutable, - _attrs, - _xmldoc, - _valData, - headPat, - _retTy, - expr, - _bindingRange, - _seqPoint)) + (SynBinding (_access, + _bindingKind, + _isInline, + _isMutable, + _attrs, + _xmldoc, + _valData, + headPat, + _retTy, + expr, + _bindingRange, + _seqPoint)) = validateExpr expr && validatePattern headPat @@ -321,7 +316,7 @@ let isValidAST ast = | SynExpr.FromParseError (_synExpr, _range) | SynExpr.DiscardAfterMissingQualificationAfterDot (_synExpr, _range) -> false | SynExpr.Fixed _ -> true - | SynExpr.InterpolatedString (parts, _) -> + | SynExpr.InterpolatedString (parts, _, _) -> parts |> List.forall (function @@ -333,7 +328,8 @@ let isValidAST ast = | SynPat.Const (_const, _range) -> true | SynPat.Wild _ | SynPat.Null _ -> true - | SynPat.Named (pat, _ident, _isThis, _accessOpt, _range) -> validatePattern pat + | SynPat.Named (_ident, _isThis, _accessOpt, _range) -> true + | SynPat.As (pat1, pat2, _) -> validatePattern pat1 && validatePattern pat2 | SynPat.Typed (pat, _typ, _range) -> validatePattern pat | SynPat.Attrib (pat, _attrib, _range) -> validatePattern pat | SynPat.Or (pat1, pat2, _range) -> validatePattern pat1 && validatePattern pat2 @@ -563,7 +559,7 @@ let private formatRange let sel = sourceCode.[start..finish].TrimEnd('\r') if startWithMember sel then - (String.Join(String.Empty, "type T = ", Environment.NewLine, String(' ', startCol), sel), TypeMember) + (String.Join(String.Empty, "type T = ", Environment.NewLine, System.String(' ', startCol), sel), TypeMember) elif String.startsWithOrdinal "and" (sel.TrimStart()) then let p = getPatch startCol lines.[..startLine - 1] @@ -579,13 +575,13 @@ let private formatRange if startLine = endLine then (pattern.Replace(sel, replacement, 1), p) else - (String(' ', startCol) + (System.String(' ', startCol) + pattern.Replace(sel, replacement, 1), p) elif startLine = endLine then (sel, Nothing) else - (String(' ', startCol) + sel, Nothing) + (System.String(' ', startCol) + sel, Nothing) let post = if finish < sourceCode.Length then diff --git a/src/Fantomas/CodePrinter.fs b/src/Fantomas/CodePrinter.fs index db2d45d824..86d4de46fb 100644 --- a/src/Fantomas/CodePrinter.fs +++ b/src/Fantomas/CodePrinter.fs @@ -3,8 +3,8 @@ module internal Fantomas.CodePrinter open System open System.Text.RegularExpressions open FSharp.Compiler.Text -open FSharp.Compiler.SourceCodeServices -open FSharp.Compiler.SyntaxTree +open FSharp.Compiler.Syntax +open FSharp.Compiler.Xml open Fantomas open Fantomas.FormatConfig open Fantomas.SourceParser @@ -85,29 +85,25 @@ and genSigFile astContext (ParsedSigFileInput (hs, mns)) = +> (if hs.IsEmpty then sepNone else sepNln) +> col sepNln mns (genSigModuleOrNamespace astContext) -and genParsedHashDirective (ParsedHashDirective (h, s, r)) = - let printArgument arg = +and genParsedHashDirective (ParsedHashDirective (h, args, r)) = + let genArg (arg: ParsedHashDirectiveArgument) = match arg with - | "" -> sepNone - // Use verbatim string to escape '\' correctly - | _ when arg.Contains("\\") -> !-(sprintf "@\"%O\"" arg) - | _ -> !-(sprintf "\"%O\"" arg) - - let printIdent (ctx: Context) = - Map.tryFind ParsedHashDirective_ ctx.TriviaMainNodes - |> Option.defaultValue [] - |> List.tryFind (fun t -> RangeHelpers.rangeEq t.Range r) - |> Option.bind - (fun t -> - match t.ContentItself with - | Some (KeywordString c) -> Some c - | _ -> None) - |> function - | Some kw -> !-kw - | None -> col sepSpace s printArgument - <| ctx - - !- "#" -- h +> sepSpace +> printIdent + | ParsedHashDirectiveArgument.String (value, stringKind, range) -> + let stringStart, stringEnd = + match stringKind with + | SynStringKind.Regular -> "\"", "\"" + | SynStringKind.Verbatim -> "@\"", "\"" + | SynStringKind.TripleQuote -> "\"\"\"", "\"\"\"" + + !-(sprintf "%s%s%s" stringStart value stringEnd) + |> genTriviaFor ParsedHashDirectiveArgument_String range + | ParsedHashDirectiveArgument.SourceIdentifier (identifier, _, range) -> + !-identifier + |> genTriviaFor ParsedHashDirectiveArgument_String range + + !- "#" -- h + +> sepSpace + +> col sepSpace args genArg |> genTriviaFor ParsedHashDirective_ r and genModuleOrNamespaceKind (kind: SynModuleOrNamespaceKind) = @@ -124,11 +120,8 @@ and genModuleOrNamespace astContext (ModuleOrNamespace (ats, px, ao, lids, mds, match firstDecl with | None -> sepNone | Some mdl -> - let attrs = - getRangesFromAttributesFromModuleDeclaration mdl - sepNln - +> sepNlnConsideringTriviaContentBeforeWithAttributesFor (synModuleDeclToFsAstType mdl) mdl.Range attrs + +> sepNlnConsideringTriviaContentBeforeForMainNode (synModuleDeclToFsAstType mdl) mdl.Range let lidsFullRange = match lids with @@ -152,7 +145,7 @@ and genModuleOrNamespace astContext (ModuleOrNamespace (ats, px, ao, lids, mds, genPreXmlDoc px +> genAttributes astContext ats - +> ifElse (moduleKind = AnonModule) genTriviaForAnonModuleIdent moduleOrNamespace + +> ifElse (moduleKind = SynModuleOrNamespaceKind.AnonModule) genTriviaForAnonModuleIdent moduleOrNamespace +> sepModuleAndFirstDecl +> genModuleDeclList astContext mds @@ -165,11 +158,8 @@ and genSigModuleOrNamespace astContext (SigModuleOrNamespace (ats, px, ao, lids, | Some mdl -> match mdl with | SynModuleSigDecl.Types _ -> - let attrs = - getRangesFromAttributesFromSynModuleSigDeclaration mdl - - sepNlnConsideringTriviaContentBeforeWithAttributesFor SynModuleSigDecl_Types mdl.Range attrs - | SynModuleSigDecl.Val _ -> sepNlnConsideringTriviaContentBeforeForMainNode ValSpfn_ mdl.Range + sepNlnConsideringTriviaContentBeforeForMainNode SynModuleSigDecl_Types mdl.Range + | SynModuleSigDecl.Val _ -> sepNlnConsideringTriviaContentBeforeForMainNode SynValSig_ mdl.Range | _ -> sepNone +> sepNln @@ -187,7 +177,7 @@ and genSigModuleOrNamespace astContext (SigModuleOrNamespace (ats, px, ao, lids, genPreXmlDoc px +> genAttributes astContext ats - +> ifElse (moduleKind = AnonModule) sepNone moduleOrNamespace + +> ifElse (moduleKind = SynModuleOrNamespaceKind.AnonModule) sepNone moduleOrNamespace +> sepModuleAndFirstDecl +> genSigModuleDeclList astContext mds @@ -227,12 +217,9 @@ and genModuleDeclList astContext e = |> finalContinuation) | AttributesL (xs, y :: rest) -> - let attrs = - getRangesFromAttributesFromModuleDeclaration y - let expr = col sepNln xs (genModuleDecl astContext) - +> sepNlnConsideringTriviaContentBeforeWithAttributesFor (synModuleDeclToFsAstType y) y.Range attrs + +> sepNlnConsideringTriviaContentBeforeForMainNode (synModuleDeclToFsAstType y) y.Range +> genModuleDecl astContext y let r = List.head xs |> fun mdl -> mdl.Range @@ -247,11 +234,8 @@ and genModuleDeclList astContext e = |> finalContinuation) | m :: rest -> - let attrs = - getRangesFromAttributesFromModuleDeclaration m - let sepNln = - sepNlnConsideringTriviaContentBeforeWithAttributesFor (synModuleDeclToFsAstType m) m.Range attrs + sepNlnConsideringTriviaContentBeforeForMainNode (synModuleDeclToFsAstType m) m.Range let expr = genModuleDecl astContext m @@ -285,11 +269,8 @@ and genSigModuleDeclList astContext (e: SynModuleSigDecl list) = ColMultilineItem(expr, sepNln) :: ysItems |> finalContinuation) | s :: rest -> - let attrs = - getRangesFromAttributesFromSynModuleSigDeclaration s - let sepNln = - sepNlnConsideringTriviaContentBeforeWithAttributesFor (synModuleSigDeclToFsAstType s) s.Range attrs + sepNlnConsideringTriviaContentBeforeForMainNode (synModuleSigDeclToFsAstType s) s.Range let expr = genSigModuleDecl astContext s @@ -363,7 +344,7 @@ and genModuleDecl astContext (node: SynModuleDecl) = let sepBAndBs = match List.tryHead bs with | Some b' -> - let r = b'.RangeOfBindingAndRhs + let r = b'.RangeOfBindingWithRhs sepNln +> sepNlnConsideringTriviaContentBeforeForMainNode (synBindingToFsAstType b) r @@ -373,13 +354,13 @@ and genModuleDecl astContext (node: SynModuleDecl) = +> sepBAndBs +> colEx (fun (b': SynBinding) -> - let r = b'.RangeOfBindingAndRhs + let r = b'.RangeOfBindingWithRhs sepNln +> sepNlnConsideringTriviaContentBeforeForMainNode (synBindingToFsAstType b) r) bs (fun andBinding -> - enterNodeFor (synBindingToFsAstType b) andBinding.RangeOfBindingAndRhs + enterNodeFor (synBindingToFsAstType b) andBinding.RangeOfBindingWithRhs +> genLetBinding { astContext with IsFirstChild = false } "and " andBinding) | ModuleAbbrev (s1, s2) -> !- "module " -- s1 +> sepEq +> sepSpace -- s2 @@ -407,7 +388,7 @@ and genModuleDecl astContext (node: SynModuleDecl) = (fun t -> ColMultilineItem( genTypeDefn { astContext with IsFirstChild = false } t, - sepNlnConsideringTriviaContentBeforeForMainNode TypeDefn_ t.Range + sepNlnConsideringTriviaContentBeforeForMainNode SynTypeDefn_ t.Range )) ts) @@ -439,15 +420,9 @@ and genSigModuleDecl astContext node = let items = ColMultilineItem(genSigTypeDefn { astContext with IsFirstChild = true } t, sepNone) :: (List.map - (fun t -> + (fun (t: SynTypeDefnSig) -> let sepNln = - let attributeRanges = - getRangesFromAttributesFromSynTypeDefnSig t - - sepNlnConsideringTriviaContentBeforeWithAttributesFor - TypeDefnSig_ - t.FullRange - attributeRanges + sepNlnConsideringTriviaContentBeforeForMainNode SynTypeDefnSig_ t.Range ColMultilineItem(genSigTypeDefn { astContext with IsFirstChild = false } t, sepNln)) ts) @@ -510,7 +485,9 @@ and genAttributesCore astContext (ats: SynAttribute seq) = ifElse (Seq.isEmpty ats) sepNone (expressionFitsOnRestOfLine shortExpression longExpression) and genOnelinerAttributes astContext ats = - let ats = List.collect (fun a -> a.Attributes) ats + let ats = + List.collect (fun (a: SynAttributeList) -> a.Attributes) ats + ifElse (Seq.isEmpty ats) sepNone (genAttributesCore astContext ats +> sepSpace) /// Try to group attributes if they are on the same line @@ -564,8 +541,8 @@ and genTyparList astContext tps = +> col wordOr tps (genTypar astContext) +> sepCloseT) -and genTypeAndParam astContext typeName tds tcs preferPostfix = - let types openSep closeSep = +and genTypeAndParam astContext typeName (tds: SynTyparDecls option) tcs = + let types openSep tds tcs closeSep = (!-openSep +> coli sepComma @@ -577,23 +554,33 @@ and genTypeAndParam astContext typeName tds tcs preferPostfix = +> colPre (!- " when ") wordAnd tcs (genTypeConstraint astContext) -- closeSep) - if List.isEmpty tds then - !-typeName - elif preferPostfix then - !-typeName +> types "<" ">" - elif List.atMostOne tds then + match tds with + | None -> !-typeName + | Some (SynTyparDecls.PostfixList (tds, tcs, _range)) -> !-typeName +> types "<" tds tcs ">" + | Some (SynTyparDecls.PrefixList (tds, _range)) -> types "(" tds [] ")" -- " " -- typeName + | Some (SynTyparDecls.SinglePrefix (td, _range)) -> genTyparDecl { astContext with IsFirstTypeParam = true } - (List.head tds) + td +> sepSpace -- typeName +> colPre (!- " when ") wordAnd tcs (genTypeConstraint astContext) - else - types "(" ")" -- " " -- typeName -and genTypeParamPostfix astContext tds tcs = - genTypeAndParam astContext "" tds tcs true +and genTypeParamPostfix astContext tds = + match tds with + | Some (SynTyparDecls.PostfixList (tds, tcs, _range)) -> + (!- "<" + +> coli + sepComma + tds + (fun i -> + genTyparDecl + { astContext with + IsFirstTypeParam = i = 0 }) + +> colPre (!- " when ") wordAnd tcs (genTypeConstraint astContext) + -- ">") + | _ -> sepNone and genLetBinding astContext pref b = let genPref = !-pref @@ -607,6 +594,7 @@ and genLetBinding astContext pref b = false px ats + b.AfterAttributesBeforeHeadPattern genPref ao isInline @@ -619,11 +607,48 @@ and genLetBinding astContext pref b = valInfo e | e, PatLongIdent (ao, s, ps, tpso) when (List.isNotEmpty ps) -> - genSynBindingFunction astContext false px ats genPref ao isInline isMutable s p.Range ps tpso e + genSynBindingFunction + astContext + false + px + ats + b.AfterAttributesBeforeHeadPattern + genPref + ao + isInline + isMutable + s + p.Range + ps + tpso + e | TypedExpr (Typed, e, t), pat -> - genSynBindingValue astContext px ats genPref ao isInline isMutable pat (Some t) e + genSynBindingValue + astContext + px + ats + b.AfterAttributesBeforeHeadPattern + genPref + ao + isInline + isMutable + pat + (Some t) + e | _, PatTuple _ -> genLetBindingDestructedTuple astContext px ats pref ao isInline isMutable p e - | _, pat -> genSynBindingValue astContext px ats genPref ao isInline isMutable pat None e + | _, pat -> + genSynBindingValue + astContext + px + ats + b.AfterAttributesBeforeHeadPattern + genPref + ao + isInline + isMutable + pat + None + e | _ -> sepNone | DoBinding (ats, px, e) -> let prefix = @@ -637,7 +662,7 @@ and genLetBinding astContext pref b = +> autoIndentAndNlnIfExpressionExceedsPageWidth (genExpr astContext e) | b -> failwithf "%O isn't a let binding" b - +> leaveNodeFor (synBindingToFsAstType b) b.RangeOfBindingAndRhs + +> leaveNodeFor (synBindingToFsAstType b) b.RangeOfBindingWithRhs and genProperty astContext prefix ao propertyKind ps e = let tuplerize ps = @@ -707,7 +732,7 @@ and genMemberBindingList astContext node = | [] -> finalContinuation [] | mb :: rest -> let expr = genMemberBinding astContext mb - let r = mb.RangeOfBindingAndRhs + let r = mb.RangeOfBindingWithRhs let sepNln = sepNlnConsideringTriviaContentBeforeForMainNode (synBindingToFsAstType mb) r @@ -758,7 +783,7 @@ and genMemberBinding astContext b = | MemberBinding (ats, px, ao, isInline, mf, p, e, synValInfo) -> let prefix = - genMemberFlagsForMemberBinding astContext mf b.RangeOfBindingAndRhs + genMemberFlagsForMemberBinding astContext mf b.RangeOfBindingWithRhs match e, p with | TypedExpr (Typed, e, t), PatLongIdent (ao, s, ps, tpso) when (List.isNotEmpty ps) -> @@ -767,6 +792,7 @@ and genMemberBinding astContext b = true px ats + b.AfterAttributesBeforeHeadPattern prefix ao isInline @@ -779,9 +805,36 @@ and genMemberBinding astContext b = synValInfo e | e, PatLongIdent (ao, s, ps, tpso) when (List.isNotEmpty ps) -> - genSynBindingFunction astContext true px ats prefix ao isInline false s p.Range ps tpso e - | TypedExpr (Typed, e, t), pat -> genSynBindingValue astContext px ats prefix ao isInline false pat (Some t) e - | _, pat -> genSynBindingValue astContext px ats prefix ao isInline false pat None e + genSynBindingFunction + astContext + true + px + ats + b.AfterAttributesBeforeHeadPattern + prefix + ao + isInline + false + s + p.Range + ps + tpso + e + | TypedExpr (Typed, e, t), pat -> + genSynBindingValue + astContext + px + ats + b.AfterAttributesBeforeHeadPattern + prefix + ao + isInline + false + pat + (Some t) + e + | _, pat -> + genSynBindingValue astContext px ats b.AfterAttributesBeforeHeadPattern prefix ao isInline false pat None e | ExplicitCtor (ats, px, ao, p, e, so) -> let prefix = @@ -819,16 +872,16 @@ and genMemberBinding astContext b = +> sepSpaceOrIndentAndNlnIfExpressionExceedsPageWidth (genExpr astContext e) | b -> failwithf "%O isn't a member binding" b - |> genTriviaFor (synBindingToFsAstType b) b.RangeOfBindingAndRhs + |> genTriviaFor (synBindingToFsAstType b) b.RangeOfBindingWithRhs -and genMemberFlags astContext (mf: MemberFlags) = +and genMemberFlags astContext (mf: SynMemberFlags) = match mf with | MFMember _ -> !- "member " | MFStaticMember _ -> !- "static member " | MFConstructor _ -> sepNone | MFOverride _ -> ifElse astContext.InterfaceRange.IsSome (!- "member ") (!- "override ") -and genMemberFlagsForMemberBinding astContext (mf: MemberFlags) (rangeOfBindingAndRhs: Range) = +and genMemberFlagsForMemberBinding astContext (mf: SynMemberFlags) (rangeOfBindingAndRhs: Range) = fun ctx -> let keywordFromTrivia = [ yield! (Map.tryFindOrEmptyList SynMemberDefn_Member ctx.TriviaMainNodes) @@ -866,15 +919,8 @@ and genMemberFlagsForMemberBinding astContext (mf: MemberFlags) (rangeOfBindingA |> Option.defaultValue (!- "override ") <| ctx -and genVal astContext (Val (ats, px, ao, s, identRange, t, vi, isInline, _) as node) = - let range, synValTyparDecls = - match node with - | ValSpfn (_, _, synValTyparDecls, _, _, _, _, _, _, _, range) -> range, synValTyparDecls - - let genericParams = - match synValTyparDecls with - | SynValTyparDecls ([], _, _) -> sepNone - | SynValTyparDecls (tpd, _, cst) -> genTypeParamPostfix astContext tpd cst +and genVal astContext (Val (ats, px, ao, s, identRange, t, vi, isInline, tds, range)) = + let typeName = genTypeAndParam astContext s tds [] let (FunType namedArgs) = (t, vi) @@ -883,15 +929,14 @@ and genVal astContext (Val (ats, px, ao, s, identRange, t, vi, isInline, _) as n +> (!- "val " +> onlyIf isInline (!- "inline ") +> opt sepSpace ao genAccess - -- s - +> genericParams + +> typeName |> genTriviaFor Ident_ identRange) +> sepColonWithSpacesFixed +> ifElse (List.isNotEmpty namedArgs) (autoIndentAndNlnIfExpressionExceedsPageWidth (genTypeList astContext namedArgs)) (genConstraints astContext t vi) - |> genTriviaFor ValSpfn_ range + |> genTriviaFor SynValSig_ range and genRecordFieldName astContext (RecordFieldName (s, eo) as node) = let rfn, _, _ = node @@ -1404,7 +1449,7 @@ and genExpr astContext synExpr ctx = let genCompExprStatement astContext ces = match ces with | LetOrUseStatement (prefix, binding) -> - enterNodeFor (synBindingToFsAstType binding) binding.RangeOfBindingAndRhs + enterNodeFor (synBindingToFsAstType binding) binding.RangeOfBindingWithRhs +> genLetBinding astContext prefix binding | LetOrUseBangStatement (isUse, pat, expr, r) -> enterNodeFor SynExpr_LetOrUseBang r // print Trivia before entire LetBang expression @@ -1422,7 +1467,7 @@ and genExpr astContext synExpr ctx = let getRangeOfCompExprStatement ces = match ces with - | LetOrUseStatement (_, binding) -> binding.RangeOfBindingAndRhs + | LetOrUseStatement (_, binding) -> binding.RangeOfBindingWithRhs | LetOrUseBangStatement (_, _, _, r) -> r | AndBangStatement (_, _, r) -> r | OtherStatement expr -> expr.Range @@ -2372,7 +2417,8 @@ and genExpr astContext synExpr ctx = r.EndLine (r.EndColumn + 1) ) - | SynExpr.InterpolatedString (parts, _) -> + | SynExpr.InterpolatedString (parts, _stringKind, _) -> + // TODO: string kind fun (ctx: Context) -> let stringRanges = List.choose @@ -3360,7 +3406,7 @@ and collectMultilineItemForLetOrUses // https://github.com/dotnet/fsharp/issues/10198 let bindingHasInKeyword (binding: SynBinding) : bool = let inRange = - Range.mkRange binding.RangeOfBindingAndRhs.FileName binding.RangeOfBindingAndRhs.End e.Range.Start + Range.mkRange binding.RangeOfBindingWithRhs.FileName binding.RangeOfBindingWithRhs.End e.Range.Start inKeyWordTrivia |> TriviaHelpers.``keyword token after start column and on same line`` inRange @@ -3368,7 +3414,7 @@ and collectMultilineItemForLetOrUses let multilineBinding p x = let expr = - enterNodeFor (synBindingToFsAstType x) x.RangeOfBindingAndRhs + enterNodeFor (synBindingToFsAstType x) x.RangeOfBindingWithRhs +> genLetBinding { astContext with IsFirstChild = p <> "and" } @@ -3376,7 +3422,7 @@ and collectMultilineItemForLetOrUses x +> genInKeyword x e - let range = x.RangeOfBindingAndRhs + let range = x.RangeOfBindingWithRhs let sepNln = sepNlnConsideringTriviaContentBeforeForMainNode (synBindingToFsAstType x) range @@ -3394,7 +3440,7 @@ and collectMultilineItemForLetOrUses // maybe the let binding and expression are short so they form one ColMultilineItem // Something like: let a = 1 in () - let range = b.RangeOfBindingAndRhs + let range = b.RangeOfBindingWithRhs let sepNlnForBinding = sepNlnConsideringTriviaContentBeforeForMainNode (synBindingToFsAstType b) range @@ -3402,7 +3448,7 @@ and collectMultilineItemForLetOrUses if bindingHasInKeyword b then // single multiline item let expr = - enterNodeFor (synBindingToFsAstType b) b.RangeOfBindingAndRhs + enterNodeFor (synBindingToFsAstType b) b.RangeOfBindingWithRhs +> genLetBinding astContext p b +> genInKeyword b e +> expressionFitsOnRestOfLine expr (sepNln +> sepNlnForExpr +> expr) @@ -3415,7 +3461,7 @@ and collectMultilineItemForLetOrUses and genInKeyword (binding: SynBinding) (e: SynExpr) (ctx: Context) = let inKeyWordTrivia (binding: SynBinding) = let inRange = - ctx.MkRange binding.RangeOfBindingAndRhs.End e.Range.Start + ctx.MkRange binding.RangeOfBindingWithRhs.End e.Range.Start Map.tryFindOrEmptyList IN ctx.TriviaTokenNodes |> TriviaHelpers.``keyword token after start column and on same line`` inRange @@ -3449,15 +3495,19 @@ and sepNlnBetweenTypeAndMembers (tdr: SynTypeDefnRepr) (ms: SynMemberDefn list) sepNlnTypeAndMembers tdr.Range.End range mainNodeType | None -> sepNone -and genTypeDefn astContext (TypeDef (ats, px, ao, tds, tcs, tdr, ms, s, preferPostfix) as node) = +and genTypeDefn astContext (TypeDef (ats, px, ao, tds, tcs, tdr, ms, s, _) as node) = let typeName = genPreXmlDoc px +> ifElse astContext.IsFirstChild - (genAttributes astContext ats -- "type ") + (genAttributes astContext ats + +> genAfterAttributesBefore + SynTypeDefn_AfterAttributesBeforeComponentInfo + node.AfterAttributesBeforeComponentInfo + -- "type ") (!- "and " +> genOnelinerAttributes astContext ats) +> opt sepSpace ao genAccess - +> genTypeAndParam astContext s tds tcs preferPostfix + +> genTypeAndParam astContext s tds tcs match tdr with | Simple (TDSREnum ecs) -> @@ -3716,7 +3766,7 @@ and genTypeDefn astContext (TypeDef (ats, px, ao, tds, tcs, tdr, ms, s, preferPo +> unindent | ExceptionRepr (ExceptionDefRepr (ats, px, ao, uc)) -> genExceptionBody astContext ats px ao uc - |> genTriviaFor TypeDefn_ node.Range + |> genTriviaFor SynTypeDefn_ node.Range and genMultilineSimpleRecordTypeDefn tdr ms ao' fs astContext = // the typeName is already printed @@ -3773,7 +3823,7 @@ 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, fullRange)) = +and genSigTypeDefn astContext (SigTypeDef (ats, px, ao, tds, tcs, tdr, ms, s, _, fullRange)) = let genTriviaForOnelinerAttributes f (ctx: Context) = match ats with | [] -> f ctx @@ -3794,7 +3844,7 @@ and genSigTypeDefn astContext (SigTypeDef (ats, px, ao, tds, tcs, tdr, ms, s, pr let typeName = genXmlTypeKeywordAttrsAccess - +> genTypeAndParam astContext s tds tcs preferPostfix + +> genTypeAndParam astContext s tds tcs match tdr with | SigSimple (TDSREnum ecs) -> @@ -3908,13 +3958,13 @@ and genSigTypeDefn astContext (SigTypeDef (ats, px, ao, tds, tcs, tdr, ms, s, pr +> ifElse needsParenthesis sepCloseT sepNone let short = - genTypeAndParam astContext s tds tcs preferPostfix + genTypeAndParam astContext s tds tcs +> sepEq +> sepSpace +> genTypeAbbrev let long = - genTypeAndParam astContext s tds tcs preferPostfix + genTypeAndParam astContext s tds tcs +> sepSpace +> sepEqFixed +> indent @@ -3961,7 +4011,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 + |> genTriviaFor SynTypeDefnSig_ fullRange and genSigSimpleRecord tdr ms ao' fs astContext = // the typeName is already printed @@ -4005,7 +4055,7 @@ and genMemberSig astContext node = | SynMemberSig.NestedType (_, r) -> r, SynMemberSig_NestedType match node with - | MSMember (Val (ats, px, ao, s, _, t, vi, isInline, ValTyparDecls (tds, _, tcs)), mf) -> + | MSMember (Val (ats, px, ao, s, _, t, vi, isInline, tds, _), mf) -> let (FunType namedArgs) = (t, vi) let isFunctionProperty = @@ -4022,8 +4072,7 @@ and genMemberSig astContext node = range +> ifElse isInline (!- "inline ") sepNone +> opt sepSpace ao genAccess - +> ifElse (s = "``new``") (!- "new") (!-s) - +> genTypeParamPostfix astContext tds tcs + +> genTypeAndParam astContext (if s = "``new``" then "new" else s) tds [] +> sepColonWithSpacesFixed +> ifElse (List.isNotEmpty namedArgs) @@ -4081,9 +4130,9 @@ and genTypeDefKind node = | TCSimple TCRecord -> sepNone | TCSimple TCUnion -> sepNone | TCSimple TCAbbrev -> sepNone - | TCSimple TCHiddenRepr -> sepNone + | TCSimple TCOpaque -> sepNone | TCSimple TCAugmentation -> sepNone - | TCSimple TCILAssemblyCode -> sepNone + | TCSimple TCIL -> sepNone | TCDelegate _ -> sepNone and genExceptionBody astContext ats px ao uc = @@ -4128,7 +4177,7 @@ and genUnionCase astContext (hasVerticalBar: bool) (UnionCase (ats, px, _, s, Un +> genOnelinerAttributes astContext ats -- s +> onlyIf (List.isNotEmpty fs) (expressionFitsOnRestOfLine shortExpr longExpr) - |> genTriviaFor UnionCase_ node.Range + |> genTriviaFor SynUnionCase_ node.Range and genEnumCase astContext (EnumCase (ats, px, _, (_, _)) as node) = let genCase (ctx: Context) = @@ -4136,7 +4185,7 @@ and genEnumCase astContext (EnumCase (ats, px, _, (_, _)) as node) = match node with | EnumCase (_, _, identInAST, (c, r)) -> let triviaNode = - Map.tryFindOrEmptyList EnumCase_ ctx.TriviaMainNodes + Map.tryFindOrEmptyList SynEnumCase_ ctx.TriviaMainNodes |> List.tryFind (fun tn -> RangeHelpers.rangeEq tn.Range r) match triviaNode with @@ -4165,20 +4214,21 @@ and genEnumCase astContext (EnumCase (ats, px, _, (_, _)) as node) = and genField astContext prefix (Field (ats, px, ao, isStatic, isMutable, t, so) as node) = let range = match node with - | SynField.Field (_, _, _, _, _, _, _, range) -> range + | SynField (_, _, _, _, _, _, _, range) -> range // Being protective on union case declaration let t = genType astContext astContext.IsUnionField t genPreXmlDoc px +> genAttributes astContext ats + +> genAfterAttributesBefore SynField_AfterAttributesBeforeIdentifier node.AfterAttributesBeforeIdentifier +> ifElse isStatic (!- "static ") sepNone -- prefix +> ifElse isMutable (!- "mutable ") sepNone +> opt sepSpace ao genAccess +> opt sepColon so (!-) +> t - |> genTriviaFor Field_ range + |> genTriviaFor SynField_ range and genType astContext outerBracket t = let rec loop current = @@ -4497,7 +4547,7 @@ and genClause astContext hasBar (Clause (p, e, eo) as ce) = genTriviaBeforeClausePipe p.Range +> (onlyIf hasBar sepBar +> patAndBody - |> genTriviaFor SynMatchClause_Clause ce.Range) + |> genTriviaFor SynMatchClause_ ce.Range) and genClauses astContext cs = col sepNln cs (genClause astContext true) @@ -4511,9 +4561,6 @@ and genMemberDefnList astContext nodes = match nodes with | [] -> finalContinuation [] | PropertyWithGetSetMemberDefn (gs, rest) -> - let attrs = - getRangesFromAttributesFromSynBinding (fst gs) - let rangeOfFirstMember = List.head nodes |> fun m -> m.Range let expr = @@ -4521,7 +4568,7 @@ and genMemberDefnList astContext nodes = +> genPropertyWithGetSet astContext gs (Some rangeOfFirstMember) let sepNln = - sepNlnConsideringTriviaContentBeforeWithAttributesFor SynMemberDefn_Member rangeOfFirstMember attrs + sepNlnConsideringTriviaContentBeforeForMainNode SynMemberDefn_Member rangeOfFirstMember collectItems rest @@ -4529,13 +4576,10 @@ and genMemberDefnList astContext nodes = ColMultilineItem(expr, sepNln) :: restItems |> finalContinuation) | m :: rest -> - let attrs = - getRangesFromAttributesFromSynMemberDefinition m - let expr = genMemberDefn astContext m let sepNln = - sepNlnConsideringTriviaContentBeforeWithAttributesFor (synMemberDefnToFsAstType m) m.Range attrs + sepNlnConsideringTriviaContentBeforeForMainNode (synMemberDefnToFsAstType m) m.Range collectItems rest @@ -4643,14 +4687,14 @@ and genMemberDefn astContext node = |> List.map (fun andBinding -> let expr = - enterNodeFor (synBindingToFsAstType b) andBinding.RangeOfBindingAndRhs + enterNodeFor (synBindingToFsAstType b) andBinding.RangeOfBindingWithRhs +> genLetBinding { astContext with IsFirstChild = false } "and " andBinding ColMultilineItem( expr, sepNlnConsideringTriviaContentBeforeForMainNode - NormalBinding_ - andBinding.RangeOfBindingAndRhs + SynBindingKind_Normal + andBinding.RangeOfBindingWithRhs )) ColMultilineItem(genLetBinding { astContext with IsFirstChild = true } prefix b, sepNone) @@ -4696,7 +4740,7 @@ and genMemberDefn astContext node = -- genPropertyKind (not isFunctionProperty) mk ) - | MDAbstractSlot (ats, px, ao, s, t, vi, ValTyparDecls (tds, _, tcs), MFMemberFlags mk) -> + | MDAbstractSlot (ats, px, ao, s, t, vi, ValTyparDecls (tds, _), MFMemberFlags mk) -> let (FunType namedArgs) = (t, vi) let isFunctionProperty = @@ -4725,7 +4769,7 @@ and genMemberDefn astContext node = +> genAttributes astContext ats +> opt sepSpace ao genAccess +> genAbstractMemberKeyword - +> genTypeParamPostfix astContext tds tcs + +> genTypeParamPostfix astContext tds +> sepColonWithSpacesFixed +> autoIndentAndNlnIfExpressionExceedsPageWidth (genTypeList astContext namedArgs) -- genPropertyKind (not isFunctionProperty) mk @@ -4810,17 +4854,18 @@ and genPat astContext pat = +> sepColon +> atCurrentColumnIndent (genType astContext false t)) - | PatNamed (ao, PatNullary PatWild, s) -> + | PatNamed (ao, s) -> opt sepSpace ao genAccess +> infixOperatorFromTrivia pat.Range s - | PatNamed (ao, p, s) -> - opt sepSpace ao genAccess +> genPat astContext p - -- sprintf " as %s" s + | PatAs (p1, p2, r) -> + genPat astContext p1 -- " as " + +> genPat astContext p2 + |> genTriviaFor SynPat_As r | PatLongIdent (ao, s, ps, tpso) -> let aoc = opt sepSpace ao genAccess let tpsoc = - opt sepNone tpso (fun (ValTyparDecls (tds, _, tcs)) -> genTypeParamPostfix astContext tds tcs) + opt sepNone tpso (fun (ValTyparDecls (tds, _)) -> genTypeParamPostfix astContext tds) // Override escaped new keyword let s = if s = "``new``" then "new" else s @@ -4967,8 +5012,9 @@ and genPat astContext pat = and genSynBindingFunction (astContext: ASTContext) (isMemberDefinition: bool) - (px: FSharp.Compiler.XmlDoc.PreXmlDoc) + (px: PreXmlDoc) (ats: SynAttributes) + (afterAttributesBeforeHeadPattern: Range option) (pref: Context -> Context) (ao: SynAccess option) (isInline: bool) @@ -5002,10 +5048,7 @@ and genSynBindingFunction let genFunctionName = getIndentBetweenTicksFromSynPat patRange functionName - +> opt - sepNone - genericTypeParameters - (fun (ValTyparDecls (tds, _, tcs)) -> genTypeParamPostfix astContext tds tcs) + +> opt sepNone genericTypeParameters (fun (ValTyparDecls (tds, _)) -> genTypeParamPostfix astContext tds) let genSignature = let rangeBetweenBindingPatternAndExpression = @@ -5049,7 +5092,8 @@ and genSynBindingFunction +> unindent) ctx - expressionFitsOnRestOfLine short long + genAfterAttributesBefore SynBinding_AfterAttributes_BeforeHeadPattern afterAttributesBeforeHeadPattern + +> expressionFitsOnRestOfLine short long let body (ctx: Context) = genExprKeepIndentInBranch astContext e ctx @@ -5068,8 +5112,9 @@ and genSynBindingFunction and genSynBindingFunctionWithReturnType (astContext: ASTContext) (isMemberDefinition: bool) - (px: FSharp.Compiler.XmlDoc.PreXmlDoc) + (px: PreXmlDoc) (ats: SynAttributes) + (afterAttributesBeforeHeadPattern: Range option) (pref: Context -> Context) (ao: SynAccess option) (isInline: bool) @@ -5105,10 +5150,7 @@ and genSynBindingFunctionWithReturnType let genFunctionName = getIndentBetweenTicksFromSynPat patRange functionName - +> opt - sepNone - genericTypeParameters - (fun (ValTyparDecls (tds, _, tcs)) -> genTypeParamPostfix astContext tds tcs) + +> opt sepNone genericTypeParameters (fun (ValTyparDecls (tds, _)) -> genTypeParamPostfix astContext tds) let genReturnType isFixed = let genMetadataAttributes = @@ -5160,7 +5202,8 @@ and genSynBindingFunctionWithReturnType +> unindent) ctx - expressionFitsOnRestOfLine short long + genAfterAttributesBefore SynBinding_AfterAttributes_BeforeHeadPattern afterAttributesBeforeHeadPattern + +> expressionFitsOnRestOfLine short long let body = genExprKeepIndentInBranch astContext e @@ -5177,7 +5220,7 @@ and genSynBindingFunctionWithReturnType and genLetBindingDestructedTuple (astContext: ASTContext) - (px: FSharp.Compiler.XmlDoc.PreXmlDoc) + (px: PreXmlDoc) (ats: SynAttributes) (pref: string) (ao: SynAccess option) @@ -5225,8 +5268,9 @@ and genLetBindingDestructedTuple and genSynBindingValue (astContext: ASTContext) - (px: FSharp.Compiler.XmlDoc.PreXmlDoc) + (px: PreXmlDoc) (ats: SynAttributes) + (afterAttributesBeforeHeadPattern: Range option) (pref: Context -> Context) (ao: SynAccess option) (isInline: bool) @@ -5285,7 +5329,8 @@ and genSynBindingValue genPreXmlDoc px +> genAttrIsFirstChild +> leadingExpressionIsMultiline - (genPref + (genAfterAttributesBefore SynBinding_AfterAttributes_BeforeHeadPattern afterAttributesBeforeHeadPattern + +> genPref +> afterLetKeyword +> sepSpace +> genValueName @@ -5315,6 +5360,9 @@ and genParenTupleWithIndentAndNewlines (astContext: ASTContext) (ps: SynPat list +> sepCloseT |> genTriviaFor SynPat_Paren pr +and genAfterAttributesBefore (astType: FsAstType) (r: Range option) : Context -> Context = + optSingle (fun r -> genTriviaFor astType r id) r + and collectMultilineItemForSynExprKeepIndent (astContext: ASTContext) (inKeyWordTrivia: TriviaNode list) @@ -5469,15 +5517,15 @@ and genConst (c: SynConst) (r: Range) = | SynConst.UInt64 _ | SynConst.UIntPtr _ | SynConst.UserNum _ -> genConstNumber c r - | SynConst.String (s, r) -> + | SynConst.String (s, _, r) -> + // TODO: take string kind into account fun (ctx: Context) -> let trivia = Map.tryFindOrEmptyList SynConst_String ctx.TriviaMainNodes |> List.tryFind (fun tv -> RangeHelpers.rangeEq tv.Range r) match trivia with - | Some ({ ContentItself = Some (StringContent sc) } as tn) - | Some ({ ContentItself = Some (KeywordString sc) } as tn) -> + | Some ({ ContentItself = Some (StringContent sc) } as tn) -> printContentBefore tn +> !-sc +> printContentAfter tn @@ -5518,26 +5566,21 @@ and genConst (c: SynConst) (r: Range) = !-(sprintf "\'%s\'" escapedChar) expr ctx - | SynConst.Bytes (bytes, r) -> + | SynConst.Bytes (bytes, _, r) -> + // TODO: take kind into account genConstBytes bytes r |> genTriviaFor SynConst_Bytes r - | SynConst.Measure (c, m) -> + | SynConst.Measure (c, numberRange, m) -> let measure = match m with | Measure m -> !-m - let genNumber (ctx: Context) = - match m with - | SynMeasure.Seq (_, mr) -> - let numberRange = - ctx.MkRange r.Start (Pos.mkPos mr.StartLine (mr.StartColumn - 1)) - - genConstNumber c numberRange ctx - | _ -> genConstNumber c r ctx + let genNumber (ctx: Context) = genConstNumber c numberRange ctx genNumber +> measure +> leaveNodeTokenByName r GREATER + | SynConst.SourceIdentifier (c, _, r) -> !-c |> genTriviaFor SynConst_SourceIdentifier r and genConstNumber (c: SynConst) (r: Range) = fun (ctx: Context) -> diff --git a/src/Fantomas/Context.fs b/src/Fantomas/Context.fs index 46333fec70..93f8a1b81b 100644 --- a/src/Fantomas/Context.fs +++ b/src/Fantomas/Context.fs @@ -3,8 +3,8 @@ module Fantomas.Context open System open FSharp.Compiler.Text open FSharp.Compiler.Text.Range -open FSharp.Compiler.Text.Pos -open FSharp.Compiler.SyntaxTree +open FSharp.Compiler.Text.Position +open FSharp.Compiler.Syntax open Fantomas open Fantomas.FormatConfig open Fantomas.TriviaTypes @@ -1177,8 +1177,7 @@ let internal printTriviaContent (c: TriviaContent) (ctx: Context) = | IdentOperatorAsWord _ | IdentBetweenTicks _ | CharContent _ - | EmbeddedIL _ - | KeywordString _ -> sepNone // don't print here but somewhere in CodePrinter + | EmbeddedIL _ -> sepNone // don't print here but somewhere in CodePrinter | Directive s | Comment (LineCommentOnSingleLine s) -> (ifElse addNewline sepNlnForTrivia sepNone) @@ -1308,37 +1307,6 @@ let internal sepNlnConsideringTriviaContentBeforeForToken (fsTokenKey: FsTokenTy let internal sepNlnConsideringTriviaContentBeforeForMainNode (mainNode: FsAstType) (range: Range) = sepConsideringTriviaContentBeforeForMainNode sepNln mainNode range -let internal sepNlnConsideringTriviaContentBeforeWithAttributesFor - (mainNode: FsAstType) - (ownRange: Range) - (attributeRanges: Range seq) - (ctx: Context) - = - let triviaNodeBeforeMain = - match Map.tryFind mainNode ctx.TriviaMainNodes with - | Some triviaNodes -> - List.exists - (fun { Range = r; ContentBefore = cb } -> - hasPrintableContent cb - && RangeHelpers.rangeEq r ownRange) - triviaNodes - | None -> false - - let triviaNodeBeforeAttribute = - match Map.tryFind SynAttributeList_ ctx.TriviaMainNodes with - | Some attributeNodes -> - List.exists - (fun { Range = r; ContentBefore = cb } -> - hasPrintableContent cb - && Seq.exists (RangeHelpers.rangeEq r) attributeRanges) - attributeNodes - | None -> false - - if triviaNodeBeforeMain || triviaNodeBeforeAttribute then - ctx - else - sepNln ctx - let internal sepNlnForEmptyModule (mainNode: FsAstType) (moduleRange: Range) (ctx: Context) = match Map.tryFind mainNode ctx.TriviaMainNodes with | Some nodes -> @@ -1366,7 +1334,7 @@ let internal sepNlnForEmptyNamespace (namespaceRange: Range) ctx = | _ -> sepNln ctx let internal sepNlnTypeAndMembers - (lastPositionBeforeMembers: Pos) + (lastPositionBeforeMembers: Position) (firstMemberRange: Range) (mainNodeType: FsAstType) (ctx: Context) diff --git a/src/Fantomas/SourceParser.fs b/src/Fantomas/SourceParser.fs index d3d5dde1cc..7124c1ff01 100644 --- a/src/Fantomas/SourceParser.fs +++ b/src/Fantomas/SourceParser.fs @@ -1,13 +1,12 @@ module internal Fantomas.SourceParser open System -open FSharp.Compiler.SourceCodeServices.PrettyNaming -open FSharp.Compiler.SourceCodeServices.FSharpKeywords +open FSharp.Compiler.Syntax +open FSharp.Compiler.Syntax.PrettyNaming +open FSharp.Compiler.Tokenization.FSharpKeywords open FSharp.Compiler.Text -open FSharp.Compiler.SyntaxTree -open FSharp.Compiler.XmlDoc +open FSharp.Compiler.Xml open Fantomas -open Fantomas.AstExtensions open Fantomas.TriviaTypes /// Don't put space before and after these operators @@ -176,12 +175,12 @@ let (|OpNameFull|) (x: Identifier) = // Type params -let inline (|Typar|) (SynTypar.Typar (Ident s, req, _)) = +let inline (|Typar|) (SynTypar.SynTypar (Ident s, req, _)) = match req with - | NoStaticReq -> (s, false) - | HeadTypeStaticReq -> (s, true) + | TyparStaticReq.None -> (s, false) + | TyparStaticReq.HeadType -> (s, true) -let inline (|ValTyparDecls|) (SynValTyparDecls (tds, b, tcs)) = (tds, b, tcs) +let inline (|ValTyparDecls|) (SynValTyparDecls (tds, b)) = (tds, b) // Literals @@ -215,7 +214,7 @@ let (|Measure|) x = let (|String|_|) e = match e with - | SynExpr.Const (SynConst.String (s, _), _) -> Some s + | SynExpr.Const (SynConst.String (s, _, _), _) -> Some s | _ -> None let (|Unit|_|) = @@ -321,11 +320,8 @@ let (|Types|_|) = let (|NestedModule|_|) = function - | SynModuleDecl.NestedModule (SynComponentInfo.ComponentInfo (ats, _, _, LongIdent s, px, _, ao, _), - isRecursive, - xs, - _, - _) -> Some(ats, px, ao, s, isRecursive, xs) + | SynModuleDecl.NestedModule (SynComponentInfo (ats, _, _, LongIdent s, px, _, ao, _), isRecursive, xs, _, _) -> + Some(ats, px, ao, s, isRecursive, xs) | _ -> None let (|Exception|_|) = @@ -372,7 +368,7 @@ let (|SigTypes|_|) = let (|SigNestedModule|_|) = function - | SynModuleSigDecl.NestedModule (SynComponentInfo.ComponentInfo (ats, _, _, LongIdent s, px, _, ao, _), _, xs, _) -> + | SynModuleSigDecl.NestedModule (SynComponentInfo (ats, _, _, LongIdent s, px, _, ao, _), _, xs, _) -> Some(ats, px, ao, s, xs) | _ -> None @@ -397,17 +393,18 @@ let (|SigExceptionDef|) = (ats, px, ao, uc, ms) -let (|UnionCase|) (SynUnionCase.UnionCase (ats, Ident s, uct, px, ao, _)) = (ats, px, ao, s, uct) +let (|UnionCase|) (SynUnionCase (ats, Ident s, uct, px, ao, _)) = (ats, px, ao, s, uct) let (|UnionCaseType|) = function - | SynUnionCaseType.UnionCaseFields fs -> fs - | SynUnionCaseType.UnionCaseFullType _ -> failwith "UnionCaseFullType should be used internally only." + | SynUnionCaseKind.Fields fs -> fs + | SynUnionCaseKind.FullType _ -> failwith "UnionCaseFullType should be used internally only." -let (|Field|) (SynField.Field (ats, isStatic, ido, t, isMutable, px, ao, _)) = +let (|Field|) (SynField (ats, isStatic, ido, t, isMutable, px, ao, _)) = (ats, px, ao, isStatic, isMutable, t, Option.map (|Ident|) ido) -let (|EnumCase|) (SynEnumCase.EnumCase (ats, Ident s, c, px, r)) = (ats, px, s, (c, r)) +// TODO: use added range in CodePrinter +let (|EnumCase|) (SynEnumCase (ats, Ident s, c, _, px, r)) = (ats, px, s, (c, r)) // Member definitions (11 cases) @@ -458,7 +455,7 @@ let (|MDLetBindings|_|) = let (|MDAbstractSlot|_|) = function - | SynMemberDefn.AbstractSlot (ValSpfn (ats, Ident s, tds, t, vi, _, _, px, ao, _, _), mf, _) -> + | SynMemberDefn.AbstractSlot (SynValSig (ats, Ident s, tds, t, vi, _, _, px, ao, _, _), mf, _) -> Some(ats, px, ao, s, t, vi, tds, mf) | _ -> None @@ -475,43 +472,43 @@ let (|MDAutoProperty|_|) = // Interface impl -let (|InterfaceImpl|) (SynInterfaceImpl.InterfaceImpl (t, bs, range)) = (t, bs, range) +let (|InterfaceImpl|) (SynInterfaceImpl (t, bs, range)) = (t, bs, range) // Bindings let (|PropertyGet|_|) = function - | MemberKind.PropertyGet -> Some() + | SynMemberKind.PropertyGet -> Some() | _ -> None let (|PropertySet|_|) = function - | MemberKind.PropertySet -> Some() + | SynMemberKind.PropertySet -> Some() | _ -> None let (|PropertyGetSet|_|) = function - | MemberKind.PropertyGetSet -> Some() + | SynMemberKind.PropertyGetSet -> Some() | _ -> None -let (|MFProperty|_|) (mf: MemberFlags) = +let (|MFProperty|_|) (mf: SynMemberFlags) = match mf.MemberKind with - | MemberKind.PropertyGet - | MemberKind.PropertySet - | MemberKind.PropertyGetSet as mk -> Some mk + | SynMemberKind.PropertyGet + | SynMemberKind.PropertySet + | SynMemberKind.PropertyGetSet as mk -> Some mk | _ -> None -let (|MFMemberFlags|) (mf: MemberFlags) = mf.MemberKind +let (|MFMemberFlags|) (mf: SynMemberFlags) = mf.MemberKind /// This pattern finds out which keyword to use -let (|MFMember|MFStaticMember|MFConstructor|MFOverride|) (mf: MemberFlags) = +let (|MFMember|MFStaticMember|MFConstructor|MFOverride|) (mf: SynMemberFlags) = match mf.MemberKind with - | MemberKind.ClassConstructor - | MemberKind.Constructor -> MFConstructor() - | MemberKind.Member - | MemberKind.PropertyGet - | MemberKind.PropertySet - | MemberKind.PropertyGetSet as mk -> + | SynMemberKind.ClassConstructor + | SynMemberKind.Constructor -> MFConstructor() + | SynMemberKind.Member + | SynMemberKind.PropertyGet + | SynMemberKind.PropertySet + | SynMemberKind.PropertyGetSet as mk -> if mf.IsInstance && mf.IsOverrideOrExplicitImpl then MFOverride mk elif mf.IsInstance then @@ -521,14 +518,14 @@ let (|MFMember|MFStaticMember|MFConstructor|MFOverride|) (mf: MemberFlags) = let (|DoBinding|LetBinding|MemberBinding|PropertyBinding|ExplicitCtor|) = function - | SynBinding.Binding (ao, _, _, _, ats, px, SynValData (Some MFConstructor, _, ido), pat, _, expr, _, _) -> + | SynBinding (ao, _, _, _, ats, px, SynValData (Some MFConstructor, _, ido), pat, _, expr, _, _) -> ExplicitCtor(ats, px, ao, pat, expr, Option.map (|Ident|) ido) - | SynBinding.Binding (ao, _, isInline, _, ats, px, SynValData (Some (MFProperty _ as mf), _, _), pat, _, expr, _, _) -> + | SynBinding (ao, _, isInline, _, ats, px, SynValData (Some (MFProperty _ as mf), _, _), pat, _, expr, _, _) -> PropertyBinding(ats, px, ao, isInline, mf, pat, expr) - | SynBinding.Binding (ao, _, isInline, _, ats, px, SynValData (Some mf, synValInfo, _), pat, _, expr, _, _) -> + | SynBinding (ao, _, isInline, _, ats, px, SynValData (Some mf, synValInfo, _), pat, _, expr, _, _) -> MemberBinding(ats, px, ao, isInline, mf, pat, expr, synValInfo) - | SynBinding.Binding (_, DoBinding, _, _, ats, px, _, _, _, expr, _, _) -> DoBinding(ats, px, expr) - | SynBinding.Binding (ao, _, isInline, isMutable, attrs, px, SynValData (_, valInfo, _), pat, _, expr, _, _) -> + | SynBinding (_, SynBindingKind.Do, _, _, ats, px, _, _, _, expr, _, _) -> DoBinding(ats, px, expr) + | SynBinding (ao, _, isInline, isMutable, attrs, px, SynValData (_, valInfo, _), pat, _, expr, _, _) -> LetBinding(attrs, px, ao, isInline, isMutable, pat, expr, valInfo) // Expressions (55 cases, lacking to handle 11 cases) @@ -1165,9 +1162,14 @@ let (|PatTyped|_|) = | SynPat.Typed (p, t, _) -> Some(p, t) | _ -> None -let (|PatNamed|_|) = +let (|PatNamed|_|) pat = + match pat with + | SynPat.Named (IdentOrKeyword (OpNameFullInPattern (s, _)), _, ao, _) -> Some(ao, s) + | _ -> None + +let (|PatAs|_|) = function - | SynPat.Named (p, IdentOrKeyword (OpNameFullInPattern (s, _)), _, ao, _) -> Some(ao, p, s) + | SynPat.As (p1, p2, r) -> Some(p1, p2, r) | _ -> None let (|PatLongIdent|_|) = @@ -1245,9 +1247,9 @@ let (|SimplePats|SPSTyped|) = let (|RecordField|) = function - | SynField.Field (ats, _, ido, _, _, px, ao, _) -> (ats, px, ao, Option.map (|Ident|) ido) + | SynField (ats, _, ido, _, _, px, ao, _) -> (ats, px, ao, Option.map (|Ident|) ido) -let (|Clause|) (SynMatchClause.Clause (p, eo, e, _, _)) = (p, e, eo) +let (|Clause|) (SynMatchClause (p, eo, e, _, _)) = (p, e, eo) /// Process compiler-generated matches in an appropriate way let rec private skipGeneratedLambdas expr = @@ -1257,7 +1259,7 @@ let rec private skipGeneratedLambdas expr = and skipGeneratedMatch expr = match expr with - | SynExpr.Match (_, _, [ SynMatchClause.Clause (_, _, innerExpr, _, _) as clause ], matchRange) when + | SynExpr.Match (_, _, [ SynMatchClause.SynMatchClause (_, _, innerExpr, _, _) as clause ], matchRange) when matchRange.Start = clause.Range.Start -> skipGeneratedMatch innerExpr @@ -1324,41 +1326,33 @@ type TypeDefnKindSingle = | TCRecord | TCUnion | TCAbbrev - | TCHiddenRepr + | TCOpaque | TCAugmentation - | TCILAssemblyCode + | TCIL let (|TCSimple|TCDelegate|) = function - | TyconUnspecified -> TCSimple TCUnspecified - | TyconClass -> TCSimple TCClass - | TyconInterface -> TCSimple TCInterface - | TyconStruct -> TCSimple TCStruct - | TyconRecord -> TCSimple TCRecord - | TyconUnion -> TCSimple TCUnion - | TyconAbbrev -> TCSimple TCAbbrev - | TyconHiddenRepr -> TCSimple TCHiddenRepr - | TyconAugmentation -> TCSimple TCAugmentation - | TyconILAssemblyCode -> TCSimple TCILAssemblyCode - | TyconDelegate (t, vi) -> TCDelegate(t, vi) - -let (|TypeDef|) - (SynTypeDefn.TypeDefn (SynComponentInfo.ComponentInfo (ats, tds, tcs, LongIdent s, px, preferPostfix, ao, _), - tdr, - ms, - _)) - = + | SynTypeDefnKind.Unspecified -> TCSimple TCUnspecified + | SynTypeDefnKind.Class -> TCSimple TCClass + | SynTypeDefnKind.Interface -> TCSimple TCInterface + | SynTypeDefnKind.Struct -> TCSimple TCStruct + | SynTypeDefnKind.Record -> TCSimple TCRecord + | SynTypeDefnKind.Union -> TCSimple TCUnion + | SynTypeDefnKind.Abbrev -> TCSimple TCAbbrev + | SynTypeDefnKind.Opaque -> TCSimple TCOpaque + | SynTypeDefnKind.Augmentation -> TCSimple TCAugmentation + | SynTypeDefnKind.IL -> TCSimple TCIL + | SynTypeDefnKind.Delegate (t, vi) -> TCDelegate(t, vi) + +let (|TypeDef|) (SynTypeDefn (SynComponentInfo (ats, tds, tcs, LongIdent s, px, preferPostfix, ao, _), tdr, ms, _, _)) = (ats, px, ao, tds, tcs, tdr, ms, s, preferPostfix) let (|SigTypeDef|) - (SynTypeDefnSig.TypeDefnSig (SynComponentInfo.ComponentInfo (ats, tds, tcs, LongIdent s, px, preferPostfix, ao, _), - tdr, - ms, - _) as node) + (SynTypeDefnSig (SynComponentInfo (ats, tds, tcs, LongIdent s, px, preferPostfix, ao, _), tdr, ms, range)) = - (ats, px, ao, tds, tcs, tdr, ms, s, preferPostfix, node.FullRange) + (ats, px, ao, tds, tcs, tdr, ms, s, preferPostfix, range) -let (|TyparDecl|) (SynTyparDecl.TyparDecl (ats, tp)) = (ats, tp) +let (|TyparDecl|) (SynTyparDecl (ats, tp)) = (ats, tp) // Types (15 cases) @@ -1478,15 +1472,15 @@ type SingleTyparConstraintKind = let (|TyparSingle|TyparDefaultsToType|TyparSubtypeOfType|TyparSupportsMember|TyparIsEnum|TyparIsDelegate|) = function - | WhereTyparIsValueType (tp, _) -> TyparSingle(TyparIsValueType, tp) - | WhereTyparIsReferenceType (tp, _) -> TyparSingle(TyparIsReferenceType, tp) - | WhereTyparIsUnmanaged (tp, _) -> TyparSingle(TyparIsUnmanaged, tp) - | WhereTyparSupportsNull (tp, _) -> TyparSingle(TyparSupportsNull, tp) - | WhereTyparIsComparable (tp, _) -> TyparSingle(TyparIsComparable, tp) - | WhereTyparIsEquatable (tp, _) -> TyparSingle(TyparIsEquatable, tp) - | WhereTyparDefaultsToType (tp, t, _) -> TyparDefaultsToType(tp, t) - | WhereTyparSubtypeOfType (tp, t, _) -> TyparSubtypeOfType(tp, t) - | WhereTyparSupportsMember (tps, msg, _) -> + | SynTypeConstraint.WhereTyparIsValueType (tp, _) -> TyparSingle(TyparIsValueType, tp) + | SynTypeConstraint.WhereTyparIsReferenceType (tp, _) -> TyparSingle(TyparIsReferenceType, tp) + | SynTypeConstraint.WhereTyparIsUnmanaged (tp, _) -> TyparSingle(TyparIsUnmanaged, tp) + | SynTypeConstraint.WhereTyparSupportsNull (tp, _) -> TyparSingle(TyparSupportsNull, tp) + | SynTypeConstraint.WhereTyparIsComparable (tp, _) -> TyparSingle(TyparIsComparable, tp) + | SynTypeConstraint.WhereTyparIsEquatable (tp, _) -> TyparSingle(TyparIsEquatable, tp) + | SynTypeConstraint.WhereTyparDefaultsToType (tp, t, _) -> TyparDefaultsToType(tp, t) + | SynTypeConstraint.WhereTyparSubtypeOfType (tp, t, _) -> TyparSubtypeOfType(tp, t) + | SynTypeConstraint.WhereTyparSupportsMember (tps, msg, _) -> TyparSupportsMember( List.choose (function @@ -1495,8 +1489,8 @@ let (|TyparSingle|TyparDefaultsToType|TyparSubtypeOfType|TyparSupportsMember|Typ tps, msg ) - | WhereTyparIsEnum (tp, ts, _) -> TyparIsEnum(tp, ts) - | WhereTyparIsDelegate (tp, ts, _) -> TyparIsDelegate(tp, ts) + | SynTypeConstraint.WhereTyparIsEnum (tp, ts, _) -> TyparIsEnum(tp, ts) + | SynTypeConstraint.WhereTyparIsDelegate (tp, ts, _) -> TyparIsDelegate(tp, ts) let (|MSMember|MSInterface|MSInherit|MSValField|MSNestedType|) = function @@ -1507,9 +1501,19 @@ let (|MSMember|MSInterface|MSInherit|MSValField|MSNestedType|) = | SynMemberSig.NestedType (tds, _) -> MSNestedType tds let (|Val|) - (ValSpfn (ats, (IdentOrKeyword (OpNameFullInPattern (s, _)) as ident), tds, t, vi, isInline, _, px, ao, _, _)) + (SynValSig (ats, + (IdentOrKeyword (OpNameFullInPattern (s, _)) as ident), + SynValTyparDecls (typars, _), + t, + vi, + isInline, + _, + px, + ao, + _, + range)) = - (ats, px, ao, s, ident.idRange, t, vi, isInline, tds) + (ats, px, ao, s, ident.idRange, t, vi, isInline, typars, range) // Misc @@ -1555,55 +1559,6 @@ let (|Extern|_|) = None | _ -> None -let private collectAttributesRanges (a: SynAttributes) = - [ yield! (List.map (fun (al: SynAttributeList) -> al.Range) a) - yield! (List.collect (fun a -> a.Attributes |> List.map (fun a -> a.Range)) a) ] - -let getRangesFromAttributesFromModuleDeclaration (mdl: SynModuleDecl) : Range list = - match mdl with - | SynModuleDecl.Let (_, bindings, _) -> - bindings - |> List.collect (fun (Binding (_, _, _, _, attrs, _, _, _, _, _, _, _)) -> collectAttributesRanges attrs) - | SynModuleDecl.Types (types, _) -> - types - |> List.collect - (fun t -> - match t with - | SynTypeDefn.TypeDefn (SynComponentInfo.ComponentInfo (attrs, _, _, _, _, _, _, _), _, _, _) -> - collectAttributesRanges attrs) - | SynModuleDecl.NestedModule (SynComponentInfo.ComponentInfo (attrs, _, _, _, _, _, _, _), _, _, _, _) -> - collectAttributesRanges attrs - | _ -> List.empty - -let getRangesFromAttributesFromSynModuleSigDeclaration (sdl: SynModuleSigDecl) = - match sdl with - | SynModuleSigDecl.NestedModule (SynComponentInfo.ComponentInfo (attrs, _, _, _, _, _, _, _), _, _, _) - | SynModuleSigDecl.Types (SynTypeDefnSig.TypeDefnSig (SynComponentInfo.ComponentInfo (attrs, _, _, _, _, _, _, _), - _, - _, - _) :: _, - _) -> collectAttributesRanges attrs - | _ -> List.empty - -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) - -let getRangesFromAttributesFromSynValSig (valSig: SynValSig) = - match valSig with - | SynValSig.ValSpfn (attrs, _, _, _, _, _, _, _, _, _, _) -> attrs |> List.map (fun a -> a.Range) - -let getRangesFromAttributesFromSynMemberDefinition (mdn: SynMemberDefn) = - match mdn with - | SynMemberDefn.Member (mb, _) -> getRangesFromAttributesFromSynBinding mb - | SynMemberDefn.AbstractSlot (valSig, _, _) -> getRangesFromAttributesFromSynValSig valSig - | SynMemberDefn.LetBindings (lb :: _, _, _, _) -> getRangesFromAttributesFromSynBinding lb - | _ -> [] - let rec (|UppercaseSynExpr|LowercaseSynExpr|) (synExpr: SynExpr) = let upperOrLower (v: string) = let isUpper = diff --git a/src/Fantomas/SourceTransformer.fs b/src/Fantomas/SourceTransformer.fs index a36d79e6a9..387ba7bf1c 100644 --- a/src/Fantomas/SourceTransformer.fs +++ b/src/Fantomas/SourceTransformer.fs @@ -1,6 +1,6 @@ module internal Fantomas.SourceTransformer -open FSharp.Compiler.SyntaxTree +open FSharp.Compiler.Syntax open FSharp.Compiler.Text open Fantomas.Context open Fantomas.SourceParser @@ -185,6 +185,7 @@ let synConstToFsAstType = | SynConst.Bytes _ -> SynConst_Bytes | SynConst.UInt16s _ -> SynConst_UInt16s | SynConst.Measure _ -> SynConst_Measure + | SynConst.SourceIdentifier _ -> SynConst_SourceIdentifier let rec synExprToFsAstType (expr: SynExpr) : FsAstType * Range = match expr with @@ -209,11 +210,11 @@ let rec synExprToFsAstType (expr: SynExpr) : FsAstType * Range = | SynExpr.LetOrUse (_, _, bs, e, _) -> match bs with | [] -> synExprToFsAstType e - | SynBinding.Binding (kind = kind) as b :: _ -> + | SynBinding (kind = kind) as b :: _ -> match kind with - | SynBindingKind.StandaloneExpression -> StandaloneExpression_, b.RangeOfBindingAndRhs - | SynBindingKind.NormalBinding -> NormalBinding_, b.RangeOfBindingAndRhs - | SynBindingKind.DoBinding -> DoBinding_, b.RangeOfBindingAndRhs + | SynBindingKind.StandaloneExpression -> SynBindingKind_StandaloneExpression, b.RangeOfBindingWithRhs + | SynBindingKind.Normal -> SynBindingKind_Normal, b.RangeOfBindingWithRhs + | SynBindingKind.Do -> SynBindingKind_Do, b.RangeOfBindingWithRhs | SynExpr.TryWith _ -> SynExpr_TryWith, expr.Range | SynExpr.YieldOrReturnFrom _ -> SynExpr_YieldOrReturnFrom, expr.Range | SynExpr.While _ -> SynExpr_While, expr.Range @@ -261,7 +262,7 @@ let rec synExprToFsAstType (expr: SynExpr) : FsAstType * Range = let synModuleSigDeclToFsAstType = function - | SynModuleSigDecl.Val _ -> ValSpfn_ + | SynModuleSigDecl.Val _ -> SynValSig_ | SynModuleSigDecl.Exception _ -> SynModuleSigDecl_Exception | SynModuleSigDecl.NestedModule _ -> SynModuleSigDecl_NestedModule | SynModuleSigDecl.Types _ -> SynModuleSigDecl_Types @@ -270,8 +271,8 @@ let synModuleSigDeclToFsAstType = | SynModuleSigDecl.NamespaceFragment _ -> SynModuleSigDecl_NamespaceFragment | SynModuleSigDecl.ModuleAbbrev _ -> SynModuleSigDecl_ModuleAbbrev -let synBindingToFsAstType (Binding (_, kind, _, _, _, _, _, _, _, _, _, _)) = +let synBindingToFsAstType (SynBinding (_, kind, _, _, _, _, _, _, _, _, _, _)) = match kind with - | SynBindingKind.StandaloneExpression -> StandaloneExpression_ - | SynBindingKind.NormalBinding -> NormalBinding_ - | SynBindingKind.DoBinding -> DoBinding_ + | SynBindingKind.StandaloneExpression -> SynBindingKind_StandaloneExpression + | SynBindingKind.Normal -> SynBindingKind_Normal + | SynBindingKind.Do -> SynBindingKind_Do diff --git a/src/Fantomas/TokenParser.fs b/src/Fantomas/TokenParser.fs index 36cd77beac..0a8b46241f 100644 --- a/src/Fantomas/TokenParser.fs +++ b/src/Fantomas/TokenParser.fs @@ -2,16 +2,17 @@ module internal Fantomas.TokenParser open System open System.Text +open FSharp.Compiler.Syntax +open FSharp.Compiler.Tokenization open Fantomas open Fantomas.TokenParserBoolExpr open Fantomas.TriviaTypes -open FSharp.Compiler.SourceCodeServices let private whiteSpaceTag = 4 let private lineCommentTag = 8 let private commentTag = 3 let private greaterTag = 160 -let private identTag = 191 +let private identTag = 192 // workaround for cases where tokenizer dont output "delayed" part of operator after ">." // See https://github.com/fsharp/FSharp.Compiler.Service/issues/874 @@ -787,12 +788,6 @@ let rec private (|HashTokens|_|) (tokens: Token list) = | _ -> Some(head :: tokensFromSameLine, rest) | _ -> None -let private (|KeywordString|_|) (token: Token) = - if token.TokenInfo.Tag = 192 then - Some token - else - None - let private (|BlockCommentTokens|_|) (tokens: Token list) = let rec collectTokens (rest: Token list) (finalContinuation: Token list -> Token list) : Token list * Token list = match rest with @@ -948,15 +943,6 @@ let rec private getTriviaFromTokensThemSelves getTriviaFromTokensThemSelves mkRange lastButOne lastToken rest info - | KeywordString ks :: rest -> - let range = getRangeBetween mkRange ks ks - - let info = - Trivia.Create(KeywordString(ks.Content)) range - |> List.prependItem foundTrivia - - getTriviaFromTokensThemSelves mkRange lastNonWhiteSpaceToken (Some ks) rest info - | KeywordOrOperatorToken koo :: rest -> let range = getRangeBetween mkRange koo koo diff --git a/src/Fantomas/Trivia.fs b/src/Fantomas/Trivia.fs index f99c36133c..10528367ae 100644 --- a/src/Fantomas/Trivia.fs +++ b/src/Fantomas/Trivia.fs @@ -1,12 +1,12 @@ module internal Fantomas.Trivia -open FSharp.Compiler.SourceCodeServices +open FSharp.Compiler.Text +open FSharp.Compiler.Syntax +open FSharp.Compiler.Tokenization open Fantomas open Fantomas.SourceParser open Fantomas.AstTransformer open Fantomas.TriviaTypes -open FSharp.Compiler.Text -open FSharp.Compiler.SyntaxTree let isMainNode (node: TriviaNode) = match node.Type with @@ -152,7 +152,7 @@ let private findConstNumberNodeOnLineAndColumn (nodes: TriviaNodeAssigner list) | MainNode SynConst_UserNum -> constantRange.StartLine = tn.Range.StartLine && constantRange.StartColumn = tn.Range.StartColumn - | MainNode EnumCase_ -> + | MainNode SynEnumCase_ -> tn.Range.EndLine = constantRange.EndLine && tn.Range.EndColumn = constantRange.EndColumn | _ -> false) @@ -224,25 +224,6 @@ let private findParsedHashOnLineAndEndswith (triviaNodes: TriviaNodeAssigner lis && t.Range.EndColumn >= endColumn | _ -> false) -// Only return the attributeList when the trivia is under it and above the AST node of which the attribute is a child node. -// f.ex. -// [] -// #if BAR -// let meh = () -// The trivia '#if BAR' should be linked to the [] attribute -// -// The reason for this is that the range of the attribute is not part of the range of the parent binding. -// This can lead to weird results when used in CodePrinter. -let private triviaBetweenAttributeAndParentBinding (triviaNodes: TriviaNodeAssigner list) line = - triviaNodes - |> List.tryFind - (fun tn -> - match tn.AttributeLinesBetweenParent with - | Some linesBetween -> - linesBetween + tn.Range.EndLine >= line - && line > tn.Range.EndLine - | _ -> false) - let private findASTNodeOfTypeThatContains (nodes: TriviaNodeAssigner list) typeName range = nodes |> List.filter @@ -265,29 +246,21 @@ let private addAllTriviaAsContentAfter (trivia: Trivia list) (singleNode: Trivia ContentAfter = contentAfter } |> List.singleton -let private addTriviaToTriviaNode - triviaBetweenAttributeAndParentBinding - (startOfSourceCode: int) - (triviaNodes: TriviaNodeAssigner list) - trivia - = +let private addTriviaToTriviaNode (startOfSourceCode: int) (triviaNodes: TriviaNodeAssigner list) trivia = match trivia with | { Item = Comment (LineCommentOnSingleLine _ as comment) Range = range } -> - match triviaBetweenAttributeAndParentBinding triviaNodes range.StartLine with - | Some _ as node -> updateTriviaNode (fun tn -> tn.ContentAfter.Add(Comment(comment))) triviaNodes node - | None -> - let nodeAfterLine = - findFirstNodeAfterLine triviaNodes range.StartLine + let nodeAfterLine = + findFirstNodeAfterLine triviaNodes range.StartLine - match nodeAfterLine with - | Some _ -> - nodeAfterLine - |> updateTriviaNode (fun tn -> tn.ContentBefore.Add(Comment(comment))) triviaNodes - | None -> - // try and find a node above - findNodeBeforeLineFromStart triviaNodes range.StartLine - |> updateTriviaNode (fun tn -> tn.ContentAfter.Add(Comment(comment))) triviaNodes + match nodeAfterLine with + | Some _ -> + nodeAfterLine + |> updateTriviaNode (fun tn -> tn.ContentBefore.Add(Comment(comment))) triviaNodes + | None -> + // try and find a node above + findNodeBeforeLineFromStart triviaNodes range.StartLine + |> updateTriviaNode (fun tn -> tn.ContentAfter.Add(Comment(comment))) triviaNodes | { Item = Comment (BlockComment (comment, _, _)) Range = range } -> @@ -331,25 +304,18 @@ let private addTriviaToTriviaNode // Newlines are only relevant if they occur after the first line of source code | { Item = Newline; Range = range } when (range.StartLine > startOfSourceCode) -> - match triviaBetweenAttributeAndParentBinding triviaNodes range.StartLine with - | Some _ as node -> updateTriviaNode (fun tn -> tn.ContentAfter.Add(Newline)) triviaNodes node - | _ -> - let nodeAfterLine = - findFirstNodeAfterLine triviaNodes range.StartLine + let nodeAfterLine = + findFirstNodeAfterLine triviaNodes range.StartLine - match nodeAfterLine with - | Some _ -> - nodeAfterLine - |> updateTriviaNode (fun tn -> tn.ContentBefore.Add(Newline)) triviaNodes - | None -> - // try and find a node above - findNodeBeforeLineFromStart triviaNodes range.StartLine - |> updateTriviaNode (fun tn -> tn.ContentAfter.Add(Newline)) triviaNodes + match nodeAfterLine with + | Some _ -> + nodeAfterLine + |> updateTriviaNode (fun tn -> tn.ContentBefore.Add(Newline)) triviaNodes + | None -> + // try and find a node above + findNodeBeforeLineFromStart triviaNodes range.StartLine + |> updateTriviaNode (fun tn -> tn.ContentAfter.Add(Newline)) triviaNodes - | { Item = KeywordString _ - Range = range } -> - findNodeForKeywordString triviaNodes range - |> updateTriviaNode (fun tn -> tn.ContentItself <- Some trivia.Item) triviaNodes | { Item = Keyword ({ Content = keyword } as kw) Range = range } when (keyword = "override" @@ -421,21 +387,21 @@ let private addTriviaToTriviaNode | { Item = Directive dc as directive Range = range } -> - match triviaBetweenAttributeAndParentBinding triviaNodes range.StartLine with - | Some _ as node -> updateTriviaNode (fun tn -> tn.ContentAfter.Add(directive)) triviaNodes node - | _ -> - match findFirstNodeAfterLine triviaNodes range.StartLine with - | Some _ as node -> updateTriviaNode (fun tn -> tn.ContentBefore.Add(directive)) triviaNodes node - | None -> - let findNode nodes = - findNodeBeforeLineFromStart nodes range.StartLine + let nodeAfterLine = + findFirstNodeAfterLine triviaNodes range.StartLine - findNode triviaNodes - |> updateTriviaNode - (fun tn -> - let directive = Directive dc - tn.ContentAfter.Add(directive)) - triviaNodes + match nodeAfterLine with + | Some _ as node -> updateTriviaNode (fun tn -> tn.ContentBefore.Add(directive)) triviaNodes node + | None -> + let findNode nodes = + findNodeBeforeLineFromStart nodes range.StartLine + + findNode triviaNodes + |> updateTriviaNode + (fun tn -> + let directive = Directive dc + tn.ContentAfter.Add(directive)) + triviaNodes | { Item = StringContent _ as siNode Range = range } -> @@ -506,15 +472,6 @@ let collectTrivia (mkRange: MkRange) tokens (ast: ParsedInput) = | ParsedInput.SigFile (ParsedSigFileInput.ParsedSigFileInput (_, _, _, _, mns)) -> sigAstToNode mns - let hasAnyAttributesWithLinesBetweenParent = - List.exists (fun (tn: TriviaNodeAssigner) -> Option.isSome tn.AttributeLinesBetweenParent) triviaNodesFromAST - - let triviaBetweenAttributeAndParentBinding = - if hasAnyAttributesWithLinesBetweenParent then - triviaBetweenAttributeAndParentBinding - else - (fun _ _ -> None) - let triviaNodesFromTokens = TokenParser.getTriviaNodesFromTokens mkRange tokens @@ -536,10 +493,7 @@ let collectTrivia (mkRange: MkRange) tokens (ast: ParsedInput) = match ast, triviaNodes with | EmptyFile _, h :: _ -> addAllTriviaAsContentAfter trivias h | _ -> - List.fold - (addTriviaToTriviaNode triviaBetweenAttributeAndParentBinding startOfSourceCode) - triviaNodes - trivias + List.fold (addTriviaToTriviaNode startOfSourceCode) triviaNodes trivias |> List.choose (fun tn -> if triviaNodeIsNotEmpty tn then diff --git a/src/Fantomas/TriviaTypes.fs b/src/Fantomas/TriviaTypes.fs index 6040323322..815484d94c 100644 --- a/src/Fantomas/TriviaTypes.fs +++ b/src/Fantomas/TriviaTypes.fs @@ -1,7 +1,7 @@ module Fantomas.TriviaTypes -open FSharp.Compiler.SourceCodeServices open FSharp.Compiler.Text +open FSharp.Compiler.Tokenization type FsTokenType = | AMP @@ -78,7 +78,6 @@ let a = 7 type TriviaContent = | Keyword of Token - | KeywordString of string | Number of string | StringContent of string | IdentOperatorAsWord of string @@ -193,11 +192,12 @@ type FsAstType = | SynMemberSig_NestedType | SynIndexerArg_One | SynIndexerArg_Two - | SynMatchClause_Clause + | SynMatchClause_ | ArgOptions_ - | InterfaceImpl_ - | TypeDefn_ - | TypeDefnSig_ + | SynInterfaceImpl_ + | SynTypeDefn_ + | SynTypeDefn_AfterAttributesBeforeComponentInfo + | SynTypeDefnSig_ // | SynTypeDefnSigRepr_ObjectModel use first nested node | SynTypeDefnSigRepr_Exception | SynMemberDefn_Open @@ -217,17 +217,21 @@ type FsAstType = | SynSimplePat_Attrib | SynSimplePats_SimplePats | SynSimplePats_Typed - | StandaloneExpression_ - | NormalBinding_ - | DoBinding_ + | SynBindingKind_StandaloneExpression + | SynBindingKind_Normal + | SynBindingKind_Do + | SynBinding_AfterAttributes_BeforeHeadPattern | SynBindingReturnInfo_ - | SynValTyparDecls_ - | TyparDecl_ - | Typar_ - | ValSpfn_ + | SynTyparDecls_PostfixList + | SynTyparDecls_SinglePrefix + | SynTyparDecls_PrefixList + | SynTyparDecl_ + // | Typar_ , unused + | SynValSig_ // | SynPat_Const, use SynConst instead | SynPat_Wild | SynPat_Named + | SynPat_As | SynPat_Typed | SynPat_Attrib // | SynPat_Or, use the inner patterns instead @@ -265,23 +269,24 @@ type FsAstType = | SynConst_Bytes | SynConst_UInt16s | SynConst_Measure - | Pats_ - | NamePatPairs_ - | ComponentInfo_ + | SynConst_SourceIdentifier + | SynArgPats_Pats + | SynArgPats_NamePatPairs + | SynComponentInfo_ // | SynTypeDefnRepr_ObjectModel use first nested node // | SynTypeDefnRepr_Simple use first nested node | SynTypeDefnRepr_Exception - | SynTypeDefnKind_TyconUnspecified - | SynTypeDefnKind_TyconClass - | SynTypeDefnKind_TyconInterface - | SynTypeDefnKind_TyconStruct - | SynTypeDefnKind_TyconRecord - | SynTypeDefnKind_TyconUnion - | SynTypeDefnKind_TyconAbbrev - | SynTypeDefnKind_TyconHiddenRepr - | SynTypeDefnKind_TyconAugmentation - | SynTypeDefnKind_TyconILAssemblyCode - | SynTypeDefnKind_TyconDelegate + | SynTypeDefnKind_Unspecified + | SynTypeDefnKind_Class + | SynTypeDefnKind_Interface + | SynTypeDefnKind_Struct + | SynTypeDefnKind_Record + | SynTypeDefnKind_Union + | SynTypeDefnKind_Abbrev + | SynTypeDefnKind_Opaque + | SynTypeDefnKind_Augmentation + | SynTypeDefnKind_IL + | SynTypeDefnKind_Delegate | SynTypeDefnSimpleRepr_None | SynTypeDefnSimpleRepr_Union | SynTypeDefnSimpleRepr_Enum @@ -294,11 +299,12 @@ type FsAstType = | SynExceptionDefnRepr_ | SynAttribute_ | SynAttributeList_ - | UnionCase_ - | UnionCaseFields_ - | UnionCaseFullType_ - | EnumCase_ - | Field_ + | SynUnionCase_ + | SynUnionCaseKind_Fields + | SynUnionCaseKind_FullType + | SynEnumCase_ + | SynField_ + | SynField_AfterAttributesBeforeIdentifier | SynType_LongIdent | SynType_App | SynType_LongIdentApp @@ -320,6 +326,8 @@ type FsAstType = | SynValInfo_ | SynArgInfo_ | ParsedHashDirective_ + | ParsedHashDirectiveArgument_String + | ParsedHashDirectiveArgument_SourceIdentifier // Modules and namespaces cannot really be trusted // Their range can be influenced by non code constructs (like comments) // | SynModuleOrNamespaceSig_AnonModule @@ -352,10 +360,9 @@ type TriviaNode = ContentAfter: TriviaContent list Range: Range } -type TriviaNodeAssigner(nodeType: TriviaNodeType, range: Range, ?linesBetweenParent: int) = +type TriviaNodeAssigner(nodeType: TriviaNodeType, range: Range) = member this.Type = nodeType member this.Range = range - member this.AttributeLinesBetweenParent = linesBetweenParent member val ContentBefore = ResizeArray() with get, set member val ContentItself = Option.None with get, set member val ContentAfter = ResizeArray() with get, set