From 6b4eb3d26c66618654c544925aaca5f5a007161f Mon Sep 17 00:00:00 2001 From: nojaf Date: Fri, 23 Apr 2021 10:47:20 +0200 Subject: [PATCH] Correct range of SynTypeDefnSig. --- src/fsharp/SyntaxTree.fs | 8 +++ src/fsharp/SyntaxTree.fsi | 3 + src/fsharp/pars.fsy | 17 ++++-- .../SurfaceArea.netstandard.fs | 2 + tests/service/Symbols.fs | 60 +++++++++++++++++++ 5 files changed, 84 insertions(+), 6 deletions(-) diff --git a/src/fsharp/SyntaxTree.fs b/src/fsharp/SyntaxTree.fs index 1194c6789a2..184eb63af42 100644 --- a/src/fsharp/SyntaxTree.fs +++ b/src/fsharp/SyntaxTree.fs @@ -1220,6 +1220,14 @@ type SynMemberSig = nestedType: SynTypeDefnSig * range: range + member d.Range = + match d with + | SynMemberSig.Member (range=m) + | SynMemberSig.Interface (range=m) + | SynMemberSig.Inherit (range=m) + | SynMemberSig.ValField (range=m) + | SynMemberSig.NestedType (range=m) -> m + [] type SynTypeDefnKind = | Unspecified diff --git a/src/fsharp/SyntaxTree.fsi b/src/fsharp/SyntaxTree.fsi index 1acc931a9d0..9dbf267e6d1 100644 --- a/src/fsharp/SyntaxTree.fsi +++ b/src/fsharp/SyntaxTree.fsi @@ -1407,6 +1407,9 @@ type SynMemberSig = nestedType: SynTypeDefnSig * range: range + /// Gets the syntax range of this construct + member Range: range + /// Represents the kind of a type definition whether explicit or inferred [] type SynTypeDefnKind = diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index 69b741f37d2..b2a0f280a64 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -908,17 +908,21 @@ tyconSpfnRhsBlock: /* The right-hand-side of a type definition in a signature */ tyconSpfnRhs: | tyconDefnOrSpfnSimpleRepr - { let m = $1.Range - (fun lhsm nameInfo augmentation -> - SynTypeDefnSig(nameInfo, SynTypeDefnSigRepr.Simple ($1, m), augmentation, m)) } + { (fun lhsm nameInfo augmentation -> + let declRange = unionRanges lhsm $1.Range + let mWhole = (declRange, augmentation) ||> unionRangeWithListBy (fun (mem: SynMemberSig) -> mem.Range) + SynTypeDefnSig(nameInfo, SynTypeDefnSigRepr.Simple ($1, $1.Range), augmentation, mWhole)) } | tyconClassSpfn - { let m = lhs parseState + { let objectModelRange = lhs parseState let needsCheck, (kind, decls) = $1 (fun nameRange nameInfo augmentation -> if needsCheck && isNil decls then reportParseErrorAt nameRange (FSComp.SR.parsEmptyTypeDefinition()) - SynTypeDefnSig(nameInfo, SynTypeDefnSigRepr.ObjectModel (kind, decls, m), augmentation, m)) } + + let declRange = unionRanges nameRange objectModelRange + let mWhole = (declRange, augmentation) ||> unionRangeWithListBy (fun (mem: SynMemberSig) -> mem.Range) + SynTypeDefnSig(nameInfo, SynTypeDefnSigRepr.ObjectModel (kind, decls, objectModelRange), augmentation, mWhole)) } | DELEGATE OF topType { let m = lhs parseState @@ -926,7 +930,8 @@ tyconSpfnRhs: let invoke = SynMemberSig.Member(SynValSig([], mkSynId m "Invoke", inferredTyparDecls, ty, arity, false, false, PreXmlDoc.Empty, None, None, m), AbstractMemberFlags SynMemberKind.Member, m) (fun nameRange nameInfo augmentation -> if not (isNil augmentation) then raiseParseErrorAt m (FSComp.SR.parsAugmentationsIllegalOnDelegateType()) - SynTypeDefnSig(nameInfo, SynTypeDefnSigRepr.ObjectModel (SynTypeDefnKind.Delegate (ty, arity), [invoke], m), [], m)) } + let mWhole = unionRanges nameRange m + SynTypeDefnSig(nameInfo, SynTypeDefnSigRepr.ObjectModel (SynTypeDefnKind.Delegate (ty, arity), [invoke], m), [], mWhole)) } /* The right-hand-side of an object type definition in a signature */ diff --git a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs index f539c4cf7f1..e3088fffd57 100644 --- a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs +++ b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs @@ -7253,6 +7253,8 @@ FSharp.Compiler.Syntax.SynMemberSig: FSharp.Compiler.Syntax.SynMemberSig+Member FSharp.Compiler.Syntax.SynMemberSig: FSharp.Compiler.Syntax.SynMemberSig+NestedType FSharp.Compiler.Syntax.SynMemberSig: FSharp.Compiler.Syntax.SynMemberSig+Tags FSharp.Compiler.Syntax.SynMemberSig: FSharp.Compiler.Syntax.SynMemberSig+ValField +FSharp.Compiler.Syntax.SynMemberSig: FSharp.Compiler.Text.Range Range +FSharp.Compiler.Syntax.SynMemberSig: FSharp.Compiler.Text.Range get_Range() FSharp.Compiler.Syntax.SynMemberSig: Int32 Tag FSharp.Compiler.Syntax.SynMemberSig: Int32 get_Tag() FSharp.Compiler.Syntax.SynMemberSig: System.String ToString() diff --git a/tests/service/Symbols.fs b/tests/service/Symbols.fs index 5e8e565526b..681067f62f0 100644 --- a/tests/service/Symbols.fs +++ b/tests/service/Symbols.fs @@ -553,6 +553,66 @@ type Meh = assertRange (3, 0) (5,11) r | _ -> Assert.Fail "Could not get valid AST" + [] + let ``Range of TypeDefnSig record should end at last member`` () = + let parseResults = + getParseResultsOfSignatureFile + """namespace X +type MyRecord = + { Level: int } + member Score : unit -> int""" + + match parseResults with + | ParsedInput.SigFile (ParsedSigFileInput (modules = [ + SynModuleOrNamespaceSig(decls = [SynModuleSigDecl.Types(types = [SynTypeDefnSig.SynTypeDefnSig(range = r)])]) ])) -> + assertRange (2, 5) (4, 30) r + | _ -> Assert.Fail "Could not get valid AST" + + [] + let ``Range of TypeDefnSig object model should end at last member`` () = + let parseResults = + getParseResultsOfSignatureFile + """namespace X +type MyRecord = + class + end + member Score : unit -> int""" + + match parseResults with + | ParsedInput.SigFile (ParsedSigFileInput (modules = [ + SynModuleOrNamespaceSig(decls = [SynModuleSigDecl.Types(types = [SynTypeDefnSig.SynTypeDefnSig(range = r)])]) ])) -> + assertRange (2, 5) (5, 30) r + | _ -> Assert.Fail "Could not get valid AST" + + [] + let ``Range of TypeDefnSig delegate of should start from name`` () = + let parseResults = + getParseResultsOfSignatureFile + """namespace Y +type MyFunction = + delegate of int -> string""" + + match parseResults with + | ParsedInput.SigFile (ParsedSigFileInput (modules = [ + SynModuleOrNamespaceSig(decls = [SynModuleSigDecl.Types(types = [SynTypeDefnSig.SynTypeDefnSig(range = r)])]) ])) -> + assertRange (2, 5) (3, 29) r + | _ -> Assert.Fail "Could not get valid AST" + + [] + let ``Range of TypeDefnSig simple should end at last val`` () = + let parseResults = + getParseResultsOfSignatureFile + """namespace Z +type SomeCollection with + val LastIndex : int + val SomeThingElse : int -> string""" + + match parseResults with + | ParsedInput.SigFile (ParsedSigFileInput (modules = [ + SynModuleOrNamespaceSig(decls = [SynModuleSigDecl.Types(types = [SynTypeDefnSig.SynTypeDefnSig(range = r)])]) ])) -> + assertRange (2, 5) (4, 37) r + | _ -> Assert.Fail "Could not get valid AST" + module SynMatchClause = [] let ``Range of single SynMatchClause`` () =