Skip to content

Commit f845cb7

Browse files
committed
Refactor to support standalone operation of RefactoringActions
Modified interfaces, objects and tests to support combined and independent execution of EncapsulateFieldUseBackingFieldRefactoringAction and EncapsulateFieldUseBackingUDTMemberRefactoringAction
1 parent a0e2e31 commit f845cb7

18 files changed

+482
-113
lines changed

Rubberduck.Refactorings/EncapsulateField/ConflictDetection/EncapsulateFieldConflictFinderBase.cs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,30 @@ public abstract class EncapsulateFieldConflictFinderBase
2424
protected List<IEncapsulateFieldCandidate> _fieldCandidates { set; get; } = new List<IEncapsulateFieldCandidate>();
2525
protected List<IUserDefinedTypeMemberCandidate> _udtMemberCandidates { set; get; } = new List<IUserDefinedTypeMemberCandidate>();
2626

27-
public EncapsulateFieldConflictFinderBase(IDeclarationFinderProvider declarationFinderProvider, IEnumerable<IEncapsulateFieldCandidate> candidates, IEnumerable<IUserDefinedTypeMemberCandidate> udtMemberCandidates)
27+
public EncapsulateFieldConflictFinderBase(IDeclarationFinderProvider declarationFinderProvider, IEnumerable<IEncapsulateFieldCandidate> candidates)
2828
{
2929
_declarationFinderProvider = declarationFinderProvider;
3030
_fieldCandidates.AddRange(candidates);
31-
_udtMemberCandidates.AddRange(udtMemberCandidates);
31+
_fieldCandidates.ForEach(c => LoadUDTMembers(_udtMemberCandidates, c));
32+
}
33+
34+
private void LoadUDTMembers(List<IUserDefinedTypeMemberCandidate> udtMembers, IEncapsulateFieldCandidate candidate)
35+
{
36+
if (!(candidate is IUserDefinedTypeCandidate udtCandidate))
37+
{
38+
return;
39+
}
40+
41+
foreach (var member in udtCandidate.Members)
42+
{
43+
udtMembers.Add(member);
44+
45+
if (member.WrappedCandidate is IUserDefinedTypeCandidate childUDT
46+
&& childUDT.Declaration.AsTypeDeclaration.HasPrivateAccessibility())
47+
{
48+
LoadUDTMembers(udtMembers, childUDT);
49+
}
50+
}
3251
}
3352

3453
public virtual bool TryValidateEncapsulationAttributes(IEncapsulateFieldCandidate field, out string errorMessage)
@@ -39,7 +58,7 @@ public virtual bool TryValidateEncapsulationAttributes(IEncapsulateFieldCandidat
3958
return true;
4059
}
4160

42-
var declarationType = field is IConvertToUDTMember udtMember
61+
var declarationType = field is IEncapsulateFieldAsUDTMemberCandidate udtMember
4362
? DeclarationType.UserDefinedTypeMember
4463
: field.Declaration.DeclarationType;
4564

Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,16 @@ namespace Rubberduck.Refactorings.EncapsulateField
88
{
99
public class EncapsulateFieldModel : IRefactoringModel
1010
{
11+
private readonly IObjectStateUDT _defaultObjectStateUDT;
12+
1113
public EncapsulateFieldModel(EncapsulateFieldUseBackingFieldModel backingFieldModel,
12-
EncapsulateFieldUseBackingUDTMemberModel udtModel)
14+
EncapsulateFieldUseBackingUDTMemberModel udtModel)
1315
{
1416
EncapsulateFieldUseBackingFieldModel = backingFieldModel;
1517
EncapsulateFieldUseBackingUDTMemberModel = udtModel;
1618
ResetConflictDetection(EncapsulateFieldStrategy.UseBackingFields);
19+
ObjectStateUDTCandidates = udtModel.ObjectStateUDTCandidates;
20+
_defaultObjectStateUDT = ObjectStateUDTCandidates.SingleOrDefault(os => !os.IsExistingDeclaration);
1721
}
1822

1923
public EncapsulateFieldUseBackingUDTMemberModel EncapsulateFieldUseBackingUDTMemberModel { get; }
@@ -22,7 +26,22 @@ public EncapsulateFieldModel(EncapsulateFieldUseBackingFieldModel backingFieldMo
2226

2327
public IRefactoringPreviewProvider<EncapsulateFieldModel> PreviewProvider { set; get; }
2428

25-
public IEnumerable<IObjectStateUDT> ObjectStateUDTCandidates => EncapsulateFieldUseBackingUDTMemberModel.ObjectStateUDTCandidates;
29+
public IReadOnlyCollection<IObjectStateUDT> ObjectStateUDTCandidates { private set; get; }
30+
31+
public IObjectStateUDT ObjectStateUDTField
32+
{
33+
set
34+
{
35+
EncapsulateFieldUseBackingUDTMemberModel.ObjectStateUDTField = value;
36+
foreach (var candidate in EncapsulateFieldUseBackingUDTMemberModel.SelectedFieldCandidates)
37+
{
38+
EncapsulateFieldUseBackingUDTMemberModel.ConflictFinder.AssignNoConflictIdentifiers(candidate);
39+
}
40+
}
41+
get => EncapsulateFieldStrategy == EncapsulateFieldStrategy.ConvertFieldsToUDTMembers
42+
? EncapsulateFieldUseBackingUDTMemberModel.ObjectStateUDTField
43+
: null;
44+
}
2645

2746
private EncapsulateFieldStrategy _strategy;
2847
public EncapsulateFieldStrategy EncapsulateFieldStrategy
@@ -81,11 +100,5 @@ public IEnumerable<IEncapsulateFieldCandidate> SelectedFieldCandidates
81100

82101
public IEncapsulateFieldCandidate this[string encapsulatedFieldTargetID]
83102
=> EncapsulationCandidates.Where(c => c.TargetID.Equals(encapsulatedFieldTargetID)).Single();
84-
85-
public IObjectStateUDT ObjectStateUDTField
86-
{
87-
get => EncapsulateFieldUseBackingUDTMemberModel.ObjectStateUDTField;
88-
set => EncapsulateFieldUseBackingUDTMemberModel.ObjectStateUDTField = value;
89-
}
90103
}
91104
}

Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldPreviewProvider.cs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,19 @@ namespace Rubberduck.Refactorings.EncapsulateField
77
public class EncapsulateFieldPreviewProvider : IRefactoringPreviewProvider<EncapsulateFieldModel>
88
{
99
private readonly EncapsulateFieldUseBackingFieldPreviewProvider _useBackingFieldPreviewer;
10-
private readonly EncapsulateFieldUseBackingUDTMemberPreviewProvider _useUDTMembmerPreviewer;
11-
private readonly IDeclarationFinderProvider _declarationFinderProvider;
12-
public EncapsulateFieldPreviewProvider(IDeclarationFinderProvider declarationFinderProvider,
10+
private readonly EncapsulateFieldUseBackingUDTMemberPreviewProvider _useBackingUDTMemberPreviewer;
11+
public EncapsulateFieldPreviewProvider(
1312
EncapsulateFieldUseBackingFieldPreviewProvider useBackingFieldPreviewProvider,
14-
EncapsulateFieldUseBackingUDTMemberPreviewProvider useUDTMemberPreviewProvide)
13+
EncapsulateFieldUseBackingUDTMemberPreviewProvider useBackingUDTMemberPreviewProvide)
1514
{
16-
_declarationFinderProvider = declarationFinderProvider;
1715
_useBackingFieldPreviewer = useBackingFieldPreviewProvider;
18-
_useUDTMembmerPreviewer = useUDTMemberPreviewProvide;
16+
_useBackingUDTMemberPreviewer = useBackingUDTMemberPreviewProvide;
1917
}
2018

2119
public string Preview(EncapsulateFieldModel model)
2220
{
2321
var preview = model.EncapsulateFieldStrategy == EncapsulateFieldStrategy.ConvertFieldsToUDTMembers
24-
? _useUDTMembmerPreviewer.Preview(model.EncapsulateFieldUseBackingUDTMemberModel)
22+
? _useBackingUDTMemberPreviewer.Preview(model.EncapsulateFieldUseBackingUDTMemberModel)
2523
: _useBackingFieldPreviewer.Preview(model.EncapsulateFieldUseBackingFieldModel);
2624

2725
return preview;

Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ public enum EncapsulateFieldStrategy
1616

1717
public class EncapsulateFieldRefactoring : InteractiveRefactoringBase<EncapsulateFieldModel>
1818
{
19-
private readonly IDeclarationFinderProvider _declarationFinderProvider;
2019
private readonly ISelectedDeclarationProvider _selectedDeclarationProvider;
2120
private readonly IRewritingManager _rewritingManager;
2221
private readonly EncapsulateFieldRefactoringAction _refactoringAction;
@@ -27,7 +26,6 @@ public EncapsulateFieldRefactoring(
2726
EncapsulateFieldRefactoringAction refactoringAction,
2827
EncapsulateFieldPreviewProvider previewProvider,
2928
IEncapsulateFieldModelFactory encapsulateFieldModelFactory,
30-
IDeclarationFinderProvider declarationFinderProvider,
3129
RefactoringUserInteraction<IEncapsulateFieldPresenter, EncapsulateFieldModel> userInteraction,
3230
IRewritingManager rewritingManager,
3331
ISelectionProvider selectionProvider,
@@ -36,7 +34,6 @@ public EncapsulateFieldRefactoring(
3634
{
3735
_refactoringAction = refactoringAction;
3836
_previewProvider = previewProvider;
39-
_declarationFinderProvider = declarationFinderProvider;
4037
_selectedDeclarationProvider = selectedDeclarationProvider;
4138
_rewritingManager = rewritingManager;
4239
_modelFactory = encapsulateFieldModelFactory;

Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoringAction.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,11 @@ public class EncapsulateFieldRefactoringAction : IRefactoringAction<EncapsulateF
99
{
1010
private readonly EncapsulateFieldUseBackingFieldRefactoringAction _useBackingField;
1111
private readonly EncapsulateFieldUseBackingUDTMemberRefactoringAction _useBackingUDTMember;
12-
private readonly IDeclarationFinderProvider _declarationFinderProvider;
1312

14-
public EncapsulateFieldRefactoringAction(IDeclarationFinderProvider declarationFinderProvider,
13+
public EncapsulateFieldRefactoringAction(
1514
EncapsulateFieldUseBackingFieldRefactoringAction encapsulateFieldUseBackingField,
1615
EncapsulateFieldUseBackingUDTMemberRefactoringAction encapsulateFieldUseUDTMember)
1716
{
18-
_declarationFinderProvider = declarationFinderProvider;
1917
_useBackingField = encapsulateFieldUseBackingField;
2018
_useBackingUDTMember = encapsulateFieldUseUDTMember;
2119
}

Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoringActionsProvider.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,21 @@ public interface IEncapsulateFieldRefactoringActionsProvider
2121

2222
public class EncapsulateFieldRefactoringActionsProvider : IEncapsulateFieldRefactoringActionsProvider
2323
{
24-
private readonly IDeclarationFinderProvider _declarationFinderProvider;
25-
private readonly IRewritingManager _rewritingManager;
2624
private readonly ReplaceReferencesRefactoringAction _replaceReferences;
2725
private readonly ReplaceDeclarationIdentifierRefactoringAction _replaceDeclarationIdentifiers;
2826
private readonly CodeBlockInsertRefactoringAction _codeBlockInsertRefactoringAction;
2927
private readonly ReplacePrivateUDTMemberReferencesRefactoringAction _replaceUDTMemberReferencesRefactoringAction;
3028
private readonly DeclareFieldsAsUDTMembersRefactoringAction _declareFieldsAsUDTMembersRefactoringAction;
3129
private readonly EncapsulateFieldInsertNewCodeRefactoringAction _encapsulateFieldInsertNewCodeRefactoringAction;
3230

33-
public EncapsulateFieldRefactoringActionsProvider(IDeclarationFinderProvider declarationFinderProvider,
34-
IRewritingManager rewritingManager,
31+
public EncapsulateFieldRefactoringActionsProvider(
3532
ReplaceReferencesRefactoringAction replaceReferencesRefactoringAction,
3633
ReplacePrivateUDTMemberReferencesRefactoringAction replaceUDTMemberReferencesRefactoringAction,
3734
ReplaceDeclarationIdentifierRefactoringAction replaceDeclarationIdentifierRefactoringAction,
3835
DeclareFieldsAsUDTMembersRefactoringAction declareFieldsAsUDTMembersRefactoringAction,
3936
EncapsulateFieldInsertNewCodeRefactoringAction encapsulateFieldInsertNewCodeRefactoringAction,
4037
CodeBlockInsertRefactoringAction codeBlockInsertRefactoringAction)
4138
{
42-
_declarationFinderProvider = declarationFinderProvider;
43-
_rewritingManager = rewritingManager;
4439
_replaceReferences = replaceReferencesRefactoringAction;
4540
_replaceUDTMemberReferencesRefactoringAction = replaceUDTMemberReferencesRefactoringAction;
4641
_replaceDeclarationIdentifiers = replaceDeclarationIdentifierRefactoringAction;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using Rubberduck.Parsing.Symbols;
2+
3+
namespace Rubberduck.Refactorings.EncapsulateField
4+
{
5+
/// <summary>
6+
/// <c>EncapsulateFieldRequest</c> aggregates attributes necessary for the <c>EncapsulateFieldUseBackingFieldRefactoringAction</c>.
7+
/// </summary>
8+
/// <remarks>
9+
/// <c>EncapsulateFieldRequest</c> provides the data needed to encapsulate a field.
10+
/// There is no validation or conflict checking performed for non-UserDefinedTypes.
11+
/// The caller can specify a readonly Property and select an <c>IdentifierName</c> for
12+
/// the Property. If the target is a UserDefinedType Field and the UserDefinedType is Private,
13+
/// then the propertyIdentifier parameter is ignored and PropertyIdentifiers for each UserDefinedTypeMember
14+
/// are generated by the refactoring action.
15+
/// </remarks>
16+
public class EncapsulateFieldRequest
17+
{
18+
public EncapsulateFieldRequest(VariableDeclaration target, bool isReadOnly = false, string propertyIdentifier = null)
19+
{
20+
Declaration = target;
21+
IsReadOnly = isReadOnly;
22+
PropertyIdentifier = propertyIdentifier;
23+
}
24+
25+
public VariableDeclaration Declaration { get; }
26+
public string PropertyIdentifier { set; get; }
27+
public bool IsReadOnly { set; get; }
28+
29+
public IEncapsulateFieldCandidate ApplyRequest(IEncapsulateFieldCandidate candidate)
30+
{
31+
candidate.EncapsulateFlag = true;
32+
candidate.IsReadOnly = IsReadOnly;
33+
if (PropertyIdentifier != null)
34+
{
35+
candidate.PropertyIdentifier = PropertyIdentifier;
36+
}
37+
return candidate;
38+
}
39+
}
40+
}
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,31 @@
11
using System.Collections.Generic;
22
using System.Linq;
3-
using Rubberduck.Parsing.VBA;
43
using Rubberduck.VBEditor;
54
using Rubberduck.Refactorings.CodeBlockInsert;
65
using Rubberduck.Refactorings.EncapsulateField;
7-
using System;
86

97
namespace Rubberduck.Refactorings.EncapsulateFieldUseBackingUDTMember
108
{
119
public class EncapsulateFieldUseBackingUDTMemberModel : IRefactoringModel
1210
{
13-
private readonly IObjectStateUDT _defaultObjectStateUDT;
14-
private readonly IDeclarationFinderProvider _declarationFinderProvider;
15-
private readonly string _defaultObjectStateUDTTypeName;
16-
private readonly IObjectStateUDT _preExistingObjectStateUDT;
17-
18-
private List<IConvertToUDTMember> _convertedFields;
19-
private List<IObjectStateUDT> _objStateCandidates;
20-
21-
public EncapsulateFieldUseBackingUDTMemberModel(IEnumerable<IConvertToUDTMember> candidates,
22-
IObjectStateUDT defaultObjectStateUserDefinedType,
23-
IEnumerable<IObjectStateUDT> objectStateUserDefinedTypeCandidates,
24-
IDeclarationFinderProvider declarationFinderProvider)
25-
{
26-
_convertedFields = new List<IConvertToUDTMember>(candidates);
27-
_declarationFinderProvider = declarationFinderProvider;
28-
_defaultObjectStateUDT = defaultObjectStateUserDefinedType;
29-
30-
QualifiedModuleName = candidates.First().QualifiedModuleName;
31-
_defaultObjectStateUDTTypeName = $"T{QualifiedModuleName.ComponentName}";
11+
private List<IEncapsulateFieldAsUDTMemberCandidate> _encapsulateAsUDTMemberCandidates;
3212

33-
_objStateCandidates = new List<IObjectStateUDT>();
34-
35-
if (objectStateUserDefinedTypeCandidates.Any())
36-
{
37-
_objStateCandidates.AddRange(objectStateUserDefinedTypeCandidates.Distinct());
13+
public EncapsulateFieldUseBackingUDTMemberModel(IObjectStateUDT targetObjectStateUserDefinedTypeField,
14+
IEnumerable<IEncapsulateFieldAsUDTMemberCandidate> encapsulateAsUDTMemberCandidates,
15+
IEnumerable<IObjectStateUDT> objectStateUserDefinedTypeCandidates)
16+
{
17+
_encapsulateAsUDTMemberCandidates = new List<IEncapsulateFieldAsUDTMemberCandidate>(encapsulateAsUDTMemberCandidates);
3818

39-
_preExistingObjectStateUDT = objectStateUserDefinedTypeCandidates
40-
.FirstOrDefault(os => os.AsTypeDeclaration.IdentifierName.StartsWith(_defaultObjectStateUDTTypeName, StringComparison.InvariantCultureIgnoreCase));
19+
ObjectStateUDTField = targetObjectStateUserDefinedTypeField;
4120

42-
if (_preExistingObjectStateUDT != null)
43-
{
44-
HasPreExistingObjectStateUDT = true;
45-
_defaultObjectStateUDT.IsSelected = false;
46-
_preExistingObjectStateUDT.IsSelected = true;
47-
_convertedFields.ForEach(c => c.ObjectStateUDT = _preExistingObjectStateUDT);
48-
}
49-
}
21+
ObjectStateUDTCandidates = objectStateUserDefinedTypeCandidates.ToList();
5022

51-
_objStateCandidates.Add(_defaultObjectStateUDT);
23+
QualifiedModuleName = encapsulateAsUDTMemberCandidates.First().QualifiedModuleName;
5224

5325
ResetNewContent();
54-
55-
_convertedFields.ForEach(c => c.ObjectStateUDT = ObjectStateUDTField);
5626
}
5727

58-
private void ResetNewContent()
28+
public void ResetNewContent()
5929
{
6030
NewContent = new Dictionary<NewContentType, List<string>>
6131
{
@@ -66,17 +36,17 @@ private void ResetNewContent()
6636
};
6737
}
6838

69-
public bool HasPreExistingObjectStateUDT { get; }
39+
public IReadOnlyCollection<IObjectStateUDT> ObjectStateUDTCandidates { get; }
7040

7141
public IEncapsulateFieldConflictFinder ConflictFinder { set; get; }
7242

7343
public bool IncludeNewContentMarker { set; get; } = false;
7444

7545
public IReadOnlyCollection<IEncapsulateFieldCandidate> EncapsulationCandidates
76-
=> _convertedFields.Cast<IEncapsulateFieldCandidate>().ToList();
46+
=> _encapsulateAsUDTMemberCandidates.Cast<IEncapsulateFieldCandidate>().ToList();
7747

7848
public IEnumerable<IEncapsulateFieldCandidate> SelectedFieldCandidates
79-
=> EncapsulationCandidates.Where(v => v.EncapsulateFlag);
49+
=> EncapsulationCandidates.Where(v => v.EncapsulateFlag && v.Declaration != ObjectStateUDTField?.Declaration);
8050

8151
public void AddContentBlock(NewContentType contentType, string block)
8252
=> NewContent[contentType].Add(block);
@@ -85,29 +55,29 @@ public void AddContentBlock(NewContentType contentType, string block)
8555

8656
public QualifiedModuleName QualifiedModuleName { get; }
8757

88-
public IEnumerable<IObjectStateUDT> ObjectStateUDTCandidates => _objStateCandidates;
89-
58+
private IObjectStateUDT _objectStateUDT;
9059
public IObjectStateUDT ObjectStateUDTField
9160
{
92-
get => _objStateCandidates.SingleOrDefault(os => os.IsSelected)
93-
?? _defaultObjectStateUDT;
94-
9561
set
9662
{
97-
if (value is null)
63+
if (_objectStateUDT == value)
9864
{
99-
_objStateCandidates.ForEach(osc => osc.IsSelected = (osc == _defaultObjectStateUDT));
10065
return;
10166
}
10267

103-
var matchingCandidate = _objStateCandidates
104-
.SingleOrDefault(os => os.FieldIdentifier.Equals(value.FieldIdentifier))
105-
?? _defaultObjectStateUDT;
106-
107-
_objStateCandidates.ForEach(osc => osc.IsSelected = (osc == matchingCandidate));
68+
if (_objectStateUDT != null)
69+
{
70+
_objectStateUDT.IsSelected = false;
71+
}
10872

109-
_convertedFields.ForEach(cf => cf.ObjectStateUDT = matchingCandidate);
73+
_objectStateUDT = value;
74+
if (_objectStateUDT != null)
75+
{
76+
_objectStateUDT.IsSelected = true;
77+
}
78+
_encapsulateAsUDTMemberCandidates.ForEach(cf => cf.ObjectStateUDT = _objectStateUDT);
11079
}
80+
get => _objectStateUDT;
11181
}
11282
}
11383
}

Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldUseBackingUDTMember/EncapsulateFieldUseBackingUDTMemberPreviewProvider.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public override string Preview(EncapsulateFieldUseBackingUDTMemberModel model)
1818
model.IncludeNewContentMarker = true;
1919
try
2020
{
21+
model.ResetNewContent();
2122
preview = base.Preview(model);
2223
}
2324
catch (Exception e) { }

Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@ public ArrayCandidate(Declaration declaration, Func<string,string> parameterName
3535
public override bool TryValidateEncapsulationAttributes(out string errorMessage)
3636
{
3737
errorMessage = string.Empty;
38-
if (!EncapsulateFlag) { return true; }
38+
if (!EncapsulateFlag)
39+
{
40+
return true;
41+
}
3942

4043
if (HasExternalRedimOperation(out errorMessage))
4144
{

0 commit comments

Comments
 (0)