Skip to content

Commit e29f3b2

Browse files
committed
Add EncapsulateFieldInsertNewCodeRefactoringAction
1 parent c86a359 commit e29f3b2

File tree

2 files changed

+166
-0
lines changed

2 files changed

+166
-0
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using Rubberduck.VBEditor;
2+
using Rubberduck.Refactorings.CodeBlockInsert;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
6+
namespace Rubberduck.Refactorings.EncapsulateField
7+
{
8+
public class EncapsulateFieldInsertNewCodeModel : IRefactoringModel
9+
{
10+
public EncapsulateFieldInsertNewCodeModel(IEnumerable<IEncapsulateFieldCandidate> selectedFieldCandidates)
11+
{
12+
_selectedCandidates = selectedFieldCandidates.ToList();
13+
if (_selectedCandidates.Any())
14+
{
15+
QualifiedModuleName = _selectedCandidates.Select(f => f.QualifiedModuleName).First();
16+
}
17+
}
18+
19+
public bool IncludeNewContentMarker { set; get; } = false;
20+
21+
public QualifiedModuleName QualifiedModuleName { get; } = new QualifiedModuleName();
22+
23+
private Dictionary<NewContentType, List<string>> _newContent { set; get; }
24+
public Dictionary<NewContentType, List<string>> NewContent
25+
{
26+
set => _newContent = value;
27+
get => _newContent;
28+
}
29+
30+
private List<IEncapsulateFieldCandidate> _selectedCandidates;
31+
public IEnumerable<IEncapsulateFieldCandidate> SelectedFieldCandidates
32+
=> _selectedCandidates;
33+
//{
34+
// //set => _selectedCandidates = value.ToList();
35+
// get => _selectedCandidates;
36+
//}
37+
}
38+
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
using Rubberduck.Parsing.Grammar;
2+
using Rubberduck.Parsing.Rewriter;
3+
using Rubberduck.Parsing.Symbols;
4+
using Rubberduck.Parsing.VBA;
5+
using Rubberduck.Refactorings.Common;
6+
using Rubberduck.Resources;
7+
using Rubberduck.Refactorings.CodeBlockInsert;
8+
using System;
9+
using System.Diagnostics;
10+
using System.Linq;
11+
12+
namespace Rubberduck.Refactorings.EncapsulateField
13+
{
14+
public class EncapsulateFieldInsertNewCodeRefactoringAction : CodeOnlyRefactoringActionBase<EncapsulateFieldInsertNewCodeModel>
15+
{
16+
private const string FourSpaces = " ";
17+
18+
private readonly IDeclarationFinderProvider _declarationFinderProvider;
19+
private readonly IRewritingManager _rewritingManager;
20+
private readonly ICodeBuilder _codeBuilder;
21+
private readonly ICodeOnlyRefactoringAction<CodeBlockInsertModel> _codeBlockInsertRefactoringAction;
22+
public EncapsulateFieldInsertNewCodeRefactoringAction(
23+
CodeBlockInsertRefactoringAction codeBlockInsertRefactoringAction,
24+
IDeclarationFinderProvider declarationFinderProvider,
25+
IRewritingManager rewritingManager,
26+
ICodeBuilder codeBuilder)
27+
: base(rewritingManager)
28+
{
29+
_declarationFinderProvider = declarationFinderProvider;
30+
_rewritingManager = rewritingManager;
31+
_codeBuilder = codeBuilder;
32+
_codeBlockInsertRefactoringAction = codeBlockInsertRefactoringAction;
33+
}
34+
35+
public override void Refactor(EncapsulateFieldInsertNewCodeModel model, IRewriteSession rewriteSession)
36+
{
37+
var codeSectionStartIndex = _declarationFinderProvider.DeclarationFinder
38+
.Members(model.QualifiedModuleName).Where(m => m.IsMember())
39+
.OrderBy(c => c.Selection)
40+
.FirstOrDefault()?.Context.Start.TokenIndex;
41+
42+
var codeBlockInsertModel = new CodeBlockInsertModel()
43+
{
44+
QualifiedModuleName = model.QualifiedModuleName,
45+
SelectedFieldCandidates = model.SelectedFieldCandidates,
46+
NewContent = model.NewContent,
47+
CodeSectionStartIndex = codeSectionStartIndex,
48+
IncludeComments = model.IncludeNewContentMarker
49+
};
50+
51+
LoadNewPropertyBlocks(codeBlockInsertModel, _codeBuilder, rewriteSession);
52+
53+
_codeBlockInsertRefactoringAction.Refactor(codeBlockInsertModel, rewriteSession);
54+
}
55+
56+
public void LoadNewPropertyBlocks(CodeBlockInsertModel model, ICodeBuilder codeBuilder, IRewriteSession rewriteSession)
57+
{
58+
if (model.IncludeComments)
59+
{
60+
model.AddContentBlock(NewContentType.PostContentMessage, RubberduckUI.EncapsulateField_PreviewMarker);
61+
}
62+
63+
foreach (var propertyAttributes in model.SelectedFieldCandidates.SelectMany(f => f.PropertyAttributeSets))
64+
{
65+
Debug.Assert(propertyAttributes.Declaration.DeclarationType.HasFlag(DeclarationType.Variable) || propertyAttributes.Declaration.DeclarationType.HasFlag(DeclarationType.UserDefinedTypeMember));
66+
67+
LoadPropertyGetCodeBlock(model, propertyAttributes, codeBuilder);
68+
69+
if (propertyAttributes.GenerateLetter)
70+
{
71+
LoadPropertyLetCodeBlock(model, propertyAttributes, codeBuilder);
72+
}
73+
74+
if (propertyAttributes.GenerateSetter)
75+
{
76+
LoadPropertySetCodeBlock(model, propertyAttributes, codeBuilder);
77+
}
78+
}
79+
}
80+
81+
private static void LoadPropertyLetCodeBlock(CodeBlockInsertModel model, PropertyAttributeSet propertyAttributes, ICodeBuilder codeBuilder)
82+
{
83+
var letterContent = $"{FourSpaces}{propertyAttributes.BackingField} = {propertyAttributes.ParameterName}";
84+
if (!codeBuilder.TryBuildPropertyLetCodeBlock(propertyAttributes.Declaration, propertyAttributes.PropertyName, out var propertyLet, content: letterContent))
85+
{
86+
throw new ArgumentException();
87+
}
88+
model.AddContentBlock(NewContentType.CodeSectionBlock, propertyLet);
89+
}
90+
91+
private static void LoadPropertySetCodeBlock(CodeBlockInsertModel model, PropertyAttributeSet propertyAttributes, ICodeBuilder codeBuilder)
92+
{
93+
var setterContent = $"{FourSpaces}{Tokens.Set} {propertyAttributes.BackingField} = {propertyAttributes.ParameterName}";
94+
if (!codeBuilder.TryBuildPropertySetCodeBlock(propertyAttributes.Declaration, propertyAttributes.PropertyName, out var propertySet, content: setterContent))
95+
{
96+
throw new ArgumentException();
97+
}
98+
model.AddContentBlock(NewContentType.CodeSectionBlock, propertySet);
99+
}
100+
101+
private static void LoadPropertyGetCodeBlock(CodeBlockInsertModel model, PropertyAttributeSet propertyAttributes, ICodeBuilder codeBuilder)
102+
{
103+
var getterContent = $"{propertyAttributes.PropertyName} = {propertyAttributes.BackingField}";
104+
if (propertyAttributes.UsesSetAssignment)
105+
{
106+
getterContent = $"{Tokens.Set} {getterContent}";
107+
}
108+
109+
if (propertyAttributes.AsTypeName.Equals(Tokens.Variant) && !propertyAttributes.Declaration.IsArray)
110+
{
111+
getterContent = string.Join(Environment.NewLine,
112+
$"{Tokens.If} IsObject({propertyAttributes.BackingField}) {Tokens.Then}",
113+
$"{FourSpaces}{Tokens.Set} {propertyAttributes.PropertyName} = {propertyAttributes.BackingField}",
114+
Tokens.Else,
115+
$"{FourSpaces}{propertyAttributes.PropertyName} = {propertyAttributes.BackingField}",
116+
$"{Tokens.End} {Tokens.If}",
117+
Environment.NewLine);
118+
}
119+
120+
if (!codeBuilder.TryBuildPropertyGetCodeBlock(propertyAttributes.Declaration, propertyAttributes.PropertyName, out var propertyGet, content: $"{FourSpaces}{getterContent}"))
121+
{
122+
throw new ArgumentException();
123+
}
124+
125+
model.AddContentBlock(NewContentType.CodeSectionBlock, propertyGet);
126+
}
127+
}
128+
}

0 commit comments

Comments
 (0)