Skip to content

Commit 371ad27

Browse files
committed
Add EncapsulateFieldUseBackingUDTMemberModelFactory
Some changes in folder organization as well
1 parent 96087d7 commit 371ad27

File tree

4 files changed

+269
-6
lines changed

4 files changed

+269
-6
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using Rubberduck.Parsing.VBA;
4+
using Rubberduck.VBEditor;
5+
using Rubberduck.Refactorings.CodeBlockInsert;
6+
using Rubberduck.Refactorings.EncapsulateField;
7+
using System;
8+
9+
namespace Rubberduck.Refactorings.EncapsulateFieldUseBackingUDTMember
10+
{
11+
public class EncapsulateFieldUseBackingUDTMemberModel : IRefactoringModel
12+
{
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}";
32+
33+
_objStateCandidates = new List<IObjectStateUDT>();
34+
35+
if (objectStateUserDefinedTypeCandidates.Any())
36+
{
37+
_objStateCandidates.AddRange(objectStateUserDefinedTypeCandidates.Distinct());
38+
39+
_preExistingObjectStateUDT = objectStateUserDefinedTypeCandidates
40+
.FirstOrDefault(os => os.AsTypeDeclaration.IdentifierName.StartsWith(_defaultObjectStateUDTTypeName, StringComparison.InvariantCultureIgnoreCase));
41+
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+
}
50+
51+
_objStateCandidates.Add(_defaultObjectStateUDT);
52+
53+
ResetNewContent();
54+
55+
_convertedFields.ForEach(c => c.ObjectStateUDT = ObjectStateUDTField);
56+
}
57+
58+
private void ResetNewContent()
59+
{
60+
NewContent = new Dictionary<NewContentType, List<string>>
61+
{
62+
{ NewContentType.PostContentMessage, new List<string>() },
63+
{ NewContentType.DeclarationBlock, new List<string>() },
64+
{ NewContentType.CodeSectionBlock, new List<string>() },
65+
{ NewContentType.TypeDeclarationBlock, new List<string>() }
66+
};
67+
}
68+
69+
public bool HasPreExistingObjectStateUDT { get; }
70+
71+
public IEncapsulateFieldConflictFinder ConflictFinder { set; get; }
72+
73+
public bool IncludeNewContentMarker { set; get; } = false;
74+
75+
public IReadOnlyCollection<IEncapsulateFieldCandidate> EncapsulationCandidates
76+
=> _convertedFields.Cast<IEncapsulateFieldCandidate>().ToList();
77+
78+
public IEnumerable<IEncapsulateFieldCandidate> SelectedFieldCandidates
79+
=> EncapsulationCandidates.Where(v => v.EncapsulateFlag);
80+
81+
public void AddContentBlock(NewContentType contentType, string block)
82+
=> NewContent[contentType].Add(block);
83+
84+
public Dictionary<NewContentType, List<string>> NewContent { set; get; }
85+
86+
public QualifiedModuleName QualifiedModuleName { get; }
87+
88+
public IEnumerable<IObjectStateUDT> ObjectStateUDTCandidates => _objStateCandidates;
89+
90+
public IObjectStateUDT ObjectStateUDTField
91+
{
92+
get => _objStateCandidates.SingleOrDefault(os => os.IsSelected)
93+
?? _defaultObjectStateUDT;
94+
95+
set
96+
{
97+
if (value is null)
98+
{
99+
_objStateCandidates.ForEach(osc => osc.IsSelected = (osc == _defaultObjectStateUDT));
100+
return;
101+
}
102+
103+
var matchingCandidate = _objStateCandidates
104+
.SingleOrDefault(os => os.FieldIdentifier.Equals(value.FieldIdentifier))
105+
?? _defaultObjectStateUDT;
106+
107+
_objStateCandidates.ForEach(osc => osc.IsSelected = (osc == matchingCandidate));
108+
109+
_convertedFields.ForEach(cf => cf.ObjectStateUDT = matchingCandidate);
110+
}
111+
}
112+
}
113+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
using Rubberduck.Parsing.Symbols;
2+
using Rubberduck.Parsing.VBA;
3+
using Rubberduck.Refactorings.Common;
4+
using Rubberduck.Refactorings.EncapsulateField;
5+
using Rubberduck.Refactorings.EncapsulateFieldUseBackingUDTMember;
6+
using Rubberduck.VBEditor;
7+
using System.Collections.Generic;
8+
using System.Linq;
9+
10+
namespace Rubberduck.Refactorings
11+
{
12+
public interface IEncapsulateFieldUseBackingUDTMemberModelFactory : IEncapsulateFieldModelsFactory<EncapsulateFieldUseBackingUDTMemberModel>
13+
{ }
14+
15+
public class EncapsulateFieldUseBackingUDTMemberModelFactory : IEncapsulateFieldUseBackingUDTMemberModelFactory
16+
{
17+
private readonly IDeclarationFinderProvider _declarationFinderProvider;
18+
private readonly IEncapsulateFieldCandidateFactory _fieldCandidateFactory;
19+
20+
public EncapsulateFieldUseBackingUDTMemberModelFactory(IDeclarationFinderProvider declarationFinderProvider, IEncapsulateFieldCandidateFactory fieldCandidateFactory)
21+
{
22+
_declarationFinderProvider = declarationFinderProvider;
23+
_fieldCandidateFactory = fieldCandidateFactory;
24+
}
25+
26+
public EncapsulateFieldUseBackingUDTMemberModel Create(QualifiedModuleName qmn) {
27+
var fields = _declarationFinderProvider.DeclarationFinder.UserDeclarations(DeclarationType.Variable)
28+
.Where(v => v.ParentDeclaration is ModuleDeclaration
29+
&& !v.IsWithEvents);
30+
31+
var candidates = fields.Select(f => _fieldCandidateFactory.Create(f));
32+
33+
var objectStateUDTCandidates = candidates.Where(c => c is IUserDefinedTypeCandidate udt
34+
&& udt.CanBeObjectStateUDT)
35+
.Select(udtc => new ObjectStateUDT(udtc as IUserDefinedTypeCandidate));
36+
37+
return Create(candidates, objectStateUDTCandidates);
38+
}
39+
40+
public EncapsulateFieldUseBackingUDTMemberModel Create(IEnumerable<IEncapsulateFieldCandidate> candidates, IEnumerable<IObjectStateUDT> objectStateUDTCandidates)
41+
{
42+
var fieldCandidates = new List<IEncapsulateFieldCandidate>(candidates);
43+
var objectStateFieldCandidates = new List<IObjectStateUDT>(objectStateUDTCandidates);
44+
45+
var udtMemberCandidates = new List<IUserDefinedTypeMemberCandidate>();
46+
fieldCandidates.ForEach(c => LoadUDTMembers(udtMemberCandidates, c));
47+
48+
var conflictsFinder = new ConvertFieldsToUDTMembersStrategyConflictFinder(_declarationFinderProvider, candidates, udtMemberCandidates, objectStateUDTCandidates);
49+
fieldCandidates.ForEach(c => c.ConflictFinder = conflictsFinder);
50+
51+
var defaultObjectStateUDT = CreateStateUDTField(candidates.First().QualifiedModuleName);
52+
conflictsFinder.AssignNoConflictIdentifiers(defaultObjectStateUDT, _declarationFinderProvider);
53+
54+
var convertedToUDTMemberCandidates = new List<IConvertToUDTMember>();
55+
foreach (var field in candidates)
56+
{
57+
if (field is ConvertToUDTMember cm)
58+
{
59+
convertedToUDTMemberCandidates.Add(cm);
60+
continue;
61+
}
62+
convertedToUDTMemberCandidates.Add(new ConvertToUDTMember(field, defaultObjectStateUDT));
63+
}
64+
65+
return new EncapsulateFieldUseBackingUDTMemberModel(convertedToUDTMemberCandidates, defaultObjectStateUDT, objectStateUDTCandidates, _declarationFinderProvider)
66+
{
67+
ConflictFinder = conflictsFinder
68+
};
69+
}
70+
71+
private IObjectStateUDT CreateStateUDTField(QualifiedModuleName qualifiedModuleName)
72+
{
73+
var stateUDT = new ObjectStateUDT(qualifiedModuleName) as IObjectStateUDT;
74+
stateUDT.IsSelected = true;
75+
76+
return stateUDT;
77+
}
78+
79+
private void ResolveConflict(IEncapsulateFieldConflictFinder conflictFinder, IEncapsulateFieldCandidate candidate)
80+
{
81+
conflictFinder.AssignNoConflictIdentifiers(candidate);
82+
if (candidate is IUserDefinedTypeCandidate udtCandidate)
83+
{
84+
foreach (var member in udtCandidate.Members)
85+
{
86+
conflictFinder.AssignNoConflictIdentifiers(member);
87+
if (member.WrappedCandidate is IUserDefinedTypeCandidate childUDT
88+
&& childUDT.Declaration.AsTypeDeclaration.HasPrivateAccessibility())
89+
{
90+
ResolveConflict(conflictFinder, childUDT);
91+
}
92+
}
93+
}
94+
}
95+
96+
private void LoadUDTMembers(List<IUserDefinedTypeMemberCandidate> udtMembers, IEncapsulateFieldCandidate candidate)
97+
{
98+
if (candidate is IUserDefinedTypeCandidate udtCandidate)
99+
{
100+
foreach (var member in udtCandidate.Members)
101+
{
102+
udtMembers.Add(member);
103+
if (member.WrappedCandidate is IUserDefinedTypeCandidate childUDT
104+
&& childUDT.Declaration.AsTypeDeclaration.HasPrivateAccessibility())
105+
{
106+
LoadUDTMembers(udtMembers, childUDT);
107+
}
108+
}
109+
}
110+
}
111+
}
112+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using Rubberduck.Parsing.Rewriter;
2+
using Rubberduck.VBEditor;
3+
using System;
4+
5+
namespace Rubberduck.Refactorings.EncapsulateFieldUseBackingUDTMember
6+
{
7+
public class EncapsulateFieldUseBackingUDTMemberPreviewProvider : RefactoringPreviewProviderWrapperBase<EncapsulateFieldUseBackingUDTMemberModel>
8+
{
9+
public EncapsulateFieldUseBackingUDTMemberPreviewProvider(EncapsulateFieldUseBackingUDTMemberRefactoringAction refactoringAction,
10+
IRewritingManager rewritingManager)
11+
: base(refactoringAction, rewritingManager)
12+
{ }
13+
14+
public override string Preview(EncapsulateFieldUseBackingUDTMemberModel model)
15+
{
16+
var preview = string.Empty;
17+
var initialFlagValue = model.IncludeNewContentMarker;
18+
model.IncludeNewContentMarker = true;
19+
try
20+
{
21+
preview = base.Preview(model);
22+
}
23+
catch (Exception e) { }
24+
finally
25+
{
26+
model.IncludeNewContentMarker = initialFlagValue;
27+
}
28+
return preview;
29+
}
30+
31+
protected override QualifiedModuleName ComponentToShow(EncapsulateFieldUseBackingUDTMemberModel model)
32+
{
33+
return model.QualifiedModuleName;
34+
}
35+
}
36+
}

Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldUseBackingUDTMemberRefactoringAction.cs renamed to Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldUseBackingUDTMember/EncapsulateFieldUseBackingUDTMemberRefactoringAction.cs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
using Rubberduck.Refactorings.CodeBlockInsert;
1111
using System.Collections.Generic;
1212
using System.Linq;
13+
using Rubberduck.Refactorings.EncapsulateField;
14+
using Rubberduck.Refactorings.EncapsulateFieldInsertNewCode;
1315

14-
namespace Rubberduck.Refactorings.EncapsulateField
16+
namespace Rubberduck.Refactorings.EncapsulateFieldUseBackingUDTMember
1517
{
16-
public class EncapsulateFieldUseBackingUDTMemberRefactoringAction : CodeOnlyRefactoringActionBase<EncapsulateFieldModel>
18+
public class EncapsulateFieldUseBackingUDTMemberRefactoringAction : CodeOnlyRefactoringActionBase<EncapsulateFieldUseBackingUDTMemberModel>
1719
{
1820
private readonly IDeclarationFinderProvider _declarationFinderProvider;
1921
private readonly ICodeOnlyRefactoringAction<DeclareFieldsAsUDTMembersModel> _declareFieldAsUDTMemberRefactoringAction;
@@ -40,7 +42,7 @@ public EncapsulateFieldUseBackingUDTMemberRefactoringAction(
4042
_replaceUDTMemberReferencesModelFactory = replaceUDTMemberReferencesModelFactory;
4143
}
4244

43-
public override void Refactor(EncapsulateFieldModel model, IRewriteSession rewriteSession)
45+
public override void Refactor(EncapsulateFieldUseBackingUDTMemberModel model, IRewriteSession rewriteSession)
4446
{
4547
if (!model.SelectedFieldCandidates.Any())
4648
{
@@ -62,7 +64,7 @@ public override void Refactor(EncapsulateFieldModel model, IRewriteSession rewri
6264
InsertNewContent(model, rewriteSession);
6365
}
6466

65-
private void ModifyFields(EncapsulateFieldModel encapsulateFieldModel, IRewriteSession rewriteSession)
67+
private void ModifyFields(EncapsulateFieldUseBackingUDTMemberModel encapsulateFieldModel, IRewriteSession rewriteSession)
6668
{
6769
var rewriter = rewriteSession.CheckOutModuleRewriter(encapsulateFieldModel.QualifiedModuleName);
6870

@@ -92,7 +94,7 @@ private void ModifyFields(EncapsulateFieldModel encapsulateFieldModel, IRewriteS
9294
}
9395
}
9496

95-
private void ModifyReferences(EncapsulateFieldModel model, IRewriteSession rewriteSession)
97+
private void ModifyReferences(EncapsulateFieldUseBackingUDTMemberModel model, IRewriteSession rewriteSession)
9698
{
9799
var udtFields = model.SelectedFieldCandidates
98100
.Where(f => (f.Declaration.AsTypeDeclaration?.DeclarationType.HasFlag(DeclarationType.UserDefinedType) ?? false)
@@ -140,7 +142,7 @@ private void ModifyReferences(EncapsulateFieldModel model, IRewriteSession rewri
140142
_replaceFieldReferencesRefactoringAction.Refactor(modelReplaceField, rewriteSession);
141143
}
142144

143-
private void InsertNewContent(EncapsulateFieldModel model, IRewriteSession rewriteSession)
145+
private void InsertNewContent(EncapsulateFieldUseBackingUDTMemberModel model, IRewriteSession rewriteSession)
144146
{
145147
var encapsulateFieldInsertNewCodeModel = new EncapsulateFieldInsertNewCodeModel(model.SelectedFieldCandidates)
146148
{

0 commit comments

Comments
 (0)