diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index 97b866b7695..1bfa151a0e4 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -803,7 +803,8 @@ moduleSpfn: if isRec then raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsInvalidUseOfRec()) let info = SynComponentInfo($1, [], [], path, xml, false, vis, rhs parseState 3) if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) - SynModuleSigDecl.NestedModule(info, isRec, $5, rhs2 parseState 1 5) } + let m = (rhs2 parseState 1 4, $5) ||> unionRangeWithListBy (fun (d: SynModuleSigDecl) -> d.Range) + SynModuleSigDecl.NestedModule(info, isRec, $5, m) } | opt_attributes opt_declVisibility tyconSpfns { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) @@ -811,9 +812,11 @@ moduleSpfn: match $3 with | [] -> raiseParseErrorAt (rhs parseState 3) (FSComp.SR.parsUnexpectedEmptyModuleDefn()) | h :: t -> h, t - let tc = (SynTypeDefnSig(SynComponentInfo($1@cas, a, cs, b, c, d, d2, d3), e, f, g)) + let attrs = $1@cas + let mTc = (g, attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range) + let tc = (SynTypeDefnSig(SynComponentInfo(attrs, a, cs, b, c, d, d2, d3), e, f, mTc)) let lastType = List.tryLast rest |> Option.defaultValue tc |> fun t -> t.Range - let m = mkRange lastType.FileName (lhs parseState).Start lastType.End + let m = mkRange lastType.FileName mTc.Start lastType.End SynModuleSigDecl.Types (tc :: rest, m) } | opt_attributes opt_declVisibility exconSpfn @@ -1009,6 +1012,7 @@ classMemberSpfn: match getSetRangeOpt with | None -> unionRanges m ty.Range | Some m2 -> unionRanges m m2 + |> fun m -> (m, $1) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range) let valSpfn = SynValSig($1, id, explicitValTyparDecls, ty, arity, isInline, false, doc, vis2, optLiteralValue, wholeRange) let _, flags = $3 SynMemberSig.Member(valSpfn, flags (getSetAdjuster arity), wholeRange) } diff --git a/tests/service/Symbols.fs b/tests/service/Symbols.fs index 03e32098547..28fce3c387f 100644 --- a/tests/service/Symbols.fs +++ b/tests/service/Symbols.fs @@ -596,11 +596,11 @@ type Meh = match parseResults with | ParsedInput.SigFile (ParsedSigFileInput (modules = [ SynModuleOrNamespaceSig(decls = [SynModuleSigDecl.Types(range = r)]) ])) -> - assertRange (3, 0) (5,11) r + assertRange (3, 5) (5,11) r | _ -> Assert.Fail "Could not get valid AST" [] - let ``Range of TypeDefnSig record should end at last member`` () = + let ``Range of SynTypeDefnSig record should end at last member`` () = let parseResults = getParseResultsOfSignatureFile """namespace X @@ -615,7 +615,7 @@ type MyRecord = | _ -> Assert.Fail "Could not get valid AST" [] - let ``Range of TypeDefnSig object model should end at last member`` () = + let ``Range of SynTypeDefnSig object model should end at last member`` () = let parseResults = getParseResultsOfSignatureFile """namespace X @@ -631,7 +631,7 @@ type MyRecord = | _ -> Assert.Fail "Could not get valid AST" [] - let ``Range of TypeDefnSig delegate of should start from name`` () = + let ``Range of SynTypeDefnSig delegate of should start from name`` () = let parseResults = getParseResultsOfSignatureFile """namespace Y @@ -645,7 +645,7 @@ type MyFunction = | _ -> Assert.Fail "Could not get valid AST" [] - let ``Range of TypeDefnSig simple should end at last val`` () = + let ``Range of SynTypeDefnSig simple should end at last val`` () = let parseResults = getParseResultsOfSignatureFile """namespace Z @@ -659,6 +659,79 @@ type SomeCollection with assertRange (2, 5) (4, 37) r | _ -> Assert.Fail "Could not get valid AST" + [] + let ``Range of attribute should be included in SynTypeDefnSig`` () = + let parseResults = + getParseResultsOfSignatureFile + """ +namespace SomeNamespace + +[] +type MyType = + class + end +""" + + match parseResults with + | ParsedInput.SigFile (ParsedSigFileInput (modules = [ + SynModuleOrNamespaceSig(decls = [SynModuleSigDecl.Types(types = [SynTypeDefnSig.SynTypeDefnSig(range = r)]) as t]) ])) -> + assertRange (4, 0) (7, 7) r + assertRange (4, 0) (7, 7) t.Range + | _ -> Assert.Fail "Could not get valid AST" + + [] + let ``Range of attributes should be included in recursive types`` () = + let parseResults = + getParseResultsOfSignatureFile + """ +namespace SomeNamespace + +type Foo = + | Bar + +and [] Bang = + internal + { + LongNameBarBarBarBarBarBarBar: int + } + override GetHashCode : unit -> int +""" + + match parseResults with + | ParsedInput.SigFile (ParsedSigFileInput (modules = [ + SynModuleOrNamespaceSig(decls = [SynModuleSigDecl.Types(types = [ + SynTypeDefnSig.SynTypeDefnSig(range = r1) + SynTypeDefnSig.SynTypeDefnSig(range = r2) + ]) as t]) ])) -> + assertRange (4, 5) (5, 9) r1 + assertRange (7, 4) (12, 42) r2 + assertRange (4, 5) (12, 42) t.Range + | _ -> Assert.Fail "Could not get valid AST" + + [] + let ``Range of attribute should be included in SynValSpfn and Member`` () = + let parseResults = + getParseResultsOfSignatureFile + """ +namespace SomeNamespace + +type FooType = + [] // ValSpfn + abstract x : int +""" + + match parseResults with + | ParsedInput.SigFile (ParsedSigFileInput (modules = [ + SynModuleOrNamespaceSig(decls = + [ SynModuleSigDecl.Types(types = [ + SynTypeDefnSig.SynTypeDefnSig(typeRepr = + SynTypeDefnSigRepr.ObjectModel(memberSigs = [ + SynMemberSig.Member(range = mr; memberSig = SynValSig(range = mv)) ])) + ]) ]) ])) -> + assertRange (5, 4) (6, 20) mr + assertRange (5, 4) (6, 20) mv + | _ -> Assert.Fail "Could not get valid AST" + module SynMatchClause = [] let ``Range of single SynMatchClause`` () = @@ -807,4 +880,26 @@ __SOURCE_FILE__""" SynModuleDecl.DoExpr(expr = SynExpr.Const(SynConst.SourceIdentifier("__SOURCE_FILE__", _, range), _)) ]) ])) -> assertRange (2, 0) (2, 15) range + | _ -> Assert.Fail "Could not get valid AST" + +module NestedModules = + + [] + let ``Range of attribute should be included in SynModuleSigDecl.NestedModule`` () = + let parseResults = + getParseResultsOfSignatureFile + """ +namespace SomeNamespace + +[] +module Nested = + val x : int +""" + + match parseResults with + | ParsedInput.SigFile (ParsedSigFileInput (modules = [ SynModuleOrNamespaceSig(decls = [ + SynModuleSigDecl.NestedModule _ as nm + ]) as sigModule ])) -> + assertRange (4, 0) (6, 15) nm.Range + assertRange (2, 0) (6, 15) sigModule.Range | _ -> Assert.Fail "Could not get valid AST" \ No newline at end of file