Skip to content

Commit 7a39de2

Browse files
auduchinokbaronfel
authored andcommitted
Fix member declaration ranges (#7676)
* Fix member declaration ranges * Fix member declaration ranges * Update baseline * Update baseline
1 parent 2bc8fed commit 7a39de2

File tree

4 files changed

+211
-76
lines changed

4 files changed

+211
-76
lines changed

src/fsharp/pars.fsy

Lines changed: 64 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1623,21 +1623,23 @@ classDefnMemberGetSetElement:
16231623
/* The core of a member definition */
16241624
memberCore:
16251625
/* Methods and simple getter properties */
1626-
| opt_inline bindingPattern opt_topReturnTypeWithTypeConstraints EQUALS typedSeqExprBlock
1627-
{ let mRhs = $5.Range
1628-
let mWhole = unionRanges (rhs2 parseState 3 4) mRhs
1629-
let optReturnType = $3
1630-
let bindingBuilder,mBindLhs = $2
1631-
(fun vis memFlagsBuilder attrs ->
1632-
[ SynMemberDefn.Member (bindingBuilder (vis,$1,false,mBindLhs,NoSequencePointAtInvisibleBinding,optReturnType,$5,mRhs,[],attrs,Some(memFlagsBuilder MemberKind.Member)),unionRanges mWhole mBindLhs) ]) }
1626+
| opt_inline bindingPattern opt_topReturnTypeWithTypeConstraints EQUALS typedSeqExprBlock
1627+
{ let mRhs = $5.Range
1628+
let optReturnType = $3
1629+
let bindingBuilder, mBindLhs = $2
1630+
(fun vis memFlagsBuilder attrs rangeStart ->
1631+
let memberFlags = Some (memFlagsBuilder MemberKind.Member)
1632+
let binding = bindingBuilder (vis, $1, false, mBindLhs, NoSequencePointAtInvisibleBinding, optReturnType, $5, mRhs, [], attrs, memberFlags)
1633+
let memberRange = unionRanges rangeStart mRhs
1634+
[ SynMemberDefn.Member (binding, memberRange) ]) }
16331635

16341636
/* Properties with explicit get/set, also indexer properties */
1635-
| opt_inline bindingPattern opt_topReturnTypeWithTypeConstraints classDefnMemberGetSet
1637+
| opt_inline bindingPattern opt_topReturnTypeWithTypeConstraints classDefnMemberGetSet
16361638
{ let mWhole = (rhs parseState 2, $4) ||> unionRangeWithListBy (fun (_,_,_,_,_,m2) -> m2)
1637-
let propertyNameBindingBuilder,_ = $2
1639+
let propertyNameBindingBuilder, _ = $2
16381640
let optPropertyType = $3
16391641
let isMutable = false
1640-
(fun visNoLongerUsed memFlagsBuilder attrs ->
1642+
(fun visNoLongerUsed memFlagsBuilder attrs rangeStart ->
16411643
let hasGet = ref false
16421644
let hasSet = ref false
16431645

@@ -1665,21 +1667,21 @@ memberCore:
16651667
| SynPat.Attrib (p,_,_) -> go p
16661668
| _ -> raiseParseErrorAt mBindLhs (FSComp.SR.parsInvalidDeclarationSyntax())
16671669
go pv
1668-
if getset = "get" then (
1670+
if getset = "get" then
16691671
if !hasGet then
16701672
reportParseErrorAt mBindLhs (FSComp.SR.parsGetAndOrSetRequired())
16711673
None
16721674
else
16731675
hasGet := true
16741676
Some MemberKind.PropertyGet
1675-
) else if getset = "set" then (
1677+
else if getset = "set" then
16761678
if !hasSet then
16771679
reportParseErrorAt mBindLhs (FSComp.SR.parsGetAndOrSetRequired())
16781680
None
16791681
else
16801682
hasSet := true
16811683
Some MemberKind.PropertySet
1682-
) else
1684+
else
16831685
raiseParseErrorAt mBindLhs (FSComp.SR.parsGetAndOrSetRequired())
16841686

16851687
match memberKind with
@@ -1697,7 +1699,7 @@ memberCore:
16971699

16981700
let optReturnType =
16991701
match (memberKind, optReturnType) with
1700-
| MemberKind.PropertySet,_ -> optReturnType
1702+
| MemberKind.PropertySet, _ -> optReturnType
17011703
| _, None -> optPropertyType
17021704
| _ -> optReturnType
17031705

@@ -1719,35 +1721,39 @@ memberCore:
17191721
| _ -> SynInfo.unnamedTopArg
17201722

17211723
match memberKind, valSynInfo, memFlags.IsInstance with
1722-
| MemberKind.PropertyGet,SynValInfo ([],_ret), false
1723-
| MemberKind.PropertyGet,SynValInfo ([_],_ret), true ->
1724+
| MemberKind.PropertyGet, SynValInfo ([], _ret), false
1725+
| MemberKind.PropertyGet, SynValInfo ([_], _ret), true ->
17241726
raiseParseErrorAt mBindLhs (FSComp.SR.parsGetterMustHaveAtLeastOneArgument())
17251727

1726-
| MemberKind.PropertyGet,SynValInfo (thisArg :: indexOrUnitArgs :: rest,ret), true ->
1727-
if not rest.IsEmpty then reportParseErrorAt mBindLhs (FSComp.SR.parsGetterAtMostOneArgument())
1728-
SynValInfo ([thisArg; indexOrUnitArgs],ret)
1728+
| MemberKind.PropertyGet, SynValInfo (thisArg :: indexOrUnitArgs :: rest, ret), true ->
1729+
if not rest.IsEmpty then
1730+
reportParseErrorAt mBindLhs (FSComp.SR.parsGetterAtMostOneArgument ())
1731+
SynValInfo ([thisArg; indexOrUnitArgs], ret)
17291732

1730-
| MemberKind.PropertyGet,SynValInfo (indexOrUnitArgs :: rest,ret), false ->
1731-
if not rest.IsEmpty then reportParseErrorAt mBindLhs (FSComp.SR.parsGetterAtMostOneArgument())
1732-
SynValInfo ([indexOrUnitArgs],ret)
1733+
| MemberKind.PropertyGet, SynValInfo (indexOrUnitArgs :: rest,ret), false ->
1734+
if not rest.IsEmpty then
1735+
reportParseErrorAt mBindLhs (FSComp.SR.parsGetterAtMostOneArgument ())
1736+
SynValInfo ([indexOrUnitArgs], ret)
17331737

1734-
| MemberKind.PropertySet,SynValInfo ([thisArg;valueArg],ret), true ->
1735-
SynValInfo ([thisArg; adjustValueArg valueArg],ret)
1738+
| MemberKind.PropertySet, SynValInfo ([thisArg;valueArg], ret), true ->
1739+
SynValInfo ([thisArg; adjustValueArg valueArg], ret)
17361740

1737-
| MemberKind.PropertySet,SynValInfo (thisArg :: indexArgs :: valueArg :: rest,ret), true ->
1738-
if not rest.IsEmpty then reportParseErrorAt mBindLhs (FSComp.SR.parsSetterAtMostTwoArguments())
1739-
SynValInfo ([thisArg; indexArgs @ adjustValueArg valueArg],ret)
1741+
| MemberKind.PropertySet, SynValInfo (thisArg :: indexArgs :: valueArg :: rest, ret), true ->
1742+
if not rest.IsEmpty then
1743+
reportParseErrorAt mBindLhs (FSComp.SR.parsSetterAtMostTwoArguments ())
1744+
SynValInfo ([thisArg; indexArgs @ adjustValueArg valueArg], ret)
17401745

1741-
| MemberKind.PropertySet,SynValInfo ([valueArg],ret), false ->
1742-
SynValInfo ([adjustValueArg valueArg],ret)
1746+
| MemberKind.PropertySet, SynValInfo ([valueArg], ret), false ->
1747+
SynValInfo ([adjustValueArg valueArg], ret)
17431748

1744-
| MemberKind.PropertySet,SynValInfo (indexArgs :: valueArg :: rest,ret), _ ->
1745-
if not rest.IsEmpty then reportParseErrorAt mBindLhs (FSComp.SR.parsSetterAtMostTwoArguments())
1746-
SynValInfo ([indexArgs @ adjustValueArg valueArg],ret)
1749+
| MemberKind.PropertySet, SynValInfo (indexArgs :: valueArg :: rest,ret), _ ->
1750+
if not rest.IsEmpty then
1751+
reportParseErrorAt mBindLhs (FSComp.SR.parsSetterAtMostTwoArguments ())
1752+
SynValInfo ([indexArgs @ adjustValueArg valueArg], ret)
17471753

17481754
| _ ->
17491755
// should be unreachable, cover just in case
1750-
raiseParseErrorAt mBindLhs (FSComp.SR.parsInvalidProperty())
1756+
raiseParseErrorAt mBindLhs (FSComp.SR.parsInvalidProperty ())
17511757

17521758
let valSynData = SynValData(Some(memFlags), valSynInfo,None)
17531759

@@ -1808,7 +1814,9 @@ memberCore:
18081814

18091815
go pv,PreXmlDoc.Merge doc2 doc
18101816

1811-
Some <| SynMemberDefn.Member (Binding (vis, NormalBinding, isInline, isMutable, attrs, xmlDocAdjusted, valSynData, bindingPatAdjusted, rhsRetInfo, rhsExpr, mBindLhs, spBind),mWhole)))
1817+
let binding = Binding (vis, NormalBinding, isInline, isMutable, attrs, xmlDocAdjusted, valSynData, bindingPatAdjusted, rhsRetInfo, rhsExpr, mBindLhs, spBind)
1818+
let memberRange = unionRanges rangeStart mWhole
1819+
Some (SynMemberDefn.Member (binding, memberRange))))
18121820
}
18131821

18141822

@@ -1827,10 +1835,12 @@ classDefnMember:
18271835
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2))
18281836
[mkClassMemberLocalBindings(true,Some (rhs parseState 3),$1,$2,$4)] }
18291837

1830-
| opt_attributes opt_declVisibility memberFlags memberCore opt_ODECLEND
1831-
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2))
1832-
let _,flags = $3
1833-
$4 $2 flags $1 }
1838+
| opt_attributes opt_declVisibility memberFlags memberCore opt_ODECLEND
1839+
{ let rangeStart = rhs parseState 1
1840+
if Option.isSome $2 then
1841+
errorR (Error (FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier (), rhs parseState 2))
1842+
let _, flags = $3
1843+
$4 $2 flags $1 rangeStart }
18341844

18351845
| opt_attributes opt_declVisibility interfaceMember appType opt_interfaceImplDefn
18361846
{ if not (isNil $1) then errorR(Error(FSComp.SR.parsAttributesAreNotPermittedOnInterfaceImplementations(),rhs parseState 1))
@@ -1869,9 +1879,11 @@ classDefnMember:
18691879
$4 (Some (rhs parseState 3)) $1 true }
18701880

18711881
| opt_attributes opt_declVisibility memberFlags autoPropsDefnDecl opt_ODECLEND
1872-
{ if Option.isSome $2 then errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2))
1873-
let isStatic, flags = $3
1874-
$4 $1 isStatic flags }
1882+
{ let rangeStart = rhs parseState 1
1883+
if Option.isSome $2 then
1884+
errorR(Error(FSComp.SR.parsVisibilityDeclarationsShouldComePriorToIdentifier(),rhs parseState 2))
1885+
let isStatic, flags = $3
1886+
$4 $1 isStatic flags rangeStart }
18751887

18761888
| opt_attributes opt_declVisibility NEW atomicPattern optAsSpec EQUALS typedSeqExprBlock opt_ODECLEND
18771889
{ let m = unionRanges (rhs2 parseState 3 6) $7.Range
@@ -1903,12 +1915,13 @@ valDefnDecl:
19031915
/* An auto-property definition in an object type definition */
19041916
autoPropsDefnDecl:
19051917
| VAL opt_mutable opt_access ident opt_typ EQUALS typedSeqExprBlock classMemberSpfnGetSet
1906-
{ let doc = grabXmlDoc(parseState,5)
1907-
let mValDecl = unionRanges (rhs parseState 1) $7.Range
1908-
let mGetSetOpt, getSet = $8
1909-
if $2 then errorR(Error(FSComp.SR.parsMutableOnAutoPropertyShouldBeGetSet(),rhs parseState 3))
1910-
(fun attribs isStatic flags ->
1911-
[ SynMemberDefn.AutoProperty(attribs, isStatic, $4, $5, getSet, flags, doc, $3, $7, mGetSetOpt, mValDecl) ]) }
1918+
{ let doc = grabXmlDoc(parseState, 5)
1919+
let mGetSetOpt, getSet = $8
1920+
if $2 then
1921+
errorR (Error (FSComp.SR.parsMutableOnAutoPropertyShouldBeGetSet (), rhs parseState 3))
1922+
(fun attribs isStatic flags rangeStart ->
1923+
let memberRange = unionRanges rangeStart $7.Range
1924+
[ SynMemberDefn.AutoProperty(attribs, isStatic, $4, $5, getSet, flags, doc, $3, $7, mGetSetOpt, memberRange) ]) }
19121925

19131926

19141927
/* An optional type on an auto-property definition */
@@ -2022,10 +2035,12 @@ objectImplementationMembers:
20222035
/* One member in an object expression or interface implementation */
20232036
objectImplementationMember:
20242037
| opt_attributes memberOrOverride memberCore opt_ODECLEND
2025-
{ $3 None OverrideMemberFlags $1 }
2038+
{ let rangeStart = rhs parseState 1
2039+
$3 None OverrideMemberFlags $1 rangeStart }
20262040

20272041
| opt_attributes memberOrOverride autoPropsDefnDecl opt_ODECLEND
2028-
{ $3 $1 false OverrideMemberFlags }
2042+
{ let rangeStart = rhs parseState 1
2043+
$3 $1 false OverrideMemberFlags rangeStart }
20292044

20302045
| opt_attributes memberOrOverride error
20312046
{ [] }

tests/service/Common.fs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,14 +190,20 @@ let parseAndCheckScript (file, input) =
190190
let parseSourceCode (name: string, code: string) =
191191
let location = Path.Combine(Path.GetTempPath(),"test"+string(hash (name, code)))
192192
try Directory.CreateDirectory(location) |> ignore with _ -> ()
193-
let projPath = Path.Combine(location, name + ".fsproj")
194193
let filePath = Path.Combine(location, name + ".fs")
195194
let dllPath = Path.Combine(location, name + ".dll")
196195
let args = mkProjectCommandLineArgs(dllPath, [filePath])
197196
let options, errors = checker.GetParsingOptionsFromCommandLineArgs(List.ofArray args)
198197
let parseResults = checker.ParseFile(filePath, FSharp.Compiler.Text.SourceText.ofString code, options) |> Async.RunSynchronously
199198
parseResults.ParseTree
200199

200+
open FSharp.Compiler.Ast
201+
202+
let parseSourceCodeAndGetModule (source: string) =
203+
match parseSourceCode ("test", source) with
204+
| Some (ParsedInput.ImplFile (ParsedImplFileInput (_, _, _, _, _, [ moduleOrNamespace ], _))) -> moduleOrNamespace
205+
| _ -> failwith "Could not get module decls"
206+
201207
/// Extract range info
202208
let tups (m:Range.range) = (m.StartLine, m.StartColumn), (m.EndLine, m.EndColumn)
203209

tests/service/ServiceUntypedParseTests.fs

Lines changed: 136 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -127,25 +127,139 @@ let foo6 = ()
127127
[<>]
128128
let foo7 = ()
129129
"""
130-
match parseSourceCode ("test", source) with
131-
| Some (ParsedInput.ImplFile (ParsedImplFileInput (_,_,_,_,_,[SynModuleOrNamespace (_,_,_,decls,_,_,_,_)],_))) ->
132-
decls |> List.map (fun decl ->
133-
match decl with
134-
| SynModuleDecl.Let (_,[Binding(_,_,_,_,attributeLists,_,_,_,_,_,_,_)],_) ->
135-
attributeLists |> List.map (fun list ->
136-
let r = list.Range
137-
138-
list.Attributes.Length,
139-
((r.StartLine, r.StartColumn), (r.EndLine, r.EndColumn)))
140-
141-
| _ -> failwith "Could not get binding")
142-
|> shouldEqual
143-
[ [ (1, ((2, 0), (2, 5))) ]
144-
[ (1, ((5, 0), (5, 5))); (2, ((6, 0), (6, 7))) ]
145-
[ (1, ((9, 0), (9, 5))); (2, ((9, 6), (9, 13))) ]
146-
[ (1, ((12, 0), (13, 0))) ]
147-
[ (1, ((15, 0), (15, 4))) ]
148-
[ (0, ((18, 0), (18, 2))) ]
149-
[ (0, ((21, 0), (21, 4))) ] ]
150-
151-
| _ -> failwith "Could not get module decls"
130+
let (SynModuleOrNamespace (_, _, _, decls, _, _, _, _)) = parseSourceCodeAndGetModule source
131+
decls |> List.map (fun decl ->
132+
match decl with
133+
| SynModuleDecl.Let (_,[Binding(_,_,_,_,attributeLists,_,_,_,_,_,_,_)],_) ->
134+
attributeLists |> List.map (fun list ->
135+
let r = list.Range
136+
137+
list.Attributes.Length,
138+
((r.StartLine, r.StartColumn), (r.EndLine, r.EndColumn)))
139+
140+
| _ -> failwith "Could not get binding")
141+
|> shouldEqual
142+
[ [ (1, ((2, 0), (2, 5))) ]
143+
[ (1, ((5, 0), (5, 5))); (2, ((6, 0), (6, 7))) ]
144+
[ (1, ((9, 0), (9, 5))); (2, ((9, 6), (9, 13))) ]
145+
[ (1, ((12, 0), (13, 0))) ]
146+
[ (1, ((15, 0), (15, 4))) ]
147+
[ (0, ((18, 0), (18, 2))) ]
148+
[ (0, ((21, 0), (21, 4))) ] ]
149+
150+
151+
module TypeMemberRanges =
152+
153+
let getTypeMemberRange source =
154+
let (SynModuleOrNamespace (_, _, _, decls, _, _, _, _)) = parseSourceCodeAndGetModule source
155+
match decls with
156+
| [ SynModuleDecl.Types ([ TypeDefn (_, SynTypeDefnRepr.ObjectModel (_, memberDecls, _), _, _) ], _) ] ->
157+
memberDecls |> List.map (fun memberDecl ->
158+
let range = memberDecl.Range
159+
(range.StartLine, range.StartColumn), (range.EndLine, range.EndColumn))
160+
161+
| _ -> failwith "Could not get member"
162+
163+
164+
[<Test>]
165+
let ``Member range 01 - Simple``() =
166+
let source = """
167+
type T =
168+
member x.Foo() = ()
169+
"""
170+
getTypeMemberRange source |> shouldEqual [ (3, 4), (3, 23) ]
171+
172+
173+
[<Test>]
174+
let ``Member range 02 - Static``() =
175+
let source = """
176+
type T =
177+
static member Foo() = ()
178+
"""
179+
getTypeMemberRange source |> shouldEqual [ (3, 4), (3, 28) ]
180+
181+
182+
[<Test>]
183+
let ``Member range 03 - Attribute``() =
184+
let source = """
185+
type T =
186+
[<Foo>]
187+
static member Foo() = ()
188+
"""
189+
getTypeMemberRange source |> shouldEqual [ (3, 4), (4, 28) ]
190+
191+
192+
[<Test>]
193+
let ``Member range 04 - Property``() =
194+
let source = """
195+
type T =
196+
member x.P = ()
197+
"""
198+
getTypeMemberRange source |> shouldEqual [ (3, 4), (3, 19) ]
199+
200+
201+
[<Test>]
202+
let ``Member range 05 - Setter only property``() =
203+
let source = """
204+
type T =
205+
member x.P with set (value) = v <- value
206+
"""
207+
getTypeMemberRange source |> shouldEqual [ (3, 4), (3, 44) ]
208+
209+
210+
[<Test>]
211+
let ``Member range 06 - Read-write property``() =
212+
let source = """
213+
type T =
214+
member this.MyReadWriteProperty
215+
with get () = x
216+
and set (value) = x <- value
217+
"""
218+
getTypeMemberRange source |> shouldEqual [ (3, 4), (5, 36)
219+
(3, 4), (5, 36) ]
220+
221+
222+
[<Test>]
223+
let ``Member range 07 - Auto property``() =
224+
let source = """
225+
type T =
226+
member val Property1 = ""
227+
"""
228+
getTypeMemberRange source |> shouldEqual [ (3, 4), (3, 29) ]
229+
230+
231+
[<Test>]
232+
let ``Member range 08 - Auto property with setter``() =
233+
let source = """
234+
type T =
235+
member val Property1 = "" with get, set
236+
"""
237+
getTypeMemberRange source |> shouldEqual [ (3, 4), (3, 29) ]
238+
239+
240+
[<Test>]
241+
let ``Member range 09 - Abstract slot``() =
242+
let source = """
243+
type T =
244+
abstract P: int
245+
abstract M: unit -> unit
246+
"""
247+
getTypeMemberRange source |> shouldEqual [ (3, 4), (3, 19)
248+
(4, 4), (4, 28) ]
249+
250+
[<Test>]
251+
let ``Member range 10 - Val field``() =
252+
let source = """
253+
type T =
254+
val x: int
255+
"""
256+
getTypeMemberRange source |> shouldEqual [ (3, 4), (3, 14) ]
257+
258+
259+
[<Test>]
260+
let ``Member range 11 - Ctor``() =
261+
let source = """
262+
type T =
263+
new (x:int) = ()
264+
"""
265+
getTypeMemberRange source |> shouldEqual [ (3, 4), (3, 20) ]

0 commit comments

Comments
 (0)