Skip to content

Commit c4f7bed

Browse files
ijklamvzarytovskii
andauthored
Allow access modifiers to auto properties getters and setters (#16687)
* Allow access modifies to auto properties * move types * update release note * Put it under preview flag * add and update baseline * move checks leave parser * update ServiceNavigation; fantomas * add tests * fix tests * fix tests * fix tests * fix tests * fix * fix * fix * fix * add spaces * fix grammar --------- Co-authored-by: Vlad Zarytovskii <[email protected]>
1 parent efa5537 commit c4f7bed

File tree

52 files changed

+588
-67
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+588
-67
lines changed

docs/release-notes/.FSharp.Compiler.Service/8.0.300.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
* Add switch to generate types and members with IL visibility that accurately represents their F# visibility. ([PR #15484](https://github.com/dotnet/fsharp/pull/15484)
2727
* Allow returning bool instead of unit option for partial active patterns. ([Language suggestion #1041](https://github.com/fsharp/fslang-suggestions/issues/1041), [PR #16473](https://github.com/dotnet/fsharp/pull/16473))
2828
* Symbols: Add GenericArguments to FSharpEntity ([PR #16470](https://github.com/dotnet/fsharp/pull/16470))
29+
* Allow access modifies to auto properties getters and setters ([PR 16687](https://github.com/dotnet/fsharp/pull/16687), [Language suggestion #430](https://github.com/fsharp/fslang-suggestions/issues/430))
2930

3031
### Changed
3132

docs/release-notes/.Language/preview.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* Bidirectional F#/C# interop for 'unmanaged' constraint. ([PR #12154](https://github.com/dotnet/fsharp/pull/12154))
66
* Make `.Is*` discriminated union properties visible. ([Language suggestion #222](https://github.com/fsharp/fslang-suggestions/issues/222), [PR #16341](https://github.com/dotnet/fsharp/pull/16341))
77
* Allow returning bool instead of unit option for partial active patterns. ([Language suggestion #1041](https://github.com/fsharp/fslang-suggestions/issues/1041), [PR #16473](https://github.com/dotnet/fsharp/pull/16473))
8+
* Allow access modifies to auto properties getters and setters ([PR 16687](https://github.com/dotnet/fsharp/pull/16687), [Language suggestion #430](https://github.com/fsharp/fslang-suggestions/issues/430))
89

910
### Fixed
1011

src/Compiler/Checking/CheckDeclarations.fs

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4309,7 +4309,7 @@ module TcDeclarations =
43094309
| _ -> ()
43104310

43114311
/// Split auto-properties into 'let' and 'member' bindings
4312-
let private SplitAutoProps members =
4312+
let private SplitAutoProps (g: TcGlobals) members =
43134313
let membersIncludingAutoProps, vals_Inherits_Abstractslots =
43144314
members |> List.partition (fun memb ->
43154315
match memb with
@@ -4359,7 +4359,7 @@ module TcDeclarations =
43594359
let rec postAutoProps memb =
43604360
match memb with
43614361
| SynMemberDefn.AutoProperty(ident = id) when String.IsNullOrEmpty(id.idText) -> []
4362-
| SynMemberDefn.AutoProperty(attributes=Attributes attribs; isStatic=isStatic; ident=id; typeOpt=tyOpt; propKind=propKind; memberFlags=memberFlags; memberFlagsForSet=memberFlagsForSet; xmlDoc=xmlDoc; accessibility=access; trivia = { GetSetKeywords = mGetSetOpt }) ->
4362+
| SynMemberDefn.AutoProperty(attributes=Attributes attribs; isStatic=isStatic; ident=id; typeOpt=tyOpt; propKind=propKind; memberFlags=memberFlags; memberFlagsForSet=memberFlagsForSet; xmlDoc=xmlDoc; trivia = { GetSetKeywords = mGetSetOpt }; accessibility = access; getterAccessibility = getterAccess; setterAccessibility = setterAccess) ->
43634363
let mMemberPortion = id.idRange
43644364
// Only the keep the non-field-targeted attributes
43654365
let attribs = attribs |> List.filter (fun a -> match a.Target with Some t when t.idText = "field" -> false | _ -> true)
@@ -4372,7 +4372,41 @@ module TcDeclarations =
43724372
match propKind, mGetSetOpt with
43734373
| SynMemberKind.PropertySet, Some getSetKeywords -> errorR(Error(FSComp.SR.parsMutableOnAutoPropertyShouldBeGetSetNotJustSet(), getSetKeywords.Range))
43744374
| _ -> ()
4375-
4375+
4376+
let getterAccess, setterAccess =
4377+
match propKind with
4378+
| SynMemberKind.PropertyGetSet ->
4379+
match access with
4380+
| Some _ ->
4381+
match getterAccess, setterAccess with
4382+
| None, None -> access, access
4383+
| Some x, _
4384+
| _, Some x ->
4385+
errorR(Error(FSComp.SR.parsMultipleAccessibilitiesForGetSet(), x.Range))
4386+
None, None
4387+
| None ->
4388+
match getterAccess, setterAccess with
4389+
| Some x, _
4390+
| _, Some x ->
4391+
checkLanguageFeatureAndRecover g.langVersion LanguageFeature.AllowAccessModifiersToAutoPropertiesGettersAndSetters x.Range
4392+
getterAccess, setterAccess
4393+
| _, _ -> None, None
4394+
| SynMemberKind.PropertySet ->
4395+
match access, setterAccess with
4396+
| Some _, Some x ->
4397+
errorR(Error(FSComp.SR.parsMultipleAccessibilitiesForGetSet(), x.Range))
4398+
None, None
4399+
| _, None -> None, access
4400+
| None, _ -> None, setterAccess
4401+
| SynMemberKind.Member
4402+
| SynMemberKind.PropertyGet
4403+
| _ ->
4404+
match access, getterAccess with
4405+
| Some _, Some x ->
4406+
errorR(Error(FSComp.SR.parsMultipleAccessibilitiesForGetSet(), x.Range))
4407+
None, None
4408+
| _, None -> access, None
4409+
| None, _ -> getterAccess, None
43764410
[
43774411
match propKind with
43784412
| SynMemberKind.Member
@@ -4382,7 +4416,7 @@ module TcDeclarations =
43824416
let rhsExpr = SynExpr.Ident fldId
43834417
let retInfo = match tyOpt with None -> None | Some ty -> Some (None, SynReturnInfo((ty, SynInfo.unnamedRetVal), ty.Range))
43844418
let attribs = mkAttributeList attribs mMemberPortion
4385-
let binding = mkSynBinding (xmlDoc, headPat) (access, false, false, mMemberPortion, DebugPointAtBinding.NoneAtInvisible, retInfo, rhsExpr, rhsExpr.Range, [], attribs, Some memberFlags, SynBindingTrivia.Zero)
4419+
let binding = mkSynBinding (xmlDoc, headPat) (getterAccess, false, false, mMemberPortion, DebugPointAtBinding.NoneAtInvisible, retInfo, rhsExpr, rhsExpr.Range, [], attribs, Some memberFlags, SynBindingTrivia.Zero)
43864420
SynMemberDefn.Member (binding, mMemberPortion)
43874421
yield getter
43884422
| _ -> ()
@@ -4394,7 +4428,7 @@ module TcDeclarations =
43944428
let vId = ident("v", mMemberPortion)
43954429
let headPat = SynPat.LongIdent (SynLongIdent(headPatIds, [], List.replicate headPatIds.Length None), None, Some noInferredTypars, SynArgPats.Pats [mkSynPatVar None vId], None, mMemberPortion)
43964430
let rhsExpr = mkSynAssign (SynExpr.Ident fldId) (SynExpr.Ident vId)
4397-
let binding = mkSynBinding (xmlDoc, headPat) (access, false, false, mMemberPortion, DebugPointAtBinding.NoneAtInvisible, None, rhsExpr, rhsExpr.Range, [], [], Some memberFlagsForSet, SynBindingTrivia.Zero)
4431+
let binding = mkSynBinding (xmlDoc, headPat) (setterAccess, false, false, mMemberPortion, DebugPointAtBinding.NoneAtInvisible, None, rhsExpr, rhsExpr.Range, [], [], Some memberFlagsForSet, SynBindingTrivia.Zero)
43984432
SynMemberDefn.Member (binding, mMemberPortion)
43994433
yield setter
44004434
| _ -> ()]
@@ -4418,9 +4452,9 @@ module TcDeclarations =
44184452
/// where simpleRepr can contain inherit type, declared fields and virtual slots.
44194453
/// body = members
44204454
/// where members contain methods/overrides, also implicit ctor, inheritCall and local definitions.
4421-
let rec private SplitTyconDefn (SynTypeDefn(typeInfo=synTyconInfo;typeRepr=trepr; members=extraMembers)) =
4455+
let rec private SplitTyconDefn g (SynTypeDefn(typeInfo=synTyconInfo;typeRepr=trepr; members=extraMembers)) =
44224456
let extraMembers = desugarGetSetMembers extraMembers
4423-
let extraMembers, extra_vals_Inherits_Abstractslots = SplitAutoProps extraMembers
4457+
let extraMembers, extra_vals_Inherits_Abstractslots = SplitAutoProps g extraMembers
44244458
let implements1 = extraMembers |> List.choose (function SynMemberDefn.Interface (interfaceType=ty) -> Some(ty, ty.Range) | _ -> None)
44254459

44264460
match trepr with
@@ -4441,7 +4475,7 @@ module TcDeclarations =
44414475

44424476
let slotsigs = members |> List.choose (function SynMemberDefn.AbstractSlot (slotSig = x; flags = y) -> Some(x, y) | _ -> None)
44434477

4444-
let members,_vals_Inherits_Abstractslots = SplitAutoProps members
4478+
let members,_vals_Inherits_Abstractslots = SplitAutoProps g members
44454479

44464480
let isConcrete =
44474481
members |> List.exists (function
@@ -4503,7 +4537,7 @@ module TcDeclarations =
45034537

45044538
// Split the definitions into "core representations" and "members". The code to process core representations
45054539
// is shared between processing of signature files and implementation files.
4506-
let mutRecDefnsAfterSplit = mutRecDefns |> MutRecShapes.mapTycons SplitTyconDefn
4540+
let mutRecDefnsAfterSplit = mutRecDefns |> MutRecShapes.mapTycons (fun i -> SplitTyconDefn g i)
45074541

45084542
// Create the entities for each module and type definition, and process the core representation of each type definition.
45094543
let tycons, envMutRecPrelim, mutRecDefnsAfterCore =

src/Compiler/FSComp.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1746,4 +1746,6 @@ featureReuseSameFieldsInStructUnions,"Share underlying fields in a [<Struct>] di
17461746
3862,parsStaticMemberImcompleteSyntax,"Incomplete declaration of a static construct. Use 'static let','static do','static member' or 'static val' for declaration."
17471747
3863,parsExpectingField,"Expecting record field"
17481748
3864,tooManyMethodsInDotNetTypeWritingAssembly,"The type '%s' has too many methods. Found: '%d', maximum: '%d'"
1749-
3865,parsOnlySimplePatternsAreAllowedInConstructors,"Only simple patterns are allowed in primary constructors"
1749+
3865,parsOnlySimplePatternsAreAllowedInConstructors,"Only simple patterns are allowed in primary constructors"
1750+
featureAllowAccessModifiersToAutoPropertiesGettersAndSetters,"Allow access modifiers to auto properties getters and setters"
1751+
3866,parsAccessModifiersBeforeGettersAndSettersNotAllowedInSigFile,"The modifier will be ignored because access modifiers before getters and setters are not allowed in signature file."

src/Compiler/Facilities/LanguageFeatures.fs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ type LanguageFeature =
8585
| WarningIndexedPropertiesGetSetSameType
8686
| WarningWhenTailCallAttrOnNonRec
8787
| BooleanReturningAndReturnTypeDirectedPartialActivePattern
88+
| AllowAccessModifiersToAutoPropertiesGettersAndSetters
8889
| EnforceAttributeTargetsOnFunctions
8990
| EnforceAttributeTargetsUnionCaseDeclarations
9091
| LowerInterpolatedStringToConcat
@@ -201,6 +202,7 @@ type LanguageVersion(versionText) =
201202
LanguageFeature.WarningWhenTailCallAttrOnNonRec, previewVersion
202203
LanguageFeature.UnionIsPropertiesVisible, previewVersion
203204
LanguageFeature.BooleanReturningAndReturnTypeDirectedPartialActivePattern, previewVersion
205+
LanguageFeature.AllowAccessModifiersToAutoPropertiesGettersAndSetters, previewVersion
204206
LanguageFeature.EnforceAttributeTargetsOnFunctions, previewVersion
205207
LanguageFeature.EnforceAttributeTargetsUnionCaseDeclarations, previewVersion
206208
LanguageFeature.LowerInterpolatedStringToConcat, previewVersion
@@ -348,6 +350,8 @@ type LanguageVersion(versionText) =
348350
| LanguageFeature.WarningWhenTailCallAttrOnNonRec -> FSComp.SR.featureChkTailCallAttrOnNonRec ()
349351
| LanguageFeature.BooleanReturningAndReturnTypeDirectedPartialActivePattern ->
350352
FSComp.SR.featureBooleanReturningAndReturnTypeDirectedPartialActivePattern ()
353+
| LanguageFeature.AllowAccessModifiersToAutoPropertiesGettersAndSetters ->
354+
FSComp.SR.featureAllowAccessModifiersToAutoPropertiesGettersAndSetters ()
351355
| LanguageFeature.EnforceAttributeTargetsOnFunctions -> FSComp.SR.featureEnforceAttributeTargetsOnFunctions ()
352356
| LanguageFeature.EnforceAttributeTargetsUnionCaseDeclarations -> FSComp.SR.featureEnforceAttributeTargetsUnionCaseDeclarations ()
353357
| LanguageFeature.LowerInterpolatedStringToConcat -> FSComp.SR.featureLowerInterpolatedStringToConcat ()

src/Compiler/Facilities/LanguageFeatures.fsi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ type LanguageFeature =
7676
| WarningIndexedPropertiesGetSetSameType
7777
| WarningWhenTailCallAttrOnNonRec
7878
| BooleanReturningAndReturnTypeDirectedPartialActivePattern
79+
| AllowAccessModifiersToAutoPropertiesGettersAndSetters
7980
| EnforceAttributeTargetsOnFunctions
8081
| EnforceAttributeTargetsUnionCaseDeclarations
8182
| LowerInterpolatedStringToConcat

src/Compiler/Service/ServiceNavigation.fs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -332,9 +332,19 @@ module NavigationImpl =
332332
[
333333
createMember (rcid, NavigationItemKind.Field, FSharpGlyph.Field, range, enclosingEntityKind, false, access)
334334
]
335-
| SynMemberDefn.AutoProperty(ident = id; accessibility = access) ->
335+
| SynMemberDefn.AutoProperty(
336+
ident = id; accessibility = access; getterAccessibility = getterAccessibility; setterAccessibility = setterAccessibility; propKind = propKind) ->
337+
let getterAccessibility = getterAccessibility |> Option.orElse access
338+
let setterAccessibility = setterAccessibility |> Option.orElse access
339+
336340
[
337-
createMember (id, NavigationItemKind.Field, FSharpGlyph.Field, id.idRange, enclosingEntityKind, false, access)
341+
match propKind with
342+
| SynMemberKind.PropertyGetSet ->
343+
yield createMember (id, NavigationItemKind.Field, FSharpGlyph.Field, id.idRange, enclosingEntityKind, false, getterAccessibility)
344+
yield createMember (id, NavigationItemKind.Field, FSharpGlyph.Field, id.idRange, enclosingEntityKind, false, setterAccessibility)
345+
| SynMemberKind.PropertySet ->
346+
yield createMember (id, NavigationItemKind.Field, FSharpGlyph.Field, id.idRange, enclosingEntityKind, false, setterAccessibility)
347+
| _ -> yield createMember (id, NavigationItemKind.Field, FSharpGlyph.Field, id.idRange, enclosingEntityKind, false, getterAccessibility)
338348
]
339349
| SynMemberDefn.AbstractSlot(slotSig = SynValSig(ident = SynIdent(id, _); synType = ty; accessibility = access)) ->
340350
[

src/Compiler/SyntaxTree/ParseHelpers.fs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1101,7 +1101,7 @@ let mkSynUnionCase attributes (access: SynAccess option) id kind mDecl (xmlDoc,
11011101
SynUnionCase(attributes, id, kind, xmlDoc, None, mDecl, trivia)
11021102

11031103
let mkAutoPropDefn mVal access ident typ mEquals (expr: SynExpr) accessors xmlDoc attribs flags rangeStart =
1104-
let mWith, (getSet, getSetOpt) = accessors
1104+
let mWith, (getSet, getSetOpt, getterAccess, setterAccess) = accessors
11051105

11061106
let memberRange =
11071107
match getSetOpt with
@@ -1135,6 +1135,8 @@ let mkAutoPropDefn mVal access ident typ mEquals (expr: SynExpr) accessors xmlDo
11351135
memberFlagsForSet,
11361136
xmlDoc,
11371137
access,
1138+
getterAccess,
1139+
setterAccess,
11381140
expr,
11391141
memberRange,
11401142
trivia

src/Compiler/SyntaxTree/ParseHelpers.fsi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ val mkAutoPropDefn:
272272
typ: SynType option ->
273273
mEquals: range option ->
274274
expr: SynExpr ->
275-
accessors: range option * (SynMemberKind * GetSetKeywords option) ->
275+
accessors: range option * (SynMemberKind * GetSetKeywords option * SynAccess option * SynAccess option) ->
276276
xmlDoc: PreXmlDoc ->
277277
attribs: SynAttributes ->
278278
flags: (SynMemberKind -> SynMemberFlags) * SynLeadingKeyword ->

src/Compiler/SyntaxTree/SyntaxTree.fs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1463,6 +1463,8 @@ type SynMemberDefn =
14631463
memberFlagsForSet: SynMemberFlags *
14641464
xmlDoc: PreXmlDoc *
14651465
accessibility: SynAccess option *
1466+
getterAccessibility: SynAccess option *
1467+
setterAccessibility: SynAccess option *
14661468
synExpr: SynExpr *
14671469
range: range *
14681470
trivia: SynMemberDefnAutoPropertyTrivia

src/Compiler/SyntaxTree/SyntaxTree.fsi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1656,6 +1656,8 @@ type SynMemberDefn =
16561656
memberFlagsForSet: SynMemberFlags *
16571657
xmlDoc: PreXmlDoc *
16581658
accessibility: SynAccess option *
1659+
getterAccessibility: SynAccess option *
1660+
setterAccessibility: SynAccess option *
16591661
synExpr: SynExpr *
16601662
range: range *
16611663
trivia: SynMemberDefnAutoPropertyTrivia

0 commit comments

Comments
 (0)