diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index b2a0f280a64..16125ff4e1c 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -721,7 +721,8 @@ fileModuleSpec: | opt_attributes opt_declVisibility moduleIntro moduleSpfnsPossiblyEmptyBlock { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) let m2 = rhs parseState 3 - let m = (rhs2 parseState 1 4) + let mDeclsAndAttrs = (List.map (fun (a: SynAttributeList) -> a.Range) $1) @ (List.map (fun (d: SynModuleSigDecl) -> d.Range) $4) + let m = (m2, mDeclsAndAttrs) ||> unionRangeWithListBy id let isRec, path2, xml, vis = $3 (fun (isRec2, path, _) -> if not (isNil path) then errorR(Error(FSComp.SR.parsNamespaceOrModuleNotBoth(), m2)) @@ -1155,7 +1156,8 @@ fileModuleImpl: | opt_attributes opt_declVisibility moduleIntro moduleDefnsOrExprPossiblyEmptyOrBlock { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) let m2 = rhs parseState 3 - let m = (m2, $4) ||> unionRangeWithListBy (fun modu -> modu.Range) + let mDeclsAndAttrs = (List.map (fun (a: SynAttributeList) -> a.Range) $1) @ (List.map (fun (d: SynModuleDecl) -> d.Range) $4) + let m = (m2, mDeclsAndAttrs) ||> unionRangeWithListBy id let isRec2, path2, xml, vis = $3 (fun (isRec, path, _) -> if not (isNil path) then errorR(Error(FSComp.SR.parsNamespaceOrModuleNotBoth(), m2)) diff --git a/tests/service/Symbols.fs b/tests/service/Symbols.fs index 0f156f7417c..d62e57c930a 100644 --- a/tests/service/Symbols.fs +++ b/tests/service/Symbols.fs @@ -491,6 +491,23 @@ type X = int assertRange (3, 0) (5, 12) r | _ -> Assert.Fail "Could not get valid AST" + [] + let ``Module range should start at first attribute`` () = + let parseResults = + getParseResults + """ +[< Foo >] +module Bar + +let s : string = "s" +""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ + SynModuleOrNamespace.SynModuleOrNamespace(kind = SynModuleOrNamespaceKind.NamedModule; range = r) ])) -> + assertRange (2, 0) (5, 20) r + | _ -> Assert.Fail "Could not get valid AST" + module SynConsts = [] let ``Measure contains the range of the constant`` () = @@ -545,6 +562,23 @@ type Bar = | Bar of string * int assertRange (3, 0) (5, 32) r | _ -> Assert.Fail "Could not get valid AST" + [] + let ``Module range should start at first attribute`` () = + let parseResults = + getParseResultsOfSignatureFile + """ + [< Foo >] +module Bar + +val s : string +""" + + match parseResults with + | ParsedInput.SigFile (ParsedSigFileInput (modules = [ + SynModuleOrNamespaceSig.SynModuleOrNamespaceSig(kind = SynModuleOrNamespaceKind.NamedModule; range = r) ])) -> + assertRange (2, 1) (5, 14) r + | _ -> Assert.Fail "Could not get valid AST" + module SignatureTypes = [] let ``Range of Type should end at end keyword`` () =