diff --git a/Rubberduck.Refactorings/Common/CodeBuilder.cs b/Rubberduck.Refactorings/Common/CodeBuilder.cs
new file mode 100644
index 0000000000..3e14a75c5b
--- /dev/null
+++ b/Rubberduck.Refactorings/Common/CodeBuilder.cs
@@ -0,0 +1,284 @@
+using Rubberduck.Parsing.Grammar;
+using Rubberduck.Parsing.Symbols;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Rubberduck.Refactorings
+{
+ public interface ICodeBuilder
+ {
+ ///
+ /// Returns ModuleBodyElementDeclaration signature with an ImprovedArgument list
+ ///
+ ///
+ ///
+ string ImprovedFullMemberSignature(ModuleBodyElementDeclaration declaration);
+
+ ///
+ /// Returns a ModuleBodyElementDeclaration block
+ /// with an ImprovedArgument List
+ ///
+ ///
+ /// Main body content/logic of the member
+ ///
+ ///
+ ///
+ string BuildMemberBlockFromPrototype(ModuleBodyElementDeclaration declaration,
+ string content = null,
+ string accessibility = null,
+ string newIdentifier = null);
+
+ ///
+ /// Returns the argument list for the input ModuleBodyElementDeclaration with the following improvements:
+ /// 1. Explicitly declares Property Let\Set value parameter as ByVal
+ /// 2. Ensures UserDefined Type parameters are declared either explicitly or implicitly as ByRef
+ ///
+ ///
+ ///
+ string ImprovedArgumentList(ModuleBodyElementDeclaration declaration);
+
+ ///
+ /// Generates a Property Get codeblock based on the prototype declaration
+ ///
+ /// VariableDeclaration or UserDefinedTypeMember
+ ///
+ ///
+ /// Member body content. Formatting is the responsibility of the caller
+ /// Defaults to 'value' unless otherwise specified
+ ///
+ bool TryBuildPropertyGetCodeBlock(Declaration prototype,
+ string propertyIdentifier,
+ out string codeBlock,
+ string accessibility = null,
+ string content = null);
+
+ ///
+ /// Generates a Property Let codeblock based on the prototype declaration
+ ///
+ /// VariableDeclaration or UserDefinedTypeMember
+ ///
+ ///
+ /// Membmer body content. Formatting is the responsibility of the caller
+ /// Defaults to 'value' unless otherwise specified
+ ///
+ bool TryBuildPropertyLetCodeBlock(Declaration prototype,
+ string propertyIdentifier,
+ out string codeBlock,
+ string accessibility = null,
+ string content = null,
+ string parameterIdentifier = null);
+
+ ///
+ /// Generates a Property Set codeblock based on the prototype declaration
+ ///
+ /// VariableDeclaration or UserDefinedTypeMember
+ ///
+ ///
+ /// Membmer body content. Formatting is the responsibility of the caller
+ /// Defaults to 'value' unless otherwise specified
+ ///
+ bool TryBuildPropertySetCodeBlock(Declaration prototype,
+ string propertyIdentifier,
+ out string codeBlock,
+ string accessibility = null,
+ string content = null,
+ string parameterIdentifier = null);
+ }
+
+ public class CodeBuilder : ICodeBuilder
+ {
+ public string BuildMemberBlockFromPrototype(ModuleBodyElementDeclaration declaration,
+ string content = null,
+ string accessibility = null,
+ string newIdentifier = null)
+ {
+
+ var elements = new List()
+ {
+ ImprovedFullMemberSignatureInternal(declaration, accessibility, newIdentifier),
+ Environment.NewLine,
+ string.IsNullOrEmpty(content) ? null : $"{content}{Environment.NewLine}",
+ ProcedureEndStatement(declaration.DeclarationType),
+ Environment.NewLine,
+ };
+ return string.Concat(elements);
+ }
+
+ public bool TryBuildPropertyGetCodeBlock(Declaration prototype, string propertyIdentifier, out string codeBlock, string accessibility = null, string content = null)
+ => TryBuildPropertyBlockFromTarget(prototype, DeclarationType.PropertyGet, propertyIdentifier, out codeBlock, accessibility, content);
+
+ public bool TryBuildPropertyLetCodeBlock(Declaration prototype, string propertyIdentifier, out string codeBlock, string accessibility = null, string content = null, string parameterIdentifier = null)
+ => TryBuildPropertyBlockFromTarget(prototype, DeclarationType.PropertyLet, propertyIdentifier, out codeBlock, accessibility, content, parameterIdentifier);
+
+ public bool TryBuildPropertySetCodeBlock(Declaration prototype, string propertyIdentifier, out string codeBlock, string accessibility = null, string content = null, string parameterIdentifier = null)
+ => TryBuildPropertyBlockFromTarget(prototype, DeclarationType.PropertySet, propertyIdentifier, out codeBlock, accessibility, content, parameterIdentifier);
+
+ private bool TryBuildPropertyBlockFromTarget(T prototype, DeclarationType letSetGetType, string propertyIdentifier, out string codeBlock, string accessibility = null, string content = null, string parameterIdentifier = null) where T : Declaration
+ {
+ codeBlock = string.Empty;
+ if (!letSetGetType.HasFlag(DeclarationType.Property))
+ {
+ throw new ArgumentException();
+ }
+
+ if (!(prototype is VariableDeclaration || prototype.DeclarationType.HasFlag(DeclarationType.UserDefinedTypeMember)))
+ {
+ return false;
+ }
+
+ var propertyValueParam = parameterIdentifier ?? Resources.RubberduckUI.EncapsulateField_DefaultPropertyParameter;
+
+ var asType = prototype.IsArray
+ ? $"{Tokens.Variant}"
+ : IsEnumField(prototype) && prototype.AsTypeDeclaration.Accessibility.Equals(Accessibility.Private)
+ ? $"{Tokens.Long}"
+ : $"{prototype.AsTypeName}";
+
+ var asTypeClause = $"{Tokens.As} {asType}";
+
+ var paramMechanism = IsUserDefinedType(prototype) ? Tokens.ByRef : Tokens.ByVal;
+
+ var letSetParamExpression = $"{paramMechanism} {propertyValueParam} {asTypeClause}";
+
+ codeBlock = letSetGetType.HasFlag(DeclarationType.PropertyGet)
+ ? string.Join(Environment.NewLine, $"{accessibility ?? Tokens.Public} {ProcedureTypeStatement(letSetGetType)} {propertyIdentifier}() {asTypeClause}", content, ProcedureEndStatement(letSetGetType))
+ : string.Join(Environment.NewLine, $"{accessibility ?? Tokens.Public} {ProcedureTypeStatement(letSetGetType)} {propertyIdentifier}({letSetParamExpression})", content, ProcedureEndStatement(letSetGetType));
+ return true;
+ }
+
+ public string ImprovedFullMemberSignature(ModuleBodyElementDeclaration declaration)
+ => ImprovedFullMemberSignatureInternal(declaration);
+
+ private string ImprovedFullMemberSignatureInternal(ModuleBodyElementDeclaration declaration, string accessibility = null, string newIdentifier = null)
+ {
+ var accessibilityToken = declaration.Accessibility.Equals(Accessibility.Implicit)
+ ? Tokens.Public
+ : $"{declaration.Accessibility.ToString()}";
+
+ var asTypeName = string.IsNullOrEmpty(declaration.AsTypeName)
+ ? string.Empty
+ : $" {Tokens.As} {declaration.AsTypeName}";
+
+ var elements = new List()
+ {
+ accessibility ?? accessibilityToken,
+ $" {ProcedureTypeStatement(declaration.DeclarationType)} ",
+ newIdentifier ?? declaration.IdentifierName,
+ $"({ImprovedArgumentList(declaration)})",
+ asTypeName
+ };
+ return string.Concat(elements).Trim();
+
+ }
+
+ public string ImprovedArgumentList(ModuleBodyElementDeclaration declaration)
+ {
+ var arguments = Enumerable.Empty();
+ if (declaration is IParameterizedDeclaration parameterizedDeclaration)
+ {
+ arguments = parameterizedDeclaration.Parameters
+ .OrderBy(parameter => parameter.Selection)
+ .Select(parameter => BuildParameterDeclaration(
+ parameter,
+ parameter.Equals(parameterizedDeclaration.Parameters.LastOrDefault())
+ && declaration.DeclarationType.HasFlag(DeclarationType.Property)
+ && !declaration.DeclarationType.Equals(DeclarationType.PropertyGet)));
+ }
+ return $"{string.Join(", ", arguments)}";
+ }
+
+ private static string BuildParameterDeclaration(ParameterDeclaration parameter, bool forceExplicitByValAccess)
+ {
+ var optionalParamType = parameter.IsParamArray
+ ? Tokens.ParamArray
+ : parameter.IsOptional ? Tokens.Optional : string.Empty;
+
+ var paramMechanism = parameter.IsImplicitByRef
+ ? string.Empty
+ : parameter.IsByRef ? Tokens.ByRef : Tokens.ByVal;
+
+ if (forceExplicitByValAccess
+ && (string.IsNullOrEmpty(paramMechanism) || paramMechanism.Equals(Tokens.ByRef))
+ && !IsUserDefinedType(parameter))
+ {
+ paramMechanism = Tokens.ByVal;
+ }
+
+ var name = parameter.IsArray
+ ? $"{parameter.IdentifierName}()"
+ : parameter.IdentifierName;
+
+ var paramDeclarationElements = new List()
+ {
+ FormatOptionalElement(optionalParamType),
+ FormatOptionalElement(paramMechanism),
+ $"{name} ",
+ FormatAsTypeName(parameter.AsTypeName),
+ FormatDefaultValue(parameter.DefaultValue)
+ };
+
+ return string.Concat(paramDeclarationElements).Trim();
+ }
+
+ private static string FormatOptionalElement(string element)
+ => string.IsNullOrEmpty(element) ? string.Empty : $"{element} ";
+
+ private static string FormatAsTypeName(string AsTypeName)
+ => string.IsNullOrEmpty(AsTypeName) ? string.Empty : $"As {AsTypeName} ";
+
+ private static string FormatDefaultValue(string DefaultValue)
+ => string.IsNullOrEmpty(DefaultValue) ? string.Empty : $"= {DefaultValue}";
+
+ private static string ProcedureEndStatement(DeclarationType declarationType)
+ {
+ switch (declarationType)
+ {
+ case DeclarationType.Function:
+ return $"{Tokens.End} {Tokens.Function}";
+ case DeclarationType.Procedure:
+ return $"{Tokens.End} {Tokens.Sub}";
+ case DeclarationType.PropertyGet:
+ case DeclarationType.PropertyLet:
+ case DeclarationType.PropertySet:
+ return $"{Tokens.End} {Tokens.Property}";
+ default:
+ throw new ArgumentException();
+ }
+ }
+
+ private static string ProcedureTypeStatement(DeclarationType declarationType)
+ {
+ switch (declarationType)
+ {
+ case DeclarationType.Function:
+ return Tokens.Function;
+ case DeclarationType.Procedure:
+ return Tokens.Sub;
+ case DeclarationType.PropertyGet:
+ return $"{Tokens.Property} {Tokens.Get}";
+ case DeclarationType.PropertyLet:
+ return $"{Tokens.Property} {Tokens.Let}";
+ case DeclarationType.PropertySet:
+ return $"{Tokens.Property} {Tokens.Set}";
+ default:
+ throw new ArgumentException();
+ }
+ }
+
+ private static bool IsEnumField(VariableDeclaration declaration)
+ => IsMemberVariable(declaration)
+ && (declaration.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.Enumeration) ?? false);
+
+ private static bool IsEnumField(Declaration declaration)
+ => IsMemberVariable(declaration)
+ && (declaration.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.Enumeration) ?? false);
+
+ private static bool IsUserDefinedType(Declaration declaration)
+ => (declaration.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.UserDefinedType) ?? false);
+
+ private static bool IsMemberVariable(Declaration declaration)
+ => declaration.DeclarationType.HasFlag(DeclarationType.Variable)
+ && !declaration.ParentDeclaration.DeclarationType.HasFlag(DeclarationType.Member);
+ }
+}
diff --git a/Rubberduck.Refactorings/Common/DeclarationExtensions.cs b/Rubberduck.Refactorings/Common/DeclarationExtensions.cs
index 4e9f7b24c2..2c8519b8e8 100644
--- a/Rubberduck.Refactorings/Common/DeclarationExtensions.cs
+++ b/Rubberduck.Refactorings/Common/DeclarationExtensions.cs
@@ -1,10 +1,6 @@
using Rubberduck.Parsing;
using Rubberduck.Parsing.Grammar;
using Rubberduck.Parsing.Symbols;
-using Rubberduck.Refactorings.Common;
-using System;
-using System.Collections.Generic;
-using System.Linq;
namespace Rubberduck.Refactorings.Common
{
@@ -45,62 +41,5 @@ public static bool IsDeclaredInList(this Declaration declaration)
return declaration.Context.TryGetAncestor(out var varList)
&& varList.ChildCount > 1;
}
-
- ///
- /// Generates a Property Member code block specified by the letSetGet DeclarationType argument.
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static string FieldToPropertyBlock(this Declaration variable, DeclarationType letSetGetType, string propertyIdentifier, string accessibility = null, string content = null, string parameterIdentifier = null)
- {
- //"value" is the default
- var propertyValueParam = parameterIdentifier ?? Resources.RubberduckUI.EncapsulateField_DefaultPropertyParameter;
-
- var propertyEndStmt = $"{Tokens.End} {Tokens.Property}";
-
- var asType = variable.IsArray
- ? $"{Tokens.Variant}"
- : variable.IsEnumField() && variable.AsTypeDeclaration.HasPrivateAccessibility()
- ? $"{Tokens.Long}"
- : $"{variable.AsTypeName}";
-
- var asTypeClause = $"{Tokens.As} {asType}";
-
- var paramAccessibility = variable.IsUserDefinedType() ? Tokens.ByRef : Tokens.ByVal;
-
- var letSetParameter = $"{paramAccessibility} {propertyValueParam} {Tokens.As} {asType}";
-
- switch (letSetGetType)
- {
- case DeclarationType.PropertyGet:
- return string.Join(Environment.NewLine, $"{accessibility ?? Tokens.Public} {PropertyTypeStatement(letSetGetType)} {propertyIdentifier}() {asTypeClause}", content, propertyEndStmt);
- case DeclarationType.PropertyLet:
- case DeclarationType.PropertySet:
- return string.Join(Environment.NewLine, $"{accessibility ?? Tokens.Public} {PropertyTypeStatement(letSetGetType)} {propertyIdentifier}({letSetParameter})", content, propertyEndStmt);
- default:
- throw new ArgumentException();
- }
- }
-
- private static string PropertyTypeStatement(DeclarationType declarationType)
- {
- switch (declarationType)
- {
- case DeclarationType.PropertyGet:
- return $"{Tokens.Property} {Tokens.Get}";
- case DeclarationType.PropertyLet:
- return $"{Tokens.Property} {Tokens.Let}";
- case DeclarationType.PropertySet:
- return $"{Tokens.Property} {Tokens.Set}";
- default:
- throw new ArgumentException();
- }
-
- }
}
}
diff --git a/Rubberduck.Refactorings/Common/ModuleBodyElementDeclarationExtensions.cs b/Rubberduck.Refactorings/Common/ModuleBodyElementDeclarationExtensions.cs
deleted file mode 100644
index 5b2bd87671..0000000000
--- a/Rubberduck.Refactorings/Common/ModuleBodyElementDeclarationExtensions.cs
+++ /dev/null
@@ -1,176 +0,0 @@
-using Rubberduck.Parsing.Grammar;
-using Rubberduck.Parsing.Symbols;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Rubberduck.Refactorings.Common
-{
- public static class ModuleBodyElementDeclarationExtensions
- {
- ///
- /// Returns ModuleBodyElementDeclaration signature with an ImprovedArgument list
- /// 1. Explicitly declares Property Let\Set value parameter as ByVal
- /// 2. Ensures UserDefined Type parameters are declared either explicitly or implicitly as ByRef
- ///
- ///
- ///
- public static string FullMemberSignature(this ModuleBodyElementDeclaration declaration,
- string accessibility = null,
- string newIdentifier = null)
- {
- var accessibilityToken = declaration.Accessibility.Equals(Accessibility.Implicit)
- ? Tokens.Public
- : $"{declaration.Accessibility.ToString()}";
-
- var asTypeClause = declaration.AsTypeName == null
- ? string.Empty
- : $" {Tokens.As} {declaration.AsTypeName}";
-
- var fullSignatureFormat = RetrieveFullSignatureFormat(declaration);
-
- var fullSignature = string.Format(fullSignatureFormat,
- accessibility ?? accessibilityToken,
- newIdentifier ?? declaration.IdentifierName,
- ImprovedArgumentList(declaration),
- asTypeClause);
-
- return fullSignature.Trim();
- }
-
- public static string AsCodeBlock(this ModuleBodyElementDeclaration declaration,
- string content = null,
- string accessibility = null,
- string newIdentifier = null)
- {
- var endStatement = string.Empty;
- switch (declaration.Context)
- {
- case VBAParser.SubStmtContext _:
- endStatement = $"{Tokens.End} {Tokens.Sub}";
- break;
- case VBAParser.FunctionStmtContext _:
- endStatement = $"{Tokens.End} {Tokens.Function}";
- break;
- case VBAParser.PropertyGetStmtContext _:
- case VBAParser.PropertyLetStmtContext _:
- case VBAParser.PropertySetStmtContext _:
- endStatement = $"{Tokens.End} {Tokens.Property}";
- break;
- default:
- throw new ArgumentException();
- }
-
- if (content != null)
- {
- return string.Format("{0}{1}{2}{1}{3}{1}",
- FullMemberSignature(declaration, accessibility, newIdentifier),
- Environment.NewLine,
- content,
- endStatement);
- }
-
- return string.Format("{0}{1}{2}{1}",
- FullMemberSignature(declaration, accessibility, newIdentifier),
- Environment.NewLine,
- endStatement);
- }
-
- ///
- /// 1. Explicitly declares Property Let\Set value parameter as ByVal
- /// 2. Ensures UserDefined Type parameters are declared either explicitly or implicitly as ByRef
- ///
- ///
- ///
- public static string ImprovedArgumentList(this ModuleBodyElementDeclaration declaration)
- {
- var arguments = Enumerable.Empty();
- if (declaration is IParameterizedDeclaration parameterizedDeclaration)
- {
- arguments = parameterizedDeclaration.Parameters
- .OrderBy(parameter => parameter.Selection)
- .Select(parameter => BuildParameterDeclaration(
- parameter,
- parameter.Equals(parameterizedDeclaration.Parameters.LastOrDefault())
- && declaration.DeclarationType.HasFlag(DeclarationType.Property)
- && !declaration.DeclarationType.Equals(DeclarationType.PropertyGet)));
- }
- return $"{string.Join(", ", arguments)}";
- }
-
- private static string BuildParameterDeclaration(ParameterDeclaration parameter, bool forceExplicitByValAccess)
- {
- var accessibility = parameter.IsImplicitByRef
- ? string.Empty
- : parameter.IsByRef
- ? Tokens.ByRef
- : Tokens.ByVal;
-
- if (forceExplicitByValAccess)
- {
- accessibility = Tokens.ByVal;
- }
-
- if (accessibility.Equals(Tokens.ByVal)
- && (parameter.AsTypeDeclaration?.DeclarationType.HasFlag(DeclarationType.UserDefinedType) ?? false))
- {
- accessibility = Tokens.ByRef;
- }
-
- var name = parameter.IsArray
- ? $"{parameter.IdentifierName}()"
- : parameter.IdentifierName;
-
- var optional = parameter.IsParamArray
- ? Tokens.ParamArray
- : parameter.IsOptional
- ? Tokens.Optional
- : string.Empty;
-
- var defaultValue = parameter.DefaultValue;
-
- return $"{FormatStandardElement(optional)}{FormatStandardElement(accessibility)}{FormatStandardElement(name)}{FormattedAsTypeName(parameter.AsTypeName)}{FormattedDefaultValue(defaultValue)}".Trim();
- }
-
- private static string RetrieveFullSignatureFormat(Declaration declaration)
- {
- var fullSignatureFormat = $"{{0}} THE_MEMBER_TYPE {{1}}({{2}}){{3}}";
-
- switch (declaration.Context)
- {
- case VBAParser.SubStmtContext _:
- fullSignatureFormat = fullSignatureFormat.Replace("THE_MEMBER_TYPE", Tokens.Sub);
- break;
- case VBAParser.FunctionStmtContext _:
- fullSignatureFormat = fullSignatureFormat.Replace("THE_MEMBER_TYPE", Tokens.Function);
- break;
- case VBAParser.PropertyGetStmtContext _:
- fullSignatureFormat = fullSignatureFormat.Replace("THE_MEMBER_TYPE", $"{Tokens.Property} {Tokens.Get}");
- break;
- case VBAParser.PropertyLetStmtContext _:
- fullSignatureFormat = fullSignatureFormat.Replace("THE_MEMBER_TYPE", $"{Tokens.Property} {Tokens.Let}");
- break;
- case VBAParser.PropertySetStmtContext _:
- fullSignatureFormat = fullSignatureFormat.Replace("THE_MEMBER_TYPE", $"{Tokens.Property} {Tokens.Set}");
- break;
- default:
- throw new ArgumentException();
- }
- return fullSignatureFormat;
- }
-
- private static string FormatStandardElement(string element) => string.IsNullOrEmpty(element)
- ? string.Empty
- : $"{element} ";
-
- private static string FormattedAsTypeName(string AsTypeName) => string.IsNullOrEmpty(AsTypeName)
- ? string.Empty
- : $"As {AsTypeName} ";
-
- private static string FormattedDefaultValue(string DefaultValue) => string.IsNullOrEmpty(DefaultValue)
- ? string.Empty
- : $"= {DefaultValue}";
- }
-}
\ No newline at end of file
diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs
index 3b92a5463d..78003eddce 100644
--- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs
+++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs
@@ -21,6 +21,7 @@ public class EncapsulateFieldRefactoring : InteractiveRefactoringBase userInteraction,
IRewritingManager rewritingManager,
ISelectionProvider selectionProvider,
- ISelectedDeclarationProvider selectedDeclarationProvider)
+ ISelectedDeclarationProvider selectedDeclarationProvider,
+ ICodeBuilder codeBuilder)
:base(selectionProvider, userInteraction)
{
_declarationFinderProvider = declarationFinderProvider;
_selectedDeclarationProvider = selectedDeclarationProvider;
_indenter = indenter;
+ _codeBuilder = codeBuilder;
_rewritingManager = rewritingManager;
}
@@ -112,8 +115,8 @@ private IEncapsulateFieldRewriteSession RefactorRewrite(EncapsulateFieldModel mo
if (!model.SelectedFieldCandidates.Any()) { return refactorRewriteSession; }
var strategy = model.EncapsulateFieldStrategy == EncapsulateFieldStrategy.ConvertFieldsToUDTMembers
- ? new ConvertFieldsToUDTMembers(_declarationFinderProvider, model, _indenter) as IEncapsulateStrategy
- : new UseBackingFields(_declarationFinderProvider, model, _indenter) as IEncapsulateStrategy;
+ ? new ConvertFieldsToUDTMembers(_declarationFinderProvider, model, _indenter, _codeBuilder) as IEncapsulateStrategy
+ : new UseBackingFields(_declarationFinderProvider, model, _indenter, _codeBuilder) as IEncapsulateStrategy;
return strategy.RefactorRewrite(refactorRewriteSession, asPreview);
}
diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs
index a0c7d3da00..57289c1db1 100644
--- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs
+++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs
@@ -21,8 +21,8 @@ public class ConvertFieldsToUDTMembers : EncapsulateFieldStrategyBase
{
private IObjectStateUDT _stateUDTField;
- public ConvertFieldsToUDTMembers(IDeclarationFinderProvider declarationFinderProvider, EncapsulateFieldModel model, IIndenter indenter)
- : base(declarationFinderProvider, model, indenter)
+ public ConvertFieldsToUDTMembers(IDeclarationFinderProvider declarationFinderProvider, EncapsulateFieldModel model, IIndenter indenter, ICodeBuilder codeBuilder)
+ : base(declarationFinderProvider, model, indenter, codeBuilder)
{
_stateUDTField = model.ObjectStateUDTField;
}
@@ -66,40 +66,6 @@ protected override void LoadNewDeclarationBlocks()
return;
}
- protected override void LoadNewPropertyBlocks()
- {
- var propertyGenerationSpecs = SelectedFields.SelectMany(f => f.PropertyAttributeSets);
-
- foreach (var selectedField in SelectedFields)
- {
- var converted = selectedField as IConvertToUDTMember;
- foreach (var set in selectedField.PropertyAttributeSets)
- {
- if (converted.Declaration is VariableDeclaration variableDeclaration)
- {
- var getContent = $"{set.PropertyName} = {set.BackingField}";
- if (set.UsesSetAssignment)
- {
- getContent = $"{Tokens.Set} {getContent}";
- }
- AddContentBlock(NewContentTypes.MethodBlock, variableDeclaration.FieldToPropertyBlock(DeclarationType.PropertyGet, set.PropertyName, content: $"{_defaultIndent}{getContent}"));
- if (converted.IsReadOnly)
- {
- continue;
- }
- if (set.GenerateLetter)
- {
- AddContentBlock(NewContentTypes.MethodBlock, variableDeclaration.FieldToPropertyBlock(DeclarationType.PropertyLet, set.PropertyName, content: $"{_defaultIndent}{set.BackingField} = {set.ParameterName}"));
- }
- if (set.GenerateSetter)
- {
- AddContentBlock(NewContentTypes.MethodBlock, variableDeclaration.FieldToPropertyBlock(DeclarationType.PropertySet, set.PropertyName, content: $"{_defaultIndent}{Tokens.Set} {set.BackingField} = {set.ParameterName}"));
- }
- }
- }
- }
- }
-
protected override void LoadFieldReferenceContextReplacements(IEncapsulateFieldCandidate field)
{
Debug.Assert(field is IConvertToUDTMember);
diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs
index c84a667889..bf6c9f2d12 100644
--- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs
+++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs
@@ -10,6 +10,7 @@
using Rubberduck.VBEditor;
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -41,6 +42,7 @@ public abstract class EncapsulateFieldStrategyBase : IEncapsulateStrategy
protected QualifiedModuleName _targetQMN;
private readonly int? _codeSectionStartIndex;
protected const string _defaultIndent = " "; //4 spaces
+ protected ICodeBuilder _codeBuilder;
protected Dictionary IdentifierReplacements { get; } = new Dictionary();
@@ -50,10 +52,11 @@ protected enum NewContentTypes { TypeDeclarationBlock, DeclarationBlock, MethodB
protected IEnumerable SelectedFields { private set; get; }
- public EncapsulateFieldStrategyBase(IDeclarationFinderProvider declarationFinderProvider, EncapsulateFieldModel model, IIndenter indenter)
+ public EncapsulateFieldStrategyBase(IDeclarationFinderProvider declarationFinderProvider, EncapsulateFieldModel model, IIndenter indenter, ICodeBuilder codeBuilder)
{
_targetQMN = model.QualifiedModuleName;
_indenter = indenter;
+ _codeBuilder = codeBuilder;
SelectedFields = model.SelectedFieldCandidates;
_codeSectionStartIndex = declarationFinderProvider.DeclarationFinder
@@ -138,39 +141,62 @@ private void InsertNewContent(IEncapsulateFieldRewriteSession refactorRewriteSes
}
}
- protected virtual void LoadNewPropertyBlocks()
+ protected void LoadNewPropertyBlocks()
{
- foreach (var attributeSet in SelectedFields.SelectMany(f => f.PropertyAttributeSets))
+ foreach (var propertyAttributes in SelectedFields.SelectMany(f => f.PropertyAttributeSets))
{
- if (attributeSet.Declaration is VariableDeclaration || attributeSet.Declaration.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember))
- {
- var getContent = $"{attributeSet.PropertyName} = {attributeSet.BackingField}";
- if (attributeSet.UsesSetAssignment)
- {
- getContent = $"{Tokens.Set} {getContent}";
- }
- if (attributeSet.AsTypeName.Equals(Tokens.Variant) && !attributeSet.Declaration.IsArray)
- {
- getContent = string.Join(Environment.NewLine,
- $"{Tokens.If} IsObject({attributeSet.BackingField}) {Tokens.Then}",
- $"{_defaultIndent}{Tokens.Set} {attributeSet.PropertyName} = {attributeSet.BackingField}",
- Tokens.Else,
- $"{_defaultIndent}{attributeSet.PropertyName} = {attributeSet.BackingField}",
- $"{Tokens.End} {Tokens.If}",
- Environment.NewLine);
- }
+ AddPropertyCodeBlocks(propertyAttributes);
+ }
+ }
+
+ private void AddPropertyCodeBlocks(PropertyAttributeSet propertyAttributes)
+ {
+ Debug.Assert(propertyAttributes.Declaration.DeclarationType.HasFlag(DeclarationType.Variable) || propertyAttributes.Declaration.DeclarationType.HasFlag(DeclarationType.UserDefinedTypeMember));
- AddContentBlock(NewContentTypes.MethodBlock, attributeSet.Declaration.FieldToPropertyBlock(DeclarationType.PropertyGet, attributeSet.PropertyName, content: $"{_defaultIndent}{getContent}"));
+ var getContent = $"{propertyAttributes.PropertyName} = {propertyAttributes.BackingField}";
+ if (propertyAttributes.UsesSetAssignment)
+ {
+ getContent = $"{Tokens.Set} {getContent}";
+ }
- if (attributeSet.GenerateLetter)
- {
- AddContentBlock(NewContentTypes.MethodBlock, attributeSet.Declaration.FieldToPropertyBlock(DeclarationType.PropertyLet, attributeSet.PropertyName, content: $"{_defaultIndent}{attributeSet.BackingField} = {attributeSet.ParameterName}"));
- }
- if (attributeSet.GenerateSetter)
- {
- AddContentBlock(NewContentTypes.MethodBlock, attributeSet.Declaration.FieldToPropertyBlock(DeclarationType.PropertySet, attributeSet.PropertyName, content: $"{_defaultIndent}{Tokens.Set} {attributeSet.BackingField} = {attributeSet.ParameterName}"));
- }
+ if (propertyAttributes.AsTypeName.Equals(Tokens.Variant) && !propertyAttributes.Declaration.IsArray)
+ {
+ getContent = string.Join(Environment.NewLine,
+ $"{Tokens.If} IsObject({propertyAttributes.BackingField}) {Tokens.Then}",
+ $"{_defaultIndent}{Tokens.Set} {propertyAttributes.PropertyName} = {propertyAttributes.BackingField}",
+ Tokens.Else,
+ $"{_defaultIndent}{propertyAttributes.PropertyName} = {propertyAttributes.BackingField}",
+ $"{Tokens.End} {Tokens.If}",
+ Environment.NewLine);
+ }
+
+ if (!_codeBuilder.TryBuildPropertyGetCodeBlock(propertyAttributes.Declaration, propertyAttributes.PropertyName, out var propertyGet, content: $"{_defaultIndent}{getContent}"))
+ {
+ throw new ArgumentException();
+ }
+ AddContentBlock(NewContentTypes.MethodBlock, propertyGet);
+
+ if (!(propertyAttributes.GenerateLetter || propertyAttributes.GenerateSetter))
+ {
+ return;
+ }
+
+ if (propertyAttributes.GenerateLetter)
+ {
+ if (!_codeBuilder.TryBuildPropertyLetCodeBlock(propertyAttributes.Declaration, propertyAttributes.PropertyName, out var propertyLet, content: $"{_defaultIndent}{propertyAttributes.BackingField} = {propertyAttributes.ParameterName}"))
+ {
+ throw new ArgumentException();
+ }
+ AddContentBlock(NewContentTypes.MethodBlock, propertyLet);
+ }
+
+ if (propertyAttributes.GenerateSetter)
+ {
+ if (!_codeBuilder.TryBuildPropertySetCodeBlock(propertyAttributes.Declaration, propertyAttributes.PropertyName, out var propertySet, content: $"{_defaultIndent}{Tokens.Set} {propertyAttributes.BackingField} = {propertyAttributes.ParameterName}"))
+ {
+ throw new ArgumentException();
}
+ AddContentBlock(NewContentTypes.MethodBlock, propertySet);
}
}
diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/UseBackingFields.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/UseBackingFields.cs
index 7172200a33..b4f5b16dfb 100644
--- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/UseBackingFields.cs
+++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/UseBackingFields.cs
@@ -16,8 +16,8 @@ namespace Rubberduck.Refactorings.EncapsulateField
{
public class UseBackingFields : EncapsulateFieldStrategyBase
{
- public UseBackingFields(IDeclarationFinderProvider declarationFinderProvider, EncapsulateFieldModel model, IIndenter indenter)
- : base(declarationFinderProvider, model, indenter){ }
+ public UseBackingFields(IDeclarationFinderProvider declarationFinderProvider, EncapsulateFieldModel model, IIndenter indenter, ICodeBuilder codeBuilder)
+ : base(declarationFinderProvider, model, indenter, codeBuilder) { }
protected override void ModifyFields(IEncapsulateFieldRewriteSession refactorRewriteSession)
{
diff --git a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceModel.cs b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceModel.cs
index 22af322d07..ec40082048 100644
--- a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceModel.cs
+++ b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceModel.cs
@@ -34,7 +34,7 @@ public class ExtractInterfaceModel : IRefactoringModel
DeclarationType.PropertySet,
};
- public ExtractInterfaceModel(IDeclarationFinderProvider declarationFinderProvider, ClassModuleDeclaration target)
+ public ExtractInterfaceModel(IDeclarationFinderProvider declarationFinderProvider, ClassModuleDeclaration target, ICodeBuilder codeBuilder)
{
TargetDeclaration = target;
DeclarationFinderProvider = declarationFinderProvider;
@@ -47,10 +47,10 @@ public ExtractInterfaceModel(IDeclarationFinderProvider declarationFinderProvide
InterfaceName = $"I{TargetDeclaration.IdentifierName}";
InterfaceInstancing = ImplementingClassInstancing;
- LoadMembers();
+ LoadMembers(codeBuilder);
}
- private void LoadMembers()
+ private void LoadMembers(ICodeBuilder codeBuilder)
{
Members = new ObservableCollection(DeclarationFinderProvider.DeclarationFinder
.Members(TargetDeclaration.QualifiedModuleName)
@@ -59,7 +59,7 @@ private void LoadMembers()
&& MemberTypes.Contains(item.DeclarationType))
.OrderBy(o => o.Selection.StartLine)
.ThenBy(t => t.Selection.StartColumn)
- .Select(d => new InterfaceMember(d))
+ .Select(d => new InterfaceMember(d, codeBuilder))
.ToList());
}
}
diff --git a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs
index 692abd59e8..090c11a860 100644
--- a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs
+++ b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs
@@ -13,16 +13,19 @@ public class ExtractInterfaceRefactoring : InteractiveRefactoringBase _refactoringAction;
private readonly IDeclarationFinderProvider _declarationFinderProvider;
+ private readonly ICodeBuilder _codeBuilder;
public ExtractInterfaceRefactoring(
ExtractInterfaceRefactoringAction refactoringAction,
IDeclarationFinderProvider declarationFinderProvider,
RefactoringUserInteraction userInteraction,
- ISelectionProvider selectionProvider)
+ ISelectionProvider selectionProvider,
+ ICodeBuilder codeBuilder)
:base(selectionProvider, userInteraction)
{
_refactoringAction = refactoringAction;
_declarationFinderProvider = declarationFinderProvider;
+ _codeBuilder = codeBuilder;
}
private static readonly DeclarationType[] ModuleTypes =
@@ -55,7 +58,7 @@ protected override ExtractInterfaceModel InitializeModel(Declaration target)
throw new InvalidDeclarationTypeException(target);
}
- return new ExtractInterfaceModel(_declarationFinderProvider, targetClass);
+ return new ExtractInterfaceModel(_declarationFinderProvider, targetClass, _codeBuilder);
}
protected override void RefactorImpl(ExtractInterfaceModel model)
diff --git a/Rubberduck.Refactorings/ExtractInterface/InterfaceMember.cs b/Rubberduck.Refactorings/ExtractInterface/InterfaceMember.cs
index 7cfaf3ed05..e8b77e74f8 100644
--- a/Rubberduck.Refactorings/ExtractInterface/InterfaceMember.cs
+++ b/Rubberduck.Refactorings/ExtractInterface/InterfaceMember.cs
@@ -1,20 +1,16 @@
using System;
-using System.Collections.Generic;
using System.ComponentModel;
-using System.Linq;
using System.Runtime.CompilerServices;
-using Rubberduck.Parsing.Grammar;
using Rubberduck.Parsing.Symbols;
-using Rubberduck.Refactorings.Common;
-using Rubberduck.Refactorings.ImplementInterface;
namespace Rubberduck.Refactorings.ExtractInterface
{
public class InterfaceMember : INotifyPropertyChanged
{
private readonly ModuleBodyElementDeclaration _element;
+ private readonly ICodeBuilder _codeBuilder;
- public InterfaceMember(Declaration member)
+ public InterfaceMember(Declaration member, ICodeBuilder codeBuilder)
{
Member = member;
if (!(member is ModuleBodyElementDeclaration mbed))
@@ -22,6 +18,7 @@ public InterfaceMember(Declaration member)
throw new ArgumentException();
}
_element = mbed;
+ _codeBuilder = codeBuilder;
}
public Declaration Member { get; }
@@ -37,9 +34,9 @@ public bool IsSelected
}
}
- public string FullMemberSignature => _element.FullMemberSignature();
+ public string FullMemberSignature => _codeBuilder.ImprovedFullMemberSignature(_element);
- public string Body => _element.AsCodeBlock();
+ public string Body => _codeBuilder.BuildMemberBlockFromPrototype(_element);
public event PropertyChangedEventHandler PropertyChanged;
diff --git a/Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterfaceImplementationsRefactoringAction.cs b/Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterfaceImplementationsRefactoringAction.cs
index 9cc0003d18..0c3091b84a 100644
--- a/Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterfaceImplementationsRefactoringAction.cs
+++ b/Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterfaceImplementationsRefactoringAction.cs
@@ -4,17 +4,19 @@
using Rubberduck.Parsing.Grammar;
using Rubberduck.Parsing.Rewriter;
using Rubberduck.Parsing.Symbols;
-using Rubberduck.Refactorings.Common;
+
namespace Rubberduck.Refactorings.AddInterfaceImplementations
{
public class AddInterfaceImplementationsRefactoringAction : CodeOnlyRefactoringActionBase
{
private readonly string _memberBody;
+ private readonly ICodeBuilder _codeBuilder;
- public AddInterfaceImplementationsRefactoringAction(IRewritingManager rewritingManager)
+ public AddInterfaceImplementationsRefactoringAction(IRewritingManager rewritingManager, ICodeBuilder codeBuilder)
: base(rewritingManager)
{
+ _codeBuilder = codeBuilder;
_memberBody = $" {Tokens.Err}.Raise 5 {Resources.Refactorings.Refactorings.ImplementInterface_TODO}";
}
@@ -36,23 +38,33 @@ private string GetInterfaceMember(Declaration member, string interfaceName)
{
if (member is ModuleBodyElementDeclaration mbed)
{
- return mbed.AsCodeBlock(accessibility: Tokens.Private, newIdentifier: $"{interfaceName}_{member.IdentifierName}", content: _memberBody);
+ return _codeBuilder.BuildMemberBlockFromPrototype(mbed, accessibility: Tokens.Private, newIdentifier: $"{interfaceName}_{member.IdentifierName}", content: _memberBody);
}
- if (member.DeclarationType.Equals(DeclarationType.Variable))
+ if (member is VariableDeclaration variable)
{
- var propertyGet = member.FieldToPropertyBlock(DeclarationType.PropertyGet, $"{interfaceName}_{member.IdentifierName}", Tokens.Private, _memberBody);
+ if (!_codeBuilder.TryBuildPropertyGetCodeBlock(variable, $"{interfaceName}_{variable.IdentifierName}", out var propertyGet, Tokens.Private, _memberBody))
+ {
+ throw new InvalidOperationException();
+ }
+
var members = new List { propertyGet };
- if (member.AsTypeName.Equals(Tokens.Variant) || !member.IsObject)
+ if (variable.AsTypeName.Equals(Tokens.Variant) || !variable.IsObject)
{
- var propertyLet = member.FieldToPropertyBlock(DeclarationType.PropertyLet, $"{interfaceName}_{member.IdentifierName}", Tokens.Private, _memberBody);
+ if (!_codeBuilder.TryBuildPropertyLetCodeBlock(variable, $"{interfaceName}_{variable.IdentifierName}", out var propertyLet, Tokens.Private, _memberBody))
+ {
+ throw new InvalidOperationException();
+ }
members.Add(propertyLet);
}
- if (member.AsTypeName.Equals(Tokens.Variant) || member.IsObject)
+ if (variable.AsTypeName.Equals(Tokens.Variant) || variable.IsObject)
{
- var propertySet = member.FieldToPropertyBlock(DeclarationType.PropertySet, $"{interfaceName}_{member.IdentifierName}", Tokens.Private, _memberBody);
+ if (!_codeBuilder.TryBuildPropertySetCodeBlock(variable, $"{interfaceName}_{variable.IdentifierName}", out var propertySet, Tokens.Private, _memberBody))
+ {
+ throw new InvalidOperationException();
+ }
members.Add(propertySet);
}
diff --git a/RubberduckTests/CodeBuilderTests.cs b/RubberduckTests/CodeBuilderTests.cs
new file mode 100644
index 0000000000..58326a60be
--- /dev/null
+++ b/RubberduckTests/CodeBuilderTests.cs
@@ -0,0 +1,413 @@
+using NUnit.Framework;
+using Rubberduck.Parsing.Symbols;
+using Rubberduck.Refactorings;
+using RubberduckTests.Mocks;
+using System;
+using System.Linq;
+
+namespace RubberduckTests
+{
+ [TestFixture]
+ public class CodeBuilderTests
+ {
+
+ [TestCase("fizz", DeclarationType.Variable, "Integer")]
+ [TestCase("FirstValue", DeclarationType.UserDefinedTypeMember, "Long")]
+ [TestCase("fazz", DeclarationType.Variable, "Long")]
+ [TestCase("fuzz", DeclarationType.Variable, "ETestType2")]
+ [Category(nameof(CodeBuilder))]
+ public void PropertyBlockFromPrototype_PropertyGet(string targetIdentifier, DeclarationType declarationType, string typeName)
+ {
+ var testParams = new PropertyBlockFromPrototypeParams("Bazz", DeclarationType.PropertyGet);
+ string inputCode =
+$@"
+
+Private Type TTestType
+ FirstValue As Long
+ SecondValue As Variant
+End Type
+
+Private Enum ETestType
+ EFirstValue = 0
+ ESecondValue
+End Enum
+
+Public Enum ETestType2
+ EThirdValue = 0
+ EFourthValue
+End Enum
+
+Private fizz As Integer
+
+Private fazz As ETestType
+
+Private fuzz As ETestType2
+";
+ var result = ParseAndTest(inputCode,
+ targetIdentifier,
+ declarationType,
+ testParams,
+ PropertyGetBlockFromPrototypeTest);
+
+ StringAssert.Contains($"Property Get {testParams.Identifier}() As {typeName}", result);
+ }
+
+ [TestCase("fizz", DeclarationType.Variable, "Integer", "Public")]
+ [TestCase("FirstValue", DeclarationType.UserDefinedTypeMember, "Long", "Public")]
+ [TestCase("fazz", DeclarationType.Variable, "Long", "Public")]
+ [TestCase("fuzz", DeclarationType.Variable, "ETestType2", "Private")]
+ [Category(nameof(CodeBuilder))]
+ public void PropertyBlockFromPrototype_PropertyGetAccessibility(string targetIdentifier, DeclarationType declarationType, string typeName, string accessibility)
+ {
+ var testParams = new PropertyBlockFromPrototypeParams("Bazz", DeclarationType.PropertyGet, accessibility);
+ string inputCode =
+$@"
+
+Private Type TTestType
+ FirstValue As Long
+ SecondValue As Variant
+End Type
+
+Private Enum ETestType
+ EFirstValue = 0
+ ESecondValue
+End Enum
+
+Public Enum ETestType2
+ EThirdValue = 0
+ EFourthValue
+End Enum
+
+Private fizz As Integer
+
+Private fazz As ETestType
+
+Private fuzz As ETestType2
+";
+ var result = ParseAndTest(inputCode,
+ targetIdentifier,
+ declarationType,
+ testParams,
+ PropertyGetBlockFromPrototypeTest);
+
+ StringAssert.Contains($"{accessibility} Property Get {testParams.Identifier}() As {typeName}", result);
+ }
+
+ [TestCase("fizz", DeclarationType.Variable, "Integer", "Bazz = fizz")]
+ [TestCase("FirstValue", DeclarationType.UserDefinedTypeMember, "Long", "Bazz = fozz.FirstValue")]
+ [TestCase("fazz", DeclarationType.Variable, "Long", "Bazz = fazz")]
+ [TestCase("fuzz", DeclarationType.Variable, "TTestType2", "Bazz = fuzz")]
+ [Category(nameof(CodeBuilder))]
+ public void PropertyBlockFromPrototype_PropertyGetContent(string targetIdentifier, DeclarationType declarationType, string typeName, string content)
+ {
+ var testParams = new PropertyBlockFromPrototypeParams("Bazz", DeclarationType.PropertyGet, content: content);
+ string inputCode =
+$@"
+
+Private Type TTestType
+ FirstValue As Long
+ SecondValue As Variant
+End Type
+
+Private Enum ETestType
+ EFirstValue = 0
+ ESecondValue
+End Enum
+
+Public Enum ETestType2
+ EThirdValue = 0
+ EFourthValue
+End Enum
+
+Private fizz As Integer
+
+Private fozz As TTestType
+
+Private fazz As ETestType
+
+Private fuzz As TTestType2
+";
+ var result = ParseAndTest(inputCode,
+ targetIdentifier,
+ declarationType,
+ testParams,
+ PropertyGetBlockFromPrototypeTest);
+
+ StringAssert.Contains(content, result);
+ }
+
+
+ [TestCase("fizz", DeclarationType.Variable, "Integer", "Bazz = fizz")]
+ [Category(nameof(CodeBuilder))]
+ public void PropertyBlockFromPrototype_PropertyGetChangeParamName(string targetIdentifier, DeclarationType declarationType, string typeName, string content)
+ {
+ var testParams = new PropertyBlockFromPrototypeParams("Bazz", DeclarationType.PropertyGet, paramIdentifier: "testParam");
+ string inputCode =
+$@"
+Private fizz As Integer
+";
+ var result = ParseAndTest(inputCode,
+ targetIdentifier,
+ declarationType,
+ testParams,
+ PropertyGetBlockFromPrototypeTest);
+
+ StringAssert.Contains("Property Get Bazz() As Integer", result);
+ }
+
+ [TestCase("fizz", DeclarationType.Variable, "Integer")]
+ [TestCase("FirstValue", DeclarationType.UserDefinedTypeMember, "Long")]
+ [TestCase("fazz", DeclarationType.Variable, "Long")]
+ [TestCase("fuzz", DeclarationType.Variable, "ETestType2")]
+ [Category(nameof(CodeBuilder))]
+ public void PropertyBlockFromPrototype_PropertyLet(string targetIdentifier, DeclarationType declarationType, string typeName)
+ {
+ var testParams = new PropertyBlockFromPrototypeParams("Bazz", DeclarationType.PropertyLet);
+ string inputCode =
+$@"
+
+Private Type TTestType
+ FirstValue As Long
+ SecondValue As Variant
+End Type
+
+Private Enum ETestType
+ EFirstValue = 0
+ ESecondValue
+End Enum
+
+Public Enum ETestType2
+ EThirdValue = 0
+ EFourthValue
+End Enum
+
+Private fizz As Integer
+
+Private fazz As ETestType
+
+Private fuzz As ETestType2
+";
+ var result = ParseAndTest(inputCode,
+ targetIdentifier,
+ declarationType,
+ testParams,
+ PropertyLetBlockFromPrototypeTest);
+
+ StringAssert.Contains($"Property Let {testParams.Identifier}(ByVal value As {typeName})", result);
+ }
+
+ [TestCase("fizz", DeclarationType.Variable, "Variant")]
+ [TestCase("SecondValue", DeclarationType.UserDefinedTypeMember, "Variant")]
+ [Category(nameof(CodeBuilder))]
+ public void PropertyBlockFromPrototype_PropertySet(string targetIdentifier, DeclarationType declarationType, string typeName)
+ {
+ var testParams = new PropertyBlockFromPrototypeParams("Bazz", DeclarationType.PropertySet);
+ string inputCode =
+$@"
+
+Private Type TTestType
+ FirstValue As Long
+ SecondValue As Variant
+End Type
+
+Private fizz As Variant
+
+";
+ var result = ParseAndTest(inputCode,
+ targetIdentifier,
+ declarationType,
+ testParams,
+ PropertySetBlockFromPrototypeTest);
+
+ StringAssert.Contains($"Property Set {testParams.Identifier}(ByVal value As {typeName})", result);
+ }
+
+ [TestCase(DeclarationType.PropertyLet)]
+ [TestCase(DeclarationType.PropertySet)]
+ [TestCase(DeclarationType.Procedure)]
+ [Category(nameof(CodeBuilder))]
+ public void MemberBlockFromPrototype_AppliesByVal(DeclarationType declarationType)
+ {
+ var procedureIdentifier = "TestProcedure";
+ var procType = ProcedureTypeIdentifier(declarationType);
+
+ string inputCode =
+$@"
+Public {procType.procType} {procedureIdentifier}(arg1 As Long, arg2 As String)
+End {procType.endStmt}
+";
+ var result = ParseAndTest(inputCode,
+ procedureIdentifier,
+ declarationType,
+ new MemberBlockFromPrototypeTestParams(),
+ MemberBlockFromPrototypeTest);
+
+ var expected = declarationType.HasFlag(DeclarationType.Property)
+ ? "(arg1 As Long, ByVal arg2 As String)"
+ : "(arg1 As Long, arg2 As String)";
+
+ StringAssert.Contains($"{procType.procType} {procedureIdentifier}{expected}", result);
+ }
+
+ [TestCase(DeclarationType.PropertyLet)]
+ [TestCase(DeclarationType.PropertySet)]
+ [TestCase(DeclarationType.Procedure)]
+ [Category(nameof(CodeBuilder))]
+ public void ImprovedArgumentList_AppliesByVal(DeclarationType declarationType)
+ {
+ var procedureIdentifier = "TestProperty";
+ var procType = ProcedureTypeIdentifier(declarationType);
+
+ string inputCode =
+$@"
+Public {procType.procType} {procedureIdentifier}(arg1 As Long, arg2 As String)
+End {procType.endStmt}
+";
+ var result = ParseAndTest(inputCode,
+ procedureIdentifier,
+ declarationType,
+ ImprovedArgumentListTest);
+
+ var expected = declarationType.HasFlag(DeclarationType.Property)
+ ? "arg1 As Long, ByVal arg2 As String"
+ : "arg1 As Long, arg2 As String";
+
+ StringAssert.AreEqualIgnoringCase(expected, result);
+ }
+
+
+ [TestCase(DeclarationType.PropertyGet)]
+ [TestCase(DeclarationType.Function)]
+ [Category(nameof(CodeBuilder))]
+ public void ImprovedArgumentList_FunctionTypes(DeclarationType declarationType)
+ {
+ var procedureIdentifier = "TestProperty";
+ var procType = ProcedureTypeIdentifier(declarationType);
+
+ string inputCode =
+$@"
+Public {procType.procType} {procedureIdentifier}(arg1 As Long, arg2 As String) As Long
+End {procType.endStmt}
+";
+ var result = ParseAndTest(inputCode,
+ procedureIdentifier,
+ declarationType,
+ ImprovedArgumentListTest);
+
+ StringAssert.AreEqualIgnoringCase($"arg1 As Long, arg2 As String", result);
+ }
+
+ private string ParseAndTest(string inputCode, string targetIdentifier, DeclarationType declarationType, Func theTest)
+ {
+ var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object;
+ var state = MockParser.CreateAndParse(vbe);
+ using (state)
+ {
+ var target = state.DeclarationFinder.DeclarationsWithType(declarationType)
+ .Where(d => d.IdentifierName == targetIdentifier).OfType()
+ .Single();
+ return theTest(target);
+ }
+ }
+
+ private string ParseAndTest(string inputCode, string targetIdentifier, DeclarationType declarationType, MemberBlockFromPrototypeTestParams testParams, Func theTest)
+ {
+ var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object;
+ var state = MockParser.CreateAndParse(vbe);
+ using (state)
+ {
+ var target = state.DeclarationFinder.DeclarationsWithType(declarationType)
+ .Where(d => d.IdentifierName == targetIdentifier).OfType()
+ .Single();
+ return theTest(target, testParams);
+ }
+ }
+
+ private string ParseAndTest(string inputCode, string targetIdentifier, DeclarationType declarationType, PropertyBlockFromPrototypeParams testParams, Func theTest)
+ {
+ var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object;
+ var state = MockParser.CreateAndParse(vbe);
+ using (state)
+ {
+ var target = state.DeclarationFinder.DeclarationsWithType(declarationType)
+ .Where(d => d.IdentifierName == targetIdentifier).OfType()
+ .Single();
+ return theTest(target, testParams);
+ }
+ }
+
+ private static string PropertyGetBlockFromPrototypeTest(T target, PropertyBlockFromPrototypeParams testParams) where T : Declaration
+ {
+ new CodeBuilder().TryBuildPropertyGetCodeBlock(target, testParams.Identifier, out string result, testParams.Accessibility, testParams.Content); //, testParams.WriteParam);
+ return result;
+ }
+
+ private static string PropertyLetBlockFromPrototypeTest(T target, PropertyBlockFromPrototypeParams testParams) where T : Declaration
+ {
+ new CodeBuilder().TryBuildPropertyLetCodeBlock(target, testParams.Identifier, out string result, testParams.Accessibility, testParams.Content, testParams.WriteParam);
+ return result;
+ }
+
+ private static string PropertySetBlockFromPrototypeTest(T target, PropertyBlockFromPrototypeParams testParams) where T : Declaration
+ {
+ new CodeBuilder().TryBuildPropertySetCodeBlock(target, testParams.Identifier, out string result, testParams.Accessibility, testParams.Content, testParams.WriteParam);
+ return result;
+ }
+
+ private static string ImprovedArgumentListTest(ModuleBodyElementDeclaration mbed)
+ => new CodeBuilder().ImprovedArgumentList(mbed);
+
+ private static string MemberBlockFromPrototypeTest(ModuleBodyElementDeclaration mbed, MemberBlockFromPrototypeTestParams testParams)
+ => new CodeBuilder().BuildMemberBlockFromPrototype(mbed, testParams.Accessibility, testParams.Content, testParams.NewIdentifier);
+
+ private (string procType, string endStmt) ProcedureTypeIdentifier(DeclarationType declarationType)
+ {
+ switch (declarationType)
+ {
+ case DeclarationType.Function:
+ return ("Function", "Function");
+ case DeclarationType.Procedure:
+ return ("Sub", "Sub");
+ case DeclarationType.PropertyGet:
+ return ("Property Get", "Property");
+ case DeclarationType.PropertyLet:
+ return ("Property Let", "Property");
+ case DeclarationType.PropertySet:
+ return ("Property Set", "Property");
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+
+ private struct PropertyBlockFromPrototypeParams
+ {
+ public PropertyBlockFromPrototypeParams(string identifier, DeclarationType propertyType, string accessibility = null, string content = null, string paramIdentifier = null)
+ {
+ Identifier = identifier;
+ DeclarationType = propertyType;
+ Accessibility = accessibility;
+ Content = content;
+ WriteParam = paramIdentifier;
+ }
+ public DeclarationType DeclarationType { get; }
+ public string Identifier { get; }
+ public string Accessibility {get; }
+ public string Content { get; }
+ public string WriteParam { get; }
+ }
+
+ private struct MemberBlockFromPrototypeTestParams
+ {
+ public MemberBlockFromPrototypeTestParams(ModuleBodyElementDeclaration mbed, string accessibility = null, string content = null, string newIdentifier = null)
+ {
+ Accessibility = accessibility;
+ Content = content;
+ NewIdentifier = newIdentifier;
+ }
+
+ public string Accessibility { get; }
+ public string Content { get; }
+ public string NewIdentifier { get; }
+ }
+ }
+}
diff --git a/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs b/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs
index 0eab0cae07..f37cfef86f 100644
--- a/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs
+++ b/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs
@@ -34,6 +34,7 @@
using Rubberduck.VBEditor.SourceCodeHandling;
using Rubberduck.VBEditor.Utility;
using RubberduckTests.Settings;
+using Rubberduck.Refactorings;
namespace RubberduckTests.CodeExplorer
{
@@ -506,12 +507,12 @@ public MockedCodeExplorer ImplementIndenterCommand()
public MockedCodeExplorer ImplementExtractInterfaceCommand()
{
- var addImplementationsBaseRefactoring = new AddInterfaceImplementationsRefactoringAction(null);
+ var addImplementationsBaseRefactoring = new AddInterfaceImplementationsRefactoringAction(null, new CodeBuilder());
var addComponentService = TestAddComponentService(State.ProjectsProvider);
var extractInterfaceBaseRefactoring = new ExtractInterfaceRefactoringAction(addImplementationsBaseRefactoring, State, State, null, State.ProjectsProvider, addComponentService);
var userInteraction = new RefactoringUserInteraction(null, _uiDispatcher.Object);
ViewModel.CodeExplorerExtractInterfaceCommand = new CodeExplorerExtractInterfaceCommand(
- new ExtractInterfaceRefactoring(extractInterfaceBaseRefactoring, State, userInteraction, null),
+ new ExtractInterfaceRefactoring(extractInterfaceBaseRefactoring, State, userInteraction, null, new CodeBuilder()),
State, null, VbeEvents.Object);
return this;
}
diff --git a/RubberduckTests/Commands/RefactorCommands/EncapsulateFieldCommandTests.cs b/RubberduckTests/Commands/RefactorCommands/EncapsulateFieldCommandTests.cs
index 24f9382554..2d9a377960 100644
--- a/RubberduckTests/Commands/RefactorCommands/EncapsulateFieldCommandTests.cs
+++ b/RubberduckTests/Commands/RefactorCommands/EncapsulateFieldCommandTests.cs
@@ -64,7 +64,7 @@ protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state
.Setup(m => m.Invoke(It.IsAny()))
.Callback((Action action) => action.Invoke());
var userInteraction = new RefactoringUserInteraction(factory, uiDispatcherMock.Object);
- var refactoring = new EncapsulateFieldRefactoring(state, null, userInteraction, rewritingManager, selectionService, selectedDeclarationProvider);
+ var refactoring = new EncapsulateFieldRefactoring(state, null, userInteraction, rewritingManager, selectionService, selectedDeclarationProvider, new CodeBuilder());
var notifier = new EncapsulateFieldFailedNotifier(msgBox);
var selectedDeclarationService = new SelectedDeclarationProvider(selectionService, state);
return new RefactorEncapsulateFieldCommand(refactoring, notifier, state, selectionService, selectedDeclarationService);
diff --git a/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs b/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs
index 40537193b9..d0678ec0bf 100644
--- a/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs
+++ b/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs
@@ -173,11 +173,11 @@ protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state
uiDispatcherMock
.Setup(m => m.Invoke(It.IsAny()))
.Callback((Action action) => action.Invoke());
- var addImplementationsBaseRefactoring = new AddInterfaceImplementationsRefactoringAction(rewritingManager);
+ var addImplementationsBaseRefactoring = new AddInterfaceImplementationsRefactoringAction(rewritingManager, new CodeBuilder());
var addComponentService = TestAddComponentService(state.ProjectsProvider);
var baseRefactoring = new ExtractInterfaceRefactoringAction(addImplementationsBaseRefactoring, state, state, rewritingManager, state.ProjectsProvider, addComponentService);
var userInteraction = new RefactoringUserInteraction(factory, uiDispatcherMock.Object);
- var refactoring = new ExtractInterfaceRefactoring(baseRefactoring, state, userInteraction, selectionService);
+ var refactoring = new ExtractInterfaceRefactoring(baseRefactoring, state, userInteraction, selectionService, new CodeBuilder());
var notifier = new ExtractInterfaceFailedNotifier(msgBox);
return new RefactorExtractInterfaceCommand(refactoring, notifier, state, selectionService);
}
diff --git a/RubberduckTests/Commands/RefactorCommands/ImplementInterfaceCommandTests.cs b/RubberduckTests/Commands/RefactorCommands/ImplementInterfaceCommandTests.cs
index a37e3cea0f..aa5d7590f7 100644
--- a/RubberduckTests/Commands/RefactorCommands/ImplementInterfaceCommandTests.cs
+++ b/RubberduckTests/Commands/RefactorCommands/ImplementInterfaceCommandTests.cs
@@ -3,6 +3,7 @@
using Rubberduck.Interaction;
using Rubberduck.Parsing.Rewriter;
using Rubberduck.Parsing.VBA;
+using Rubberduck.Refactorings;
using Rubberduck.Refactorings.AddInterfaceImplementations;
using Rubberduck.Refactorings.ImplementInterface;
using Rubberduck.UI.Command;
@@ -57,7 +58,7 @@ public void ImplementInterface_CanExecute_ImplementsInterfaceSelected()
protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state, IRewritingManager rewritingManager, ISelectionService selectionService)
{
var msgBox = new Mock().Object;
- var addImplementationsBaseRefactoring = new AddInterfaceImplementationsRefactoringAction(rewritingManager);
+ var addImplementationsBaseRefactoring = new AddInterfaceImplementationsRefactoringAction(rewritingManager, new CodeBuilder());
var baseRefactoring = new ImplementInterfaceRefactoringAction(addImplementationsBaseRefactoring, rewritingManager);
var refactoring = new ImplementInterfaceRefactoring(baseRefactoring, state, selectionService);
var notifier = new ImplementInterfaceFailedNotifier(msgBox);
diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFIeldTestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFIeldTestSupport.cs
index 82ed2fa073..b7878733e0 100644
--- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFIeldTestSupport.cs
+++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFIeldTestSupport.cs
@@ -119,7 +119,7 @@ public string RefactoredCode(CodeString codeString, Func()
.Single(module => module.IdentifierName == "Class");
- var model = new ExtractInterfaceModel(state, targetClass);
+ var model = new ExtractInterfaceModel(state, targetClass, new CodeBuilder());
return modelAdjustment(model);
}
protected override IRefactoringAction TestBaseRefactoring(RubberduckParserState state, IRewritingManager rewritingManager)
{
- var addInterfaceImplementationsAction = new AddInterfaceImplementationsRefactoringAction(rewritingManager);
+ var addInterfaceImplementationsAction = new AddInterfaceImplementationsRefactoringAction(rewritingManager, new CodeBuilder());
var addComponentService = TestAddComponentService(state?.ProjectsProvider);
return new ExtractInterfaceRefactoringAction(addInterfaceImplementationsAction, state, state, rewritingManager, state?.ProjectsProvider, addComponentService);
}
diff --git a/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceTests.cs b/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceTests.cs
index 6f19d1b5ea..47970b8836 100644
--- a/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceTests.cs
+++ b/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceTests.cs
@@ -150,7 +150,7 @@ public void ExtractInterfaceRefactoring_IgnoresField()
.First();
//Specify Params to remove
- var model = new ExtractInterfaceModel(state, target);
+ var model = new ExtractInterfaceModel(state, target, new CodeBuilder());
Assert.AreEqual(0, model.Members.Count);
}
}
@@ -178,7 +178,7 @@ public void ExtractInterfaceRefactoring_DefaultsToPublicInterfaceForExposedImple
.First();
//Specify Params to remove
- var model = new ExtractInterfaceModel(state, target);
+ var model = new ExtractInterfaceModel(state, target, new CodeBuilder());
Assert.AreEqual(ClassInstancing.Public, model.InterfaceInstancing);
}
}
@@ -204,7 +204,7 @@ public void ExtractInterfaceRefactoring_DefaultsToPrivateInterfaceForNonExposedI
.First();
//Specify Params to remove
- var model = new ExtractInterfaceModel(state, target);
+ var model = new ExtractInterfaceModel(state, target, new CodeBuilder());
Assert.AreEqual(ClassInstancing.Private, model.InterfaceInstancing);
}
}
@@ -309,10 +309,10 @@ End Sub
RefactoringUserInteraction userInteraction,
ISelectionService selectionService)
{
- var addImplementationsBaseRefactoring = new AddInterfaceImplementationsRefactoringAction(rewritingManager);
+ var addImplementationsBaseRefactoring = new AddInterfaceImplementationsRefactoringAction(rewritingManager, new CodeBuilder());
var addComponentService = TestAddComponentService(state?.ProjectsProvider);
var baseRefactoring = new ExtractInterfaceRefactoringAction(addImplementationsBaseRefactoring, state, state, rewritingManager, state?.ProjectsProvider, addComponentService);
- return new ExtractInterfaceRefactoring(baseRefactoring, state, userInteraction, selectionService);
+ return new ExtractInterfaceRefactoring(baseRefactoring, state, userInteraction, selectionService, new CodeBuilder());
}
private static IAddComponentService TestAddComponentService(IProjectsProvider projectsProvider)
diff --git a/RubberduckTests/Refactoring/ImplementInterface/ImplementInterfaceRefactoringActionTests.cs b/RubberduckTests/Refactoring/ImplementInterface/ImplementInterfaceRefactoringActionTests.cs
index 9ee9ca8c9f..f807a1cbc0 100644
--- a/RubberduckTests/Refactoring/ImplementInterface/ImplementInterfaceRefactoringActionTests.cs
+++ b/RubberduckTests/Refactoring/ImplementInterface/ImplementInterfaceRefactoringActionTests.cs
@@ -772,7 +772,7 @@ private static ImplementInterfaceModel TestModel(RubberduckParserState state)
protected override IRefactoringAction TestBaseRefactoring(RubberduckParserState state, IRewritingManager rewritingManager)
{
- var addInterfaceImplementationsAction = new AddInterfaceImplementationsRefactoringAction(rewritingManager);
+ var addInterfaceImplementationsAction = new AddInterfaceImplementationsRefactoringAction(rewritingManager, new CodeBuilder());
return new ImplementInterfaceRefactoringAction(addInterfaceImplementationsAction, rewritingManager);
}
}
diff --git a/RubberduckTests/Refactoring/ImplementInterface/ImplementInterfaceTests.cs b/RubberduckTests/Refactoring/ImplementInterface/ImplementInterfaceTests.cs
index 01c271821c..aefaaa1aac 100644
--- a/RubberduckTests/Refactoring/ImplementInterface/ImplementInterfaceTests.cs
+++ b/RubberduckTests/Refactoring/ImplementInterface/ImplementInterfaceTests.cs
@@ -217,7 +217,7 @@ End Sub
protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state,
ISelectionService selectionService)
{
- var addImplementationsBaseRefactoring = new AddInterfaceImplementationsRefactoringAction(rewritingManager);
+ var addImplementationsBaseRefactoring = new AddInterfaceImplementationsRefactoringAction(rewritingManager, new CodeBuilder());
var baseRefactoring = new ImplementInterfaceRefactoringAction(addImplementationsBaseRefactoring, rewritingManager);
return new ImplementInterfaceRefactoring(baseRefactoring, state, selectionService);
}