diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index 213c8a5a129..4042df1c1b4 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -816,11 +816,10 @@ moduleSpfn: _xmlDoc.MarkAsInvalid() let attrs = $1 @ cas let mTc = - let keywordM = rhs parseState 3 - (keywordM, attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range) |> unionRanges range + (d3, attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range) |> unionRanges range let xmlDoc = grabXmlDoc(parseState, $1, 1) let tc = (SynTypeDefnSig(SynComponentInfo(attrs, a, cs, b, xmlDoc, d, d2, d3), equalsRange, typeRepr, withKeyword, members, mTc)) - let m = (mTc, $5) ||> unionRangeWithListBy (fun (a: SynTypeDefnSig) -> a.Range) + let m = (mTc, $5) ||> unionRangeWithListBy (fun (a: SynTypeDefnSig) -> a.Range) |> unionRanges (rhs parseState 3) SynModuleSigDecl.Types (tc :: $5, m) } | opt_attributes opt_declVisibility exconSpfn @@ -895,7 +894,16 @@ tyconSpfn: $3 lhsm $1 (Some mEquals) } | typeNameInfo opt_classSpfn { let mWithKwd, members = $2 - SynTypeDefnSig($1, None, SynTypeDefnSigRepr.Simple (SynTypeDefnSimpleRepr.None (lhs parseState), lhs parseState), mWithKwd, members, lhs parseState) } + let m = + match members with + | [] -> + match mWithKwd with + | None -> rhs parseState 1 + | Some mWithKwd -> unionRanges (rhs parseState 1) mWithKwd + | decls -> + let (SynComponentInfo(range=start)) = $1 + (start, decls) ||> unionRangeWithListBy (fun (s: SynMemberSig) -> s.Range) + SynTypeDefnSig($1, None, SynTypeDefnSigRepr.Simple (SynTypeDefnSimpleRepr.None m, m), mWithKwd, members, m) } /* The right-hand-side of a type definition in a signature */ @@ -930,8 +938,14 @@ tyconSpfnRhs: SynTypeDefnSig(nameInfo, mEquals, SynTypeDefnSigRepr.Simple ($1, $1.Range), None, augmentation, mWhole)) } | tyconClassSpfn - { let objectModelRange = lhs parseState - let needsCheck, (kind, decls) = $1 + { let needsCheck, (kind, decls) = $1 + let objectModelRange = + match decls with + | [] -> lhs parseState + | decls -> + let start = mkSynRange parseState.ResultStartPosition parseState.ResultStartPosition + (start, decls) ||> unionRangeWithListBy (fun (s: SynMemberSig) -> s.Range) + (fun nameRange nameInfo mEquals augmentation -> if needsCheck && isNil decls then reportParseErrorAt nameRange (FSComp.SR.parsEmptyTypeDefinition()) diff --git a/tests/service/Symbols.fs b/tests/service/Symbols.fs index 7ee0d0b8b70..25410d3774f 100644 --- a/tests/service/Symbols.fs +++ b/tests/service/Symbols.fs @@ -1138,8 +1138,9 @@ type MyRecord = match parseResults with | ParsedInput.SigFile (ParsedSigFileInput (modules = [ - SynModuleOrNamespaceSig(decls = [SynModuleSigDecl.Types(types = [SynTypeDefnSig.SynTypeDefnSig(range = r)])]) ])) -> - assertRange (2, 0) (4, 30) r + SynModuleOrNamespaceSig(decls = [SynModuleSigDecl.Types([SynTypeDefnSig.SynTypeDefnSig(range=mSynTypeDefnSig)], mTypes)]) ])) -> + assertRange (2, 0) (4, 30) mTypes + assertRange (2, 5) (4, 30) mSynTypeDefnSig | _ -> Assert.Fail "Could not get valid AST" [] @@ -1154,8 +1155,9 @@ type MyRecord = match parseResults with | ParsedInput.SigFile (ParsedSigFileInput (modules = [ - SynModuleOrNamespaceSig(decls = [SynModuleSigDecl.Types(types = [SynTypeDefnSig.SynTypeDefnSig(range = r)])]) ])) -> - assertRange (2, 0) (5, 30) r + SynModuleOrNamespaceSig(decls = [SynModuleSigDecl.Types([SynTypeDefnSig.SynTypeDefnSig(range=mSynTypeDefnSig)], mTypes)]) ])) -> + assertRange (2, 0) (5, 30) mTypes + assertRange (2, 5) (5, 30) mSynTypeDefnSig | _ -> Assert.Fail "Could not get valid AST" [] @@ -1168,8 +1170,9 @@ type MyFunction = match parseResults with | ParsedInput.SigFile (ParsedSigFileInput (modules = [ - SynModuleOrNamespaceSig(decls = [SynModuleSigDecl.Types(types = [SynTypeDefnSig.SynTypeDefnSig(range = r)])]) ])) -> - assertRange (2, 0) (3, 29) r + SynModuleOrNamespaceSig(decls = [SynModuleSigDecl.Types([SynTypeDefnSig.SynTypeDefnSig(range=mSynTypeDefnSig)], mTypes) ]) ])) -> + assertRange (2, 0) (3, 29) mTypes + assertRange (2, 5) (3, 29) mSynTypeDefnSig | _ -> Assert.Fail "Could not get valid AST" [] @@ -1183,8 +1186,9 @@ type SomeCollection with match parseResults with | ParsedInput.SigFile (ParsedSigFileInput (modules = [ - SynModuleOrNamespaceSig(decls = [SynModuleSigDecl.Types(types = [SynTypeDefnSig.SynTypeDefnSig(range = r)])]) ])) -> - assertRange (2, 0) (4, 37) r + SynModuleOrNamespaceSig(decls = [SynModuleSigDecl.Types([SynTypeDefnSig.SynTypeDefnSig(range=mSynTypeDefnSig)], mTypes)]) ])) -> + assertRange (2, 0) (4, 37) mTypes + assertRange (2, 5) (4, 37) mSynTypeDefnSig | _ -> Assert.Fail "Could not get valid AST" [] @@ -1227,13 +1231,13 @@ and [] Bang = match parseResults with | ParsedInput.SigFile (ParsedSigFileInput (modules = [ - SynModuleOrNamespaceSig(decls = [SynModuleSigDecl.Types(types = [ + SynModuleOrNamespaceSig(decls = [SynModuleSigDecl.Types([ SynTypeDefnSig.SynTypeDefnSig(range = r1) SynTypeDefnSig.SynTypeDefnSig(range = r2) - ]) as t]) ])) -> - assertRange (4, 0) (5, 9) r1 + ], mTypes)]) ])) -> + assertRange (4, 5) (5, 9) r1 assertRange (7, 4) (12, 42) r2 - assertRange (4, 0) (12, 42) t.Range + assertRange (4, 0) (12, 42) mTypes | _ -> Assert.Fail "Could not get valid AST" [] @@ -1717,6 +1721,98 @@ module X = assertRange (4, 9) (4, 10) equalsM | _ -> Assert.Fail "Could not get valid AST" + [] + let ``Range of nested module in signature file should end at the last SynModuleSigDecl`` () = + let parseResults = + getParseResultsOfSignatureFile + """namespace Microsoft.FSharp.Core + +open System +open System.Collections.Generic +open Microsoft.FSharp.Core +open Microsoft.FSharp.Collections +open System.Collections + + +module Tuple = + + type Tuple<'T1,'T2,'T3,'T4> = + interface IStructuralEquatable + interface IStructuralComparable + interface IComparable + new : 'T1 * 'T2 * 'T3 * 'T4 -> Tuple<'T1,'T2,'T3,'T4> + member Item1 : 'T1 with get + member Item2 : 'T2 with get + member Item3 : 'T3 with get + member Item4 : 'T4 with get + + +module Choice = + + /// Helper types for active patterns with 6 choices. + [] + [] + type Choice<'T1,'T2,'T3,'T4,'T5,'T6> = + /// Choice 1 of 6 choices + | Choice1Of6 of 'T1 + /// Choice 2 of 6 choices + | Choice2Of6 of 'T2 + /// Choice 3 of 6 choices + | Choice3Of6 of 'T3 + /// Choice 4 of 6 choices + | Choice4Of6 of 'T4 + /// Choice 5 of 6 choices + | Choice5Of6 of 'T5 + /// Choice 6 of 6 choices + | Choice6Of6 of 'T6 + + + +/// Basic F# Operators. This module is automatically opened in all F# code. +[] +module Operators = + + type ``[,]``<'T> with + [] + /// Get the length of an array in the first dimension + member Length1 : int + [] + /// Get the length of the array in the second dimension + member Length2 : int + [] + /// Get the lower bound of the array in the first dimension + member Base1 : int + [] + /// Get the lower bound of the array in the second dimension + member Base2 : int +""" + + match parseResults with + | ParsedInput.SigFile (ParsedSigFileInput (modules = [ SynModuleOrNamespaceSig(decls = [ + SynModuleSigDecl.Open _ + SynModuleSigDecl.Open _ + SynModuleSigDecl.Open _ + SynModuleSigDecl.Open _ + SynModuleSigDecl.Open _ + SynModuleSigDecl.NestedModule(range=mTupleModule; moduleDecls=[ SynModuleSigDecl.Types([ + SynTypeDefnSig(typeRepr=SynTypeDefnSigRepr.ObjectModel(range=mTupleObjectModel); range=mTupleType) + ], mTupleTypes) ]) + SynModuleSigDecl.NestedModule(range=mChoiceModule) + SynModuleSigDecl.NestedModule(range=mOperatorsModule; moduleDecls=[ SynModuleSigDecl.Types([ + SynTypeDefnSig(typeRepr=SynTypeDefnSigRepr.Simple(range=mAugmentationSimple); range=mAugmentation) + ], mOperatorsTypes) ]) + ]) ])) -> + assertRange (10, 0) (20, 35) mTupleModule + assertRange (12, 4) (20, 35) mTupleTypes + assertRange (12, 9) (20, 35) mTupleType + assertRange (13, 8) (20, 35) mTupleObjectModel + assertRange (23, 0) (40, 25) mChoiceModule + assertRange (45, 0) (60, 26) mOperatorsModule + assertRange (48, 4) (60, 26) mOperatorsTypes + assertRange (48, 9) (60, 26) mAugmentation + assertRange (48, 9) (60, 26) mAugmentationSimple + | _ -> Assert.Fail "Could not get valid AST" + module SynBindings = [] let ``Range of attribute should be included in SynModuleDecl.Let`` () =