Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/Compiler/Checking/CheckDeclarations.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4142,7 +4142,9 @@ module TcDeclarations =

// Convert auto properties to let bindings in the pre-list
let rec preAutoProps memb =
match memb with
match memb with
| SynMemberDefn.AutoProperty(ident = id) when id.idText = "" -> []

| SynMemberDefn.AutoProperty(attributes=Attributes attribs; isStatic=isStatic; ident=id; typeOpt=tyOpt; propKind=propKind; xmlDoc=xmlDoc; synExpr=synExpr; range=mWholeAutoProp) ->
// Only the keep the field-targeted attributes
let attribs = attribs |> List.filter (fun a -> match a.Target with Some t when t.idText = "field" -> true | _ -> false)
Expand All @@ -4169,7 +4171,9 @@ module TcDeclarations =

// Convert auto properties to member bindings in the post-list
let rec postAutoProps memb =
match memb with
match memb with
| SynMemberDefn.AutoProperty(ident = id) when id.idText = "" -> []

| SynMemberDefn.AutoProperty(attributes=Attributes attribs; isStatic=isStatic; ident=id; typeOpt=tyOpt; propKind=propKind; memberFlags=memberFlags; memberFlagsForSet=memberFlagsForSet; xmlDoc=xmlDoc; accessibility=access; trivia = { GetSetKeywords = mGetSetOpt }) ->
let mMemberPortion = id.idRange
// Only the keep the non-field-targeted attributes
Expand Down
46 changes: 46 additions & 0 deletions src/Compiler/SyntaxTree/ParseHelpers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1099,3 +1099,49 @@ let mkSynUnionCase attributes (access: SynAccess option) id kind mDecl (xmlDoc,
let trivia: SynUnionCaseTrivia = { BarRange = Some mBar }
let mDecl = unionRangeWithXmlDoc xmlDoc mDecl
SynUnionCase(attributes, id, kind, xmlDoc, None, mDecl, trivia)

let mkAutoPropDefn mVal access ident typ mEquals (expr: SynExpr) accessors xmlDoc attribs flags rangeStart =
let mWith, (getSet, getSetOpt) = accessors
let memberRange = unionRanges rangeStart expr.Range |> unionRangeWithXmlDoc xmlDoc
let flags, leadingKeyword = flags
let leadingKeyword = appendValToLeadingKeyword mVal leadingKeyword
let memberFlags: SynMemberFlags = flags SynMemberKind.Member
let memberFlagsForSet = flags SynMemberKind.PropertySet
let isStatic = not memberFlags.IsInstance

let trivia =
{
LeadingKeyword = leadingKeyword
WithKeyword = mWith
EqualsRange = mEquals
GetSetKeywords = getSetOpt
}

SynMemberDefn.AutoProperty(
attribs,
isStatic,
ident,
typ,
getSet,
memberFlags,
memberFlagsForSet,
xmlDoc,
access,
expr,
memberRange,
trivia
)

let mkValField mVal mRhs mut access ident (typ: SynType) xmlDoc rangeStart attribs mStaticOpt =
let isStatic = Option.isSome mStaticOpt
let mValDecl = unionRanges rangeStart typ.Range |> unionRangeWithXmlDoc xmlDoc

let leadingKeyword =
match mStaticOpt with
| None -> SynLeadingKeyword.Val mVal
| Some mStatic -> SynLeadingKeyword.StaticVal(mStatic, mVal)

let fld =
SynField(attribs, isStatic, Some ident, typ, mut, xmlDoc, access, mRhs, { LeadingKeyword = Some leadingKeyword })

SynMemberDefn.ValField(fld, mValDecl)
27 changes: 27 additions & 0 deletions src/Compiler/SyntaxTree/ParseHelpers.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -247,3 +247,30 @@ val mkSynUnionCase:
mDecl: range ->
(PreXmlDoc * range) ->
SynUnionCase

val mkAutoPropDefn:
mVal: range ->
access: SynAccess option ->
ident: Ident ->
typ: SynType option ->
mEquals: range option ->
expr: SynExpr ->
accessors: range option * (SynMemberKind * GetSetKeywords option) ->
xmlDoc: PreXmlDoc ->
attribs: SynAttributes ->
flags: (SynMemberKind -> SynMemberFlags) * SynLeadingKeyword ->
rangeStart: range ->
SynMemberDefn

val mkValField:
mVal: range ->
mRhs: range ->
mut: bool ->
access: SynAccess option ->
ident: Ident ->
typ: SynType ->
xmlDoc: PreXmlDoc ->
range ->
SynAttributes ->
range option ->
SynMemberDefn
104 changes: 80 additions & 24 deletions src/Compiler/pars.fsy
Original file line number Diff line number Diff line change
Expand Up @@ -2017,42 +2017,98 @@ valDefnDecl:
| VAL opt_mutable opt_access ident COLON typ
{ let mVal = rhs parseState 1
let mRhs = rhs2 parseState 4 6
let mValDecl = rhs2 parseState 1 6
(fun rangeStart attribs mStaticOpt ->
let isStatic = Option.isSome mStaticOpt
let xmlDoc = grabXmlDocAtRangeStart(parseState, attribs, rangeStart)
let mValDecl = unionRanges rangeStart mValDecl |> unionRangeWithXmlDoc xmlDoc
let leadingKeyword =
match mStaticOpt with
| None -> SynLeadingKeyword.Val mVal
| Some mStatic -> SynLeadingKeyword.StaticVal(mStatic, mVal)
let fld = SynField(attribs, isStatic, Some $4, $6, $2, xmlDoc, $3, mRhs, { LeadingKeyword = Some leadingKeyword })
[ SynMemberDefn.ValField(fld, mValDecl) ]) }
fun rangeStart attribs mStaticOpt ->
let xmlDoc = grabXmlDocAtRangeStart (parseState, attribs, rangeStart)
[ mkValField mVal mRhs $2 $3 $4 $6 xmlDoc rangeStart attribs mStaticOpt ] }

| VAL opt_mutable opt_access ident COLON recover
{ let mVal = rhs parseState 1
let mRhs = rhs2 parseState 4 6
let mColon = rhs parseState 5
let ty = SynType.FromParseError(mColon.EndRange)
fun rangeStart attribs mStaticOpt ->
let xmlDoc = grabXmlDocAtRangeStart (parseState, attribs, rangeStart)
[ mkValField mVal mRhs $2 $3 $4 ty xmlDoc rangeStart attribs mStaticOpt ] }

| VAL opt_mutable opt_access ident recover
{ let mVal = rhs parseState 1
let mRhs = rhs2 parseState 4 6
let mColon = rhs parseState 5
let ty = SynType.FromParseError(mColon.EndRange)
fun rangeStart attribs mStaticOpt ->
let xmlDoc = grabXmlDocAtRangeStart (parseState, attribs, rangeStart)
[ mkValField mVal mRhs $2 $3 $4 ty xmlDoc rangeStart attribs mStaticOpt ] }

| VAL opt_mutable opt_access recover
{ let mVal = rhs parseState 1
let mRhs = rhs2 parseState 4 6
let id = mkSynId mVal.EndRange ""
let mColon = rhs parseState 5
let ty = SynType.FromParseError(mColon.EndRange)
fun rangeStart attribs mStaticOpt ->
let xmlDoc = grabXmlDocAtRangeStart (parseState, attribs, rangeStart)
[ mkValField mVal mRhs $2 $3 id ty xmlDoc rangeStart attribs mStaticOpt ] }


/* An auto-property definition in an object type definition */
autoPropsDefnDecl:
| VAL opt_mutable opt_access ident opt_typ EQUALS typedSequentialExprBlock classMemberSpfnGetSet
{ let mVal = rhs parseState 1
let mWith, (getSet, getSetOpt) = $8
let mEquals = rhs parseState 6
if $2 then
errorR (Error (FSComp.SR.parsMutableOnAutoPropertyShouldBeGetSet (), rhs parseState 3))
(fun attribs flags rangeStart ->
errorR (Error(FSComp.SR.parsMutableOnAutoPropertyShouldBeGetSet (), rhs parseState 2))
fun attribs flags rangeStart ->
let xmlDoc = grabXmlDocAtRangeStart (parseState, attribs, rangeStart)
[ mkAutoPropDefn mVal $3 $4 $5 (Some mEquals) $7 $8 xmlDoc attribs flags rangeStart ] }

| VAL opt_mutable opt_access ident opt_typ ends_coming_soon_or_recover
{ let mVal = rhs parseState 1
let mEnd =
match $5 with
| Some t -> t.Range
| _ -> $4.idRange
let expr = arbExpr ("autoProp1", mEnd.EndRange)
if $2 then
errorR (Error(FSComp.SR.parsMutableOnAutoPropertyShouldBeGetSet (), rhs parseState 2))
fun attribs flags rangeStart ->
let xmlDoc = grabXmlDocAtRangeStart (parseState, attribs, rangeStart)
[ mkAutoPropDefn mVal $3 $4 $5 None expr (None, (SynMemberKind.Member, None)) xmlDoc attribs flags rangeStart ] }

| VAL opt_mutable opt_access ident opt_typ OBLOCKSEP
{ let mVal = rhs parseState 1
let mEnd =
match $5 with
| Some t -> t.Range
| _ -> $4.idRange
let expr = arbExpr ("autoProp2", mEnd.EndRange)
if $2 then
errorR (Error(FSComp.SR.parsMutableOnAutoPropertyShouldBeGetSet (), rhs parseState 2))
fun attribs flags rangeStart ->
let xmlDoc = grabXmlDocAtRangeStart (parseState, attribs, rangeStart)
[ mkAutoPropDefn mVal $3 $4 $5 None expr (None, (SynMemberKind.Member, None)) xmlDoc attribs flags rangeStart ] }

| VAL opt_mutable opt_access recover
{ let mVal = rhs parseState 1
let id = mkSynId mVal.EndRange ""
let expr = arbExpr ("autoProp3", mVal.EndRange)
if $2 then
errorR (Error(FSComp.SR.parsMutableOnAutoPropertyShouldBeGetSet (), rhs parseState 2))
fun attribs flags rangeStart ->
let xmlDoc = grabXmlDocAtRangeStart(parseState, attribs, rangeStart)
let memberRange = unionRanges rangeStart $7.Range |> unionRangeWithXmlDoc xmlDoc
let flags, leadingKeyword = flags
let leadingKeyword = appendValToLeadingKeyword mVal leadingKeyword
let memberFlags = flags SynMemberKind.Member
let memberFlagsForSet = flags SynMemberKind.PropertySet
let isStatic = not memberFlags.IsInstance
let trivia = { LeadingKeyword = leadingKeyword; WithKeyword = mWith; EqualsRange = Some mEquals; GetSetKeywords = getSetOpt }
[ SynMemberDefn.AutoProperty(attribs, isStatic, $4, $5, getSet, memberFlags, memberFlagsForSet, xmlDoc, $3, $7, memberRange, trivia) ]) }
[ mkAutoPropDefn mVal $3 id None None expr (None, (SynMemberKind.Member, None)) xmlDoc attribs flags rangeStart ] }

/* An optional type on an auto-property definition */
opt_typ:
| /* EMPTY */ { None }
| COLON typ { Some $2 }
| /* EMPTY */
{ None }

| COLON typ
{ Some $2 }

| COLON recover
{ let mColon = rhs parseState 1
let ty = SynType.FromParseError(mColon.EndRange)
Some ty }


atomicPatternLongIdent:
Expand Down
4 changes: 4 additions & 0 deletions tests/service/data/SyntaxTree/Member/Auto property 01.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Module

type T =
member val P1 = 1
42 changes: 42 additions & 0 deletions tests/service/data/SyntaxTree/Member/Auto property 01.fs.bsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
ImplFile
(ParsedImplFileInput
("/root/Member/Auto property 01.fs", false, QualifiedNameOfFile Module, [],
[],
[SynModuleOrNamespace
([Module], false, NamedModule,
[Types
([SynTypeDefn
(SynComponentInfo
([], None, [], [T],
PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector),
false, None, (3,5--3,6)),
ObjectModel
(Unspecified,
[AutoProperty
([], false, P1, None, Member,
{ IsInstance = true
IsDispatchSlot = false
IsOverrideOrExplicitImpl = false
IsFinal = false
GetterOrSetterIsCompilerGenerated = false
MemberKind = Member },
{ IsInstance = true
IsDispatchSlot = false
IsOverrideOrExplicitImpl = false
IsFinal = false
GetterOrSetterIsCompilerGenerated = false
MemberKind = PropertySet },
PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector),
None, Const (Int32 1, (4,20--4,21)), (4,4--4,21),
{ LeadingKeyword =
MemberVal ((4,4--4,10), (4,11--4,14))
WithKeyword = None
EqualsRange = Some (4,18--4,19)
GetSetKeywords = None })], (4,4--4,21)), [], None,
(3,5--4,21), { LeadingKeyword = Type (3,0--3,4)
EqualsRange = Some (3,7--3,8)
WithKeyword = None })], (3,0--4,21))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--4,21), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
CodeComments = [] }, set []))
6 changes: 6 additions & 0 deletions tests/service/data/SyntaxTree/Member/Auto property 02.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module Module

type T =
member val P1 =

()
49 changes: 49 additions & 0 deletions tests/service/data/SyntaxTree/Member/Auto property 02.fs.bsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
ImplFile
(ParsedImplFileInput
("/root/Member/Auto property 02.fs", false, QualifiedNameOfFile Module, [],
[],
[SynModuleOrNamespace
([Module], false, NamedModule,
[Types
([SynTypeDefn
(SynComponentInfo
([], None, [], [T],
PreXmlDoc ((3,0), FSharp.Compiler.Xml.XmlDocCollector),
false, None, (3,5--3,6)),
ObjectModel
(Unspecified,
[AutoProperty
([], false, P1, None, Member,
{ IsInstance = true
IsDispatchSlot = false
IsOverrideOrExplicitImpl = false
IsFinal = false
GetterOrSetterIsCompilerGenerated = false
MemberKind = Member },
{ IsInstance = true
IsDispatchSlot = false
IsOverrideOrExplicitImpl = false
IsFinal = false
GetterOrSetterIsCompilerGenerated = false
MemberKind = PropertySet },
PreXmlDoc ((4,4), FSharp.Compiler.Xml.XmlDocCollector),
None,
ArbitraryAfterError
("typedSequentialExprBlock1", (4,19--4,19)),
(4,4--4,19),
{ LeadingKeyword =
MemberVal ((4,4--4,10), (4,11--4,14))
WithKeyword = None
EqualsRange = Some (4,18--4,19)
GetSetKeywords = None })], (4,4--4,19)), [], None,
(3,5--4,19), { LeadingKeyword = Type (3,0--3,4)
EqualsRange = Some (3,7--3,8)
WithKeyword = None })], (3,0--4,19));
Expr (Const (Unit, (6,0--6,2)), (6,0--6,2))],
PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector), [], None,
(1,0--6,2), { LeadingKeyword = Module (1,0--1,6) })], (true, true),
{ ConditionalDirectives = []
CodeComments = [] }, set []))

(6,0)-(6,1) parse error Possible incorrect indentation: this token is offside of context started at position (4:5). Try indenting this token further or using standard formatting conventions.
(6,0)-(6,1) parse error Expecting expression
7 changes: 7 additions & 0 deletions tests/service/data/SyntaxTree/Member/Auto property 03.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module Module

type T =
member val P1 =
member val P2 = 2

()
Loading