Skip to content

Commit 1053af3

Browse files
authored
Psi: Support auto property get set access modifiers (#1007)
1 parent eb6a7e3 commit 1053af3

File tree

55 files changed

+480
-119
lines changed

Some content is hidden

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

55 files changed

+480
-119
lines changed

ReSharper.FSharp/src/FSharp/FSharp.Psi.Features/src/AICore/FSharpFileSummarizer.fs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -78,16 +78,7 @@ type private FileSummarizerVisitor() =
7878
let addMember (memberDecl: IOverridableMemberDeclaration) (context: SummarizerContext) =
7979
let typeRepr = memberDecl.GetFcsSymbol() |> formatFcsSymbolType
8080
let accessorNames =
81-
match memberDecl with
82-
| :? IAccessorsNamesClauseOwner as prop ->
83-
match prop.AccessorsClause with
84-
| null -> Seq.empty
85-
| clause -> clause.AccessorsNamesEnumerable |> Seq.map _.Name
86-
87-
| :? IMemberSignatureOrDeclaration as memberDecl ->
88-
memberDecl.AccessorDeclarationsEnumerable |> Seq.map _.NameIdentifier.Name
89-
90-
| _ -> Seq.empty
81+
memberDecl.AccessorDeclarations |> Seq.map _.AccessorName
9182

9283
let accessors =
9384
if Seq.isEmpty accessorNames then "" else

ReSharper.FSharp/src/FSharp/FSharp.Psi.Features/src/LanguageService/FSharpElementFactory.fs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -403,14 +403,14 @@ type FSharpElementFactory(languageService: IFSharpLanguageService, [<NotNull>] c
403403

404404
typeDeclaration.TypeParameterDeclarationList
405405

406-
member this.CreateAccessorsNamesClause(withGetter, withSetter) =
406+
member this.CreateAutoPropertyDeclaration(withGetter, withSetter) =
407407
let accessors = [|
408408
if withGetter then "get"
409409
if withSetter then "set" |] |> String.concat ", "
410410

411411
let source = $"member val P = 3 with {accessors}"
412412
let t = getTypeDecl source
413-
t.MemberDeclarations[0].As<IAutoPropertyDeclaration>().AccessorsClause
413+
t.MemberDeclarations[0].As<IAutoPropertyDeclaration>()
414414

415415
member this.CreateEmptyFile() = createFile ""
416416

ReSharper.FSharp/src/FSharp/FSharp.Psi.Features/src/Parsing/FSharpImplTreeBuilder.fs

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -255,33 +255,26 @@ type FSharpImplTreeBuilder(lexer, document, decls, warnDirectives, lifetime, pat
255255
| SynMemberDefn.Member(binding, range) ->
256256
x.ProcessMemberBinding(mark, binding, range, None)
257257

258-
| SynMemberDefn.AbstractSlot(SynValSig(explicitTypeParams = typeParams; synType = synType; arity = arity; trivia = trivia), _, range, _) ->
258+
| SynMemberDefn.AbstractSlot(SynValSig(explicitTypeParams = typeParams; synType = synType; arity = arity; accessibility = accessibility), _, _, memberTrivia) ->
259259
match typeParams with
260260
| SynValTyparDecls(Some(typeParams), _) ->
261261
x.ProcessTypeParameters(typeParams, false)
262262
| _ -> ()
263263
x.ProcessReturnTypeInfo(arity, synType)
264-
x.ProcessAccessorsNamesClause(trivia, range)
264+
x.ProcessImplicitAccessors(memberTrivia.GetSetKeywords, accessibility)
265265
ElementType.ABSTRACT_MEMBER_DECLARATION
266266

267267
| SynMemberDefn.ValField(SynField(fieldType = synType), _) ->
268268
x.ProcessType(synType)
269269
ElementType.VAL_FIELD_DECLARATION
270270

271-
| SynMemberDefn.AutoProperty(_, _, _, synTypeOpt, _, _, _, _, _, expr, _, accessorClause) ->
271+
| SynMemberDefn.AutoProperty(_, _, _, synTypeOpt, _, _, _, _, accessibility, expr, _, accessorClause) ->
272272
match synTypeOpt with
273273
| Some synType -> x.ProcessType(synType)
274274
| _ -> ()
275-
x.MarkChameleonExpression(expr)
276-
277-
match accessorClause.WithKeyword, accessorClause.GetSetKeywords with
278-
| Some withKeyword, None ->
279-
x.MarkAndDone(withKeyword, ElementType.ACCESSORS_NAMES_CLAUSE)
280-
| Some withKeyword, Some getSetKeywords ->
281-
let range = Range.unionRanges withKeyword getSetKeywords.Range
282-
x.MarkAndDone(range, ElementType.ACCESSORS_NAMES_CLAUSE)
283-
| _ -> ()
284275

276+
x.MarkChameleonExpression(expr)
277+
x.ProcessImplicitAccessors(accessorClause.GetSetKeywords, accessibility)
285278
ElementType.AUTO_PROPERTY_DECLARATION
286279

287280
| _ -> failwithf "Unexpected type member: %A" typeMember

ReSharper.FSharp/src/FSharp/FSharp.Psi.Features/src/Parsing/FSharpTreeBuilderBase.fs

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -941,22 +941,47 @@ type FSharpTreeBuilderBase(lexer: ILexer, document: IDocument, warnDirectives: W
941941
x.MarkAndDone(range, ElementType.TYPE_PARAMETER_ID)
942942
x.Done(range, mark, ElementType.TYPE_REFERENCE_NAME)
943943

944-
member x.ProcessAccessorsNamesClause(trivia: SynValSigTrivia, memberRange) =
945-
match trivia.WithKeyword with
944+
member x.ProcessImplicitAccessors(getSetKeywords, accessibility) =
945+
let processAccessor (access, nameRange: range) =
946+
let mark =
947+
match access with
948+
| Some (access: SynAccess) -> x.Mark(access.Range)
949+
| None -> x.Mark(nameRange)
950+
951+
x.Done(nameRange, mark, ElementType.ACCESSOR_DECLARATION)
952+
953+
let getAccess, setAccess =
954+
match accessibility with
955+
| SynValSigAccess.GetSet(_, getAccess, setAccess) -> getAccess, setAccess
956+
| _ -> None, None
957+
958+
match getSetKeywords with
946959
| None -> ()
947-
| Some withRange ->
960+
| Some getSetKeywords ->
961+
962+
match getSetKeywords with
963+
| GetSetKeywords.GetSet(getKeyword, setKeyword) ->
964+
let getter = getAccess, getKeyword
965+
let setter = setAccess, setKeyword
966+
967+
let accessor1, accessor2 =
968+
if Range.rangeBeforePos getKeyword setKeyword.Start then getter, setter
969+
else setter, getter
970+
971+
processAccessor accessor1
972+
processAccessor accessor2
948973

949-
let accessorsMark = x.Mark(withRange)
950-
x.Done(memberRange, accessorsMark, ElementType.ACCESSORS_NAMES_CLAUSE)
974+
| GetSetKeywords.Get(get) -> processAccessor (getAccess, get)
975+
| GetSetKeywords.Set(set) -> processAccessor (setAccess, set)
951976

952977
member x.ProcessTypeMemberSignature(memberSig) =
953978
match memberSig with
954-
| SynMemberSig.Member(SynValSig(attrs, _, _, synType, arity, _, _, XmlDoc xmlDoc, _, _, _, trivia), flags, range, _) ->
979+
| SynMemberSig.Member(SynValSig(attrs, _, _, synType, arity, _, _, XmlDoc xmlDoc, accessibility, _, _, _), flags, range, memberTrivia) ->
955980
let mark = x.MarkAndProcessIntro(attrs, xmlDoc, null, range)
956981
x.ProcessReturnTypeInfo(arity, synType)
957982
let elementType =
958983
if flags.IsDispatchSlot then
959-
x.ProcessAccessorsNamesClause(trivia, range)
984+
x.ProcessImplicitAccessors(memberTrivia.GetSetKeywords, accessibility)
960985
ElementType.ABSTRACT_MEMBER_DECLARATION
961986
else
962987
match flags.MemberKind with

ReSharper.FSharp/src/FSharp/FSharp.Psi.Intentions/src/QuickFixes/AddSetterFix.fs

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,24 @@ namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.QuickFixes
22

33
open JetBrains.ReSharper.Plugins.FSharp.Psi
44
open JetBrains.ReSharper.Plugins.FSharp.Psi.Features.Daemon.Highlightings
5-
open JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree
5+
open JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing
66
open JetBrains.ReSharper.Plugins.FSharp.Psi.Tree
7-
open JetBrains.ReSharper.Psi.ExtensionsAPI
7+
open JetBrains.ReSharper.Psi
8+
open JetBrains.ReSharper.Psi.ExtensionsAPI.Tree
9+
open JetBrains.ReSharper.Psi.Tree
810
open JetBrains.ReSharper.Resources.Shell
911

1012
type AddSetterFix(error: PropertyCannotBeSetError) =
1113
inherit FSharpQuickFixBase()
1214

1315
let refExpr = error.RefExpr
14-
let mutable declaration: IAccessorsNamesClauseOwner = null
16+
let mutable declaration: IOverridableMemberDeclaration = null
17+
18+
let setterNodes setter: ITreeNode list =
19+
[ FSharpTokenType.COMMA.CreateLeafElement(); setter ]
20+
21+
let getSetNodes getter setter: ITreeNode list =
22+
[ FSharpTokenType.WITH.CreateLeafElement(); getter ] @ setterNodes setter
1523

1624
override this.IsAvailable _ =
1725
isValid refExpr &&
@@ -26,20 +34,29 @@ type AddSetterFix(error: PropertyCannotBeSetError) =
2634

2735
declaration <-
2836
match decl with
29-
| :? IAbstractMemberDeclaration as decl -> decl :> IAccessorsNamesClauseOwner
37+
| :? IAbstractMemberDeclaration as decl -> decl :> IOverridableMemberDeclaration
3038
| :? IAutoPropertyDeclaration as decl when not decl.IsVirtual -> decl
3139
| _ -> null
3240

33-
isNotNull declaration
41+
isNotNull declaration &&
42+
43+
let accessors = declaration.AccessorDeclarations
44+
accessors.All _.IsImplicit
3445

3546
override this.Text = $"Add setter to '{refExpr.ShortName}'"
3647

3748
override this.ExecutePsiTransaction _ =
3849
use writeCookie = WriteLockCookie.Create(refExpr.IsPhysical())
3950

4051
let factory = refExpr.CreateElementFactory()
41-
let accessors = factory.CreateAccessorsNamesClause(true, true)
52+
let createGetter = isNull (declaration.GetAccessor(AccessorKind.GETTER))
53+
let autoProperty = factory.CreateAutoPropertyDeclaration(createGetter, true)
54+
let accessors = autoProperty.AccessorDeclarationsEnumerable |> Seq.toList
55+
56+
let nodesToAdd =
57+
match accessors with
58+
| [getter; setter] -> getSetNodes getter setter
59+
| [setter] -> setterNodes setter
60+
| _ -> []
4261

43-
declaration.SetAccessorsClause(accessors) |> ignore
44-
if not (declaration.AccessorsClause.PrevSibling :? Whitespace) then
45-
addNodeBefore declaration.AccessorsClause (Whitespace(1))
62+
addNodesAfter declaration.LastChild nodesToAdd |> ignore

ReSharper.FSharp/src/FSharp/FSharp.Psi/src/FSharp.psi

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1446,7 +1446,7 @@ abstractMemberDeclaration options { stubBase="FSharpProperTypeMemberDeclarationB
14461446
identOrOpName{IDENTIFIER, Identifier}
14471447
postfixTypeParameterDeclarationList<TYPE_PARAMETER_LIST, TypeParameterList>?
14481448
returnTypeInfo<RETURN_INFO, ReturnTypeInfo>
1449-
accessorsNamesClause<ACESSORS_CLAUSE, AccessorsClause>?;
1449+
accessorDecls?;
14501450

14511451
valFieldDeclaration options { stubBase="FSharpProperTypeMemberDeclarationBase"; } extras {
14521452
get { methodName="Attributes" path=<valFieldDeclaration:ATTRIBUTE_LIST/attributeList:ATTRIBUTE> };
@@ -1475,17 +1475,7 @@ autoPropertyDeclaration options { stubBase="FSharpProperTypeMemberDeclarationBas
14751475
)?
14761476
EQUALS<FSHARP_EQUALS, EqualsToken>
14771477
chameleonExpression<CHAMELEON_EXPR, InitExpression>
1478-
accessorsNamesClause<ACESSORS_CLAUSE, AccessorsClause>?;
1479-
1480-
accessorsNamesClause:
1481-
WITH
1482-
(
1483-
fSharpIdentifier<ACESSOR, AccessorsNames>
1484-
|
1485-
fSharpIdentifier<ACESSOR, AccessorsNames>
1486-
COMMA<FSHARP_COMMA, Comma>
1487-
fSharpIdentifier<ACESSOR, AccessorsNames>
1488-
);
1478+
accessorDecls?;
14891479

14901480
accessorDeclaration options { stubBase="FSharpProperTypeMemberDeclarationBase"; } extras {
14911481
get { methodName="Expression" path=<accessorDeclaration:CHAMELEON_EXPR/chameleonExpression:EXPR> };

ReSharper.FSharp/src/FSharp/FSharp.Psi/src/IFSharpElementFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public interface IFSharpElementFactory
6565

6666
ITypeParameterDeclarationList CreateTypeParameterOfTypeList(FSharpList<string> names);
6767

68-
IAccessorsNamesClause CreateAccessorsNamesClause(bool withGetter, bool withSetter);
68+
IAutoPropertyDeclaration CreateAutoPropertyDeclaration(bool withGetter, bool withSetter);
6969

7070
IFSharpFile CreateEmptyFile();
7171
INamedModuleDeclaration CreateModule(string name);

ReSharper.FSharp/src/FSharp/FSharp.Psi/src/Impl/DeclaredElement/FSharpMemberBase.cs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -56,23 +56,16 @@ public override AccessRights GetAccessRights()
5656
if (IsExplicitImplementation)
5757
return AccessRights.PRIVATE;
5858

59+
var declaration = GetDeclaration();
60+
5961
// Workaround to hide extension methods from resolve in C#.
6062
// todo: calc compiled names for extension members (it'll hide needed ones properly)
6163
// todo: implement F# declared element presenter to hide compiled names in features/ui
62-
if (IsFSharpExtensionMember && GetDeclaration() is IMemberSignatureOrDeclaration memberDeclaration)
64+
if (IsFSharpExtensionMember && declaration is IMemberSignatureOrDeclaration memberDeclaration)
6365
if (!(this is IMethod && memberDeclaration.Attributes.GetCompiledName(out _)))
6466
return AccessRights.INTERNAL;
6567

66-
var mfv = Mfv;
67-
if (mfv == null)
68-
return AccessRights.NONE;
69-
70-
var accessibility = mfv.Accessibility;
71-
if (accessibility.IsInternal)
72-
return AccessRights.INTERNAL;
73-
if (accessibility.IsPrivate)
74-
return AccessRights.PRIVATE;
75-
return AccessRights.PUBLIC;
68+
return declaration?.GetAccessRights() ?? AccessRights.NONE;
7669
}
7770

7871
public override bool IsStatic => !Mfv?.IsInstanceMember ?? false;

ReSharper.FSharp/src/FSharp/FSharp.Psi/src/Impl/DeclaredElement/FSharpProperty.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ internal class FSharpProperty<TDeclaration>(
1111
[NotNull] ITypeMemberDeclaration declaration,
1212
[NotNull] FSharpMemberOrFunctionOrValue mfv)
1313
: FSharpPropertyMemberBase<TDeclaration>(declaration, mfv), IFSharpProperty
14-
where TDeclaration : IFSharpDeclaration, IModifiersOwnerDeclaration, ITypeMemberDeclaration
14+
where TDeclaration : IOverridableMemberDeclaration
1515
{
1616
public override bool IsStatic => GetContainingType() is IFSharpModule || base.IsStatic;
1717

ReSharper.FSharp/src/FSharp/FSharp.Psi/src/Impl/DeclaredElement/FSharpPropertyBase.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,13 @@
66
using JetBrains.ReSharper.Plugins.FSharp.Psi.Tree;
77
using JetBrains.ReSharper.Plugins.FSharp.Psi.Util;
88
using JetBrains.ReSharper.Psi;
9-
using JetBrains.ReSharper.Psi.Impl.Special;
109
using JetBrains.ReSharper.Psi.Resolve;
1110
using JetBrains.ReSharper.Psi.Tree;
1211

1312
namespace JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.DeclaredElement
1413
{
1514
internal abstract class FSharpPropertyMemberBase<TDeclaration> : FSharpPropertyBase<TDeclaration>
16-
where TDeclaration : IFSharpDeclaration, IModifiersOwnerDeclaration, ITypeMemberDeclaration
15+
where TDeclaration : IOverridableMemberDeclaration
1716
{
1817
protected FSharpPropertyMemberBase([NotNull] ITypeMemberDeclaration declaration,
1918
[NotNull] FSharpMemberOrFunctionOrValue mfv) : base(declaration)
@@ -82,7 +81,7 @@ bool IsReadable(FSharpMemberOrFunctionOrValue mfv) =>
8281

8382
internal abstract class FSharpPropertyBase<TDeclaration>([NotNull] ITypeMemberDeclaration declaration)
8483
: FSharpMemberBase<TDeclaration>(declaration), IFSharpParameterOwnerMember, IProperty
85-
where TDeclaration : IFSharpDeclaration, IModifiersOwnerDeclaration, ITypeMemberDeclaration
84+
where TDeclaration : IOverridableMemberDeclaration
8685
{
8786
protected override FSharpSymbol GetActualSymbol(FSharpSymbol symbol)
8887
{
@@ -124,8 +123,8 @@ public override DeclaredElementType GetElementType() =>
124123

125124
public string GetDefaultPropertyMetadataName() => ShortName;
126125

127-
public IAccessor Getter => IsReadable ? new ImplicitAccessor(this, AccessorKind.GETTER) : null;
128-
public IAccessor Setter => IsWritable ? new ImplicitAccessor(this, AccessorKind.SETTER) : null;
126+
public IAccessor Getter => IsReadable ? new FSharpPropertyImplicitAccessor(this, AccessorKind.GETTER) : null;
127+
public IAccessor Setter => IsWritable ? new FSharpPropertyImplicitAccessor(this, AccessorKind.SETTER) : null;
129128

130129
public abstract bool IsReadable { get; }
131130
public abstract bool IsWritable { get; }

0 commit comments

Comments
 (0)