Skip to content
Closed
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
4 changes: 3 additions & 1 deletion src/Compiler/Checking/CheckDeclarations.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2530,6 +2530,7 @@ let TcMutRecDefns_Phase2 (cenv: cenv) envInitial bindsm scopem mutRecNSInfo (env
| SynMemberDefn.LetBindings _
| SynMemberDefn.AutoProperty _
| SynMemberDefn.Member _
| SynMemberDefn.ReadWriteMember _
| SynMemberDefn.Open _
-> Some(TyconBindingDefn(containerInfo, newslotsOK, declKind, memb, memb.Range))

Expand Down Expand Up @@ -4832,7 +4833,8 @@ module TcDeclarations =
cspec |> List.filter (fun memb ->
match memb with
| SynMemberDefn.Interface _
| SynMemberDefn.Member _
| SynMemberDefn.Member _
| SynMemberDefn.ReadWriteMember _
| SynMemberDefn.LetBindings _
| SynMemberDefn.ImplicitCtor _
| SynMemberDefn.AutoProperty _
Expand Down
3 changes: 3 additions & 0 deletions src/Compiler/Service/ServiceInterfaceStubGenerator.fs
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,9 @@ module InterfaceStubGenerator =
else
Option.bind (List.tryPick walkSynMemberDefn) members
| SynMemberDefn.Member (binding, _range) -> walkBinding binding
| SynMemberDefn.ReadWriteMember (read = read; write = write) ->
walkExpr read.Expression
|> Option.orElseWith (fun () -> walkExpr write.Expression)
| SynMemberDefn.NestedType (typeDef, _access, _range) -> walkSynTypeDefn typeDef
| SynMemberDefn.ValField (_field, _range) -> None
| SynMemberDefn.LetBindings (bindings, _isStatic, _isRec, _range) -> List.tryPick walkBinding bindings
Expand Down
15 changes: 15 additions & 0 deletions src/Compiler/Service/ServiceNavigation.fs
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,21 @@ module NavigateTo =
walkSynMemberDefn m container
| None -> ()
| SynMemberDefn.Member (binding, _) -> addBinding binding None container
| SynMemberDefn.ReadWriteMember (identifier = pat) ->
let kind = mapMemberKind SynMemberKind.PropertyGetSet

match pat with
| SynPat.LongIdent(longDotId = SynLongIdent ([ _; id ], _, _)) ->
// instance members
addIdent kind id false container
| SynPat.LongIdent(longDotId = SynLongIdent ([ id ], _, _)) ->
// functions
addIdent kind id false container
| SynPat.Named (SynIdent (id, _), _, _, _)
| SynPat.As (_, SynPat.Named (SynIdent (id, _), _, _, _), _) ->
// values
addIdent kind id false container
| _ -> ()
| SynMemberDefn.NestedType (typeDef, _, _) -> walkSynTypeDefn typeDef container
| SynMemberDefn.ValField (field, _) -> addField field false container
| SynMemberDefn.LetBindings (bindings, _, _, _) ->
Expand Down
3 changes: 3 additions & 0 deletions src/Compiler/Service/ServiceParseTreeWalk.fs
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,9 @@ module SyntaxTraversal =
| SynMemberDefn.Inherit (synType, _identOption, range) -> traverseInherit (synType, range)
| SynMemberDefn.ValField (_synField, _range) -> None
| SynMemberDefn.NestedType (synTypeDefn, _synAccessOption, _range) -> traverseSynTypeDefn path synTypeDefn
| SynMemberDefn.ReadWriteMember (read = read; write = write) ->
traverseSynExpr path read.Expression
|> Option.orElseWith (fun () -> traverseSynExpr path write.Expression)

and traverseSynMatchClause origPath mc =
let defaultTraverse mc =
Expand Down
7 changes: 7 additions & 0 deletions src/Compiler/Service/ServiceXmlDocParser.fs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,13 @@ module XmlDocParsing =
let indent = indentOf line
XmlDocable(line, indent, [])

| SynMemberDefn.ReadWriteMember (xmlDoc = xmlDoc; identifier = synPat; range = range) ->
if isEmptyXmlDoc xmlDoc then
let line = range.StartLine
let indent = indentOf line
let paramNames = digNamesFrom synPat
XmlDocable(line, indent, paramNames)

| SynMemberDefn.Open _
| SynMemberDefn.ImplicitCtor _
| SynMemberDefn.ImplicitInherit _
Expand Down
26 changes: 26 additions & 0 deletions src/Compiler/SyntaxTree/SyntaxTree.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1367,6 +1367,18 @@ type SynMemberDefn =

| Member of memberDefn: SynBinding * range: range

| ReadWriteMember of
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to GetSetProperty.

accessibility: SynAccess option *
attributes: SynAttributes *
memberFlags: (SynMemberKind -> SynMemberFlags) *
xmlDoc: PreXmlDoc *
identifier: SynPat *
returnTypeOpt: SynReturnInfo option *
read: SynMemberDefnPropertyInfo *
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename to getter and setter

write: SynMemberDefnPropertyInfo *
range: range *
trivia: SynMemberDefnReadWriteMemberTrivia

| ImplicitCtor of
accessibility: SynAccess option *
attributes: SynAttributes *
Expand Down Expand Up @@ -1407,6 +1419,7 @@ type SynMemberDefn =
member d.Range =
match d with
| SynMemberDefn.Member (range = m)
| SynMemberDefn.ReadWriteMember (range = m)
| SynMemberDefn.Interface (range = m)
| SynMemberDefn.Open (range = m)
| SynMemberDefn.LetBindings (range = m)
Expand All @@ -1420,6 +1433,19 @@ type SynMemberDefn =

type SynMemberDefns = SynMemberDefn list

type SynMemberDefnPropertyInfo =
{
IsInline: bool
Attributes: SynAttributes
/// 'get' or 'set
IsWrite: bool
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to IsSetter

Pattern: SynPat
ReturnInfo: SynReturnInfo option
Expression: SynExpr
Range: range
Trivia: SynMemberDefnPropertyInfoTrivia
}

[<NoEquality; NoComparison; RequireQualifiedAccess>]
type SynModuleDecl =

Expand Down
26 changes: 26 additions & 0 deletions src/Compiler/SyntaxTree/SyntaxTree.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -1554,6 +1554,19 @@ type SynMemberDefn =
/// A 'member' definition within a type
| Member of memberDefn: SynBinding * range: range

/// A 'member' definition with a get and set portion
| ReadWriteMember of
accessibility: SynAccess option *
attributes: SynAttributes *
memberFlags: (SynMemberKind -> SynMemberFlags) *
xmlDoc: PreXmlDoc *
identifier: SynPat *
returnTypeOpt: SynReturnInfo option *
read: SynMemberDefnPropertyInfo *
write: SynMemberDefnPropertyInfo *
range: range *
trivia: SynMemberDefnReadWriteMemberTrivia

/// An implicit constructor definition
| ImplicitCtor of
accessibility: SynAccess option *
Expand Down Expand Up @@ -1605,6 +1618,19 @@ type SynMemberDefn =

type SynMemberDefns = SynMemberDefn list

type SynMemberDefnPropertyInfo =
{
IsInline: bool
Attributes: SynAttributes
/// 'get' or 'set
IsWrite: bool
Pattern: SynPat
ReturnInfo: SynReturnInfo option
Expression: SynExpr
Range: range
Trivia: SynMemberDefnPropertyInfoTrivia
}

/// Represents a definition within a module
[<NoEquality; NoComparison; RequireQualifiedAccess>]
type SynModuleDecl =
Expand Down
88 changes: 88 additions & 0 deletions src/Compiler/SyntaxTree/SyntaxTreeOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -985,3 +985,91 @@ let mkDynamicArgExpr expr =
SynExpr.Const(con, con.Range ident.idRange)
| SynExpr.Paren (expr = e) -> e
| e -> e

let mkSynMemberGetOrSet
(grabXmlDocAtRangeStart: SynAttributes -> range -> PreXmlDoc)
(optInline: bool)
(propertyNameBindingPat: SynPat)
(mBindPattern: range)
(mWith: range)
(memberDefnPropertyInfo: SynMemberDefnPropertyInfo)
: SynAccess option -> (SynMemberKind -> SynMemberFlags) -> SynAttributeList list -> range -> SynMemberDefn list =
fun vis memFlagsBuilder attrs rangeStart ->
let optInline = optInline || memberDefnPropertyInfo.IsInline
let attrs = attrs @ memberDefnPropertyInfo.Attributes

let memberKind =
if memberDefnPropertyInfo.IsWrite then
SynMemberKind.PropertySet
else
SynMemberKind.PropertyGet

let xmlDoc = grabXmlDocAtRangeStart attrs rangeStart

let binding =
let mLhs = unionRanges mBindPattern memberDefnPropertyInfo.Pattern.Range

let headPat =
match propertyNameBindingPat with
| SynPat.LongIdent (longDotId, _, _, typarDecls, _, access, _) ->
let getSet = if memberDefnPropertyInfo.IsWrite then "set" else "get"

let m =
unionRanges memberDefnPropertyInfo.Trivia.GetSetRange memberDefnPropertyInfo.Pattern.Range

SynPat.LongIdent(
longDotId,
Some(PropertyKeyword.With mWith),
Some(ident (getSet, memberDefnPropertyInfo.Trivia.GetSetRange)),
typarDecls,
SynArgPats.Pats([ memberDefnPropertyInfo.Pattern ]),
access,
m
)
| pat -> pat

mkSynBinding
(xmlDoc, headPat)
(vis,
optInline,
false,
mBindPattern,
DebugPointAtBinding.NoneAtInvisible,
memberDefnPropertyInfo.ReturnInfo,
memberDefnPropertyInfo.Expression,
mLhs,
[],
attrs,
Some(memFlagsBuilder memberKind),
SynBindingTrivia.Zero)

let memberRange =
unionRanges rangeStart memberDefnPropertyInfo.Expression.Range
|> unionRangeWithXmlDoc xmlDoc

[ SynMemberDefn.Member(binding, memberRange) ]

let (|GetOrSetPattern|GetOrSetWithoutArgument|NoGetSetWord|) (pat: SynPat) : Choice<(string * SynPat), string, unit> =
let isGetOrSet v =
if v = "get" || v = "set" then Some v else None

let stripParensFromUnit p =
match p with
| SynPat.Paren(pat = SynPat.Const(constant = SynConst.Unit) as patUnit) -> patUnit
| _ -> p

let rec visit p =
match p with
| SynPat.LongIdent (longDotId = SynLongIdent ([ id ], _, _); argPats = SynArgPats.Pats [ singleArg ]) ->
isGetOrSet id.idText, Some(stripParensFromUnit singleArg)
| SynPat.Named (SynIdent (nm, _), _, _, _)
| SynPat.As (_, SynPat.Named (SynIdent (nm, _), _, _, _), _) -> isGetOrSet nm.idText, None
| SynPat.Typed (p, _, _) -> visit p
| SynPat.Attrib (p, _, _) -> visit p
| _ -> None, None

match visit pat with
| None, None -> NoGetSetWord
| Some v, None -> GetOrSetWithoutArgument v
| None, Some _ -> NoGetSetWord
| Some getOrSet, Some arg -> GetOrSetPattern(getOrSet, arg)
11 changes: 11 additions & 0 deletions src/Compiler/SyntaxTree/SyntaxTreeOps.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -340,3 +340,14 @@ val (|SynPipeRight3|_|): SynExpr -> (SynExpr * SynExpr * SynExpr * SynExpr) opti
val prependIdentInLongIdentWithTrivia: ident: SynIdent -> dotm: range -> lid: SynLongIdent -> SynLongIdent

val mkDynamicArgExpr: expr: SynExpr -> SynExpr

val mkSynMemberGetOrSet:
grabXmlDocAtRangeStart: (SynAttributes -> range -> PreXmlDoc) ->
optInline: bool ->
propertyNameBindingPat: SynPat ->
mBindPattern: range ->
mWith: range ->
memberDefnPropertyInfo: SynMemberDefnPropertyInfo ->
(SynAccess option -> (SynMemberKind -> SynMemberFlags) -> SynAttributeList list -> range -> SynMemberDefn list)

val (|GetOrSetPattern|GetOrSetWithoutArgument|NoGetSetWord|): pat: SynPat -> Choice<(string * SynPat), string, unit>
14 changes: 14 additions & 0 deletions src/Compiler/SyntaxTree/SyntaxTrivia.fs
Original file line number Diff line number Diff line change
Expand Up @@ -230,3 +230,17 @@ type SynValSigTrivia =
WithKeyword = None
EqualsRange = None
}

[<NoEquality; NoComparison>]
type SynMemberDefnReadWriteMemberTrivia =
{
WithKeyword: range
AndKeyword: range
}

[<NoEquality; NoComparison>]
type SynMemberDefnPropertyInfoTrivia =
{
GetSetRange: range
EqualsRange: range
}
20 changes: 20 additions & 0 deletions src/Compiler/SyntaxTree/SyntaxTrivia.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -324,3 +324,23 @@ type SynValSigTrivia =
}

static member Zero: SynValSigTrivia

/// Represents additional information for SynMemberDefn.ReadWriteMember
[<NoEquality; NoComparison>]
type SynMemberDefnReadWriteMemberTrivia =
{
/// The syntax range of the `with` keyword
WithKeyword: range
/// The syntax range of the `and` keyword
AndKeyword: range
}

/// Represents additional information for SynMemberDefnPropertyInfo
[<NoEquality; NoComparison>]
type SynMemberDefnPropertyInfoTrivia =
{
/// The syntax range of the `get` or `set` keyword
GetSetRange: range
/// The syntax range of the `=` token after the read pattern
EqualsRange: range
}
Loading