Skip to content

Commit 224a505

Browse files
committed
Handle nested UDTs
1 parent d1badcc commit 224a505

17 files changed

+474
-75
lines changed

Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementsBuilder.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class EncapsulateFieldElementsBuilder
1616
private readonly IDeclarationFinderProvider _declarationFinderProvider;
1717
private QualifiedModuleName _targetQMN;
1818

19-
public EncapsulateFieldElementsBuilder(IDeclarationFinderProvider declarationFinderProvider, QualifiedModuleName targetQMN)//, IEncapsulateFieldValidator validator )
19+
public EncapsulateFieldElementsBuilder(IDeclarationFinderProvider declarationFinderProvider, QualifiedModuleName targetQMN)
2020
{
2121
_declarationFinderProvider = declarationFinderProvider;
2222
_targetQMN = targetQMN;
@@ -77,7 +77,7 @@ private void CreateRefactoringElements()
7777
}
7878
}
7979

80-
private IEnumerable<IObjectStateUDT> BuildObjectStateUDTCandidates(IEnumerable<IEncapsulateFieldCandidate> candidates) //, IObjectStateUDT defaultObjectStateUDT)
80+
private IEnumerable<IObjectStateUDT> BuildObjectStateUDTCandidates(IEnumerable<IEncapsulateFieldCandidate> candidates)
8181
{
8282
var udtCandidates = candidates.Where(c => c is IUserDefinedTypeCandidate udt
8383
&& udt.CanBeObjectStateUDT);
@@ -105,9 +105,9 @@ private IObjectStateUDT CreateStateUDTField()
105105
return stateUDT;
106106
}
107107

108-
private IEncapsulateFieldCandidate CreateCandidate(Declaration target, IValidateVBAIdentifiers validator)// Predicate<string> nameValidator)
108+
private IEncapsulateFieldCandidate CreateCandidate(Declaration target, IValidateVBAIdentifiers validator)
109109
{
110-
if (target.IsUserDefinedTypeField())
110+
if (target.IsUserDefinedType())
111111
{
112112
var udtValidator = EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedType);
113113
var udtField = new UserDefinedTypeCandidate(target, udtValidator) as IUserDefinedTypeCandidate;

Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ private void ChangeSettingsToConvertFieldsToUDTMembersStrategy()
9292
{
9393
foreach (var candidate in EncapsulationCandidates)
9494
{
95-
candidate.ConflictFinder = _validationsProvider.ConflictDetector(EncapsulateFieldStrategy , _declarationFinderProvider);// ConflictDetector;
95+
candidate.ConflictFinder = _validationsProvider.ConflictDetector(EncapsulateFieldStrategy , _declarationFinderProvider);
9696
candidate.NameValidator = candidate.Declaration.IsArray
9797
? EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMemberArray)
9898
: EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMember);

Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ protected override void LoadFieldReferenceContextReplacements(IEncapsulateFieldC
8282
{
8383
foreach (var member in udt.Members)
8484
{
85-
foreach (var idRef in member.ParentContextReferences)
85+
foreach (var idRef in member.FieldContextReferences)
8686
{
8787
var replacementText = member.ReferenceAccessor(idRef);
8888
if (IsExternalReferenceRequiringModuleQualification(idRef))

Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ protected virtual void LoadFieldReferenceContextReplacements(IEncapsulateFieldCa
129129
{
130130
foreach (var member in udt.Members)
131131
{
132-
foreach (var idRef in member.ParentContextReferences)
132+
foreach (var idRef in member.FieldContextReferences)
133133
{
134134
var replacementText = member.ReferenceAccessor(idRef);
135135
SetUDTMemberReferenceRewriteContent(idRef, replacementText);

Rubberduck.Refactorings/EncapsulateField/Extensions/DeclarationExtensions.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ public static bool IsConstant(this Declaration declaration)
3030
=> declaration.DeclarationType.HasFlag(DeclarationType.Constant);
3131

3232
public static bool IsUserDefinedTypeField(this Declaration declaration)
33-
=> declaration.IsMemberVariable() && (declaration.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.UserDefinedType) ?? false);
33+
=> declaration.IsMemberVariable() && IsUserDefinedType(declaration);
34+
35+
public static bool IsUserDefinedType(this Declaration declaration)
36+
=> (declaration.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.UserDefinedType) ?? false);
3437

3538
public static bool IsEnumField(this Declaration declaration)
3639
=> declaration.IsMemberVariable() && (declaration.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.Enumeration) ?? false);
@@ -40,12 +43,5 @@ public static bool IsDeclaredInList(this Declaration declaration)
4043
return declaration.Context.TryGetAncestor<VBAParser.VariableListStmtContext>(out var varList)
4144
&& varList.ChildCount > 1;
4245
}
43-
44-
public static IEnumerable<IdentifierReference> AllReferences(this IEnumerable<Declaration> declarations)
45-
{
46-
return from dec in declarations
47-
from reference in dec.References
48-
select reference;
49-
}
5046
}
5147
}

Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Text;
55
using System.Threading.Tasks;
66
using Antlr4.Runtime;
7+
using Rubberduck.Common;
78
using Rubberduck.Parsing.Grammar;
89
using Rubberduck.Parsing.Symbols;
910
using Rubberduck.VBEditor;
@@ -14,18 +15,21 @@ namespace Rubberduck.Refactorings.EncapsulateField
1415
public interface IConvertToUDTMember : IEncapsulateFieldCandidate
1516
{
1617
string UDTMemberDeclaration { get; }
17-
IObjectStateUDT ObjectStateUDT { set; get; }
1818
IEncapsulateFieldCandidate WrappedCandidate { get; }
1919
}
2020

2121
public class ConvertToUDTMember : IConvertToUDTMember
2222
{
23+
private int _hashCode;
24+
private readonly string _uniqueID;
2325
private readonly IEncapsulateFieldCandidate _wrapped;
2426
public ConvertToUDTMember(IEncapsulateFieldCandidate candidate, IObjectStateUDT objStateUDT)
2527
{
2628
_wrapped = candidate;
2729
PropertyIdentifier = _wrapped.PropertyIdentifier;
2830
ObjectStateUDT = objStateUDT;
31+
_uniqueID = BuildUniqueID(candidate, objStateUDT);
32+
_hashCode = _uniqueID.GetHashCode();
2933
}
3034

3135
public virtual string UDTMemberDeclaration
@@ -42,7 +46,7 @@ public virtual string UDTMemberDeclaration
4246

4347
public IEncapsulateFieldCandidate WrappedCandidate => _wrapped;
4448

45-
public IObjectStateUDT ObjectStateUDT { set; get; }
49+
public IObjectStateUDT ObjectStateUDT { private set; get; }
4650

4751
public string TargetID => _wrapped.TargetID;
4852

@@ -91,7 +95,7 @@ public string ParameterName
9195
get => _wrapped.ParameterName;
9296
}
9397

94-
public IValidateVBAIdentifiers NameValidator
98+
public IValidateVBAIdentifiers NameValidator
9599
{
96100
set => _wrapped.NameValidator = value;
97101
get => _wrapped.NameValidator;
@@ -109,7 +113,7 @@ private string AccessorInProperty
109113
{
110114
if (_wrapped is IUserDefinedTypeMemberCandidate udtm)
111115
{
112-
return $"{ObjectStateUDT.FieldIdentifier}.{udtm.Parent.PropertyIdentifier}.{BackingIdentifier}";
116+
return $"{ObjectStateUDT.FieldIdentifier}.{udtm.UDTField.PropertyIdentifier}.{BackingIdentifier}";
113117
}
114118
return $"{ObjectStateUDT.FieldIdentifier}.{BackingIdentifier}";
115119
}
@@ -119,9 +123,9 @@ public string ReferenceAccessor(IdentifierReference idRef)
119123
{
120124
if (idRef.QualifiedModuleName != QualifiedModuleName)
121125
{
122-
return $"{QualifiedModuleName.ComponentName}.{PropertyIdentifier}";
126+
return PropertyIdentifier;
123127
}
124-
return $"{BackingIdentifier}";
128+
return BackingIdentifier;
125129
}
126130

127131
public string IdentifierName => _wrapped.IdentifierName;
@@ -139,31 +143,46 @@ public IEnumerable<PropertyAttributeSet> PropertyAttributeSets
139143
{
140144
get
141145
{
142-
if (_wrapped is IUserDefinedTypeCandidate udt && udt.TypeDeclarationIsPrivate)
146+
var modifiedSets = new List<PropertyAttributeSet>();
147+
var sets = _wrapped.PropertyAttributeSets;
148+
for (var idx = 0; idx < sets.Count(); idx++)
143149
{
144-
var sets = new List<PropertyAttributeSet>();
145-
foreach (var member in udt.Members)
146-
{
147-
sets.Add(CreateMemberPropertyAttributeSet(member));
148-
}
149-
return sets;
150+
var attributeSet = sets.ElementAt(idx);
151+
var fields = attributeSet.BackingField.Split(new char[] { '.' });
152+
153+
attributeSet.BackingField = fields.Count() > 1
154+
? $"{ObjectStateUDT.FieldIdentifier}.{attributeSet.BackingField.CapitalizeFirstLetter()}"
155+
: $"{ObjectStateUDT.FieldIdentifier}.{attributeSet.PropertyName.CapitalizeFirstLetter()}";
156+
157+
modifiedSets.Add(attributeSet);
150158
}
151-
return new List<PropertyAttributeSet>() { AsPropertyAttributeSet };
159+
return modifiedSets;
152160
}
153161
}
154162

163+
public override bool Equals(object obj)
164+
{
165+
return obj != null
166+
&& obj is ConvertToUDTMember convertWrapper
167+
&& BuildUniqueID(convertWrapper, convertWrapper.ObjectStateUDT) == _uniqueID;
168+
}
169+
170+
public override int GetHashCode() => _hashCode;
171+
172+
private static string BuildUniqueID(IEncapsulateFieldCandidate candidate, IObjectStateUDT field) => $"{candidate.QualifiedModuleName.Name}.{field.IdentifierName}.{candidate.IdentifierName}";
173+
155174
private PropertyAttributeSet CreateMemberPropertyAttributeSet (IUserDefinedTypeMemberCandidate udtMember)
156175
{
157176
return new PropertyAttributeSet()
158177
{
159178
PropertyName = udtMember.PropertyIdentifier,
160-
BackingField = $"{ObjectStateUDT.FieldIdentifier}.{udtMember.Parent.PropertyIdentifier}.{udtMember.BackingIdentifier}",
179+
BackingField = $"{ObjectStateUDT.FieldIdentifier}.{udtMember.UDTField.PropertyIdentifier}.{udtMember.BackingIdentifier}",
161180
AsTypeName = udtMember.PropertyAsTypeName,
162181
ParameterName = udtMember.ParameterName,
163182
GenerateLetter = udtMember.ImplementLet,
164183
GenerateSetter = udtMember.ImplementSet,
165184
UsesSetAssignment = udtMember.Declaration.IsObject,
166-
IsUDTProperty = false //TODO: If udtMember is a UDT, this needs to be true
185+
IsUDTProperty = (udtMember.Declaration.AsTypeDeclaration?.DeclarationType ?? DeclarationType.Variable) == DeclarationType.UserDefinedType
167186
};
168187
}
169188

Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate
4141
{
4242
protected Declaration _target;
4343
protected QualifiedModuleName _qmn;
44+
protected readonly string _uniqueID;
4445
protected int _hashCode;
4546
private string _identifierName;
4647
protected EncapsulationIdentifiers _fieldAndProperty;
@@ -57,7 +58,8 @@ public EncapsulateFieldCandidate(Declaration declaration, IValidateVBAIdentifier
5758

5859
CanBeReadWrite = true;
5960

60-
_hashCode = ($"{_qmn.Name}.{declaration.IdentifierName}").GetHashCode();
61+
_uniqueID = $"{_qmn.Name}.{declaration.IdentifierName}";
62+
_hashCode = _uniqueID.GetHashCode();
6163

6264
ImplementLet = true;
6365
ImplementSet = false;
@@ -129,11 +131,14 @@ public override bool Equals(object obj)
129131
{
130132
return obj != null
131133
&& obj is IEncapsulateFieldCandidate efc
132-
&& $"{efc.QualifiedModuleName.Name}.{efc.TargetID}" == $"{_qmn.Name}.{IdentifierName}";
134+
&& $"{efc.QualifiedModuleName.Name}.{efc.IdentifierName}" == _uniqueID;
133135
}
134136

135137
public override int GetHashCode() => _hashCode;
136138

139+
public override string ToString()
140+
=>$"({TargetID}){Declaration.ToString()}";
141+
137142
protected virtual string AccessorInProperty
138143
=> $"{BackingIdentifier}";
139144

Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public class EncapsulationIdentifiers
1515
private string _targetIdentifier;
1616
private string _setLetParameter;
1717

18-
public EncapsulationIdentifiers(string field, IValidateVBAIdentifiers identifierValidator) // Predicate<string> IsValidPropertyName)
18+
public EncapsulationIdentifiers(string field, IValidateVBAIdentifiers identifierValidator)
1919
{
2020
_targetIdentifier = field;
2121

Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public interface IUserDefinedTypeCandidate : IEncapsulateFieldCandidate
1616
void AddMember(IUserDefinedTypeMemberCandidate member);
1717
bool TypeDeclarationIsPrivate { set; get; }
1818
bool CanBeObjectStateUDT { set; get; }
19+
bool IsSelectedObjectStateUDT { set; get; }
1920
}
2021

2122
public class UserDefinedTypeCandidate : EncapsulateFieldCandidate, IUserDefinedTypeCandidate
@@ -33,7 +34,14 @@ public void AddMember(IUserDefinedTypeMemberCandidate member)
3334
private List<IUserDefinedTypeMemberCandidate> _udtMembers = new List<IUserDefinedTypeMemberCandidate>();
3435
public IEnumerable<IUserDefinedTypeMemberCandidate> Members => _udtMembers;
3536

36-
public bool TypeDeclarationIsPrivate { set; get; }
37+
private bool _isPrivate;
38+
public bool TypeDeclarationIsPrivate
39+
{
40+
set => _isPrivate = value;
41+
get => Declaration.AsTypeDeclaration?.HasPrivateAccessibility() ?? false;
42+
}
43+
44+
public bool IsSelectedObjectStateUDT { set; get; }
3745

3846
private bool _canBeObjectStateUDT;
3947
public bool CanBeObjectStateUDT
@@ -119,6 +127,20 @@ protected override string AccessorLocalReference(IdentifierReference idRef)
119127
return TypeDeclarationIsPrivate ? $"{BackingIdentifier}" : $"{PropertyIdentifier}";
120128
}
121129

130+
public override bool Equals(object obj)
131+
{
132+
if (obj is IUserDefinedTypeCandidate udt)
133+
{
134+
return udt.TargetID.Equals(TargetID);
135+
}
136+
return false;
137+
}
138+
139+
public override int GetHashCode()
140+
{
141+
return base.GetHashCode();
142+
}
143+
122144
public override IEnumerable<PropertyAttributeSet> PropertyAttributeSets
123145
{
124146
get
@@ -128,28 +150,23 @@ public override IEnumerable<PropertyAttributeSet> PropertyAttributeSets
128150
var specs = new List<PropertyAttributeSet>();
129151
foreach (var member in Members)
130152
{
131-
specs.Add(member.AsPropertyGeneratorSpec);
153+
var sets = member.PropertyAttributeSets;
154+
var modifiedSets = new List<PropertyAttributeSet>();
155+
PropertyAttributeSet newSet;
156+
foreach (var set in sets)
157+
{
158+
newSet = set;
159+
newSet.BackingField = $"{BackingIdentifier}.{set.BackingField}";
160+
modifiedSets.Add(newSet);
161+
}
162+
specs.AddRange(modifiedSets);
132163
}
133164
return specs;
134165
}
135166
return new List<PropertyAttributeSet>() { AsPropertyAttributeSet };
136167
}
137168
}
138169

139-
public override bool Equals(object obj)
140-
{
141-
if (obj is IUserDefinedTypeCandidate udt)
142-
{
143-
return udt.TargetID.Equals(TargetID);
144-
}
145-
return false;
146-
}
147-
148-
public override int GetHashCode()
149-
{
150-
return base.GetHashCode();
151-
}
152-
153170
protected override PropertyAttributeSet AsPropertyAttributeSet
154171
{
155172
get

0 commit comments

Comments
 (0)