diff --git a/src/fsharp/pars.fsy b/src/fsharp/pars.fsy index 64011e2c40742dd8413e7d139fbe085d15a58f57..8a4988935c11f20a38d19ba7e8e515cdf50f72d6 100644 --- a/src/fsharp/pars.fsy +++ b/src/fsharp/pars.fsy @@ -1623,21 +1623,23 @@ classDefnMemberGetSetElement: /* The core of a member definition */ memberCore: /* Methods and simple getter properties */ - | opt_inline bindingPattern opt_topReturnTypeWithTypeConstraints EQUALS typedSeqExprBlock - { let mRhs = $5.Range - let mWhole = unionRanges (rhs2 parseState 3 4) mRhs - let optReturnType = $3 - let bindingBuilder,mBindLhs = $2 - (fun vis memFlagsBuilder attrs -> - [ SynMemberDefn.Member (bindingBuilder (vis,$1,false,mBindLhs,NoSequencePointAtInvisibleBinding,optReturnType,$5,mRhs,[],attrs,Some(memFlagsBuilder MemberKind.Member)),unionRanges mWhole mBindLhs) ]) } + | opt_inline bindingPattern opt_topReturnTypeWithTypeConstraints EQUALS typedSeqExprBlock + { let mRhs = $5.Range + let optReturnType = $3 + let bindingBuilder, mBindLhs = $2 + (fun vis memFlagsBuilder attrs rangeStart -> + let memberFlags = Some (memFlagsBuilder MemberKind.Member) + let binding = bindingBuilder (vis, $1, false, mBindLhs, NoSequencePointAtInvisibleBinding, optReturnType, $5, mRhs, [], attrs, memberFlags) + let memberRange = unionRanges rangeStart mRhs + [ SynMemberDefn.Member (binding, memberRange) ]) } /* Properties with explicit get/set, also indexer properties */ - | opt_inline bindingPattern opt_topReturnTypeWithTypeConstraints classDefnMemberGetSet + | opt_inline bindingPattern opt_topReturnTypeWithTypeConstraints classDefnMemberGetSet { let mWhole = (rhs parseState 2, $4) ||> unionRangeWithListBy (fun (_,_,_,_,_,m2) -> m2) - let propertyNameBindingBuilder,_ = $2 + let propertyNameBindingBuilder, _ = $2 let optPropertyType = $3 let isMutable = false - (fun visNoLongerUsed memFlagsBuilder attrs -> + (fun visNoLongerUsed memFlagsBuilder attrs rangeStart -> let hasGet = ref false let hasSet = ref false @@ -1665,21 +1667,21 @@ memberCore: | SynPat.Attrib (p,_,_) -> go p | _ -> raiseParseErrorAt mBindLhs (FSComp.SR.parsInvalidDeclarationSyntax()) go pv - if getset = "get" then ( + if getset = "get" then if !hasGet then reportParseErrorAt mBindLhs (FSComp.SR.parsGetAndOrSetRequired()) None else hasGet := true Some MemberKind.PropertyGet - ) else if getset = "set" then ( + else if getset = "set" then if !hasSet then reportParseErrorAt mBindLhs (FSComp.SR.parsGetAndOrSetRequired()) None else hasSet := true Some MemberKind.PropertySet - ) else + else raiseParseErrorAt mBindLhs (FSComp.SR.parsGetAndOrSetRequired()) match memberKind with @@ -1697,7 +1699,7 @@ memberCore: let optReturnType = match (memberKind, optReturnType) with - | MemberKind.PropertySet,_ -> optReturnType + | MemberKind.PropertySet, _ -> optReturnType | _, None -> optPropertyType | _ -> optReturnType @@ -1719,35 +1721,39 @@ memberCore: | _ -> SynInfo.unnamedTopArg match memberKind, valSynInfo, memFlags.IsInstance with - | MemberKind.PropertyGet,SynValInfo ([],_ret), false - | MemberKind.PropertyGet,SynValInfo ([_],_ret), true -> + | MemberKind.PropertyGet, SynValInfo ([], _ret), false + | MemberKind.PropertyGet, SynValInfo ([_], _ret), true -> raiseParseErrorAt mBindLhs (FSComp.SR.parsGetterMustHaveAtLeastOneArgument()) - | MemberKind.PropertyGet,SynValInfo (thisArg :: indexOrUnitArgs :: rest,ret), true -> - if not rest.IsEmpty then reportParseErrorAt mBindLhs (FSComp.SR.parsGetterAtMostOneArgument()) - SynValInfo ([thisArg; indexOrUnitArgs],ret) + | MemberKind.PropertyGet, SynValInfo (thisArg :: indexOrUnitArgs :: rest, ret), true -> + if not rest.IsEmpty then + reportParseErrorAt mBindLhs (FSComp.SR.parsGetterAtMostOneArgument ()) + SynValInfo ([thisArg; indexOrUnitArgs], ret) - | MemberKind.PropertyGet,SynValInfo (indexOrUnitArgs :: rest,ret), false -> - if not rest.IsEmpty then reportParseErrorAt mBindLhs (FSComp.SR.parsGetterAtMostOneArgument()) - SynValInfo ([indexOrUnitArgs],ret) + | MemberKind.PropertyGet, SynValInfo (indexOrUnitArgs :: rest,ret), false -> + if not rest.IsEmpty then + reportParseErrorAt mBindLhs (FSComp.SR.parsGetterAtMostOneArgument ()) + SynValInfo ([indexOrUnitArgs], ret) - | MemberKind.PropertySet,SynValInfo ([thisArg;valueArg],ret), true -> - SynValInfo ([thisArg; adjustValueArg valueArg],ret) + | MemberKind.PropertySet, SynValInfo ([thisArg;valueArg], ret), true -> + SynValInfo ([thisArg; adjustValueArg valueArg], ret) - | MemberKind.PropertySet,SynValInfo (thisArg :: indexArgs :: valueArg :: rest,ret), true -> - if not rest.IsEmpty then reportParseErrorAt mBindLhs (FSComp.SR.parsSetterAtMostTwoArguments()) - SynValInfo ([thisArg; indexArgs @ adjustValueArg valueArg],ret) + | MemberKind.PropertySet, SynValInfo (thisArg :: indexArgs :: valueArg :: rest, ret), true -> + if not rest.IsEmpty then + reportParseErrorAt mBindLhs (FSComp.SR.parsSetterAtMostTwoArguments ()) + SynValInfo ([thisArg; indexArgs @ adjustValueArg valueArg], ret) - | MemberKind.PropertySet,SynValInfo ([valueArg],ret), false -> - SynValInfo ([adjustValueArg valueArg],ret) + | MemberKind.PropertySet, SynValInfo ([valueArg], ret), false -> + SynValInfo ([adjustValueArg valueArg], ret) - | MemberKind.PropertySet,SynValInfo (indexArgs :: valueArg :: rest,ret), _ -> - if not rest.IsEmpty then reportParseErrorAt mBindLhs (FSComp.SR.parsSetterAtMostTwoArguments()) - SynValInfo ([indexArgs @ adjustValueArg valueArg],ret) + | MemberKind.PropertySet, SynValInfo (indexArgs :: valueArg :: rest,ret), _ -> + if not rest.IsEmpty then + reportParseErrorAt mBindLhs (FSComp.SR.parsSetterAtMostTwoArguments ()) + SynValInfo ([indexArgs @ adjustValueArg valueArg], ret) | _ -> // should be unreachable, cover just in case - raiseParseErrorAt mBindLhs (FSComp.SR.parsInvalidProperty()) + raiseParseErrorAt mBindLhs (FSComp.SR.parsInvalidProperty ()) let valSynData = SynValData(Some(memFlags), valSynInfo,None) @@ -1808,7 +1814,9 @@ memberCore: go pv,PreXmlDoc.Merge doc2 doc - Some <| SynMemberDefn.Member (Binding (vis, NormalBinding, isInline, isMutable, attrs, xmlDocAdjusted, valSynData, bindingPatAdjusted, rhsRetInfo, rhsExpr, mBindLhs, spBind),mWhole))) + let binding = Binding (vis, NormalBinding, isInline, isMutable, attrs, xmlDocAdjusted, valSynData, bindingPatAdjusted, rhsRetInfo, rhsExpr, mBindLhs, spBind) + let memberRange = unionRanges rangeStart mWhole + Some (SynMemberDefn.Member (binding, memberRange)))) } @@ -1827,10 +1835,12 @@ classDefnMember: { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)) [mkClassMemberLocalBindings(true,Some (rhs parseState 3),$1,$2,$4)] } - | opt_attributes opt_declVisibility memberFlags memberCore opt_ODECLEND - { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)) - let _,flags = $3 - $4 $2 flags $1 } + | opt_attributes opt_declVisibility memberFlags memberCore opt_ODECLEND + { let rangeStart = rhs parseState 1 + if Option.isSome $2 then + errorR (Error (FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier (), rhs parseState 2)) + let _, flags = $3 + $4 $2 flags $1 rangeStart } | opt_attributes opt_declVisibility interfaceMember appType opt_interfaceImplDefn { if not (isNil $1) then errorR(Error(FSComp.SR.parsAttributesAreNotPermittedOnInterfaceImplementations(),rhs parseState 1)) @@ -1869,9 +1879,11 @@ classDefnMember: $4 (Some (rhs parseState 3)) $1 true } | opt_attributes opt_declVisibility memberFlags autoPropsDefnDecl opt_ODECLEND - { if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)) - let isStatic, flags = $3 - $4 $1 isStatic flags } + { let rangeStart = rhs parseState 1 + if Option.isSome $2 then + errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2)) + let isStatic, flags = $3 + $4 $1 isStatic flags rangeStart } | opt_attributes opt_declVisibility NEW atomicPattern optAsSpec EQUALS typedSeqExprBlock opt_ODECLEND { let m = unionRanges (rhs2 parseState 3 6) $7.Range @@ -1903,12 +1915,13 @@ valDefnDecl: /* An auto-property definition in an object type definition */ autoPropsDefnDecl: | VAL opt_mutable opt_access ident opt_typ EQUALS typedSeqExprBlock classMemberSpfnGetSet - { let doc = grabXmlDoc(parseState,5) - let mValDecl = unionRanges (rhs parseState 1) $7.Range - let mGetSetOpt, getSet = $8 - if $2 then errorR(Error(FSComp.SR.parsMutableOnAutoPropertyShouldBeGetSet(),rhs parseState 3)) - (fun attribs isStatic flags -> - [ SynMemberDefn.AutoProperty(attribs, isStatic, $4, $5, getSet, flags, doc, $3, $7, mGetSetOpt, mValDecl) ]) } + { let doc = grabXmlDoc(parseState, 5) + let mGetSetOpt, getSet = $8 + if $2 then + errorR (Error (FSComp.SR.parsMutableOnAutoPropertyShouldBeGetSet (), rhs parseState 3)) + (fun attribs isStatic flags rangeStart -> + let memberRange = unionRanges rangeStart $7.Range + [ SynMemberDefn.AutoProperty(attribs, isStatic, $4, $5, getSet, flags, doc, $3, $7, mGetSetOpt, memberRange) ]) } /* An optional type on an auto-property definition */ @@ -2022,10 +2035,12 @@ objectImplementationMembers: /* One member in an object expression or interface implementation */ objectImplementationMember: | opt_attributes memberOrOverride memberCore opt_ODECLEND - { $3 None OverrideMemberFlags $1 } + { let rangeStart = rhs parseState 1 + $3 None OverrideMemberFlags $1 rangeStart } | opt_attributes memberOrOverride autoPropsDefnDecl opt_ODECLEND - { $3 $1 false OverrideMemberFlags } + { let rangeStart = rhs parseState 1 + $3 $1 false OverrideMemberFlags rangeStart } | opt_attributes memberOrOverride error { [] } diff --git a/tests/fsharp/typecheck/sigs/neg10.bsl b/tests/fsharp/typecheck/sigs/neg10.bsl index 64088e1e9e8bdf72c896f133bc69ef4c36ad9f63..c31220273daaa71def5d199704911aef86c642ea 100644 --- a/tests/fsharp/typecheck/sigs/neg10.bsl +++ b/tests/fsharp/typecheck/sigs/neg10.bsl @@ -35,9 +35,9 @@ neg10.fs(54,17,54,20): typecheck error FS0060: Override implementations in augme neg10.fs(66,19,66,21): typecheck error FS0069: Interface implementations in augmentations are now deprecated. Interface implementations should be given on the initial declaration of a type. -neg10.fs(77,27,77,34): typecheck error FS0896: Enumerations cannot have members +neg10.fs(77,13,77,34): typecheck error FS0896: Enumerations cannot have members -neg10.fs(84,20,84,29): typecheck error FS0896: Enumerations cannot have members +neg10.fs(84,13,84,29): typecheck error FS0896: Enumerations cannot have members neg10.fs(90,23,90,41): typecheck error FS0907: Enumerations cannot have interface declarations @@ -45,11 +45,11 @@ neg10.fs(99,23,99,29): typecheck error FS0907: Enumerations cannot have interfac neg10.fs(107,10,107,17): typecheck error FS0964: Type abbreviations cannot have augmentations -neg10.fs(109,27,109,34): typecheck error FS0895: Type abbreviations cannot have members +neg10.fs(109,13,109,34): typecheck error FS0895: Type abbreviations cannot have members neg10.fs(114,10,114,17): typecheck error FS0964: Type abbreviations cannot have augmentations -neg10.fs(116,20,116,29): typecheck error FS0895: Type abbreviations cannot have members +neg10.fs(116,13,116,29): typecheck error FS0895: Type abbreviations cannot have members neg10.fs(120,10,120,17): typecheck error FS0964: Type abbreviations cannot have augmentations diff --git a/tests/fsharp/typecheck/sigs/neg62.bsl b/tests/fsharp/typecheck/sigs/neg62.bsl index d2bbd52d880dc67f473d7aa8e387b26b5b3c6ea5..de4ae9d68accdff895c5e874be3d7bf5fc015346 100644 --- a/tests/fsharp/typecheck/sigs/neg62.bsl +++ b/tests/fsharp/typecheck/sigs/neg62.bsl @@ -15,15 +15,15 @@ neg62.fs(22,5,22,14): typecheck error FS0960: 'let' and 'do' bindings must come neg62.fs(28,5,28,18): typecheck error FS0960: 'let' and 'do' bindings must come before member and interface definitions in type definitions -neg62.fs(31,19,31,32): typecheck error FS3133: 'member val' definitions are only permitted in types with a primary constructor. Consider adding arguments to your type definition, e.g. 'type X(args) = ...'. +neg62.fs(31,5,31,32): typecheck error FS3133: 'member val' definitions are only permitted in types with a primary constructor. Consider adding arguments to your type definition, e.g. 'type X(args) = ...'. -neg62.fs(31,19,31,32): typecheck error FS0902: Static value definitions may only be used in types with a primary constructor. Consider adding arguments to the type definition, e.g. 'type X(args) = ...'. +neg62.fs(31,5,31,32): typecheck error FS0902: Static value definitions may only be used in types with a primary constructor. Consider adding arguments to the type definition, e.g. 'type X(args) = ...'. -neg62.fs(34,12,34,25): typecheck error FS3133: 'member val' definitions are only permitted in types with a primary constructor. Consider adding arguments to your type definition, e.g. 'type X(args) = ...'. +neg62.fs(34,5,34,25): typecheck error FS3133: 'member val' definitions are only permitted in types with a primary constructor. Consider adding arguments to your type definition, e.g. 'type X(args) = ...'. neg62.fs(49,6,49,26): typecheck error FS0081: Implicit object constructors for structs must take at least one argument -neg62.fs(50,12,50,21): typecheck error FS0901: Structs cannot contain value definitions because the default constructor for structs will not execute these bindings. Consider adding additional arguments to the primary constructor for the type. +neg62.fs(50,5,50,21): typecheck error FS0901: Structs cannot contain value definitions because the default constructor for structs will not execute these bindings. Consider adding additional arguments to the primary constructor for the type. neg62.fs(54,26,54,34): typecheck error FS3135: To indicate that this property can be set, use 'member val PropertyName = expr with get,set'. diff --git a/tests/fsharp/typecheck/sigs/neg91.bsl b/tests/fsharp/typecheck/sigs/neg91.bsl index 7021297a7f10a0ba1c41934beff9bcbd934e292d..559a4871f924d0617a3799c4c901cc9bea738532 100644 --- a/tests/fsharp/typecheck/sigs/neg91.bsl +++ b/tests/fsharp/typecheck/sigs/neg91.bsl @@ -1,5 +1,5 @@ -neg91.fs(7,16,7,30): typecheck error FS0896: Enumerations cannot have members +neg91.fs(7,9,7,30): typecheck error FS0896: Enumerations cannot have members neg91.fs(10,10,10,15): typecheck error FS0956: Members that extend interface, delegate or enum types must be placed in a module separate to the definition of the type. This module must either have the AutoOpen attribute or be opened explicitly by client code to bring the extension members into scope. diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs index 4458338c770e0253a8818fe476c9a645daf39d3c..b4e05661698ca7f05cc5738cbfe2d55baeadb52d 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/EnumTypes/E_NoMethodsOnEnums01.fs @@ -1,5 +1,5 @@ // #Regression #Conformance #ObjectOrientedTypes #Enums -//Enumerations cannot have members$ +//Enumerations cannot have members$ //The type 'Season' does not support the operator 'get_One'$ type Season = Spring=0 | Summer=1 | Autumn=2 | Winter=3 diff --git a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/TypeExtensions/basic/E_CantExtendTypeAbrev.fs b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/TypeExtensions/basic/E_CantExtendTypeAbrev.fs index beeac13d7e4a8d0884f19b1ad5ede627b9ef3ecd..2883306a70a5acfb226f00f8a0259c7c22d6bf12 100644 --- a/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/TypeExtensions/basic/E_CantExtendTypeAbrev.fs +++ b/tests/fsharpqa/Source/Conformance/ObjectOrientedTypeDefinitions/TypeExtensions/basic/E_CantExtendTypeAbrev.fs @@ -1,7 +1,7 @@ // #Regression #Conformance #ObjectOrientedTypes #TypeExtensions // Verify you can't add type extensions to a type abbreviation //Type abbreviations cannot have augmentations$ -//Type abbreviations cannot have members$ +//Type abbreviations cannot have members$ type string with member this.ReturnFive() = 5 diff --git a/tests/fsharpqa/Source/Conformance/UnitsOfMeasure/WithOOP/E_NoInstanceOnMeasure01.fs b/tests/fsharpqa/Source/Conformance/UnitsOfMeasure/WithOOP/E_NoInstanceOnMeasure01.fs index e80950ee9e4d5605ab7eacd59724131936856f9e..4ff94cf86839c9a6d6fce5c4bc3b6c516d0c859e 100644 --- a/tests/fsharpqa/Source/Conformance/UnitsOfMeasure/WithOOP/E_NoInstanceOnMeasure01.fs +++ b/tests/fsharpqa/Source/Conformance/UnitsOfMeasure/WithOOP/E_NoInstanceOnMeasure01.fs @@ -2,7 +2,7 @@ // Test error when adding instance methods to Measure types. -//Measure declarations may have only static members$ +//Measure declarations may have only static members$ [] type kg = diff --git a/tests/service/Common.fs b/tests/service/Common.fs index 6920e682afe538641ae6eb5f887d4e043c79bc84..946995e4c173dece559b0f2448b8601fa456efd2 100644 --- a/tests/service/Common.fs +++ b/tests/service/Common.fs @@ -190,7 +190,6 @@ let parseAndCheckScript (file, input) = let parseSourceCode (name: string, code: string) = let location = Path.Combine(Path.GetTempPath(),"test"+string(hash (name, code))) try Directory.CreateDirectory(location) |> ignore with _ -> () - let projPath = Path.Combine(location, name + ".fsproj") let filePath = Path.Combine(location, name + ".fs") let dllPath = Path.Combine(location, name + ".dll") let args = mkProjectCommandLineArgs(dllPath, [filePath]) @@ -198,6 +197,13 @@ let parseSourceCode (name: string, code: string) = let parseResults = checker.ParseFile(filePath, FSharp.Compiler.Text.SourceText.ofString code, options) |> Async.RunSynchronously parseResults.ParseTree +open FSharp.Compiler.Ast + +let parseSourceCodeAndGetModule (source: string) = + match parseSourceCode ("test", source) with + | Some (ParsedInput.ImplFile (ParsedImplFileInput (_, _, _, _, _, [ moduleOrNamespace ], _))) -> moduleOrNamespace + | _ -> failwith "Could not get module decls" + /// Extract range info let tups (m:Range.range) = (m.StartLine, m.StartColumn), (m.EndLine, m.EndColumn) diff --git a/tests/service/ServiceUntypedParseTests.fs b/tests/service/ServiceUntypedParseTests.fs index ac4e15656178fef0eaa7ad706c75d1ade3ff5c6b..ecf91ee4cabbddce1de6b789962fee3f591b2068 100644 --- a/tests/service/ServiceUntypedParseTests.fs +++ b/tests/service/ServiceUntypedParseTests.fs @@ -127,25 +127,139 @@ let foo6 = () [<>] let foo7 = () """ - match parseSourceCode ("test", source) with - | Some (ParsedInput.ImplFile (ParsedImplFileInput (_,_,_,_,_,[SynModuleOrNamespace (_,_,_,decls,_,_,_,_)],_))) -> - decls |> List.map (fun decl -> - match decl with - | SynModuleDecl.Let (_,[Binding(_,_,_,_,attributeLists,_,_,_,_,_,_,_)],_) -> - attributeLists |> List.map (fun list -> - let r = list.Range - - list.Attributes.Length, - ((r.StartLine, r.StartColumn), (r.EndLine, r.EndColumn))) - - | _ -> failwith "Could not get binding") - |> shouldEqual - [ [ (1, ((2, 0), (2, 5))) ] - [ (1, ((5, 0), (5, 5))); (2, ((6, 0), (6, 7))) ] - [ (1, ((9, 0), (9, 5))); (2, ((9, 6), (9, 13))) ] - [ (1, ((12, 0), (13, 0))) ] - [ (1, ((15, 0), (15, 4))) ] - [ (0, ((18, 0), (18, 2))) ] - [ (0, ((21, 0), (21, 4))) ] ] - - | _ -> failwith "Could not get module decls" + let (SynModuleOrNamespace (_, _, _, decls, _, _, _, _)) = parseSourceCodeAndGetModule source + decls |> List.map (fun decl -> + match decl with + | SynModuleDecl.Let (_,[Binding(_,_,_,_,attributeLists,_,_,_,_,_,_,_)],_) -> + attributeLists |> List.map (fun list -> + let r = list.Range + + list.Attributes.Length, + ((r.StartLine, r.StartColumn), (r.EndLine, r.EndColumn))) + + | _ -> failwith "Could not get binding") + |> shouldEqual + [ [ (1, ((2, 0), (2, 5))) ] + [ (1, ((5, 0), (5, 5))); (2, ((6, 0), (6, 7))) ] + [ (1, ((9, 0), (9, 5))); (2, ((9, 6), (9, 13))) ] + [ (1, ((12, 0), (13, 0))) ] + [ (1, ((15, 0), (15, 4))) ] + [ (0, ((18, 0), (18, 2))) ] + [ (0, ((21, 0), (21, 4))) ] ] + + +module TypeMemberRanges = + + let getTypeMemberRange source = + let (SynModuleOrNamespace (_, _, _, decls, _, _, _, _)) = parseSourceCodeAndGetModule source + match decls with + | [ SynModuleDecl.Types ([ TypeDefn (_, SynTypeDefnRepr.ObjectModel (_, memberDecls, _), _, _) ], _) ] -> + memberDecls |> List.map (fun memberDecl -> + let range = memberDecl.Range + (range.StartLine, range.StartColumn), (range.EndLine, range.EndColumn)) + + | _ -> failwith "Could not get member" + + + [] + let ``Member range 01 - Simple``() = + let source = """ +type T = + member x.Foo() = () +""" + getTypeMemberRange source |> shouldEqual [ (3, 4), (3, 23) ] + + + [] + let ``Member range 02 - Static``() = + let source = """ +type T = + static member Foo() = () +""" + getTypeMemberRange source |> shouldEqual [ (3, 4), (3, 28) ] + + + [] + let ``Member range 03 - Attribute``() = + let source = """ +type T = + [] + static member Foo() = () +""" + getTypeMemberRange source |> shouldEqual [ (3, 4), (4, 28) ] + + + [] + let ``Member range 04 - Property``() = + let source = """ +type T = + member x.P = () +""" + getTypeMemberRange source |> shouldEqual [ (3, 4), (3, 19) ] + + + [] + let ``Member range 05 - Setter only property``() = + let source = """ +type T = + member x.P with set (value) = v <- value +""" + getTypeMemberRange source |> shouldEqual [ (3, 4), (3, 44) ] + + + [] + let ``Member range 06 - Read-write property``() = + let source = """ +type T = + member this.MyReadWriteProperty + with get () = x + and set (value) = x <- value +""" + getTypeMemberRange source |> shouldEqual [ (3, 4), (5, 36) + (3, 4), (5, 36) ] + + + [] + let ``Member range 07 - Auto property``() = + let source = """ +type T = + member val Property1 = "" +""" + getTypeMemberRange source |> shouldEqual [ (3, 4), (3, 29) ] + + + [] + let ``Member range 08 - Auto property with setter``() = + let source = """ +type T = + member val Property1 = "" with get, set +""" + getTypeMemberRange source |> shouldEqual [ (3, 4), (3, 29) ] + + + [] + let ``Member range 09 - Abstract slot``() = + let source = """ +type T = + abstract P: int + abstract M: unit -> unit +""" + getTypeMemberRange source |> shouldEqual [ (3, 4), (3, 19) + (4, 4), (4, 28) ] + + [] + let ``Member range 10 - Val field``() = + let source = """ +type T = + val x: int +""" + getTypeMemberRange source |> shouldEqual [ (3, 4), (3, 14) ] + + + [] + let ``Member range 11 - Ctor``() = + let source = """ +type T = + new (x:int) = () +""" + getTypeMemberRange source |> shouldEqual [ (3, 4), (3, 20) ] diff --git a/tests/service/StructureTests.fs b/tests/service/StructureTests.fs index e3f7b7fe9b2469a2ef7ed86202447ddce9c06a47..c3583fe5ab1f17eb58493d3308c513e43ce97db3 100644 --- a/tests/service/StructureTests.fs +++ b/tests/service/StructureTests.fs @@ -106,7 +106,7 @@ type Color = => [ (2, 5, 9, 55), (2, 11, 9, 55) (3, 4, 5, 10), (3, 4, 5, 10) (7, 4, 9, 55), (7, 25, 9, 55) - (8, 15, 9, 55), (8, 27, 9, 55) + (8, 8, 9, 55), (8, 27, 9, 55) (8, 15, 9, 55), (8, 27, 9, 55) ] [] @@ -127,7 +127,7 @@ type Color = (3, 4, 4, 14), (3, 4, 4, 14) (3, 6, 4, 13), (3, 6, 4, 13) (8, 4, 10, 55), (8, 25, 10, 55) - (9, 15, 10, 55), (9, 27, 10, 55) + (9, 8, 10, 55), (9, 27, 10, 55) (9, 15, 10, 55), (9, 27, 10, 55) ] [] @@ -181,13 +181,13 @@ module MyModule = // 2 (7, 9, 15, 59), (7, 15, 15, 59) (8, 8, 11, 9), (8, 8, 11, 9) (13, 8, 15, 59), (13, 29, 15, 59) - (14, 19, 15, 59), (14, 31, 15, 59) + (14, 12, 15, 59), (14, 31, 15, 59) (14, 19, 15, 59), (14, 31, 15, 59) (17, 4, 27, 63), (17, 24, 27, 63) (19, 13, 27, 63), (19, 25, 27, 63) (20, 12, 23, 13), (20, 12, 23, 13) (25, 12, 27, 63), (25, 33, 27, 63) - (26, 23, 27, 63), (26, 35, 27, 63) + (26, 16, 27, 63), (26, 35, 27, 63) (26, 23, 27, 63), (26, 35, 27, 63) ]