diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index 1bfa151a0e4..68d94dddae4 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -156,6 +156,8 @@ let mkClassMemberLocalBindings(isStatic, initialRangeOpt, attrs, vis, BindingSet match initialRangeOpt with | None -> bindingSetRange | Some m -> unionRanges m bindingSetRange + // decls could have a leading attribute + |> fun m -> (m, decls) ||> unionRangeWithListBy (fun (SynBinding(range = m)) -> m) if not (isNil ignoredFreeAttrs) then warning(Error(FSComp.SR.parsAttributesIgnored(), wholeRange)); if isUse then errorR(Error(FSComp.SR.parsUseBindingsIllegalInImplicitClassConstructors(), wholeRange)) SynMemberDefn.LetBindings (decls, isStatic, isRec, wholeRange) @@ -167,7 +169,9 @@ let mkLocalBindings (mWhole, BindingSetPreAttrs(_, isRec, isUse, declsPreAttrs, let mkDefnBindings (mWhole, BindingSetPreAttrs(_, isRec, isUse, declsPreAttrs, _bindingSetRange), attrs, vis, attrsm) = if isUse then warning(Error(FSComp.SR.parsUseBindingsIllegalInModules(), mWhole)) - let freeAttrs, decls = declsPreAttrs attrs vis + let freeAttrs, decls = declsPreAttrs attrs vis + // decls might have an extended range due to leading attributes + let mWhole = (mWhole, decls) ||> unionRangeWithListBy (fun (SynBinding(range = m)) -> m) let letDecls = [ SynModuleDecl.Let (isRec, decls, mWhole) ] let attrDecls = if not (isNil freeAttrs) then [ SynModuleDecl.Attributes (freeAttrs, attrsm) ] else [] attrDecls @ letDecls @@ -1292,7 +1296,9 @@ moduleDefn: | opt_attributes opt_declVisibility typeKeyword tyconDefn tyconDefnList { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) let (SynTypeDefn(SynComponentInfo(cas, a, cs, b, c, d, d2, d3), e, f, g, h)) = $4 - let tc = (SynTypeDefn(SynComponentInfo($1@cas, a, cs, b, c, d, d2, d3), e, f, g, h)) + let attrs = $1@cas + let mTc = (h, attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range) + let tc = (SynTypeDefn(SynComponentInfo(attrs, a, cs, b, c, d, d2, d3), e, f, g, mTc)) let types = tc :: $5 [ SynModuleDecl.Types(types, (rhs parseState 3, types) ||> unionRangeWithListBy (fun t -> t.Range) ) ] } @@ -1717,7 +1723,8 @@ memberCore: let bindingBuilder, mBindLhs = $2 (fun vis memFlagsBuilder attrs rangeStart -> let memberFlags = Some (memFlagsBuilder SynMemberKind.Member) - let binding = bindingBuilder (vis, $1, false, mBindLhs, DebugPointAtBinding.NoneAtInvisible, optReturnType, $5, mRhs, [], attrs, memberFlags) + let mWholeBindLhs = (mBindLhs, attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range) + let binding = bindingBuilder (vis, $1, false, mWholeBindLhs, DebugPointAtBinding.NoneAtInvisible, optReturnType, $5, mRhs, [], attrs, memberFlags) let memberRange = unionRanges rangeStart mRhs [ SynMemberDefn.Member (binding, memberRange) ]) } @@ -1794,7 +1801,8 @@ memberCore: // REDO with the correct member kind let binding = bindingBuilder(vis, isInline, isMutable, mBindLhs, DebugPointAtBinding.NoneAtInvisible, optReturnType, expr, exprm, [], attrs, Some(memFlagsBuilder memberKind)) - let (SynBinding (vis, _, isInline, _, attrs, doc, valSynData, pv, rhsRetInfo, rhsExpr, mBindLhs, spBind)) = binding + let (SynBinding (vis, _, isInline, _, attrs, doc, valSynData, pv, rhsRetInfo, rhsExpr, mBindLhs, spBind)) = binding + let mWholeBindLhs = (mBindLhs, attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range) let (SynValData(_, valSynInfo, _)) = valSynData @@ -1811,16 +1819,16 @@ memberCore: match memberKind, valSynInfo, memFlags.IsInstance with | SynMemberKind.PropertyGet, SynValInfo ([], _ret), false | SynMemberKind.PropertyGet, SynValInfo ([_], _ret), true -> - raiseParseErrorAt mBindLhs (FSComp.SR.parsGetterMustHaveAtLeastOneArgument()) + raiseParseErrorAt mWholeBindLhs (FSComp.SR.parsGetterMustHaveAtLeastOneArgument()) | SynMemberKind.PropertyGet, SynValInfo (thisArg :: indexOrUnitArgs :: rest, ret), true -> if not rest.IsEmpty then - reportParseErrorAt mBindLhs (FSComp.SR.parsGetterAtMostOneArgument ()) + reportParseErrorAt mWholeBindLhs (FSComp.SR.parsGetterAtMostOneArgument ()) SynValInfo ([thisArg; indexOrUnitArgs], ret) | SynMemberKind.PropertyGet, SynValInfo (indexOrUnitArgs :: rest, ret), false -> if not rest.IsEmpty then - reportParseErrorAt mBindLhs (FSComp.SR.parsGetterAtMostOneArgument ()) + reportParseErrorAt mWholeBindLhs (FSComp.SR.parsGetterAtMostOneArgument ()) SynValInfo ([indexOrUnitArgs], ret) | SynMemberKind.PropertySet, SynValInfo ([thisArg;valueArg], ret), true -> @@ -1828,7 +1836,7 @@ memberCore: | SynMemberKind.PropertySet, SynValInfo (thisArg :: indexArgs :: valueArg :: rest, ret), true -> if not rest.IsEmpty then - reportParseErrorAt mBindLhs (FSComp.SR.parsSetterAtMostTwoArguments ()) + reportParseErrorAt mWholeBindLhs (FSComp.SR.parsSetterAtMostTwoArguments ()) SynValInfo ([thisArg; indexArgs @ adjustValueArg valueArg], ret) | SynMemberKind.PropertySet, SynValInfo ([valueArg], ret), false -> @@ -1836,12 +1844,12 @@ memberCore: | SynMemberKind.PropertySet, SynValInfo (indexArgs :: valueArg :: rest, ret), _ -> if not rest.IsEmpty then - reportParseErrorAt mBindLhs (FSComp.SR.parsSetterAtMostTwoArguments ()) + reportParseErrorAt mWholeBindLhs (FSComp.SR.parsSetterAtMostTwoArguments ()) SynValInfo ([indexArgs @ adjustValueArg valueArg], ret) | _ -> // should be unreachable, cover just in case - raiseParseErrorAt mBindLhs (FSComp.SR.parsInvalidProperty ()) + raiseParseErrorAt mWholeBindLhs (FSComp.SR.parsInvalidProperty ()) let valSynData = SynValData(Some(memFlags), valSynInfo, None) @@ -1851,7 +1859,7 @@ memberCore: let bindingPatAdjusted, xmlDocAdjusted = - let bindingOuter = propertyNameBindingBuilder(vis, optInline, isMutable, mBindLhs, spBind, optReturnType, expr, exprm, [], attrs, Some(memFlagsBuilder SynMemberKind.Member)) + let bindingOuter = propertyNameBindingBuilder(vis, optInline, isMutable, mWholeBindLhs, spBind, optReturnType, expr, exprm, [], attrs, Some(memFlagsBuilder SynMemberKind.Member)) let (SynBinding (_, _, _, _, _, doc2, _, bindingPatOuter, _, _, _, _)) = bindingOuter @@ -1859,7 +1867,7 @@ memberCore: match bindingPatOuter with | SynPat.LongIdent (lid, None, None, SynArgPats.Pats [], lidVisOuter, m) -> lid, lidVisOuter | SynPat.Named (_, id, _, visOuter, m) -> LongIdentWithDots([id], []), visOuter - | p -> raiseParseErrorAt mBindLhs (FSComp.SR.parsInvalidDeclarationSyntax()) + | p -> raiseParseErrorAt mWholeBindLhs (FSComp.SR.parsInvalidDeclarationSyntax()) // Merge the visibility from the outer point with the inner point, e.g. // member this.Size with get () = m_size @@ -1869,7 +1877,7 @@ memberCore: | None, None -> None | Some lidVisInner, None | None, Some lidVisInner -> Some lidVisInner | Some _, Some _ -> - errorR(Error(FSComp.SR.parsMultipleAccessibilitiesForGetSet(), mBindLhs)) + errorR(Error(FSComp.SR.parsMultipleAccessibilitiesForGetSet(), mWholeBindLhs)) lidVisInner // Replace the "get" or the "set" with the right name @@ -1897,11 +1905,11 @@ memberCore: | SynPat.Typed (p, ty, m) -> SynPat.Typed(go p, ty, m) | SynPat.Attrib (p, attribs, m) -> SynPat.Attrib(go p, attribs, m) | SynPat.Wild(m) -> SynPat.Wild(m) - | _ -> raiseParseErrorAt mBindLhs (FSComp.SR.parsInvalidDeclarationSyntax()) + | _ -> raiseParseErrorAt mWholeBindLhs (FSComp.SR.parsInvalidDeclarationSyntax()) go pv, PreXmlDoc.Merge doc2 doc - let binding = SynBinding (vis, SynBindingKind.Normal, isInline, isMutable, attrs, xmlDocAdjusted, valSynData, bindingPatAdjusted, rhsRetInfo, rhsExpr, mBindLhs, spBind) + let binding = SynBinding (vis, SynBindingKind.Normal, isInline, isMutable, attrs, xmlDocAdjusted, valSynData, bindingPatAdjusted, rhsRetInfo, rhsExpr, mWholeBindLhs, spBind) let memberRange = unionRanges rangeStart mWhole Some (SynMemberDefn.Member (binding, memberRange)))) } @@ -1976,14 +1984,15 @@ classDefnMember: $4 $1 isStatic flags rangeStart } | opt_attributes opt_declVisibility NEW atomicPattern optAsSpec EQUALS typedSeqExprBlock opt_ODECLEND - { let m = unionRanges (rhs2 parseState 1 6) $7.Range + { let mWholeBindLhs = rhs2 parseState 1 (if Option.isSome $5 then 5 else 4) + let m = unionRanges mWholeBindLhs $7.Range let expr = $7 let valSynData = SynValData (Some CtorMemberFlags, SynValInfo([SynInfo.InferSynArgInfoFromPat $4], SynInfo.unnamedRetVal), $5) let vis = $2 let declPat = SynPat.LongIdent (LongIdentWithDots([mkSynId (rhs parseState 3) "new"], []), None, Some noInferredTypars, SynArgPats.Pats [$4], vis, rhs parseState 3) // Check that 'SynPatForConstructorDecl' matches this correctly assert (match declPat with SynPatForConstructorDecl _ -> true | _ -> false) - [ SynMemberDefn.Member(SynBinding (None, SynBindingKind.Normal, false, false, $1, grabXmlDoc(parseState, 3), valSynData, declPat, None, expr, m, DebugPointAtBinding.NoneAtInvisible), m) ] } + [ SynMemberDefn.Member(SynBinding (None, SynBindingKind.Normal, false, false, $1, grabXmlDoc(parseState, 3), valSynData, declPat, None, expr, mWholeBindLhs, DebugPointAtBinding.NoneAtInvisible), m) ] } | opt_attributes opt_declVisibility STATIC typeKeyword tyconDefn { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(), rhs parseState 2)) @@ -2802,9 +2811,10 @@ localBinding: let localBindingRange = unionRanges (rhs2 parseState 1 5) mRhs let localBindingBuilder = (fun attrs vis mLetKwd -> - let mWhole = unionRanges mLetKwd mRhs + let mWhole = (unionRanges mLetKwd mRhs, attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range) let spBind = if IsControlFlowExpression expr then DebugPointAtBinding.NoneAtLet else DebugPointAtBinding.Yes mWhole - bindingBuilder (vis, $1, $2, mBindLhs, spBind, optReturnType, expr, mRhs, opts, attrs, None)) + let mWholeBindLhs = (mBindLhs, attrs) ||> unionRangeWithListBy (fun (a: SynAttributeList) -> a.Range) + bindingBuilder (vis, $1, $2, mWholeBindLhs, spBind, optReturnType, expr, mRhs, opts, attrs, None)) localBindingRange, localBindingBuilder } | opt_inline opt_mutable bindingPattern opt_topReturnTypeWithTypeConstraints EQUALS error diff --git a/src/fsharp/service/ServiceStructure.fs b/src/fsharp/service/ServiceStructure.fs index b58b8f42a3f..70ad81fb5c1 100644 --- a/src/fsharp/service/ServiceStructure.fs +++ b/src/fsharp/service/ServiceStructure.fs @@ -443,9 +443,8 @@ module Structure = | SynBindingKind.Normal -> let collapse = Range.endToEnd binding.RangeOfBindingWithoutRhs binding.RangeOfBindingWithRhs match memberFlags with - | Some ({MemberKind=SynMemberKind.Constructor}) -> - let collapse = Range.startToEnd expr.Range br - rcheck Scope.New Collapse.Below br collapse + | Some {MemberKind=SynMemberKind.Constructor} -> + rcheck Scope.New Collapse.Below binding.RangeOfBindingWithRhs collapse | Some _ -> rcheck Scope.Member Collapse.Below binding.RangeOfBindingWithRhs collapse | None -> diff --git a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/InvalidLiteralTests.fs b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/InvalidLiteralTests.fs index f3d62e97410..fb44f2b717b 100644 --- a/tests/FSharp.Compiler.ComponentTests/ErrorMessages/InvalidLiteralTests.fs +++ b/tests/FSharp.Compiler.ComponentTests/ErrorMessages/InvalidLiteralTests.fs @@ -15,4 +15,4 @@ let [] (A x) = 1 """ |> typecheck |> shouldFail - |> withSingleDiagnostic (Error 3391, Line 3, Col 17, Line 3, Col 22, "A [] declaration cannot use an active pattern for its identifier") + |> withSingleDiagnostic (Error 3391, Line 3, Col 5, Line 3, Col 22, "A [] declaration cannot use an active pattern for its identifier") diff --git a/tests/fsharp/typecheck/sigs/neg10.bsl b/tests/fsharp/typecheck/sigs/neg10.bsl index dcca6ff0871..efbe9b93b80 100644 --- a/tests/fsharp/typecheck/sigs/neg10.bsl +++ b/tests/fsharp/typecheck/sigs/neg10.bsl @@ -15,7 +15,7 @@ neg10.fs(16,32,16,34): typecheck error FS1207: Interfaces inherited by other int neg10.fs(17,28,17,30): typecheck error FS0887: The type 'C1' is not an interface type -neg10.fs(19,17,19,28): typecheck error FS0870: Structs cannot have an object constructor with no arguments. This is a restriction imposed on all CLI languages as structs automatically support a default constructor. +neg10.fs(19,17,19,22): typecheck error FS0870: Structs cannot have an object constructor with no arguments. This is a restriction imposed on all CLI languages as structs automatically support a default constructor. neg10.fs(21,16,21,46): typecheck error FS0001: A generic construct requires that the type 'System.Enum' have a public default constructor diff --git a/tests/fsharp/typecheck/sigs/neg16.bsl b/tests/fsharp/typecheck/sigs/neg16.bsl index 72bcb7e0b85..c32ad022d1f 100644 --- a/tests/fsharp/typecheck/sigs/neg16.bsl +++ b/tests/fsharp/typecheck/sigs/neg16.bsl @@ -73,24 +73,24 @@ neg16.fs(90,8,90,18): typecheck error FS0039: The pattern discriminator 'FooB++' neg16.fs(90,7,90,22): typecheck error FS0025: Incomplete pattern matches on this expression. -neg16.fs(97,15,97,16): typecheck error FS0823: The 'VolatileField' attribute may only be used on 'let' bindings in classes +neg16.fs(96,3,97,16): typecheck error FS0823: The 'VolatileField' attribute may only be used on 'let' bindings in classes -neg16.fs(100,11,100,14): typecheck error FS0823: The 'VolatileField' attribute may only be used on 'let' bindings in classes +neg16.fs(99,3,100,14): typecheck error FS0823: The 'VolatileField' attribute may only be used on 'let' bindings in classes -neg16.fs(100,11,100,14): typecheck error FS0879: Volatile fields must be marked 'mutable' and cannot be thread-static +neg16.fs(99,3,100,14): typecheck error FS0879: Volatile fields must be marked 'mutable' and cannot be thread-static -neg16.fs(103,7,103,9): typecheck error FS0823: The 'VolatileField' attribute may only be used on 'let' bindings in classes +neg16.fs(102,3,103,9): typecheck error FS0823: The 'VolatileField' attribute may only be used on 'let' bindings in classes -neg16.fs(103,7,103,9): typecheck error FS0879: Volatile fields must be marked 'mutable' and cannot be thread-static +neg16.fs(102,3,103,9): typecheck error FS0879: Volatile fields must be marked 'mutable' and cannot be thread-static neg16.fs(119,17,119,24): typecheck error FS0823: The 'VolatileField' attribute may only be used on 'let' bindings in classes -neg16.fs(107,16,107,19): typecheck error FS0879: Volatile fields must be marked 'mutable' and cannot be thread-static +neg16.fs(106,5,107,19): typecheck error FS0879: Volatile fields must be marked 'mutable' and cannot be thread-static -neg16.fs(110,16,110,20): typecheck error FS0879: Volatile fields must be marked 'mutable' and cannot be thread-static +neg16.fs(109,5,110,20): typecheck error FS0879: Volatile fields must be marked 'mutable' and cannot be thread-static -neg16.fs(113,9,113,11): typecheck error FS0879: Volatile fields must be marked 'mutable' and cannot be thread-static +neg16.fs(112,5,113,11): typecheck error FS0879: Volatile fields must be marked 'mutable' and cannot be thread-static -neg16.fs(116,9,116,13): typecheck error FS0879: Volatile fields must be marked 'mutable' and cannot be thread-static +neg16.fs(115,5,116,13): typecheck error FS0879: Volatile fields must be marked 'mutable' and cannot be thread-static neg16.fs(130,10,130,11): typecheck error FS0935: Types with the 'AllowNullLiteral' attribute may only inherit from or implement types which also allow the use of the null literal diff --git a/tests/fsharp/typecheck/sigs/neg20.bsl b/tests/fsharp/typecheck/sigs/neg20.bsl index 4227ab07193..75d06ce1332 100644 --- a/tests/fsharp/typecheck/sigs/neg20.bsl +++ b/tests/fsharp/typecheck/sigs/neg20.bsl @@ -305,7 +305,7 @@ neg20.fs(195,5,195,10): typecheck error FS0842: This attribute is not valid for neg20.fs(198,5,198,11): typecheck error FS0842: This attribute is not valid for use on this language element -neg20.fs(202,7,202,9): typecheck error FS0825: The 'DefaultValue' attribute may only be used on 'val' declarations +neg20.fs(201,3,202,9): typecheck error FS0825: The 'DefaultValue' attribute may only be used on 'val' declarations neg20.fs(204,5,204,14): typecheck error FS0842: This attribute is not valid for use on this language element diff --git a/tests/fsharp/typecheck/sigs/neg47.bsl b/tests/fsharp/typecheck/sigs/neg47.bsl index 52964659d68..7653ed8d5b1 100644 --- a/tests/fsharp/typecheck/sigs/neg47.bsl +++ b/tests/fsharp/typecheck/sigs/neg47.bsl @@ -1,8 +1,8 @@ neg47.fs(18,9,18,26): typecheck error FS1221: DLLImport bindings must be static members in a class or function definitions in a module -neg47.fs(24,12,24,33): typecheck error FS1221: DLLImport bindings must be static members in a class or function definitions in a module +neg47.fs(23,5,24,33): typecheck error FS1221: DLLImport bindings must be static members in a class or function definitions in a module -neg47.fs(29,16,29,27): typecheck error FS1221: DLLImport bindings must be static members in a class or function definitions in a module +neg47.fs(28,9,29,27): typecheck error FS1221: DLLImport bindings must be static members in a class or function definitions in a module -neg47.fs(33,12,33,27): typecheck error FS1221: DLLImport bindings must be static members in a class or function definitions in a module +neg47.fs(32,5,33,27): typecheck error FS1221: DLLImport bindings must be static members in a class or function definitions in a module diff --git a/tests/fsharpqa/Source/Conformance/DeclarationElements/CustomAttributes/Basic/E_StructLayout.fs b/tests/fsharpqa/Source/Conformance/DeclarationElements/CustomAttributes/Basic/E_StructLayout.fs index 7a31a7e5a4d..3a3c7a5419a 100644 --- a/tests/fsharpqa/Source/Conformance/DeclarationElements/CustomAttributes/Basic/E_StructLayout.fs +++ b/tests/fsharpqa/Source/Conformance/DeclarationElements/CustomAttributes/Basic/E_StructLayout.fs @@ -1,8 +1,8 @@ // #Regression #Conformance #DeclarationElements #Attributes // Tests to ensure that you can't use StructLayout inappropriately // Regression tests for FSHARP1.0:5931 -//The type 'SExplicitBroken' has been marked as having an Explicit layout, but the field 'v2' has not been marked with the 'FieldOffset' attribute$ -//The FieldOffset attribute can only be placed on members of types marked with the StructLayout\(LayoutKind\.Explicit\)$ +//The type 'SExplicitBroken' has been marked as having an Explicit layout, but the field 'v2' has not been marked with the 'FieldOffset' attribute$ +//The FieldOffset attribute can only be placed on members of types marked with the StructLayout\(LayoutKind\.Explicit\)$ module M diff --git a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/System.ThreadStatic/W_Deprecated01.fs b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/System.ThreadStatic/W_Deprecated01.fs index fab0d7f9e46..60f29755a2a 100644 --- a/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/System.ThreadStatic/W_Deprecated01.fs +++ b/tests/fsharpqa/Source/Conformance/SpecialAttributesAndTypes/Imported/System.ThreadStatic/W_Deprecated01.fs @@ -1,7 +1,7 @@ // #Regression #Conformance #Attributes // Regression test for FSHARP1.0:4226 // We want to make sure the warning emits the correct suggestion (val and mutable were swapped) -//Thread static and context static 'let' bindings are deprecated\. Instead use a declaration of the form 'static val mutable : ' in a class\. Add the 'DefaultValue' attribute to this declaration to indicate that the value is initialized to the default value on each new thread\.$ +//Thread static and context static 'let' bindings are deprecated\. Instead use a declaration of the form 'static val mutable : ' in a class\. Add the 'DefaultValue' attribute to this declaration to indicate that the value is initialized to the default value on each new thread\.$ module M module Foo = [] diff --git a/tests/fsharpqa/Source/EntryPoint/E_twoentrypoints001.fs b/tests/fsharpqa/Source/EntryPoint/E_twoentrypoints001.fs index 2570a557776..ab5028ccc8a 100644 --- a/tests/fsharpqa/Source/EntryPoint/E_twoentrypoints001.fs +++ b/tests/fsharpqa/Source/EntryPoint/E_twoentrypoints001.fs @@ -3,7 +3,7 @@ // Explicit program entry point: [] // attribute on multiple functions //Hello -//A function labeled with the 'EntryPointAttribute' attribute must be the last declaration in the last file in the compilation sequence. +//A function labeled with the 'EntryPointAttribute' attribute must be the last declaration in the last file in the compilation sequence. #light module M = diff --git a/tests/service/StructureTests.fs b/tests/service/StructureTests.fs index 280c2a206e8..cb9f1a6d0c8 100644 --- a/tests/service/StructureTests.fs +++ b/tests/service/StructureTests.fs @@ -651,11 +651,11 @@ type T() = """ => [ (2, 5, 11, 12), (2, 7, 11, 12) (3, 4, 4, 12), (3, 7, 4, 12) - (3, 4, 4, 12), (4, 8, 4, 12) + (3, 4, 4, 12), (3, 10, 4, 12) (6, 4, 7, 12), (6, 16, 7, 12) - (6, 4, 7, 12), (7, 8, 7, 12) + (6, 4, 7, 12), (6, 19, 7, 12) (9, 4, 11, 12), (10, 7, 11, 12) - (9, 4, 11, 12), (11, 8, 11, 12) ] + (9, 4, 11, 12), (10, 10, 11, 12) ] [] diff --git a/tests/service/Symbols.fs b/tests/service/Symbols.fs index 28fce3c387f..8babd6f27bc 100644 --- a/tests/service/Symbols.fs +++ b/tests/service/Symbols.fs @@ -296,6 +296,48 @@ type Foo = assertRange (4, 12) (4, 13) r2 | _ -> Assert.Fail "Could not get valid AST" + [] + let ``Range of attribute should be included in SynTypeDefn`` () = + let parseResults = + getParseResults + """ +[] +type Bar = + class + end""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Types(typeDefns = [t]) as types + ]) ])) -> + assertRange (2, 0) (5, 7) types.Range + assertRange (2, 0) (5, 7) t.Range + | _ -> Assert.Fail "Could not get valid AST" + + [] + let ``Range of attributes should be included in recursive types`` () = + let parseResults = + getParseResults + """ +[] +type Foo<'context, 'a> = + | Apply of ApplyCrate<'context, 'a> + +and [] Bar<'context, 'a> = + internal { + Hash : int + Foo : Foo<'a, 'b> + }""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Types(typeDefns = [t1;t2]) as types + ]) ])) -> + assertRange (2, 0) (10, 5) types.Range + assertRange (2, 0) (4, 39) t1.Range + assertRange (6, 4) (10, 5) t2.Range + | _ -> Assert.Fail "Could not get valid AST" + module SyntaxExpressions = [] let ``SynExpr.Do contains the range of the do keyword`` () = @@ -902,4 +944,213 @@ module Nested = ]) as sigModule ])) -> assertRange (4, 0) (6, 15) nm.Range assertRange (2, 0) (6, 15) sigModule.Range + | _ -> Assert.Fail "Could not get valid AST" + + [] + let ``Range of attribute should be included in SynModuleDecl.NestedModule`` () = + let parseResults = + getParseResults + """ +module TopLevel + +[] +module Nested = + ()""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.NestedModule _ as nm + ]) ])) -> + assertRange (4, 0) (6, 6) nm.Range + | _ -> Assert.Fail "Could not get valid AST" + +module SynBindings = + [] + let ``Range of attribute should be included in SynModuleDecl.Let`` () = + let parseResults = + getParseResults + """ +[] +let a = 0""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Let(bindings = [SynBinding(range = mb)]) as lt + ]) ])) -> + assertRange (2, 0) (3, 5) mb + assertRange (2, 0) (3, 9) lt.Range + | _ -> Assert.Fail "Could not get valid AST" + + [] + let ``Range of attribute between let keyword and pattern should be included in SynModuleDecl.Let`` () = + let parseResults = + getParseResults + """ +let [] (A x) = 1""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Let(bindings = [SynBinding(range = mb)]) as lt + ]) ])) -> + assertRange (2, 4) (2, 21) mb + assertRange (2, 0) (2, 25) lt.Range + | _ -> Assert.Fail "Could not get valid AST" + + [] + let ``Range of attribute should be included in SynMemberDefn.LetBindings`` () = + let parseResults = + getParseResults + """ +type Bar = + [] + let x = 8""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Types(typeDefns = [SynTypeDefn(typeRepr = SynTypeDefnRepr.ObjectModel(members = [SynMemberDefn.LetBindings(bindings = [SynBinding(range = mb)]) as m]))]) + ]) ])) -> + assertRange (3, 4) (4, 9) mb + assertRange (3, 4) (4, 13) m.Range + | _ -> Assert.Fail "Could not get valid AST" + + [] + let ``Range of attribute should be included in SynMemberDefn.Member`` () = + let parseResults = + getParseResults + """ +type Bar = + [] + member this.Something () = ()""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Types(typeDefns = [SynTypeDefn(typeRepr = SynTypeDefnRepr.ObjectModel(members = [SynMemberDefn.Member(memberDefn = SynBinding(range = mb)) as m]))]) + ]) ])) -> + assertRange (3, 4) (4, 28) mb + assertRange (3, 4) (4, 33) m.Range + | _ -> Assert.Fail "Could not get valid AST" + + [] + let ``Range of attribute should be included in binding of SynExpr.ObjExpr`` () = + let parseResults = + getParseResults + """ +{ new System.Object() with + [] + member x.ToString() = "F#" }""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.DoExpr(expr = SynExpr.ObjExpr(bindings = [SynBinding(range = mb)])) + ]) ])) -> + assertRange (3, 4) (4, 23) mb + | _ -> Assert.Fail "Could not get valid AST" + + [] + let ``Range of attribute should be included in constructor SynMemberDefn.Member`` () = + let parseResults = + getParseResults + """ +type Tiger = + [] + new () = ()""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Types(typeDefns = [SynTypeDefn(typeRepr = SynTypeDefnRepr.ObjectModel(members = [SynMemberDefn.Member(memberDefn = SynBinding(range = mb)) as m]))]) + ]) ])) -> + assertRange (3, 4) (4, 10) mb + assertRange (3, 4) (4, 15) m.Range + | _ -> Assert.Fail "Could not get valid AST" + + [] + let ``Range of attribute should be included in constructor SynMemberDefn.Member, optAsSpec`` () = + let parseResults = + getParseResults + """ +type Tiger = + [] + new () as tony = ()""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Types(typeDefns = [SynTypeDefn(typeRepr = SynTypeDefnRepr.ObjectModel(members = [SynMemberDefn.Member(memberDefn = SynBinding(range = mb)) as m]))]) + ]) ])) -> + assertRange (3, 4) (4, 18) mb + assertRange (3, 4) (4, 23) m.Range + | _ -> Assert.Fail "Could not get valid AST" + + [] + let ``Range of attribute should be included in secondary constructor`` () = + let parseResults = + getParseResults + """ +type T() = + new () = + T () + + internal new () = + T () + + [] + new () = + T ()""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Types(typeDefns = [SynTypeDefn(typeRepr = SynTypeDefnRepr.ObjectModel(members = [ + SynMemberDefn.ImplicitCtor _ + SynMemberDefn.Member(memberDefn = SynBinding(range = mb1)) as m1 + SynMemberDefn.Member(memberDefn = SynBinding(range = mb2)) as m2 + SynMemberDefn.Member(memberDefn = SynBinding(range = mb3)) as m3 + ]))]) + ]) ])) -> + assertRange (3, 4) (3, 10) mb1 + assertRange (3, 4) (4, 12) m1.Range + assertRange (6, 4) (6, 19) mb2 + assertRange (6, 4) (7, 12) m2.Range + assertRange (9, 4) (10, 10) mb3 + assertRange (9, 4) (11, 12) m3.Range + | _ -> Assert.Fail "Could not get valid AST" + + + [] + let ``Range of attribute should be included in write only SynMemberDefn.Member property`` () = + let parseResults = + getParseResults + """ +type Crane = + [] + member this.MyWriteOnlyProperty with set (value) = myInternalValue <- value""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Types(typeDefns = [SynTypeDefn(typeRepr = SynTypeDefnRepr.ObjectModel(members = [SynMemberDefn.Member(memberDefn = SynBinding(range = mb)) as m]))]) + ]) ])) -> + assertRange (3, 4) (4, 52) mb + assertRange (3, 4) (4, 79) m.Range + | _ -> Assert.Fail "Could not get valid AST" + + [] + let ``Range of attribute should be included in full SynMemberDefn.Member property`` () = + let parseResults = + getParseResults + """ +type Bird = + [] + member this.TheWord + with get () = myInternalValue + and set (value) = myInternalValue <- value""" + + match parseResults with + | ParsedInput.ImplFile (ParsedImplFileInput (modules = [ SynModuleOrNamespace.SynModuleOrNamespace(decls = [ + SynModuleDecl.Types(typeDefns = [SynTypeDefn(typeRepr = SynTypeDefnRepr.ObjectModel(members = [ + SynMemberDefn.Member(memberDefn = SynBinding(range = mb1)) as getter + SynMemberDefn.Member(memberDefn = SynBinding(range = mb2)) as setter + ]))]) + ]) ])) -> + assertRange (3, 4) (5, 19) mb1 + assertRange (3, 4) (6, 50) getter.Range + assertRange (3, 4) (6, 23) mb2 + assertRange (3, 4) (6, 50) setter.Range | _ -> Assert.Fail "Could not get valid AST" \ No newline at end of file