From 9598b1e491b0d07c3bcc0bab12ef41812df707e4 Mon Sep 17 00:00:00 2001 From: IvenBach Date: Wed, 28 Aug 2019 13:43:06 -0700 Subject: [PATCH 001/461] Add (Un|I)gnoreSelectedGroupCommand to context menu --- .../UI/UnitTesting/TestExplorerControl.xaml | 15 +++++++ .../UI/UnitTesting/TestExplorerViewModel.cs | 44 ++++++++++++++++++- .../UnitTesting/TestExplorer.Designer.cs | 18 ++++++++ .../UnitTesting/TestExplorer.resx | 6 +++ 4 files changed, 81 insertions(+), 2 deletions(-) diff --git a/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml b/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml index 1a6b946668..38d9aa18cb 100644 --- a/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml +++ b/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml @@ -57,6 +57,9 @@ + + + @@ -451,6 +454,18 @@ + + + + + + + + + + diff --git a/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs b/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs index ba5a44f266..3a0e31339b 100644 --- a/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs +++ b/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs @@ -73,6 +73,8 @@ public TestExplorerViewModel(ISelectionService selectionService, ExpandAllCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteExpandAll); IgnoreTestCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteIgnoreTestCommand); UnignoreTestCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteUnignoreTestCommand); + IgnoreSelectedGroupCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteIgnoreGroupCommand, CanIgnoreSelectedGroupCommand); + UnignoreSelectedGroupCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteUnignoreGroupCommand, CanUnignoreSelectedGroupCommand); RewritingManager = rewritingManager; AnnotationUpdater = annotationUpdater; @@ -275,6 +277,9 @@ private void HandleTestCompletion(object sender, TestCompletedEventArgs e) public CommandBase IgnoreTestCommand { get; } public CommandBase UnignoreTestCommand { get; } + public CommandBase IgnoreSelectedGroupCommand { get; } + public CommandBase UnignoreSelectedGroupCommand { get; } + #endregion #region Delegates @@ -294,6 +299,16 @@ private bool CanExecuteSelectedGroupCommand(object obj) return !Model.IsBusy && (MouseOverTest != null || MouseOverGroup != null); } + private bool CanIgnoreSelectedGroupCommand(object obj) + { + return CanExecuteSelectedGroupCommand(obj); + } + + private bool CanUnignoreSelectedGroupCommand(object obj) + { + return CanExecuteSelectedGroupCommand(obj); + } + private bool CanExecuteResetResultsCommand(object obj) { return !Model.IsBusy && Tests.OfType().Any(test => test.Result.Outcome != TestOutcome.Unknown); @@ -374,7 +389,11 @@ private void ExecuteIgnoreTestCommand(object parameter) { var rewriteSession = RewritingManager.CheckOutCodePaneSession(); - AnnotationUpdater.AddAnnotation(rewriteSession, _mousedOverTestMethod.Declaration, Parsing.Annotations.AnnotationType.IgnoreTest); + var testMethod = parameter == null + ? _mousedOverTestMethod + : (parameter as TestMethodViewModel).Method; + + AnnotationUpdater.AddAnnotation(rewriteSession, testMethod.Declaration, Parsing.Annotations.AnnotationType.IgnoreTest); rewriteSession.TryRewrite(); } @@ -382,7 +401,12 @@ private void ExecuteIgnoreTestCommand(object parameter) private void ExecuteUnignoreTestCommand(object parameter) { var rewriteSession = RewritingManager.CheckOutCodePaneSession(); - var ignoreTestAnnotations = _mousedOverTestMethod.Declaration.Annotations + + var testMethod = parameter == null + ? _mousedOverTestMethod + : (parameter as TestMethodViewModel).Method; + + var ignoreTestAnnotations = testMethod.Declaration.Annotations .Where(iannotations => iannotations.AnnotationType == Parsing.Annotations.AnnotationType.IgnoreTest); foreach (var ignoreTestAnnotation in ignoreTestAnnotations) @@ -393,6 +417,22 @@ private void ExecuteUnignoreTestCommand(object parameter) rewriteSession.TryRewrite(); } + private void ExecuteIgnoreGroupCommand (object parameter) + { + foreach (TestMethodViewModel test in _mouseOverGroup.Items) + { + ExecuteIgnoreTestCommand(test); + } + } + + private void ExecuteUnignoreGroupCommand(object parameter) + { + foreach (TestMethodViewModel test in _mouseOverGroup.Items) + { + ExecuteUnignoreTestCommand(test); + } + } + private void ExecuteCopyResultsCommand(object parameter) { const string XML_SPREADSHEET_DATA_FORMAT = "XML Spreadsheet"; diff --git a/Rubberduck.Resources/UnitTesting/TestExplorer.Designer.cs b/Rubberduck.Resources/UnitTesting/TestExplorer.Designer.cs index 4ee76f82d8..ab492f53e1 100644 --- a/Rubberduck.Resources/UnitTesting/TestExplorer.Designer.cs +++ b/Rubberduck.Resources/UnitTesting/TestExplorer.Designer.cs @@ -123,6 +123,15 @@ public static string TestExplorer_CategoryName { } } + /// + /// Looks up a localized string similar to Ignore all tests in group. + /// + public static string TestExplorer_ContextMenuIgnoreGroup { + get { + return ResourceManager.GetString("TestExplorer_ContextMenuIgnoreGroup", resourceCulture); + } + } + /// /// Looks up a localized string similar to Run all tests. /// @@ -159,6 +168,15 @@ public static string TestExplorer_ContextMenuRunSingle { } } + /// + /// Looks up a localized string similar to Unignore all tests in group. + /// + public static string TestExplorer_ContextMenuUnignoreGroup { + get { + return ResourceManager.GetString("TestExplorer_ContextMenuUnignoreGroup", resourceCulture); + } + } + /// /// Looks up a localized string similar to Duration. /// diff --git a/Rubberduck.Resources/UnitTesting/TestExplorer.resx b/Rubberduck.Resources/UnitTesting/TestExplorer.resx index 9986de320d..4b7e80f173 100644 --- a/Rubberduck.Resources/UnitTesting/TestExplorer.resx +++ b/Rubberduck.Resources/UnitTesting/TestExplorer.resx @@ -351,4 +351,10 @@ Unignore test + + Ignore all tests in group + + + Unignore all tests in group + \ No newline at end of file From 82b5bbfe2fdfed81cd216d115a7fc3c04e72eedc Mon Sep 17 00:00:00 2001 From: IvenBach Date: Wed, 28 Aug 2019 14:56:05 -0700 Subject: [PATCH 002/461] Correct (Uni|I)gnoreSelectedGroup command behavior --- .../UI/UnitTesting/TestExplorerViewModel.cs | 52 +++++++++++++------ 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs b/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs index 3a0e31339b..dc64e241cb 100644 --- a/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs +++ b/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs @@ -358,9 +358,10 @@ private void ExecuteSelectedTestsCommand(object obj) private void ExecuteRunSelectedGroupCommand(object obj) { - var tests = MouseOverTest is null - ? MouseOverGroup - : Tests.Groups.OfType().FirstOrDefault(group => group.Items.Contains(MouseOverTest)); + //var tests = MouseOverTest is null + // ? MouseOverGroup + // : Tests.Groups.OfType().FirstOrDefault(group => group.Items.Contains(MouseOverTest)); + var tests = GroupContainingSelectedTest(MouseOverTest); if (tests is null) { @@ -370,6 +371,13 @@ private void ExecuteRunSelectedGroupCommand(object obj) Model.ExecuteTests(tests.Items.OfType().ToList()); } + private CollectionViewGroup GroupContainingSelectedTest(TestMethodViewModel selectedTest) + { + return selectedTest is null + ? MouseOverGroup + : Tests.Groups.OfType().FirstOrDefault(group => group.Items.Contains(selectedTest)); + } + private void ExecuteCancelTestRunCommand(object parameter) { Model.CancelTestRun(); @@ -389,11 +397,7 @@ private void ExecuteIgnoreTestCommand(object parameter) { var rewriteSession = RewritingManager.CheckOutCodePaneSession(); - var testMethod = parameter == null - ? _mousedOverTestMethod - : (parameter as TestMethodViewModel).Method; - - AnnotationUpdater.AddAnnotation(rewriteSession, testMethod.Declaration, Parsing.Annotations.AnnotationType.IgnoreTest); + AnnotationUpdater.AddAnnotation(rewriteSession, _mousedOverTestMethod.Declaration, Parsing.Annotations.AnnotationType.IgnoreTest); rewriteSession.TryRewrite(); } @@ -401,12 +405,8 @@ private void ExecuteIgnoreTestCommand(object parameter) private void ExecuteUnignoreTestCommand(object parameter) { var rewriteSession = RewritingManager.CheckOutCodePaneSession(); - - var testMethod = parameter == null - ? _mousedOverTestMethod - : (parameter as TestMethodViewModel).Method; - var ignoreTestAnnotations = testMethod.Declaration.Annotations + var ignoreTestAnnotations = _mousedOverTestMethod.Declaration.Annotations .Where(iannotations => iannotations.AnnotationType == Parsing.Annotations.AnnotationType.IgnoreTest); foreach (var ignoreTestAnnotation in ignoreTestAnnotations) @@ -419,18 +419,36 @@ private void ExecuteUnignoreTestCommand(object parameter) private void ExecuteIgnoreGroupCommand (object parameter) { - foreach (TestMethodViewModel test in _mouseOverGroup.Items) + var rewriteSession = RewritingManager.CheckOutCodePaneSession(); + var testGroup = GroupContainingSelectedTest(MouseOverTest); + foreach (TestMethodViewModel test in testGroup.Items) { - ExecuteIgnoreTestCommand(test); + // var testMethod = parameter == null + // ? _mousedOverTestMethod + // : (parameter as TestMethodViewModel).Method; + AnnotationUpdater.AddAnnotation(rewriteSession, test.Method.Declaration, Parsing.Annotations.AnnotationType.IgnoreTest); } + + rewriteSession.TryRewrite(); } private void ExecuteUnignoreGroupCommand(object parameter) { - foreach (TestMethodViewModel test in _mouseOverGroup.Items) + var rewriteSession = RewritingManager.CheckOutCodePaneSession(); + var testGroup = GroupContainingSelectedTest(MouseOverTest); + foreach (TestMethodViewModel test in testGroup.Items) { - ExecuteUnignoreTestCommand(test); + //ExecuteUnignoreTestCommand(test); + var ignoreTestAnnotations = test.Method.Declaration.Annotations + .Where(iannotations => iannotations.AnnotationType == Parsing.Annotations.AnnotationType.IgnoreTest); + + foreach (var ignoreTestAnnotation in ignoreTestAnnotations) + { + AnnotationUpdater.RemoveAnnotation(rewriteSession, ignoreTestAnnotation); + } } + + rewriteSession.TryRewrite(); } private void ExecuteCopyResultsCommand(object parameter) From c1ccd841771d9427e92d910ac28d9792e9109445 Mon Sep 17 00:00:00 2001 From: IvenBach Date: Wed, 28 Aug 2019 16:37:04 -0700 Subject: [PATCH 003/461] Use auto property --- Rubberduck.Parsing/Symbols/Declaration.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Rubberduck.Parsing/Symbols/Declaration.cs b/Rubberduck.Parsing/Symbols/Declaration.cs index 43f73a78d6..c04e0e6ce4 100644 --- a/Rubberduck.Parsing/Symbols/Declaration.cs +++ b/Rubberduck.Parsing/Symbols/Declaration.cs @@ -132,7 +132,7 @@ public Declaration( AttributesPassContext = attributesPassContext; IsUserDefined = isUserDefined; _annotations = annotations; - _attributes = attributes ?? new Attributes(); + Attributes = attributes ?? new Attributes(); ProjectId = QualifiedName.QualifiedModuleName.ProjectId; var projectDeclaration = GetProjectParent(parentDeclaration); @@ -277,9 +277,7 @@ public static Declaration GetProjectParent(Declaration declaration) protected IEnumerable _annotations; public IEnumerable Annotations => _annotations ?? new List(); - - private readonly Attributes _attributes; - public Attributes Attributes => _attributes; + public Attributes Attributes { get; } /// /// Gets an attribute value that contains the docstring for a member. @@ -290,14 +288,14 @@ public string DescriptionString { string literalDescription; - var memberAttribute = _attributes.SingleOrDefault(a => a.Name == $"{IdentifierName}.VB_Description"); + var memberAttribute = Attributes.SingleOrDefault(a => a.Name == $"{IdentifierName}.VB_Description"); if (memberAttribute != null) { literalDescription = memberAttribute.Values.SingleOrDefault() ?? string.Empty; return CorrectlyFormatedDescription(literalDescription); } - var moduleAttribute = _attributes.SingleOrDefault(a => a.Name == "VB_Description"); + var moduleAttribute = Attributes.SingleOrDefault(a => a.Name == "VB_Description"); if (moduleAttribute != null) { literalDescription = moduleAttribute.Values.SingleOrDefault() ?? string.Empty; @@ -327,7 +325,7 @@ private static string CorrectlyFormatedDescription(string literalDescription) /// Gets an attribute value indicating whether a member is an enumerator provider. /// Types with such a member support For Each iteration. /// - public bool IsEnumeratorMember => _attributes.Any(a => a.Name.EndsWith("VB_UserMemId") && a.Values.Contains("-4")); + public bool IsEnumeratorMember => Attributes.Any(a => a.Name.EndsWith("VB_UserMemId") && a.Values.Contains("-4")); public virtual bool IsObject => !IsArray && IsObjectOrObjectArray; From 2fe0094d91cdc81fa622dfda66bdd0729ea65937 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Fri, 1 Nov 2019 11:54:17 -0700 Subject: [PATCH 004/461] Initial Changes Model can now host multiple encapsulation targets in preparation for encapsulating UDT members. --- .../EncapsulateField/EncapsulateFieldModel.cs | 212 ++++++++++++++---- .../EncapsulateFieldRefactoring.cs | 150 ++++++++++--- .../Refactoring/EncapsulateFieldTests.cs | 152 ++++--------- 3 files changed, 335 insertions(+), 179 deletions(-) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index b5f8e7bb2e..b04c10c8dc 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System.Collections.Generic; +using System.Linq; using Antlr4.Runtime; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; @@ -6,24 +7,58 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public class EncapsulateFieldModel : IRefactoringModel + public interface IEncapsulateField { - public EncapsulateFieldModel(Declaration target) + Declaration TargetDeclaration { get; set; } + string PropertyName { get; } + string ParameterName { get; } + bool ImplementLetSetterType { get;} + bool ImplementSetSetterType { get;} + + bool CanImplementLet { get; } + bool CanImplementSet { get; } + } + + public interface IEncapsulateUDTMember : IEncapsulateField + { + bool Encapsulate { set; get; } + } + + public interface IEncapsulateFieldModel + { + IEnumerable EncapsulationTargets { get; } + } + + public struct EncapsulateFieldConfig : IEncapsulateField + { + public EncapsulateFieldConfig(Declaration target) { TargetDeclaration = target; + PropertyName = target.IdentifierName; ParameterName = "value"; + ImplementLetSetterType = true; + ImplementSetSetterType = true; + CanImplementLet = true; + CanImplementSet = true; + Encapsulate = true; + AssignSetterAndLetterAvailability(target, out var canImplSet, out var canImplLet); + CanImplementLet = canImplLet; + CanImplementSet = canImplSet; } - private Declaration _targetDeclaration; - public Declaration TargetDeclaration + public EncapsulateFieldConfig(IEncapsulateField config) { - get => _targetDeclaration; - set { - _targetDeclaration = value; - AssignSetterAndLetterAvailability(); - } + TargetDeclaration = config.TargetDeclaration; + PropertyName = config.PropertyName; + ParameterName = config.ParameterName; + ImplementLetSetterType = config.ImplementLetSetterType; + ImplementSetSetterType = config.ImplementSetSetterType; + CanImplementLet = config.CanImplementLet; + CanImplementSet = config.CanImplementSet; + Encapsulate = config is IEncapsulateUDTMember udt ? udt.Encapsulate : true; } + public Declaration TargetDeclaration { get; set; } public string PropertyName { get; set; } public string ParameterName { get; set; } public bool ImplementLetSetterType { get; set; } @@ -31,57 +66,140 @@ public Declaration TargetDeclaration public bool CanImplementLet { get; private set; } public bool CanImplementSet { get; private set; } + public bool Encapsulate { get; set; } + + private static void AssignSetterAndLetterAvailability(Declaration targetDeclaration, out bool canImplSet, out bool canImplLet) + { + var isVariant = targetDeclaration.AsTypeName.Equals(Tokens.Variant); + var isValueType = !isVariant && (SymbolList.ValueTypes.Contains(targetDeclaration.AsTypeName) || + targetDeclaration.DeclarationType == DeclarationType.Enumeration); + + canImplSet = !isValueType; + canImplLet = isValueType || isVariant; + } + } - private void AssignSetterAndLetterAvailability() + public class EncapsulateFieldModel : IRefactoringModel, IEncapsulateFieldModel, IEncapsulateField + { + public EncapsulateFieldModel(Declaration target) { - var isVariant = _targetDeclaration.AsTypeName.Equals(Tokens.Variant); - var isValueType = !isVariant && (SymbolList.ValueTypes.Contains(_targetDeclaration.AsTypeName) || - _targetDeclaration.DeclarationType == DeclarationType.Enumeration); + AddTarget(target); + } + + private readonly object _targetsLock = new object(); + private Dictionary _targets = new Dictionary(); + + public void AddTarget(Declaration target) + { + lock (_targetsLock) + { + _targets.Add(target, new EncapsulateFieldConfig(target)); + } + } - if (_targetDeclaration.References.Any(r => r.IsAssignment)) + public void AddTarget(IEncapsulateField encapsulateFieldConfig) + { + lock (_targetsLock) { - if (isVariant) + if (_targets.ContainsKey(encapsulateFieldConfig.TargetDeclaration)) { - RuleContext node = _targetDeclaration.References.First(r => r.IsAssignment).Context; - while (!(node is VBAParser.LetStmtContext) && !(node is VBAParser.SetStmtContext)) - { - node = node.Parent; - } - - if (node is VBAParser.LetStmtContext) - { - CanImplementLet = true; - } - else - { - CanImplementSet = true; - } + _targets[encapsulateFieldConfig.TargetDeclaration] = encapsulateFieldConfig; + return; } - else if (isValueType) + _targets.Add(encapsulateFieldConfig.TargetDeclaration, encapsulateFieldConfig); + } + } + + private IEncapsulateField DefaultTarget + { + get + { + lock (_targetsLock) { - CanImplementLet = true; - } - else + return _targets.Values.ElementAt(0); + }; + } + } + + + public IEnumerable EncapsulationTargets + { + get + { + var result = Enumerable.Empty(); + lock (_targetsLock) { - CanImplementSet = true; - } + result = _targets.Values.Select(v => v as IEncapsulateField).ToList(); + }; + return result; + } + } + + public Declaration TargetDeclaration + { + get => DefaultTarget.TargetDeclaration; + set + { + AddTarget(value); } - else + } + + public string PropertyName + { + get => DefaultTarget.PropertyName; + set { - if (isValueType) + var config = new EncapsulateFieldConfig(DefaultTarget) { - CanImplementLet = true; - } - else if (!isVariant) + PropertyName = value + }; + AddTarget(config); + } + } + + public string ParameterName + { + get => DefaultTarget.ParameterName; + set + { + var config = new EncapsulateFieldConfig(DefaultTarget) { - CanImplementSet = true; - } - else + ParameterName = value + }; + AddTarget(config); + } + } + + public bool ImplementLetSetterType + { + get => DefaultTarget.ImplementLetSetterType; + set + { + var config = new EncapsulateFieldConfig(DefaultTarget) { - CanImplementLet = true; - CanImplementSet = true; - } + ImplementLetSetterType = value + }; + AddTarget(config); } } + + public bool ImplementSetSetterType + { + get => DefaultTarget.ImplementSetSetterType; + set + { + var config = new EncapsulateFieldConfig(DefaultTarget) + { + ImplementSetSetterType = value + }; + AddTarget(config); + } + } + + public bool CanImplementLet + => DefaultTarget.CanImplementLet; + + public bool CanImplementSet + => DefaultTarget.CanImplementSet; } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 3a216f6288..975bf4f155 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -11,6 +11,7 @@ using Rubberduck.SmartIndenter; using Rubberduck.VBEditor.Utility; using Environment = System.Environment; +using System.Collections.Generic; namespace Rubberduck.Refactorings.EncapsulateField { @@ -18,19 +19,41 @@ public class EncapsulateFieldRefactoring : InteractiveRefactoringBase _properties; + private List _newFields; public EncapsulateFieldRefactoring(IDeclarationFinderProvider declarationFinderProvider, IIndenter indenter, IRefactoringPresenterFactory factory, IRewritingManager rewritingManager, ISelectionService selectionService) :base(rewritingManager, selectionService, factory) { _declarationFinderProvider = declarationFinderProvider; _indenter = indenter; + _properties = new List(); + _newFields = new List(); } protected override Declaration FindTargetDeclaration(QualifiedSelection targetSelection) { - return _declarationFinderProvider.DeclarationFinder + var selectedDeclaration = _declarationFinderProvider.DeclarationFinder.FindSelectedDeclaration(targetSelection); + if (selectedDeclaration.DeclarationType.Equals(DeclarationType.Variable)) + { + return selectedDeclaration; + } + + //TODO: the code below should no longer be needed after SelectionService PR + var variableTarget = _declarationFinderProvider.DeclarationFinder .UserDeclarations(DeclarationType.Variable) .FindVariable(targetSelection); + + if (variableTarget is null) + { + //TODO: This is blunt...handles only the simplest cases + //Need the ISelectionService PR + var udtMemberTargets = _declarationFinderProvider.DeclarationFinder + .UserDeclarations(DeclarationType.UserDefinedTypeMember); + return udtMemberTargets.FirstOrDefault(); + } + + return variableTarget; } protected override EncapsulateFieldModel InitializeModel(Declaration target) @@ -40,7 +63,7 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) throw new TargetDeclarationIsNullException(); } - if (target.DeclarationType != DeclarationType.Variable) + if (!target.DeclarationType.Equals(DeclarationType.Variable)) { throw new InvalidDeclarationTypeException(target); } @@ -48,56 +71,122 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) return new EncapsulateFieldModel(target); } - protected override void RefactorImpl(EncapsulateFieldModel model) + protected override void RefactorImpl(EncapsulateFieldModel modelConcrete) { var rewriteSession = RewritingManager.CheckOutCodePaneSession(); - AddProperty(model, rewriteSession); + + var model = modelConcrete as IEncapsulateFieldModel; + foreach (var target in model.EncapsulationTargets) + { + if (target is IEncapsulateUDTMember udtTarget) + { + AddUDTProperties(udtTarget, rewriteSession); + } + else + { + AddProperty(target, rewriteSession); + } + } + + if (model.EncapsulationTargets.Any(et => et is IEncapsulateUDTMember)) + { + var members = _declarationFinderProvider.DeclarationFinder + .Members(modelConcrete.TargetDeclaration.QualifiedName.QualifiedModuleName) + .OrderBy(declaration => declaration.QualifiedSelection); + + var fields = members.Where(d => + d.DeclarationType == DeclarationType.Variable + && !d.ParentScopeDeclaration.DeclarationType.HasFlag(DeclarationType.Member)) + .ToList(); + + var rewriter = rewriteSession.CheckOutModuleRewriter(modelConcrete.TargetDeclaration.QualifiedModuleName); + var carriageReturns = $"{Environment.NewLine}{Environment.NewLine}"; + rewriter.InsertAfter(fields.Last().Context.Stop.TokenIndex, $"{carriageReturns}{string.Join(carriageReturns, _properties)}"); + } + + if (!rewriteSession.TryRewrite()) { throw new RewriteFailedException(rewriteSession); } } - private void AddProperty(EncapsulateFieldModel model, IRewriteSession rewriteSession) + private void AddProperty(IEncapsulateField model, IRewriteSession rewriteSession) { var rewriter = rewriteSession.CheckOutModuleRewriter(model.TargetDeclaration.QualifiedModuleName); UpdateReferences(model, rewriteSession); - + var members = _declarationFinderProvider.DeclarationFinder .Members(model.TargetDeclaration.QualifiedName.QualifiedModuleName) .OrderBy(declaration => declaration.QualifiedSelection); - var fields = members.Where(d => d.DeclarationType == DeclarationType.Variable && !d.ParentScopeDeclaration.DeclarationType.HasFlag(DeclarationType.Member)).ToList(); + var insertionPoint = members.Where(d => d.DeclarationType == DeclarationType.Variable && !d.ParentScopeDeclaration.DeclarationType.HasFlag(DeclarationType.Member)) + .Last().Context.Stop.TokenIndex; - var property = Environment.NewLine + Environment.NewLine + GetPropertyText(model); - - if (model.TargetDeclaration.Accessibility != Accessibility.Private) + _properties.Add(GetPropertyText(model)); + + ForceEncapsulatedVariableAccessibility(model.TargetDeclaration, rewriteSession, Accessibility.Private); + + var property = Environment.NewLine + Environment.NewLine + string.Join(Environment.NewLine + Environment.NewLine, _properties); + rewriter.InsertAfter(insertionPoint, property); + } + + private void AddUDTProperties(IEncapsulateUDTMember udtMember, IRewriteSession rewriteSession) + { + var members = _declarationFinderProvider.DeclarationFinder + .Members(udtMember.TargetDeclaration.QualifiedModuleName) + .OrderBy(declaration => declaration.QualifiedSelection); + + var fields = members.Where(d => + d.DeclarationType == DeclarationType.Variable + && !d.ParentScopeDeclaration.DeclarationType.HasFlag(DeclarationType.Member)) + .ToList(); + + var typeDeclaration = fields.Where(m => m.DeclarationType.Equals(DeclarationType.UserDefinedType) + && udtMember.TargetDeclaration.ParentDeclaration == m) + .Single(); + + var scopeResolution = members.Where(m => m.DeclarationType.Equals(DeclarationType.Variable) + && m.AsTypeName.Equals(typeDeclaration.IdentifierName)) + .Select(v => v.IdentifierName).Single(); + + var generator = new PropertyGenerator { - var newField = $"Private {model.TargetDeclaration.IdentifierName} As {model.TargetDeclaration.AsTypeName}"; - if (fields.Count > 1) - { - newField = Environment.NewLine + newField; - } + PropertyName = udtMember.TargetDeclaration.IdentifierName, + AsTypeName = udtMember.TargetDeclaration.AsTypeName, + BackingField = $"{scopeResolution}.{udtMember.TargetDeclaration.IdentifierName}", + ParameterName = udtMember.ParameterName, + GenerateSetter = udtMember.TargetDeclaration.IsObject, //model.ImplementSetSetterType, + GenerateLetter = !udtMember.TargetDeclaration.IsObject //model.ImplementLetSetterType + }; - property = newField + property; - } + UpdateReferences(udtMember, rewriteSession); - if (model.TargetDeclaration.Accessibility == Accessibility.Private || fields.Count > 1) + _properties.Add(GetPropertyText(generator)); + } + + private void ForceEncapsulatedVariableAccessibility(Declaration target, IRewriteSession rewriteSession, Accessibility accessibility) + { + if (target.Accessibility == accessibility) { return; } + + var rewriter = rewriteSession.CheckOutModuleRewriter(target.QualifiedModuleName); + + var newField = $"{accessibility} {target.IdentifierName} As {target.AsTypeName}"; + + var varList = target.Context.GetAncestor(); + if (varList.ChildCount > 1) { - if (model.TargetDeclaration.Accessibility != Accessibility.Private) - { - rewriter.Remove(model.TargetDeclaration); - } - rewriter.InsertAfter(fields.Last().Context.Stop.TokenIndex, property); + rewriter.Remove(target); + rewriter.InsertAfter(varList.Stop.TokenIndex, $"{Environment.NewLine}{newField}"); } else { - rewriter.Replace(model.TargetDeclaration.Context.GetAncestor(), property); + rewriter.Replace(target.Context.GetAncestor(), newField); } } - private void UpdateReferences(EncapsulateFieldModel model, IRewriteSession rewriteSession) + private void UpdateReferences(IEncapsulateField model, IRewriteSession rewriteSession) { foreach (var reference in model.TargetDeclaration.References) { @@ -105,8 +194,8 @@ private void UpdateReferences(EncapsulateFieldModel model, IRewriteSession rewri rewriter.Replace(reference.Context, model.PropertyName); } } - - private string GetPropertyText(EncapsulateFieldModel model) + + private string GetPropertyText(IEncapsulateField model) { var generator = new PropertyGenerator { @@ -118,6 +207,11 @@ private string GetPropertyText(EncapsulateFieldModel model) GenerateLetter = model.ImplementLetSetterType }; + return GetPropertyText(generator); + } + + private string GetPropertyText(PropertyGenerator generator) + { var propertyTextLines = generator.AllPropertyCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None); return string.Join(Environment.NewLine, _indenter.Indent(propertyTextLines, true)); } diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index afecc7a2d4..4cb9ddfa28 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -46,6 +46,30 @@ End Property Assert.AreEqual(expectedCode, actualCode); } + [TestCase("Public")] + [TestCase("Private")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulateUserDefinedType(string accessibility) + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +{accessibility} this As TBar"; + + var selection = new Selection(7, 10); //Selects 'this' declaration + + var presenterAction = SetParameters("MyType", implementLet: true); + var actualCode = RefactoredCode(inputCode, selection, presenterAction); + StringAssert.Contains("Private this As TBar", actualCode); + StringAssert.Contains("this = value", actualCode); + StringAssert.Contains($"MyType = this", actualCode); + } + [Test] [Category("Refactorings")] [Category("Encapsulate Field")] @@ -245,21 +269,18 @@ Property Set Foo(ByVal vall As Variant) Assert.AreEqual(expectedCode, actualCode); } - [Test] + [TestCase("Public fizz As Integer\r\nPublic buzz As Boolean", "Private fizz As Integer\r\nPublic buzz As Boolean", 1, 1)] + [TestCase("Public buzz As Boolean\r\nPublic fizz As Integer", "Public buzz As Boolean\r\nPrivate fizz As Integer", 2, 1)] [Category("Refactorings")] [Category("Encapsulate Field")] - public void EncapsulatePublicField_OtherFieldsInClass() + public void EncapsulatePublicField_OtherFieldsInClass(string inputFields, string expectedFields, int rowSelection, int columnSelection) { - //Input - const string inputCode = - @"Public fizz As Integer -Public buzz As Boolean"; - var selection = new Selection(1, 1); + string inputCode = inputFields; - //Expectation - const string expectedCode = - @"Public buzz As Boolean -Private fizz As Integer + var selection = new Selection(rowSelection, columnSelection); + + string expectedCode = +$@"{expectedFields} Public Property Get Name() As Integer Name = fizz @@ -274,105 +295,28 @@ End Property Assert.AreEqual(expectedCode, actualCode); } - [Test] + [TestCase(1, 10, "Public buzz", "Private fizz As Variant", "Public fizz")] + [TestCase(2, 2, "Public fizz, _\r\nbazz", "Private buzz As Boolean", "")] + [TestCase(3, 2, "Public fizz, _\r\nbuzz", "Private bazz As Date", "Boolean, bazz As Date")] [Category("Refactorings")] [Category("Encapsulate Field")] - public void EncapsulatePublicField_FieldDeclarationHasMultipleFields_MoveFirst() + public void EncapsulatePublicField_SelectedWithinDeclarationList(int rowSelection, int columnSelection, string contains1, string contains2, string doesNotContain) { //Input - const string inputCode = - @"Public fizz, _ - buzz As Boolean, _ - bazz As Date"; - var selection = new Selection(1, 12); - - //Expectation - const string expectedCode = - @"Public buzz As Boolean, _ - bazz As Date -Private fizz As Variant - -Public Property Get Name() As Variant - If IsObject(fizz) Then - Set Name = fizz - Else - Name = fizz - End If -End Property - -Public Property Let Name(ByVal value As Variant) - fizz = value -End Property - -Public Property Set Name(ByVal value As Variant) - Set fizz = value -End Property -"; - var presenterAction = SetParameters("Name", implementSet: true, implementLet: true); - var actualCode = RefactoredCode(inputCode, selection, presenterAction); - Assert.AreEqual(expectedCode, actualCode); - } - - [Test] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void EncapsulatePublicField_FieldDeclarationHasMultipleFields_MoveSecond() - { - //Input - const string inputCode = - @"Public fizz, _ -buzz As Boolean, _ -bazz As Date"; - var selection = new Selection(2, 12); - - //Expectation - const string expectedCode = - @"Public fizz, _ -bazz As Date -Private buzz As Boolean - -Public Property Get Name() As Boolean - Name = buzz -End Property - -Public Property Let Name(ByVal value As Boolean) - buzz = value -End Property -"; - var presenterAction = SetParameters("Name", implementLet: true); - var actualCode = RefactoredCode(inputCode, selection, presenterAction); - Assert.AreEqual(expectedCode, actualCode); - } - - [Test] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void EncapsulatePublicField_FieldDeclarationHasMultipleFields_MoveLast() - { - //Input - const string inputCode = - @"Public fizz, _ + string inputCode = +$@"Public fizz, _ buzz As Boolean, _ bazz As Date"; - var selection = new Selection(3, 12); - - //Expectation - const string expectedCode = - @"Public fizz, _ -buzz As Boolean -Private bazz As Date -Public Property Get Name() As Date - Name = bazz -End Property - -Public Property Let Name(ByVal value As Date) - bazz = value -End Property -"; - var presenterAction = SetParameters("Name", implementLet: true); + var selection = new Selection(rowSelection, columnSelection); + var presenterAction = SetParameters("Name", implementSet: true, implementLet: true); var actualCode = RefactoredCode(inputCode, selection, presenterAction); - Assert.AreEqual(expectedCode, actualCode); + StringAssert.Contains(contains1, actualCode); + StringAssert.Contains(contains1, actualCode); + if (doesNotContain.Length > 0) + { + StringAssert.DoesNotContain(doesNotContain, actualCode); + } } [Test] @@ -644,8 +588,8 @@ End Property private Func SetParameters( string propertyName, - bool implementSet = false, - bool implementLet = false, + bool implementSet = false, + bool implementLet = false, string parameterName = "value") { return model => From ca17d8a87d6f43f10a506ce291fe198702665fe5 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Sun, 3 Nov 2019 06:50:47 -0800 Subject: [PATCH 005/461] WIP: more granular controls for UDT variables --- .../EncapsulateField/EncapsulateFieldModel.cs | 149 ++++++++++++---- .../EncapsulateFieldRefactoring.cs | 164 ++++++++++-------- .../Refactoring/EncapsulateFieldTests.cs | 85 ++++++++- 3 files changed, 290 insertions(+), 108 deletions(-) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index b04c10c8dc..b9ea2a3e12 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -7,6 +7,34 @@ namespace Rubberduck.Refactorings.EncapsulateField { + public struct EncapsulateUDTVariableRule + { + public Declaration Variable { set; get; } + private string _variableName; + public string VariableName + { + set { _variableName = value; } + get { return _variableName.Length == 0 ? Variable?.IdentifierName ?? string.Empty : _variableName;} + } + public Declaration UserDefinedType { set; get; } + public IEnumerable UserDefinedTypeMembers { set; get; } + public bool EncapsulateVariable { set; get; } + private bool _encapsulateAllUDTMembers; + public bool EncapsulateAllUDTMembers + { + set + { + _encapsulateAllUDTMembers = value; + if (value) + { + UDTMembersToEncapsulate = UserDefinedTypeMembers; + } + } + get => _encapsulateAllUDTMembers; + } + public IEnumerable UDTMembersToEncapsulate { set; get; } + } + public interface IEncapsulateField { Declaration TargetDeclaration { get; set; } @@ -79,6 +107,56 @@ private static void AssignSetterAndLetterAvailability(Declaration targetDeclarat } } + public struct EncapsulateUDTMemberConfig : IEncapsulateUDTMember + { + public EncapsulateUDTMemberConfig(Declaration target) + { + TargetDeclaration = target; + PropertyName = target.IdentifierName; + ParameterName = "value"; + ImplementLetSetterType = true; + ImplementSetSetterType = true; + CanImplementLet = true; + CanImplementSet = true; + Encapsulate = true; + AssignSetterAndLetterAvailability(target, out var canImplSet, out var canImplLet); + CanImplementLet = canImplLet; + CanImplementSet = canImplSet; + } + + public EncapsulateUDTMemberConfig(IEncapsulateField config) + { + TargetDeclaration = config.TargetDeclaration; + PropertyName = config.PropertyName; + ParameterName = config.ParameterName; + ImplementLetSetterType = config.ImplementLetSetterType; + ImplementSetSetterType = config.ImplementSetSetterType; + CanImplementLet = config.CanImplementLet; + CanImplementSet = config.CanImplementSet; + Encapsulate = config is IEncapsulateUDTMember udt ? udt.Encapsulate : true; + } + + public Declaration TargetDeclaration { get; set; } + public string PropertyName { get; set; } + public string ParameterName { get; set; } + public bool ImplementLetSetterType { get; set; } + public bool ImplementSetSetterType { get; set; } + + public bool CanImplementLet { get; private set; } + public bool CanImplementSet { get; private set; } + public bool Encapsulate { get; set; } + + private static void AssignSetterAndLetterAvailability(Declaration targetDeclaration, out bool canImplSet, out bool canImplLet) + { + var isVariant = targetDeclaration.AsTypeName.Equals(Tokens.Variant); + var isValueType = !isVariant && (SymbolList.ValueTypes.Contains(targetDeclaration.AsTypeName) || + targetDeclaration.DeclarationType == DeclarationType.Enumeration); + + canImplSet = !isValueType; + canImplLet = isValueType || isVariant; + } + } + public class EncapsulateFieldModel : IRefactoringModel, IEncapsulateFieldModel, IEncapsulateField { public EncapsulateFieldModel(Declaration target) @@ -86,62 +164,62 @@ public EncapsulateFieldModel(Declaration target) AddTarget(target); } - private readonly object _targetsLock = new object(); private Dictionary _targets = new Dictionary(); - public void AddTarget(Declaration target) + public void ModifyUDTRule(EncapsulateUDTVariableRule udtRule) { - lock (_targetsLock) + var rules = UDTVariableRules.Where(r => r.Variable.IdentifierName == udtRule.VariableName); + if (rules.Count() == 1) { - _targets.Add(target, new EncapsulateFieldConfig(target)); - } - } + var rule = rules.First(); + if (rule.EncapsulateVariable) + { + AddTarget(rule.Variable); + } - public void AddTarget(IEncapsulateField encapsulateFieldConfig) - { - lock (_targetsLock) - { - if (_targets.ContainsKey(encapsulateFieldConfig.TargetDeclaration)) + rule.EncapsulateAllUDTMembers = udtRule.EncapsulateAllUDTMembers; + + foreach (var udtM in rule.UDTMembersToEncapsulate) { - _targets[encapsulateFieldConfig.TargetDeclaration] = encapsulateFieldConfig; - return; + AddTarget(udtM); } - _targets.Add(encapsulateFieldConfig.TargetDeclaration, encapsulateFieldConfig); } } - private IEncapsulateField DefaultTarget + public void AddTarget(Declaration target) { - get + if (target.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)) { - lock (_targetsLock) - { - return _targets.Values.ElementAt(0); - }; + //_targets.Add(target, new EncapsulateUDTMemberConfig(target)); + AddTarget (new EncapsulateUDTMemberConfig(target)); + } + else + { + //_targets.Add(target, new EncapsulateFieldConfig(target)); + AddTarget (new EncapsulateFieldConfig(target)); } } - - public IEnumerable EncapsulationTargets + public void AddTarget(IEncapsulateField encapsulateFieldConfig) { - get + if (_targets.ContainsKey(encapsulateFieldConfig.TargetDeclaration)) { - var result = Enumerable.Empty(); - lock (_targetsLock) - { - result = _targets.Values.Select(v => v as IEncapsulateField).ToList(); - }; - return result; + _targets[encapsulateFieldConfig.TargetDeclaration] = encapsulateFieldConfig; + return; } + _targets.Add(encapsulateFieldConfig.TargetDeclaration, encapsulateFieldConfig); } + private IEncapsulateField DefaultTarget => _targets.Values.ElementAt(0); + + + public IEnumerable EncapsulationTargets + => _targets.Values.Select(v => v as IEncapsulateField).ToList(); + public Declaration TargetDeclaration { get => DefaultTarget.TargetDeclaration; - set - { - AddTarget(value); - } + set => AddTarget(value); } public string PropertyName @@ -196,6 +274,11 @@ public bool ImplementSetSetterType } } + //public bool EncapsulateTypeMembers { set; get; } + public IEnumerable UDTVariableRules { set; get; } + + public bool CanStoreStateUsingUDTMembers { set; get; } + public bool CanImplementLet => DefaultTarget.CanImplementLet; diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 975bf4f155..0db6c2ceef 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -51,7 +51,7 @@ protected override Declaration FindTargetDeclaration(QualifiedSelection targetSe var udtMemberTargets = _declarationFinderProvider.DeclarationFinder .UserDeclarations(DeclarationType.UserDefinedTypeMember); return udtMemberTargets.FirstOrDefault(); - } + } return variableTarget; } @@ -68,7 +68,49 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) throw new InvalidDeclarationTypeException(target); } - return new EncapsulateFieldModel(target); + var model = new EncapsulateFieldModel(target); + + var udtVariables = _declarationFinderProvider.DeclarationFinder + .Members(model.TargetDeclaration.QualifiedName.QualifiedModuleName) + .Where(v => v.DeclarationType.Equals(DeclarationType.Variable) + && (v.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.UserDefinedType) ?? false)); + + var udtVariableRules = new List(); + foreach (var udtVariable in udtVariables) + { + var udtDefinition = GetUDTDefinition(udtVariable); + + var udtVariableRule = new EncapsulateUDTVariableRule() + { + Variable = udtVariable, + UserDefinedType = udtDefinition.UserDefinedType, + UserDefinedTypeMembers = udtDefinition.UdtMembers, + EncapsulateVariable = true, + EncapsulateAllUDTMembers = false, + UDTMembersToEncapsulate = new List() + }; + udtVariableRules.Add(udtVariableRule); + } + + model.CanStoreStateUsingUDTMembers = udtVariableRules.Count() == 1 + || udtVariables.Distinct().Count() == udtVariableRules.Count(); + + model.UDTVariableRules = udtVariableRules; + + return model; + } + + private (Declaration UserDefinedType, IEnumerable UdtMembers) GetUDTDefinition(Declaration udtVariable) + { + var udt = _declarationFinderProvider.DeclarationFinder + .UserDeclarations(DeclarationType.UserDefinedType) + .Where(ut => ut.IdentifierName.Equals(udtVariable.AsTypeName)) + .Single(); + + var udtMembers = _declarationFinderProvider.DeclarationFinder + .UserDeclarations(DeclarationType.UserDefinedTypeMember) + .Where(utm => udt.IdentifierName == utm.ParentDeclaration.IdentifierName); + return (udt, udtMembers); } protected override void RefactorImpl(EncapsulateFieldModel modelConcrete) @@ -78,32 +120,20 @@ protected override void RefactorImpl(EncapsulateFieldModel modelConcrete) var model = modelConcrete as IEncapsulateFieldModel; foreach (var target in model.EncapsulationTargets) { + UpdateReferences(target, rewriteSession); if (target is IEncapsulateUDTMember udtTarget) { - AddUDTProperties(udtTarget, rewriteSession); + AddUDTMemberProperty(udtTarget, modelConcrete.TargetDeclaration.QualifiedModuleName); } else { - AddProperty(target, rewriteSession); + AddProperty(target); } } - if (model.EncapsulationTargets.Any(et => et is IEncapsulateUDTMember)) - { - var members = _declarationFinderProvider.DeclarationFinder - .Members(modelConcrete.TargetDeclaration.QualifiedName.QualifiedModuleName) - .OrderBy(declaration => declaration.QualifiedSelection); - - var fields = members.Where(d => - d.DeclarationType == DeclarationType.Variable - && !d.ParentScopeDeclaration.DeclarationType.HasFlag(DeclarationType.Member)) - .ToList(); - - var rewriter = rewriteSession.CheckOutModuleRewriter(modelConcrete.TargetDeclaration.QualifiedModuleName); - var carriageReturns = $"{Environment.NewLine}{Environment.NewLine}"; - rewriter.InsertAfter(fields.Last().Context.Stop.TokenIndex, $"{carriageReturns}{string.Join(carriageReturns, _properties)}"); - } + EnforceEncapsulatedVariablePrivateAccessibility(modelConcrete.TargetDeclaration, rewriteSession); + InsertProperties(modelConcrete.TargetDeclaration.QualifiedModuleName, rewriteSession); if (!rewriteSession.TryRewrite()) { @@ -111,71 +141,72 @@ protected override void RefactorImpl(EncapsulateFieldModel modelConcrete) } } - private void AddProperty(IEncapsulateField model, IRewriteSession rewriteSession) + private int DeterminePropertyInsertionTokenIndex(QualifiedModuleName qualifiedModuleName) { - var rewriter = rewriteSession.CheckOutModuleRewriter(model.TargetDeclaration.QualifiedModuleName); - - UpdateReferences(model, rewriteSession); - - var members = _declarationFinderProvider.DeclarationFinder - .Members(model.TargetDeclaration.QualifiedName.QualifiedModuleName) - .OrderBy(declaration => declaration.QualifiedSelection); - - var insertionPoint = members.Where(d => d.DeclarationType == DeclarationType.Variable && !d.ParentScopeDeclaration.DeclarationType.HasFlag(DeclarationType.Member)) - .Last().Context.Stop.TokenIndex; - - _properties.Add(GetPropertyText(model)); - - ForceEncapsulatedVariableAccessibility(model.TargetDeclaration, rewriteSession, Accessibility.Private); - - var property = Environment.NewLine + Environment.NewLine + string.Join(Environment.NewLine + Environment.NewLine, _properties); - rewriter.InsertAfter(insertionPoint, property); + return _declarationFinderProvider.DeclarationFinder + .Members(qualifiedModuleName) + .Where(d => d.DeclarationType == DeclarationType.Variable + && !d.ParentScopeDeclaration.DeclarationType.HasFlag(DeclarationType.Member)) + .OrderBy(declaration => declaration.QualifiedSelection) + .Last().Context.Stop.TokenIndex; } - private void AddUDTProperties(IEncapsulateUDTMember udtMember, IRewriteSession rewriteSession) + private void AddProperty(IEncapsulateField model) { - var members = _declarationFinderProvider.DeclarationFinder - .Members(udtMember.TargetDeclaration.QualifiedModuleName) - .OrderBy(declaration => declaration.QualifiedSelection); - - var fields = members.Where(d => - d.DeclarationType == DeclarationType.Variable - && !d.ParentScopeDeclaration.DeclarationType.HasFlag(DeclarationType.Member)) - .ToList(); + var generator = new PropertyGenerator + { + PropertyName = model.PropertyName, + AsTypeName = model.TargetDeclaration.AsTypeName, + BackingField = model.TargetDeclaration.IdentifierName, + ParameterName = model.ParameterName, + GenerateSetter = model.ImplementSetSetterType, + GenerateLetter = model.ImplementLetSetterType + }; - var typeDeclaration = fields.Where(m => m.DeclarationType.Equals(DeclarationType.UserDefinedType) - && udtMember.TargetDeclaration.ParentDeclaration == m) - .Single(); + _properties.Add(GetPropertyText(generator)); + } - var scopeResolution = members.Where(m => m.DeclarationType.Equals(DeclarationType.Variable) - && m.AsTypeName.Equals(typeDeclaration.IdentifierName)) - .Select(v => v.IdentifierName).Single(); + private void AddUDTMemberProperty(IEncapsulateUDTMember udtMember, QualifiedModuleName qmnInstanceModule) + { + var udtDeclaration = _declarationFinderProvider.DeclarationFinder + .Members(qmnInstanceModule) //udtMember.TargetDeclaration.QualifiedModuleName) + .Where(m => m.DeclarationType.Equals(DeclarationType.Variable) + && udtMember.TargetDeclaration.ParentDeclaration.IdentifierName == m.AsTypeName); var generator = new PropertyGenerator { PropertyName = udtMember.TargetDeclaration.IdentifierName, AsTypeName = udtMember.TargetDeclaration.AsTypeName, - BackingField = $"{scopeResolution}.{udtMember.TargetDeclaration.IdentifierName}", + BackingField = $"{udtDeclaration.First().IdentifierName}.{udtMember.TargetDeclaration.IdentifierName}", ParameterName = udtMember.ParameterName, GenerateSetter = udtMember.TargetDeclaration.IsObject, //model.ImplementSetSetterType, GenerateLetter = !udtMember.TargetDeclaration.IsObject //model.ImplementLetSetterType }; - UpdateReferences(udtMember, rewriteSession); _properties.Add(GetPropertyText(generator)); } - private void ForceEncapsulatedVariableAccessibility(Declaration target, IRewriteSession rewriteSession, Accessibility accessibility) + private void InsertProperties(QualifiedModuleName qualifiedModuleName, IRewriteSession rewriteSession) + { + + var insertionTokenIndex = DeterminePropertyInsertionTokenIndex(qualifiedModuleName); + var carriageReturns = $"{Environment.NewLine}{Environment.NewLine}"; + + var rewriter = rewriteSession.CheckOutModuleRewriter(qualifiedModuleName); + rewriter.InsertAfter(insertionTokenIndex, $"{carriageReturns}{string.Join(carriageReturns, _properties)}"); + } + + private void EnforceEncapsulatedVariablePrivateAccessibility(Declaration target, IRewriteSession rewriteSession) { - if (target.Accessibility == accessibility) { return; } + if (target.Accessibility == Accessibility.Private) { return; } var rewriter = rewriteSession.CheckOutModuleRewriter(target.QualifiedModuleName); - var newField = $"{accessibility} {target.IdentifierName} As {target.AsTypeName}"; + var newField = $"{Accessibility.Private} {target.IdentifierName} As {target.AsTypeName}"; - var varList = target.Context.GetAncestor(); - if (varList.ChildCount > 1) + if(target.Context.TryGetAncestor(out var varList) + && varList.ChildCount > 1) { rewriter.Remove(target); rewriter.InsertAfter(varList.Stop.TokenIndex, $"{Environment.NewLine}{newField}"); @@ -195,21 +226,6 @@ private void UpdateReferences(IEncapsulateField model, IRewriteSession rewriteSe } } - private string GetPropertyText(IEncapsulateField model) - { - var generator = new PropertyGenerator - { - PropertyName = model.PropertyName, - AsTypeName = model.TargetDeclaration.AsTypeName, - BackingField = model.TargetDeclaration.IdentifierName, - ParameterName = model.ParameterName, - GenerateSetter = model.ImplementSetSetterType, - GenerateLetter = model.ImplementLetSetterType - }; - - return GetPropertyText(generator); - } - private string GetPropertyText(PropertyGenerator generator) { var propertyTextLines = generator.AllPropertyCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None); diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index 4cb9ddfa28..a1814f4db2 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -68,6 +68,87 @@ End Type StringAssert.Contains("Private this As TBar", actualCode); StringAssert.Contains("this = value", actualCode); StringAssert.Contains($"MyType = this", actualCode); + StringAssert.DoesNotContain($"this.First = value", actualCode); + } + + [TestCase("Public")] + [TestCase("Private")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulateUserDefinedTypeMembers(string accessibility) + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +{accessibility} this As TBar"; + + var selection = new Selection(7, 10); //Selects 'this' declaration + + var ruleTBar = new EncapsulateUDTVariableRule(); + ruleTBar.VariableName = "this"; + ruleTBar.EncapsulateAllUDTMembers = true; + ruleTBar.EncapsulateVariable = true; + + var presenterAction = SetParameters("MyType", implementLet: true, rule: ruleTBar); //, encapsulateTypeMembers: true); + var actualCode = RefactoredCode(inputCode, selection, presenterAction); + StringAssert.Contains("Private this As TBar", actualCode); + StringAssert.Contains("this = value", actualCode); + StringAssert.Contains("MyType = this", actualCode); + Assert.AreEqual(actualCode.IndexOf("MyType = this"), actualCode.LastIndexOf("MyType = this")); + StringAssert.Contains($"this.First = value", actualCode); + StringAssert.Contains($"First = this.First", actualCode); + StringAssert.Contains($"this.Second = value", actualCode); + StringAssert.Contains($"Second = this.Second", actualCode); + } + + [TestCase("Public")] + [TestCase("Private")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulateUserDefinedTypeMembers_ExternallyDefinedType(string accessibility) + { + string inputCode = +$@" +Option Explicit + +{accessibility} this As TBar"; + + string typeDefinition = +$@" +Public Type TBar + First As String + Second As Long +End Type +"; + + var selection = new Selection(4, 10); //Selects 'this' declaration + + var presenterAction = SetParameters("MyType", implementLet: true); //, encapsulateTypeMembers: true); + var actualModuleCode = RefactoredCode( + "Class1", + selection, + presenterAction, + null, + false, + ("Class1", inputCode, ComponentType.ClassModule), + ("Module1", typeDefinition, ComponentType.StandardModule)); + + Assert.AreEqual(typeDefinition, actualModuleCode["Module1"]); + + + var actualCode = actualModuleCode["Class1"]; + StringAssert.Contains("Private this As TBar", actualCode); + StringAssert.Contains("this = value", actualCode); + StringAssert.Contains("MyType = this", actualCode); + Assert.AreEqual(actualCode.IndexOf("MyType = this"), actualCode.LastIndexOf("MyType = this")); + StringAssert.Contains($"this.First = value", actualCode); + StringAssert.Contains($"First = this.First", actualCode); + StringAssert.Contains($"this.Second = value", actualCode); + StringAssert.Contains($"Second = this.Second", actualCode); } [Test] @@ -590,7 +671,8 @@ private Func SetParameters( string propertyName, bool implementSet = false, bool implementLet = false, - string parameterName = "value") + string parameterName = "value", + EncapsulateUDTVariableRule rule = new EncapsulateUDTVariableRule()) { return model => { @@ -598,6 +680,7 @@ private Func SetParameters( model.ParameterName = parameterName; model.ImplementLetSetterType = implementLet; model.ImplementSetSetterType = implementSet; + model.ModifyUDTRule(rule); return model; }; } From e958f33ebe4e70b18fb3d4bdffc88ec083d8d87b Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Sun, 3 Nov 2019 17:31:40 -0800 Subject: [PATCH 006/461] Cleanup from merge --- .../Refactoring/EncapsulateFieldTests.cs | 78 ------------------- 1 file changed, 78 deletions(-) diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index a7d529a1c7..372ccc5f03 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -376,83 +376,9 @@ End Property Assert.AreEqual(expectedCode, actualCode); } -//<<<<<<< HEAD [TestCase(1, 10, "Public buzz", "Private fizz As Variant", "Public fizz")] [TestCase(2, 2, "Public fizz, _\r\nbazz", "Private buzz As Boolean", "")] [TestCase(3, 2, "Public fizz, _\r\nbuzz", "Private bazz As Date", "Boolean, bazz As Date")] -//======= - [Test] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void EncapsulatePublicField_FieldDeclarationHasMultipleFields_MoveFirst() - { - //Input - const string inputCode = - @"Public fizz, _ - buzz As Boolean, _ - bazz As Date"; - var selection = new Selection(1, 12); - - //Expectation - const string expectedCode = - @"Public buzz As Boolean, _ - bazz As Date -Private fizz As Variant - -Public Property Get Name() As Variant - If IsObject(fizz) Then - Set Name = fizz - Else - Name = fizz - End If -End Property - -Public Property Let Name(ByVal value As Variant) - fizz = value -End Property - -Public Property Set Name(ByVal value As Variant) - Set fizz = value -End Property -"; - var presenterAction = SetParameters("Name", implementSet: true, implementLet: true); - var actualCode = RefactoredCode(inputCode, selection, presenterAction); - Assert.AreEqual(expectedCode, actualCode); - } - - [Test] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void EncapsulatePublicField_FieldDeclarationHasMultipleFields_MoveSecond() - { - //Input - const string inputCode = - @"Public fizz, _ -buzz As Boolean, _ -bazz As Date"; - var selection = new Selection(2, 2); - - //Expectation - const string expectedCode = - @"Public fizz, _ -bazz As Date -Private buzz As Boolean - -Public Property Get Name() As Boolean - Name = buzz -End Property - -Public Property Let Name(ByVal value As Boolean) - buzz = value -End Property -"; - var presenterAction = SetParameters("Name", implementLet: true); - var actualCode = RefactoredCode(inputCode, selection, presenterAction); - Assert.AreEqual(expectedCode, actualCode); - } - - [Test] -//>>>>>>> rubberduck-vba/next [Category("Refactorings")] [Category("Encapsulate Field")] public void EncapsulatePublicField_SelectedWithinDeclarationList(int rowSelection, int columnSelection, string contains1, string contains2, string doesNotContain) @@ -462,10 +388,6 @@ public void EncapsulatePublicField_SelectedWithinDeclarationList(int rowSelectio $@"Public fizz, _ buzz As Boolean, _ bazz As Date"; -//<<<<<<< HEAD -//======= -// var selection = new Selection(3, 2); -//>>>>>>> rubberduck-vba/next var selection = new Selection(rowSelection, columnSelection); var presenterAction = SetParameters("Name", implementSet: true, implementLet: true); From 1685aa93ff492e586d8652f636efc22003e6c5ab Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Wed, 6 Nov 2019 20:52:10 -0800 Subject: [PATCH 007/461] WIP added target decorators --- .../EncapsulateFieldDecorators.cs | 83 ++++ .../EncapsulateField/EncapsulateFieldModel.cs | 434 ++++++++++-------- .../EncapsulateFieldRefactoring.cs | 190 +++----- 3 files changed, 386 insertions(+), 321 deletions(-) create mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs new file mode 100644 index 0000000000..3010dd1976 --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs @@ -0,0 +1,83 @@ +using Rubberduck.Parsing.Symbols; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + public class EncapsulateFieldDeclaration + { + private Declaration _decorated; + public EncapsulateFieldDeclaration(Declaration declaration) + { + _decorated = declaration; + EncapsulationAttributes = new EncapsulationAttributes(_decorated); + } + + public static EncapsulateFieldDeclaration Decorate(Declaration declaration) + { + return new EncapsulateFieldDeclaration(declaration); + } + + public Declaration Declaration => _decorated; + + public string IdentifierName => _decorated.IdentifierName; + + public DeclarationType DeclarationType => _decorated.DeclarationType; + + public EncapsulationAttributes EncapsulationAttributes { set; get; } + } + + public class EncapsulatedValueType : EncapsulateFieldDeclaration + { + public EncapsulatedValueType(EncapsulateFieldDeclaration declaration) + : base(declaration.Declaration) + { + } + } + + public class EncapsulatedUserDefinedMemberValueType : EncapsulatedValueType + { + public EncapsulatedUserDefinedMemberValueType(EncapsulatedValueType declaration, UserDefinedTypeField udtVariable) + : base(declaration) + { + EncapsulationAttributes.FieldName = $"{udtVariable.Declaration.IdentifierName}.{declaration.Declaration.IdentifierName}"; + EncapsulationAttributes.ImplementLetSetterType = true; + } + } + + public class UserDefinedTypeField : EncapsulateFieldDeclaration + { + public UserDefinedTypeField(Declaration declaration) + : base(declaration) + { + } + + public UserDefinedTypeField(EncapsulateFieldDeclaration declaration) + : base(declaration.Declaration) + { + } + } + + public class EncapsulatedVariantType : EncapsulateFieldDeclaration + { + public EncapsulatedVariantType(EncapsulateFieldDeclaration declaration) + : base(declaration.Declaration) + { + EncapsulationAttributes.CanImplementLet = true; + EncapsulationAttributes.CanImplementSet = true; + } + } + + public class EncapsulatedObjectType : EncapsulateFieldDeclaration + { + public EncapsulatedObjectType(EncapsulateFieldDeclaration declaration) + : base(declaration.Declaration) + { + EncapsulationAttributes.CanImplementLet = false; + EncapsulationAttributes.CanImplementSet = true; + } + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index b9ea2a3e12..a32539d1d2 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -1,288 +1,336 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using Antlr4.Runtime; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; +using Rubberduck.SmartIndenter; +using Rubberduck.VBEditor; namespace Rubberduck.Refactorings.EncapsulateField { - public struct EncapsulateUDTVariableRule - { - public Declaration Variable { set; get; } - private string _variableName; - public string VariableName - { - set { _variableName = value; } - get { return _variableName.Length == 0 ? Variable?.IdentifierName ?? string.Empty : _variableName;} - } - public Declaration UserDefinedType { set; get; } - public IEnumerable UserDefinedTypeMembers { set; get; } - public bool EncapsulateVariable { set; get; } - private bool _encapsulateAllUDTMembers; - public bool EncapsulateAllUDTMembers - { - set - { - _encapsulateAllUDTMembers = value; - if (value) - { - UDTMembersToEncapsulate = UserDefinedTypeMembers; - } - } - get => _encapsulateAllUDTMembers; - } - public IEnumerable UDTMembersToEncapsulate { set; get; } - } - - public interface IEncapsulateField + public interface IEncapsulateFieldAttributes { - Declaration TargetDeclaration { get; set; } - string PropertyName { get; } - string ParameterName { get; } - bool ImplementLetSetterType { get;} - bool ImplementSetSetterType { get;} - + string FieldName { set; get; } + string PropertyName { set; get; } + string ParameterName { set; get; } + bool ImplementLetSetterType { set; get; } + bool ImplementSetSetterType { set; get; } bool CanImplementLet { get; } bool CanImplementSet { get; } } - public interface IEncapsulateUDTMember : IEncapsulateField + public struct EncapsulateUDTVariableRule { - bool Encapsulate { set; get; } + public EncapsulateUDTVariableRule(string variableName, string propertyName = null, string asTypeName = "Variant") + { + Attributes = new EncapsulationAttributes(variableName, propertyName ?? $"{variableName}_{Tokens.Type}", asTypeName); + EncapsulateVariable = true; + EncapsulateAllUDTMembers = false; + } + public EncapsulationAttributes Attributes { set; get; } + public string VariableName => Attributes?.FieldName ?? string.Empty; + public bool EncapsulateVariable { set; get; } + public bool EncapsulateAllUDTMembers { set; get; } } - public interface IEncapsulateFieldModel + public class EncapsulationAttributes : IEncapsulateFieldAttributes { - IEnumerable EncapsulationTargets { get; } - } + private static string DEFAULT_LET_PARAMETER = "value"; + public EncapsulationAttributes() + { + FieldName = string.Empty; + PropertyName = string.Empty; + AsTypeName = string.Empty; + ParameterName = DEFAULT_LET_PARAMETER; + ImplementLetSetterType = false; + ImplementSetSetterType = false; + CanImplementLet = false; + CanImplementSet = false; + Encapsulate = false; + } - public struct EncapsulateFieldConfig : IEncapsulateField - { - public EncapsulateFieldConfig(Declaration target) + public EncapsulationAttributes(string fieldName, string propertyName, string asTypeName) { - TargetDeclaration = target; - PropertyName = target.IdentifierName; - ParameterName = "value"; - ImplementLetSetterType = true; - ImplementSetSetterType = true; + FieldName = fieldName; + PropertyName = propertyName; + AsTypeName = asTypeName; + ParameterName = DEFAULT_LET_PARAMETER; + ImplementLetSetterType = false; + ImplementSetSetterType = false; CanImplementLet = true; CanImplementSet = true; - Encapsulate = true; - AssignSetterAndLetterAvailability(target, out var canImplSet, out var canImplLet); - CanImplementLet = canImplLet; - CanImplementSet = canImplSet; + Encapsulate = false; + } + + public EncapsulationAttributes(Declaration target) + { + FieldName = target.IdentifierName; + PropertyName = target.IdentifierName; + AsTypeName = target.AsTypeName; + ParameterName = DEFAULT_LET_PARAMETER; + ImplementLetSetterType = false; + ImplementSetSetterType = false; + Encapsulate = false; + IsVariant = target.AsTypeName?.Equals(Tokens.Variant) ?? true; + IsValueType = !IsVariant && (SymbolList.ValueTypes.Contains(target.AsTypeName) || + target.DeclarationType == DeclarationType.Enumeration); + CanImplementLet = IsValueType || IsVariant; + CanImplementSet = !(IsValueType || IsVariant); } - public EncapsulateFieldConfig(IEncapsulateField config) + public EncapsulationAttributes(EncapsulationAttributes attributes) { - TargetDeclaration = config.TargetDeclaration; - PropertyName = config.PropertyName; - ParameterName = config.ParameterName; - ImplementLetSetterType = config.ImplementLetSetterType; - ImplementSetSetterType = config.ImplementSetSetterType; - CanImplementLet = config.CanImplementLet; - CanImplementSet = config.CanImplementSet; - Encapsulate = config is IEncapsulateUDTMember udt ? udt.Encapsulate : true; + FieldName = attributes.FieldName; + PropertyName = attributes.PropertyName; + AsTypeName = attributes.AsTypeName; + ParameterName = attributes.ParameterName; + ImplementLetSetterType = attributes.ImplementLetSetterType; + ImplementSetSetterType = attributes.ImplementSetSetterType; + CanImplementLet = attributes.CanImplementLet; + CanImplementSet = attributes.CanImplementSet; + IsVariant = attributes.IsVariant; + IsValueType = attributes.IsValueType; + Encapsulate = false; } - public Declaration TargetDeclaration { get; set; } + public string FieldName { get; set; } public string PropertyName { get; set; } + public string AsTypeName { get; set; } public string ParameterName { get; set; } public bool ImplementLetSetterType { get; set; } public bool ImplementSetSetterType { get; set; } - public bool CanImplementLet { get; private set; } - public bool CanImplementSet { get; private set; } + public bool CanImplementLet { get; set; } + public bool CanImplementSet { get; set; } public bool Encapsulate { get; set; } + public bool IsValueType { private set; get; } + public bool IsVariant { private set; get; } + } - private static void AssignSetterAndLetterAvailability(Declaration targetDeclaration, out bool canImplSet, out bool canImplLet) + public class EncapsulateFieldModel : IRefactoringModel + { + private Dictionary)> _udts = new Dictionary)>(); + private readonly IIndenter _indenter; + private IList _fields = new List(); + private IList _nonUdtVariables = new List(); + private Dictionary _nonUdtVariablesByName = new Dictionary(); + private EncapsulateFieldDeclaration _selectedTarget; + + public EncapsulateFieldModel(Declaration target, IEnumerable nonUdtVariables, IEnumerable<(Declaration udtVariable, Declaration udt, IEnumerable udtMembers)> udtTuples, IIndenter indenter) { - var isVariant = targetDeclaration.AsTypeName.Equals(Tokens.Variant); - var isValueType = !isVariant && (SymbolList.ValueTypes.Contains(targetDeclaration.AsTypeName) || - targetDeclaration.DeclarationType == DeclarationType.Enumeration); + _indenter = indenter; + + foreach (var variable in _nonUdtVariables) + { + LoadNonUDTVariable(variable); + } + + foreach (var udtTuple in udtTuples) + { + LoadUDTVariable(udtTuple.udtVariable, udtTuple.udt, udtTuple.udtMembers); + } + + var selectedField = new EncapsulateFieldDeclaration(target); + + if (UDTVariables.Contains(target)) + { + _selectedTarget = new UserDefinedTypeField(selectedField); + } + else if (selectedField.EncapsulationAttributes.IsValueType) + { + _selectedTarget = new EncapsulatedValueType(selectedField); + } + else if (selectedField.EncapsulationAttributes.IsVariant) + { + _selectedTarget = new EncapsulatedVariantType(selectedField); + } - canImplSet = !isValueType; - canImplLet = isValueType || isVariant; + _selectedTarget.EncapsulationAttributes.Encapsulate = true; + + AddEncapsulationTarget(_selectedTarget); } - } - public struct EncapsulateUDTMemberConfig : IEncapsulateUDTMember - { - public EncapsulateUDTMemberConfig(Declaration target) + private Dictionary _encapsulationAttributesByFieldDeclaration = new Dictionary(); + private Dictionary _encapsulationAttributesByFieldIdentifier = new Dictionary(); + + private Dictionary _udtVariableRules = new Dictionary(); + + public void AddUDTVariableRule(EncapsulateUDTVariableRule udtRule) { - TargetDeclaration = target; - PropertyName = target.IdentifierName; - ParameterName = "value"; - ImplementLetSetterType = true; - ImplementSetSetterType = true; - CanImplementLet = true; - CanImplementSet = true; - Encapsulate = true; - AssignSetterAndLetterAvailability(target, out var canImplSet, out var canImplLet); - CanImplementLet = canImplLet; - CanImplementSet = canImplSet; + if (_udtVariableRules.TryGetValue(udtRule.VariableName, out _)) + { + _udtVariableRules[udtRule.VariableName] = udtRule; + return; + } + _udtVariableRules.Add(udtRule.VariableName, udtRule); } - public EncapsulateUDTMemberConfig(IEncapsulateField config) + public bool TryGetUDTVariableRule(string udtVariableName, out EncapsulateUDTVariableRule rule) { - TargetDeclaration = config.TargetDeclaration; - PropertyName = config.PropertyName; - ParameterName = config.ParameterName; - ImplementLetSetterType = config.ImplementLetSetterType; - ImplementSetSetterType = config.ImplementSetSetterType; - CanImplementLet = config.CanImplementLet; - CanImplementSet = config.CanImplementSet; - Encapsulate = config is IEncapsulateUDTMember udt ? udt.Encapsulate : true; + rule = new EncapsulateUDTVariableRule(); + if (_udtVariableRules.ContainsKey(udtVariableName)) + { + rule = _udtVariableRules[udtVariableName]; + return true; + } + return false; } - public Declaration TargetDeclaration { get; set; } - public string PropertyName { get; set; } - public string ParameterName { get; set; } - public bool ImplementLetSetterType { get; set; } - public bool ImplementSetSetterType { get; set; } + public IEnumerable UDTVariableRules => _udtVariableRules.Values; - public bool CanImplementLet { get; private set; } - public bool CanImplementSet { get; private set; } - public bool Encapsulate { get; set; } + public IEnumerable UDTVariables => _udts.Keys; - private static void AssignSetterAndLetterAvailability(Declaration targetDeclaration, out bool canImplSet, out bool canImplLet) + private void LoadUDTVariable(Declaration udtVariable, Declaration udt, IEnumerable udtMembers) { - var isVariant = targetDeclaration.AsTypeName.Equals(Tokens.Variant); - var isValueType = !isVariant && (SymbolList.ValueTypes.Contains(targetDeclaration.AsTypeName) || - targetDeclaration.DeclarationType == DeclarationType.Enumeration); - - canImplSet = !isValueType; - canImplLet = isValueType || isVariant; + _udts.Add(udtVariable, (udt, udtMembers)); + var udtVariableRule = new EncapsulateUDTVariableRule(udtVariable.IdentifierName); + AddUDTVariableRule(udtVariableRule); } - } - public class EncapsulateFieldModel : IRefactoringModel, IEncapsulateFieldModel, IEncapsulateField - { - public EncapsulateFieldModel(Declaration target) + private void LoadNonUDTVariable(Declaration variable) { - AddTarget(target); + _nonUdtVariables.Add(variable); + _nonUdtVariablesByName.Add(variable.IdentifierName, variable); } - private Dictionary _targets = new Dictionary(); - - public void ModifyUDTRule(EncapsulateUDTVariableRule udtRule) + public IEnumerable GetUdtMembers(Declaration udtVariable) { - var rules = UDTVariableRules.Where(r => r.Variable.IdentifierName == udtRule.VariableName); - if (rules.Count() == 1) + if (_udts.TryGetValue(udtVariable, out var value)) { - var rule = rules.First(); - if (rule.EncapsulateVariable) - { - AddTarget(rule.Variable); - } + return value.Item2; + } + return Enumerable.Empty(); + } + + public IEncapsulateFieldAttributes this[string fieldIdentifier] => _encapsulationAttributesByFieldIdentifier[fieldIdentifier]; + + public IEncapsulateFieldAttributes this[Declaration field] => _encapsulationAttributesByFieldDeclaration[field]; + + public IEnumerable EncapsulationTargets => _fields.Select(f => f.Declaration); // _encapsulationAttributesByFieldDeclaration.Keys; - rule.EncapsulateAllUDTMembers = udtRule.EncapsulateAllUDTMembers; + public void AddEncapsulationTarget(EncapsulateFieldDeclaration target) => _fields.Add(target); - foreach (var udtM in rule.UDTMembersToEncapsulate) + public IList PropertiesContent + { + get + { + var textBlocks = new List(); + foreach (var field in _fields) { - AddTarget(udtM); + switch (field) + { + case EncapsulatedUserDefinedMemberValueType udtMemberType: + if (udtMemberType.EncapsulationAttributes.Encapsulate) + { + textBlocks.Add(BuildPropertiesTextBlock(udtMemberType.Declaration)); + } + break; + case UserDefinedTypeField udtType: + if (udtType.EncapsulationAttributes.Encapsulate) + { + textBlocks.Add(BuildPropertiesTextBlock(udtType.Declaration)); + } + break; + default: + textBlocks.Add(BuildPropertiesTextBlock(field.Declaration)); + break; + } } + return textBlocks; } } - public void AddTarget(Declaration target) + private string BuildPropertiesTextBlock(Declaration target) { - if (target.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)) - { - //_targets.Add(target, new EncapsulateUDTMemberConfig(target)); - AddTarget (new EncapsulateUDTMemberConfig(target)); - } - else + var attributes = EncapsulationAttributes(target); + var generator = new PropertyGenerator { - //_targets.Add(target, new EncapsulateFieldConfig(target)); - AddTarget (new EncapsulateFieldConfig(target)); - } + PropertyName = attributes.PropertyName, + AsTypeName = attributes.AsTypeName, + BackingField = attributes.FieldName, + ParameterName = attributes.ParameterName, + GenerateSetter = attributes.ImplementSetSetterType, + GenerateLetter = attributes.ImplementLetSetterType + }; + + return GetPropertyText(generator); } - public void AddTarget(IEncapsulateField encapsulateFieldConfig) + private string BuildUDTMemberPropertiesTextBlock(Declaration udtMember) { - if (_targets.ContainsKey(encapsulateFieldConfig.TargetDeclaration)) + var attributes = EncapsulationAttributes(udtMember); + + var udtVariable = _udts.Keys.Where(k => _udts[k].Item2.Contains(udtMember)).SingleOrDefault(); + + var generator = new PropertyGenerator { - _targets[encapsulateFieldConfig.TargetDeclaration] = encapsulateFieldConfig; - return; - } - _targets.Add(encapsulateFieldConfig.TargetDeclaration, encapsulateFieldConfig); + PropertyName = attributes.PropertyName, + AsTypeName = attributes.AsTypeName, + BackingField = $"{udtVariable.IdentifierName}.{udtMember.IdentifierName}", + ParameterName = attributes.ParameterName, + GenerateSetter = udtMember.IsObject, //model.ImplementSetSetterType, + GenerateLetter = !udtMember.IsObject //model.ImplementLetSetterType + }; + + return GetPropertyText(generator); } - private IEncapsulateField DefaultTarget => _targets.Values.ElementAt(0); - + private string GetPropertyText(PropertyGenerator generator) + { + var propertyTextLines = generator.AllPropertyCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None); + return string.Join(Environment.NewLine, _indenter.Indent(propertyTextLines, true)); + } - public IEnumerable EncapsulationTargets - => _targets.Values.Select(v => v as IEncapsulateField).ToList(); + public EncapsulationAttributes EncapsulationAttributes(Declaration target) + { + foreach ( var field in _fields) + { + if (field.Declaration == target) + { + return field.EncapsulationAttributes; + } + } + return null; + } + private EncapsulateFieldDeclaration DefaultTarget => _selectedTarget; + public Declaration TargetDeclaration { - get => DefaultTarget.TargetDeclaration; - set => AddTarget(value); + get => DefaultTarget.Declaration; + set => _selectedTarget = new EncapsulateFieldDeclaration(value); } public string PropertyName { - get => DefaultTarget.PropertyName; - set - { - var config = new EncapsulateFieldConfig(DefaultTarget) - { - PropertyName = value - }; - AddTarget(config); - } + get => DefaultTarget.EncapsulationAttributes.PropertyName; + set => DefaultTarget.EncapsulationAttributes.PropertyName = value; } public string ParameterName { - get => DefaultTarget.ParameterName; - set - { - var config = new EncapsulateFieldConfig(DefaultTarget) - { - ParameterName = value - }; - AddTarget(config); - } + get => DefaultTarget.EncapsulationAttributes.ParameterName; + set => DefaultTarget.EncapsulationAttributes.ParameterName = value; } public bool ImplementLetSetterType { - get => DefaultTarget.ImplementLetSetterType; - set - { - var config = new EncapsulateFieldConfig(DefaultTarget) - { - ImplementLetSetterType = value - }; - AddTarget(config); - } + get => DefaultTarget.EncapsulationAttributes.ImplementLetSetterType; + set => DefaultTarget.EncapsulationAttributes.ImplementLetSetterType = value; } public bool ImplementSetSetterType { - get => DefaultTarget.ImplementSetSetterType; - set - { - var config = new EncapsulateFieldConfig(DefaultTarget) - { - ImplementSetSetterType = value - }; - AddTarget(config); - } + get => DefaultTarget.EncapsulationAttributes.ImplementSetSetterType; + set => DefaultTarget.EncapsulationAttributes.ImplementSetSetterType = value; } - //public bool EncapsulateTypeMembers { set; get; } - public IEnumerable UDTVariableRules { set; get; } - - public bool CanStoreStateUsingUDTMembers { set; get; } - public bool CanImplementLet - => DefaultTarget.CanImplementLet; + => DefaultTarget.EncapsulationAttributes.CanImplementLet; public bool CanImplementSet - => DefaultTarget.CanImplementSet; + => DefaultTarget.EncapsulationAttributes.CanImplementSet; } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 2652ec5cda..833b6bdd9c 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -1,6 +1,5 @@ using System; using System.Linq; -using Rubberduck.Common; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Rewriter; @@ -20,14 +19,7 @@ public class EncapsulateFieldRefactoring : InteractiveRefactoringBase _properties; - private List _newFields; -// public EncapsulateFieldRefactoring(IDeclarationFinderProvider declarationFinderProvider, IIndenter indenter, IRefactoringPresenterFactory factory, IRewritingManager rewritingManager, ISelectionService selectionService) -// :base(rewritingManager, selectionService, factory) -//======= - public EncapsulateFieldRefactoring( IDeclarationFinderProvider declarationFinderProvider, IIndenter indenter, @@ -36,40 +28,14 @@ public EncapsulateFieldRefactoring( ISelectionProvider selectionProvider, ISelectedDeclarationProvider selectedDeclarationProvider) :base(rewritingManager, selectionProvider, factory) -//>>>>>>> rubberduck-vba/next { _declarationFinderProvider = declarationFinderProvider; _selectedDeclarationProvider = selectedDeclarationProvider; _indenter = indenter; - _properties = new List(); - _newFields = new List(); } protected override Declaration FindTargetDeclaration(QualifiedSelection targetSelection) { - //<<<<<<< HEAD - //var selectedDeclaration = _declarationFinderProvider.DeclarationFinder.FindSelectedDeclaration(targetSelection); - //if (selectedDeclaration.DeclarationType.Equals(DeclarationType.Variable)) - //{ - // return selectedDeclaration; - //} - - ////TODO: the code below should no longer be needed after SelectionService PR - //var variableTarget = _declarationFinderProvider.DeclarationFinder - // .UserDeclarations(DeclarationType.Variable) - // .FindVariable(targetSelection); - - //if (variableTarget is null) - //{ - // //TODO: This is blunt...handles only the simplest cases - // //Need the ISelectionService PR - // var udtMemberTargets = _declarationFinderProvider.DeclarationFinder - // .UserDeclarations(DeclarationType.UserDefinedTypeMember); - // return udtMemberTargets.FirstOrDefault(); - //} - - //return variableTarget; - //======= var selectedDeclaration = _selectedDeclarationProvider.SelectedDeclaration(targetSelection); if (selectedDeclaration == null || selectedDeclaration.DeclarationType != DeclarationType.Variable @@ -79,7 +45,6 @@ protected override Declaration FindTargetDeclaration(QualifiedSelection targetSe } return selectedDeclaration; - //>>>>>>> rubberduck-vba/next } protected override EncapsulateFieldModel InitializeModel(Declaration target) @@ -94,72 +59,79 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) throw new InvalidDeclarationTypeException(target); } - var model = new EncapsulateFieldModel(target); - var udtVariables = _declarationFinderProvider.DeclarationFinder - .Members(model.TargetDeclaration.QualifiedName.QualifiedModuleName) - .Where(v => v.DeclarationType.Equals(DeclarationType.Variable) + .Members(target.QualifiedName.QualifiedModuleName) + .Where(v => v.DeclarationType.Equals(DeclarationType.Variable) && (v.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.UserDefinedType) ?? false)); - var udtVariableRules = new List(); - foreach (var udtVariable in udtVariables) - { - var udtDefinition = GetUDTDefinition(udtVariable); + var udtTuples = udtVariables.Select(uv => GetUDTDefinition(uv)); - var udtVariableRule = new EncapsulateUDTVariableRule() - { - Variable = udtVariable, - UserDefinedType = udtDefinition.UserDefinedType, - UserDefinedTypeMembers = udtDefinition.UdtMembers, - EncapsulateVariable = true, - EncapsulateAllUDTMembers = false, - UDTMembersToEncapsulate = new List() - }; - udtVariableRules.Add(udtVariableRule); - } - - model.CanStoreStateUsingUDTMembers = udtVariableRules.Count() == 1 - || udtVariables.Distinct().Count() == udtVariableRules.Count(); + var nonUdtVariables = _declarationFinderProvider.DeclarationFinder + .Members(target.QualifiedName.QualifiedModuleName) + .Where(v => v.DeclarationType.Equals(DeclarationType.Variable) + && !udtVariables.Contains(v) && !v.ParentDeclaration.DeclarationType.HasFlag(DeclarationType.Member)); - model.UDTVariableRules = udtVariableRules; + var model = new EncapsulateFieldModel(target, nonUdtVariables, udtTuples, _indenter); return model; } - private (Declaration UserDefinedType, IEnumerable UdtMembers) GetUDTDefinition(Declaration udtVariable) + private (Declaration UDTVariable, Declaration UserDefinedType, IEnumerable UDTMembers) GetUDTDefinition(Declaration udtVariable) { - var udt = _declarationFinderProvider.DeclarationFinder + var userDefinedTypeDeclaration = _declarationFinderProvider.DeclarationFinder .UserDeclarations(DeclarationType.UserDefinedType) - .Where(ut => ut.IdentifierName.Equals(udtVariable.AsTypeName)) - .Single(); + .Where(ut => ut.IdentifierName.Equals(udtVariable.AsTypeName) + && (ut.Accessibility.Equals(Accessibility.Private) + && ut.QualifiedModuleName == udtVariable.QualifiedModuleName) + || (ut.Accessibility != Accessibility.Private)) + .SingleOrDefault(); var udtMembers = _declarationFinderProvider.DeclarationFinder .UserDeclarations(DeclarationType.UserDefinedTypeMember) - .Where(utm => udt.IdentifierName == utm.ParentDeclaration.IdentifierName); - return (udt, udtMembers); + .Where(utm => userDefinedTypeDeclaration.IdentifierName == utm.ParentDeclaration.IdentifierName); + return (udtVariable, userDefinedTypeDeclaration, udtMembers); } - protected override void RefactorImpl(EncapsulateFieldModel modelConcrete) + protected override void RefactorImpl(EncapsulateFieldModel model) { var rewriteSession = RewritingManager.CheckOutCodePaneSession(); - var model = modelConcrete as IEncapsulateFieldModel; + var rules = new Dictionary(); + foreach (var target in model.EncapsulationTargets) { - UpdateReferences(target, rewriteSession); - if (target is IEncapsulateUDTMember udtTarget) + if (model.TryGetUDTVariableRule(target.IdentifierName, out EncapsulateUDTVariableRule rule)) { - AddUDTMemberProperty(udtTarget, modelConcrete.TargetDeclaration.QualifiedModuleName); + rules.Add(target, rule); } - else + } + + var udtVariableTargets = model.EncapsulationTargets.Where(et => rules.ContainsKey(et)).ToList(); + foreach( var udtVariable in udtVariableTargets) + { + var rule = rules[udtVariable]; + if (rule.EncapsulateAllUDTMembers) { - AddProperty(target); + foreach (var udtMember in model.GetUdtMembers(udtVariable)) + { + var udtMemberField = new EncapsulatedValueType(new EncapsulateFieldDeclaration(udtMember)); + udtMemberField = new EncapsulatedUserDefinedMemberValueType(udtMemberField, new UserDefinedTypeField(udtVariable)); + udtMemberField.EncapsulationAttributes.Encapsulate = true; + model.AddEncapsulationTarget(udtMemberField); + } } } - EnforceEncapsulatedVariablePrivateAccessibility(modelConcrete.TargetDeclaration, rewriteSession); + foreach (var target in model.EncapsulationTargets) + { + if (target.DeclarationType.Equals(DeclarationType.Variable)) + { + EnforceEncapsulatedVariablePrivateAccessibility(target, rewriteSession); + } + UpdateReferences(target, rewriteSession, model.EncapsulationAttributes(target).PropertyName); // model.PropertyName); + } - InsertProperties(modelConcrete.TargetDeclaration.QualifiedModuleName, rewriteSession); + InsertProperties(model, rewriteSession); if (!rewriteSession.TryRewrite()) { @@ -167,64 +139,32 @@ protected override void RefactorImpl(EncapsulateFieldModel modelConcrete) } } - private int DeterminePropertyInsertionTokenIndex(QualifiedModuleName qualifiedModuleName) + private void InsertProperties(EncapsulateFieldModel model, IRewriteSession rewriteSession) { - return _declarationFinderProvider.DeclarationFinder + if (!model.EncapsulationTargets.Any()) { return; } + + var qualifiedModuleName = model.EncapsulationTargets.First().QualifiedModuleName; + + var carriageReturns = $"{Environment.NewLine}{Environment.NewLine}"; + var insertionTokenIndex = _declarationFinderProvider.DeclarationFinder .Members(qualifiedModuleName) .Where(d => d.DeclarationType == DeclarationType.Variable && !d.ParentScopeDeclaration.DeclarationType.HasFlag(DeclarationType.Member)) .OrderBy(declaration => declaration.QualifiedSelection) - .Last().Context.Stop.TokenIndex; - } + .Last().Context.Stop.TokenIndex; ; - private void AddProperty(IEncapsulateField model) - { - var generator = new PropertyGenerator - { - PropertyName = model.PropertyName, - AsTypeName = model.TargetDeclaration.AsTypeName, - BackingField = model.TargetDeclaration.IdentifierName, - ParameterName = model.ParameterName, - GenerateSetter = model.ImplementSetSetterType, - GenerateLetter = model.ImplementLetSetterType - }; - - _properties.Add(GetPropertyText(generator)); - } - - private void AddUDTMemberProperty(IEncapsulateUDTMember udtMember, QualifiedModuleName qmnInstanceModule) - { - var udtDeclaration = _declarationFinderProvider.DeclarationFinder - .Members(qmnInstanceModule) //udtMember.TargetDeclaration.QualifiedModuleName) - .Where(m => m.DeclarationType.Equals(DeclarationType.Variable) - && udtMember.TargetDeclaration.ParentDeclaration.IdentifierName == m.AsTypeName); - - var generator = new PropertyGenerator - { - PropertyName = udtMember.TargetDeclaration.IdentifierName, - AsTypeName = udtMember.TargetDeclaration.AsTypeName, - BackingField = $"{udtDeclaration.First().IdentifierName}.{udtMember.TargetDeclaration.IdentifierName}", - ParameterName = udtMember.ParameterName, - GenerateSetter = udtMember.TargetDeclaration.IsObject, //model.ImplementSetSetterType, - GenerateLetter = !udtMember.TargetDeclaration.IsObject //model.ImplementLetSetterType - }; - - - _properties.Add(GetPropertyText(generator)); - } - - private void InsertProperties(QualifiedModuleName qualifiedModuleName, IRewriteSession rewriteSession) - { - - var insertionTokenIndex = DeterminePropertyInsertionTokenIndex(qualifiedModuleName); - var carriageReturns = $"{Environment.NewLine}{Environment.NewLine}"; var rewriter = rewriteSession.CheckOutModuleRewriter(qualifiedModuleName); - rewriter.InsertAfter(insertionTokenIndex, $"{carriageReturns}{string.Join(carriageReturns, _properties)}"); + rewriter.InsertAfter(insertionTokenIndex, $"{carriageReturns}{string.Join(carriageReturns, model.PropertiesContent)}"); } private void EnforceEncapsulatedVariablePrivateAccessibility(Declaration target, IRewriteSession rewriteSession) { + if (!target.DeclarationType.Equals(DeclarationType.Variable)) + { + return; + } + if (target.Accessibility == Accessibility.Private) { return; } var rewriter = rewriteSession.CheckOutModuleRewriter(target.QualifiedModuleName); @@ -243,19 +183,13 @@ private void EnforceEncapsulatedVariablePrivateAccessibility(Declaration target, } } - private void UpdateReferences(IEncapsulateField model, IRewriteSession rewriteSession) + private void UpdateReferences(Declaration target, IRewriteSession rewriteSession, string newName = null) { - foreach (var reference in model.TargetDeclaration.References) + foreach (var reference in target.References) { var rewriter = rewriteSession.CheckOutModuleRewriter(reference.QualifiedModuleName); - rewriter.Replace(reference.Context, model.PropertyName); + rewriter.Replace(reference.Context, newName ?? target.IdentifierName); } } - - private string GetPropertyText(PropertyGenerator generator) - { - var propertyTextLines = generator.AllPropertyCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None); - return string.Join(Environment.NewLine, _indenter.Indent(propertyTextLines, true)); - } } } From a461b321e9cc25f611421b7500e642c7c46abede Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Wed, 6 Nov 2019 20:52:44 -0800 Subject: [PATCH 008/461] Tests for more granular control of UDTs --- .../Refactoring/EncapsulateFieldTests.cs | 80 +++++++++++++++++-- 1 file changed, 73 insertions(+), 7 deletions(-) diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index 372ccc5f03..1b30ab8e38 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -63,7 +63,19 @@ End Type var selection = new Selection(7, 10); //Selects 'this' declaration - var presenterAction = SetParameters("MyType", implementLet: true); + var ruleTBar = new EncapsulateUDTVariableRule("this") + { + EncapsulateAllUDTMembers = false, + EncapsulateVariable = true, + }; + + var attributes = new EncapsulationAttributes("this", "MyType", "TBar") + { + ImplementLetSetterType = true, + ImplementSetSetterType = false, + }; + + var presenterAction = SetParameters(attributes, ruleTBar); // "MyType", implementLet: true); var actualCode = RefactoredCode(inputCode, selection, presenterAction); StringAssert.Contains("Private this As TBar", actualCode); StringAssert.Contains("this = value", actualCode); @@ -88,12 +100,17 @@ End Type var selection = new Selection(7, 10); //Selects 'this' declaration - var ruleTBar = new EncapsulateUDTVariableRule(); - ruleTBar.VariableName = "this"; + var ruleTBar = new EncapsulateUDTVariableRule("this"); ruleTBar.EncapsulateAllUDTMembers = true; ruleTBar.EncapsulateVariable = true; - var presenterAction = SetParameters("MyType", implementLet: true, rule: ruleTBar); //, encapsulateTypeMembers: true); + var attributes = new EncapsulationAttributes("this", "MyType", "TBar") + { + ImplementLetSetterType = true, + ImplementSetSetterType = false, + }; + + var presenterAction = SetParameters(attributes, ruleTBar); // "MyType", implementLet: true, rule: ruleTBar); //, encapsulateTypeMembers: true); var actualCode = RefactoredCode(inputCode, selection, presenterAction); StringAssert.Contains("Private this As TBar", actualCode); StringAssert.Contains("this = value", actualCode); @@ -103,6 +120,7 @@ End Type StringAssert.Contains($"First = this.First", actualCode); StringAssert.Contains($"this.Second = value", actualCode); StringAssert.Contains($"Second = this.Second", actualCode); + StringAssert.DoesNotContain($"Second = Second", actualCode); } [TestCase("Public")] @@ -127,7 +145,19 @@ End Type var selection = new Selection(4, 10); //Selects 'this' declaration - var presenterAction = SetParameters("MyType", implementLet: true); //, encapsulateTypeMembers: true); + var ruleTBar = new EncapsulateUDTVariableRule("this") + { + EncapsulateAllUDTMembers = true, + EncapsulateVariable = true, + }; + + var attributes = new EncapsulationAttributes("this", "MyType", "TBar") + { + ImplementLetSetterType = true, + ImplementSetSetterType = false, + }; + + var presenterAction = SetParameters(attributes, ruleTBar); // "MyType", implementLet: true, rule: ruleTBar); var actualModuleCode = RefactoredCode( "Class1", selection, @@ -149,6 +179,7 @@ End Type StringAssert.Contains($"First = this.First", actualCode); StringAssert.Contains($"this.Second = value", actualCode); StringAssert.Contains($"Second = this.Second", actualCode); + StringAssert.DoesNotContain($"Second = Second", actualCode); } [Test] @@ -520,8 +551,15 @@ End Sub Sub Bar(ByVal v As Integer) End Sub"; + var attributes = new EncapsulationAttributes() + { + PropertyName = "Name", + ParameterName = "value", + ImplementLetSetterType = true, + ImplementSetSetterType = false, + }; - var presenterAction = SetParameters("Name", implementLet: true); + var presenterAction = SetParameters(attributes); // "Name", implementLet: true); var actualCode = RefactoredCode( "Class1", selection, @@ -680,7 +718,35 @@ private Func SetParameters( model.ParameterName = parameterName; model.ImplementLetSetterType = implementLet; model.ImplementSetSetterType = implementSet; - model.ModifyUDTRule(rule); + if (rule.VariableName != null) + { + model.AddUDTVariableRule(rule); + } + return model; + }; + } + + private Func SetParameters(EncapsulationAttributes attributes) + { + return model => + { + model.PropertyName = attributes.PropertyName; + model.ParameterName = attributes.ParameterName; + model.ImplementLetSetterType = attributes.ImplementLetSetterType; + model.ImplementSetSetterType = attributes.ImplementSetSetterType; + return model; + }; + } + + private Func SetParameters(EncapsulationAttributes attributes, EncapsulateUDTVariableRule rule) + { + return model => + { + model.PropertyName = attributes.PropertyName; + model.ParameterName = attributes.ParameterName; + model.ImplementLetSetterType = attributes.ImplementLetSetterType; + model.ImplementSetSetterType = attributes.ImplementSetSetterType; + model.AddUDTVariableRule(rule); return model; }; } From 106760f110ec27c8234ed8a554d14619c8b01ed9 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Fri, 8 Nov 2019 17:20:09 -0800 Subject: [PATCH 009/461] Supports multiple fields and UDT members --- .../EncapsulateFieldDecorators.cs | 71 ++- .../EncapsulateField/EncapsulateFieldModel.cs | 351 ++++++-------- .../EncapsulateFieldRefactoring.cs | 71 +-- .../FieldEncapsulationAttributes.cs | 360 ++++++++++++++ .../Refactoring/EncapsulateFieldTests.cs | 448 +++++++++++++++--- 5 files changed, 962 insertions(+), 339 deletions(-) create mode 100644 Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs index 3010dd1976..32c0635c9b 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs @@ -13,12 +13,7 @@ public class EncapsulateFieldDeclaration public EncapsulateFieldDeclaration(Declaration declaration) { _decorated = declaration; - EncapsulationAttributes = new EncapsulationAttributes(_decorated); - } - - public static EncapsulateFieldDeclaration Decorate(Declaration declaration) - { - return new EncapsulateFieldDeclaration(declaration); + EncapsulationAttributes = new FieldEncapsulationAttributes(_decorated); } public Declaration Declaration => _decorated; @@ -27,53 +22,89 @@ public static EncapsulateFieldDeclaration Decorate(Declaration declaration) public DeclarationType DeclarationType => _decorated.DeclarationType; - public EncapsulationAttributes EncapsulationAttributes { set; get; } + public IFieldEncapsulationAttributes EncapsulationAttributes { set; get; } } - public class EncapsulatedValueType : EncapsulateFieldDeclaration + public class EncapsulateValueType : EncapsulateFieldDeclaration { - public EncapsulatedValueType(EncapsulateFieldDeclaration declaration) + public EncapsulateValueType(EncapsulateFieldDeclaration declaration) : base(declaration.Declaration) { + EncapsulationAttributes.CanImplementLet = true; + EncapsulationAttributes.CanImplementSet = false; } } - public class EncapsulatedUserDefinedMemberValueType : EncapsulatedValueType + public class EncapsulatedUserDefinedMemberValueType : EncapsulateValueType { - public EncapsulatedUserDefinedMemberValueType(EncapsulatedValueType declaration, UserDefinedTypeField udtVariable) + public EncapsulatedUserDefinedMemberValueType(EncapsulateValueType declaration, EncapsulateUserDefinedType udtVariable) : base(declaration) { - EncapsulationAttributes.FieldName = $"{udtVariable.Declaration.IdentifierName}.{declaration.Declaration.IdentifierName}"; - EncapsulationAttributes.ImplementLetSetterType = true; + EncapsulationAttributes.NewFieldName = $"{udtVariable.Declaration.IdentifierName}.{declaration.Declaration.IdentifierName}"; + EncapsulationAttributes.IsValueType = true; + EncapsulationAttributes.CanImplementLet = true; + EncapsulationAttributes.CanImplementSet = false; + } + + public EncapsulatedUserDefinedMemberValueType(EncapsulateVariantType declaration, EncapsulateUserDefinedType udtVariable) + : base(declaration) + { + EncapsulationAttributes.NewFieldName = $"{udtVariable.Declaration.IdentifierName}.{declaration.Declaration.IdentifierName}"; + EncapsulationAttributes.IsVariantType = true; + EncapsulationAttributes.CanImplementLet = true; + EncapsulationAttributes.CanImplementSet = false; + } + } + + public class EncapsulatedUserDefinedMemberObjectType : EncapsulateFieldDeclaration + { + public EncapsulatedUserDefinedMemberObjectType(EncapsulateObjectType declaration, EncapsulateUserDefinedType udtVariable) + : base(declaration.Declaration) + { + EncapsulationAttributes.NewFieldName = $"{udtVariable.Declaration.IdentifierName}.{declaration.Declaration.IdentifierName}"; + EncapsulationAttributes.IsObjectType = true; + EncapsulationAttributes.CanImplementLet = false; + EncapsulationAttributes.CanImplementSet = true; } } - public class UserDefinedTypeField : EncapsulateFieldDeclaration + + public class EncapsulateUserDefinedType : EncapsulateFieldDeclaration { - public UserDefinedTypeField(Declaration declaration) + public EncapsulateUserDefinedType(Declaration declaration) : base(declaration) { + EncapsulationAttributes.CanImplementLet = true; + EncapsulationAttributes.CanImplementSet = false; } - public UserDefinedTypeField(EncapsulateFieldDeclaration declaration) + public EncapsulateUserDefinedType(EncapsulateFieldDeclaration declaration) : base(declaration.Declaration) { + EncapsulationAttributes.CanImplementLet = true; + EncapsulationAttributes.CanImplementSet = false; } } - public class EncapsulatedVariantType : EncapsulateFieldDeclaration + public class EncapsulateVariantType : EncapsulateFieldDeclaration { - public EncapsulatedVariantType(EncapsulateFieldDeclaration declaration) + public EncapsulateVariantType(EncapsulateFieldDeclaration declaration) : base(declaration.Declaration) { EncapsulationAttributes.CanImplementLet = true; EncapsulationAttributes.CanImplementSet = true; } + public EncapsulateVariantType(Declaration declaration) + : base(declaration) + { + EncapsulationAttributes.CanImplementLet = true; + EncapsulationAttributes.CanImplementSet = true; + } } - public class EncapsulatedObjectType : EncapsulateFieldDeclaration + public class EncapsulateObjectType : EncapsulateFieldDeclaration { - public EncapsulatedObjectType(EncapsulateFieldDeclaration declaration) + public EncapsulateObjectType(EncapsulateFieldDeclaration declaration) : base(declaration.Declaration) { EncapsulationAttributes.CanImplementLet = false; diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index a32539d1d2..93b0358d81 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -10,233 +10,159 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface IEncapsulateFieldAttributes + public class EncapsulateFieldModel : IRefactoringModel { - string FieldName { set; get; } - string PropertyName { set; get; } - string ParameterName { set; get; } - bool ImplementLetSetterType { set; get; } - bool ImplementSetSetterType { set; get; } - bool CanImplementLet { get; } - bool CanImplementSet { get; } - } + private readonly IIndenter _indenter; - public struct EncapsulateUDTVariableRule - { - public EncapsulateUDTVariableRule(string variableName, string propertyName = null, string asTypeName = "Variant") - { - Attributes = new EncapsulationAttributes(variableName, propertyName ?? $"{variableName}_{Tokens.Type}", asTypeName); - EncapsulateVariable = true; - EncapsulateAllUDTMembers = false; - } - public EncapsulationAttributes Attributes { set; get; } - public string VariableName => Attributes?.FieldName ?? string.Empty; - public bool EncapsulateVariable { set; get; } - public bool EncapsulateAllUDTMembers { set; get; } - } + private IDictionary)> _udtFieldToUdtDeclarationMap = new Dictionary)>(); + private IEnumerable UdtFields => _udtFieldToUdtDeclarationMap.Keys; + private IEnumerable UdtFieldMembers(Declaration udtField) => _udtFieldToUdtDeclarationMap[udtField].Item2; - public class EncapsulationAttributes : IEncapsulateFieldAttributes - { - private static string DEFAULT_LET_PARAMETER = "value"; - public EncapsulationAttributes() - { - FieldName = string.Empty; - PropertyName = string.Empty; - AsTypeName = string.Empty; - ParameterName = DEFAULT_LET_PARAMETER; - ImplementLetSetterType = false; - ImplementSetSetterType = false; - CanImplementLet = false; - CanImplementSet = false; - Encapsulate = false; - } + private Dictionary _encapsulateFieldDeclarations = new Dictionary(); - public EncapsulationAttributes(string fieldName, string propertyName, string asTypeName) - { - FieldName = fieldName; - PropertyName = propertyName; - AsTypeName = asTypeName; - ParameterName = DEFAULT_LET_PARAMETER; - ImplementLetSetterType = false; - ImplementSetSetterType = false; - CanImplementLet = true; - CanImplementSet = true; - Encapsulate = false; - } + private EncapsulateFieldDeclaration _userSelectedEncapsulationField; + private Dictionary _udtVariableEncapsulationAttributes = new Dictionary(); - public EncapsulationAttributes(Declaration target) + public EncapsulateFieldModel(Declaration target, IEnumerable allMemberFields, IDictionary)> udtFieldToUdtDeclarationMap, IIndenter indenter) { - FieldName = target.IdentifierName; - PropertyName = target.IdentifierName; - AsTypeName = target.AsTypeName; - ParameterName = DEFAULT_LET_PARAMETER; - ImplementLetSetterType = false; - ImplementSetSetterType = false; - Encapsulate = false; - IsVariant = target.AsTypeName?.Equals(Tokens.Variant) ?? true; - IsValueType = !IsVariant && (SymbolList.ValueTypes.Contains(target.AsTypeName) || - target.DeclarationType == DeclarationType.Enumeration); - CanImplementLet = IsValueType || IsVariant; - CanImplementSet = !(IsValueType || IsVariant); - } + _indenter = indenter; + _udtFieldToUdtDeclarationMap = udtFieldToUdtDeclarationMap; - public EncapsulationAttributes(EncapsulationAttributes attributes) - { - FieldName = attributes.FieldName; - PropertyName = attributes.PropertyName; - AsTypeName = attributes.AsTypeName; - ParameterName = attributes.ParameterName; - ImplementLetSetterType = attributes.ImplementLetSetterType; - ImplementSetSetterType = attributes.ImplementSetSetterType; - CanImplementLet = attributes.CanImplementLet; - CanImplementSet = attributes.CanImplementSet; - IsVariant = attributes.IsVariant; - IsValueType = attributes.IsValueType; - Encapsulate = false; - } + foreach (var field in allMemberFields.Except(UdtFields)) + { + AddEncapsulationField(DecorateDeclaration(field)); + } - public string FieldName { get; set; } - public string PropertyName { get; set; } - public string AsTypeName { get; set; } - public string ParameterName { get; set; } - public bool ImplementLetSetterType { get; set; } - public bool ImplementSetSetterType { get; set; } - - public bool CanImplementLet { get; set; } - public bool CanImplementSet { get; set; } - public bool Encapsulate { get; set; } - public bool IsValueType { private set; get; } - public bool IsVariant { private set; get; } - } + AddUDTEncapsulationFields(udtFieldToUdtDeclarationMap); - public class EncapsulateFieldModel : IRefactoringModel - { - private Dictionary)> _udts = new Dictionary)>(); - private readonly IIndenter _indenter; - private IList _fields = new List(); - private IList _nonUdtVariables = new List(); - private Dictionary _nonUdtVariablesByName = new Dictionary(); - private EncapsulateFieldDeclaration _selectedTarget; + this[target].EncapsulationAttributes.IsFlaggedToEncapsulate = true; + TargetDeclaration = target; + //_userSelectedEncapsulationField = this[target]; + } + + public IEnumerable FlaggedEncapsulationFields => _encapsulateFieldDeclarations.Values.Where(v => v.EncapsulationAttributes.IsFlaggedToEncapsulate); - public EncapsulateFieldModel(Declaration target, IEnumerable nonUdtVariables, IEnumerable<(Declaration udtVariable, Declaration udt, IEnumerable udtMembers)> udtTuples, IIndenter indenter) + private EncapsulateFieldDeclaration DecorateDeclaration(Declaration target) { - _indenter = indenter; + //TODO: Array type fields + var selectedField = new EncapsulateFieldDeclaration(target); - foreach (var variable in _nonUdtVariables) + if (selectedField.EncapsulationAttributes.IsVariantType) { - LoadNonUDTVariable(variable); + return new EncapsulateVariantType(selectedField); } - - foreach (var udtTuple in udtTuples) + else if (selectedField.EncapsulationAttributes.IsObjectType) { - LoadUDTVariable(udtTuple.udtVariable, udtTuple.udt, udtTuple.udtMembers); + return new EncapsulateObjectType(selectedField); } + return new EncapsulateValueType(selectedField); + } - var selectedField = new EncapsulateFieldDeclaration(target); + private EncapsulateFieldDeclaration DecorateUDTVariableDeclaration(Declaration target) + { + return new EncapsulateUserDefinedType(new EncapsulateFieldDeclaration(target)); + } - if (UDTVariables.Contains(target)) - { - _selectedTarget = new UserDefinedTypeField(selectedField); - } - else if (selectedField.EncapsulationAttributes.IsValueType) + private EncapsulateFieldDeclaration DecorateUDTMember(Declaration udtMember, EncapsulateUserDefinedType udtVariable) + { + var selectedField = new EncapsulateFieldDeclaration(udtMember); + if (selectedField.EncapsulationAttributes.IsVariantType) { - _selectedTarget = new EncapsulatedValueType(selectedField); + return new EncapsulatedUserDefinedMemberValueType(new EncapsulateVariantType(selectedField), udtVariable); } - else if (selectedField.EncapsulationAttributes.IsVariant) + else if (selectedField.EncapsulationAttributes.IsObjectType) { - _selectedTarget = new EncapsulatedVariantType(selectedField); + return new EncapsulatedUserDefinedMemberObjectType(new EncapsulateObjectType(selectedField), udtVariable); } - - _selectedTarget.EncapsulationAttributes.Encapsulate = true; - - AddEncapsulationTarget(_selectedTarget); + return new EncapsulatedUserDefinedMemberValueType(new EncapsulateValueType(selectedField), udtVariable); } - private Dictionary _encapsulationAttributesByFieldDeclaration = new Dictionary(); - private Dictionary _encapsulationAttributesByFieldIdentifier = new Dictionary(); - - private Dictionary _udtVariableRules = new Dictionary(); - - public void AddUDTVariableRule(EncapsulateUDTVariableRule udtRule) + public void AddUDTVariableAttributes(IUDTFieldEncapsulationAttributes udtFieldEncapsulationAttributes) { - if (_udtVariableRules.TryGetValue(udtRule.VariableName, out _)) + if (_udtVariableEncapsulationAttributes.TryGetValue(udtFieldEncapsulationAttributes.FieldName, out _)) { - _udtVariableRules[udtRule.VariableName] = udtRule; + _udtVariableEncapsulationAttributes[udtFieldEncapsulationAttributes.FieldName] = udtFieldEncapsulationAttributes; return; } - _udtVariableRules.Add(udtRule.VariableName, udtRule); + _udtVariableEncapsulationAttributes.Add(udtFieldEncapsulationAttributes.FieldName, udtFieldEncapsulationAttributes); } - public bool TryGetUDTVariableRule(string udtVariableName, out EncapsulateUDTVariableRule rule) + public bool TryGetUDTVariableAttributes(string udtVariableName, out IFieldEncapsulationAttributes rule) { - rule = new EncapsulateUDTVariableRule(); - if (_udtVariableRules.ContainsKey(udtVariableName)) + rule = null; + if (_udtVariableEncapsulationAttributes.ContainsKey(udtVariableName)) { - rule = _udtVariableRules[udtVariableName]; + rule = _udtVariableEncapsulationAttributes[udtVariableName]; return true; } return false; } - public IEnumerable UDTVariableRules => _udtVariableRules.Values; - - public IEnumerable UDTVariables => _udts.Keys; - - private void LoadUDTVariable(Declaration udtVariable, Declaration udt, IEnumerable udtMembers) + private void AddUDTEncapsulationFields(IDictionary)> udtFieldToTypeMap) { - _udts.Add(udtVariable, (udt, udtMembers)); - var udtVariableRule = new EncapsulateUDTVariableRule(udtVariable.IdentifierName); - AddUDTVariableRule(udtVariableRule); + foreach (var udtField in udtFieldToTypeMap.Keys) + { + var udtEncapsulation = DecorateUDTVariableDeclaration(udtField); + AddEncapsulationField(udtEncapsulation); + + foreach (var udtMember in UdtFieldMembers(udtField)) + { + AddEncapsulationField(DecorateUDTMember(udtMember, udtEncapsulation as EncapsulateUserDefinedType)); + } + } } - private void LoadNonUDTVariable(Declaration variable) + public EncapsulateFieldDeclaration this[Declaration declaration] { - _nonUdtVariables.Add(variable); - _nonUdtVariablesByName.Add(variable.IdentifierName, variable); + get + { + if (_encapsulateFieldDeclarations.TryGetValue(declaration, out var encapsulateFieldDefinition)) + { + return encapsulateFieldDefinition; + } + return null; + } + set + { + if (_encapsulateFieldDeclarations.ContainsKey(declaration)) + { + _encapsulateFieldDeclarations[declaration] = value; + } + } } - public IEnumerable GetUdtMembers(Declaration udtVariable) + private EncapsulateFieldDeclaration this[string encapsulatedFieldIdentifier] { - if (_udts.TryGetValue(udtVariable, out var value)) + get => _encapsulateFieldDeclarations.Values.Where(efd => efd.Declaration.IdentifierName.Equals(encapsulatedFieldIdentifier)) + .FirstOrDefault(); + set { - return value.Item2; + var key = _encapsulateFieldDeclarations.Keys.Where(k => k.IdentifierName.Equals(encapsulatedFieldIdentifier)) + .FirstOrDefault(); + _encapsulateFieldDeclarations[key] = value; } - return Enumerable.Empty(); } - public IEncapsulateFieldAttributes this[string fieldIdentifier] => _encapsulationAttributesByFieldIdentifier[fieldIdentifier]; - - public IEncapsulateFieldAttributes this[Declaration field] => _encapsulationAttributesByFieldDeclaration[field]; - - public IEnumerable EncapsulationTargets => _fields.Select(f => f.Declaration); // _encapsulationAttributesByFieldDeclaration.Keys; + public IEnumerable EncapsulateFieldDeclarations => _encapsulateFieldDeclarations.Values; - public void AddEncapsulationTarget(EncapsulateFieldDeclaration target) => _fields.Add(target); + public void AddEncapsulationField(EncapsulateFieldDeclaration target) + { + if (_encapsulateFieldDeclarations.ContainsKey(target.Declaration)) + { + _encapsulateFieldDeclarations[target.Declaration] = target; + return; + } + _encapsulateFieldDeclarations.Add(target.Declaration, target); + } public IList PropertiesContent { get { var textBlocks = new List(); - foreach (var field in _fields) + foreach (var field in FlaggedEncapsulationFields) { - switch (field) - { - case EncapsulatedUserDefinedMemberValueType udtMemberType: - if (udtMemberType.EncapsulationAttributes.Encapsulate) - { - textBlocks.Add(BuildPropertiesTextBlock(udtMemberType.Declaration)); - } - break; - case UserDefinedTypeField udtType: - if (udtType.EncapsulationAttributes.Encapsulate) - { - textBlocks.Add(BuildPropertiesTextBlock(udtType.Declaration)); - } - break; - default: - textBlocks.Add(BuildPropertiesTextBlock(field.Declaration)); - break; - } + textBlocks.Add(BuildPropertiesTextBlock(field.Declaration)); } return textBlocks; } @@ -244,12 +170,12 @@ public IList PropertiesContent private string BuildPropertiesTextBlock(Declaration target) { - var attributes = EncapsulationAttributes(target); + var attributes = this[target].EncapsulationAttributes; var generator = new PropertyGenerator { PropertyName = attributes.PropertyName, AsTypeName = attributes.AsTypeName, - BackingField = attributes.FieldName, + BackingField = attributes.NewFieldName, ParameterName = attributes.ParameterName, GenerateSetter = attributes.ImplementSetSetterType, GenerateLetter = attributes.ImplementLetSetterType @@ -258,79 +184,80 @@ private string BuildPropertiesTextBlock(Declaration target) return GetPropertyText(generator); } - private string BuildUDTMemberPropertiesTextBlock(Declaration udtMember) + private string GetPropertyText(PropertyGenerator generator) { - var attributes = EncapsulationAttributes(udtMember); + var propertyTextLines = generator.AllPropertyCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None); + return string.Join(Environment.NewLine, _indenter.Indent(propertyTextLines, true)); + } - var udtVariable = _udts.Keys.Where(k => _udts[k].Item2.Contains(udtMember)).SingleOrDefault(); + //private EncapsulateFieldDeclaration DefaultTarget => _userSelectedEncapsulationField; - var generator = new PropertyGenerator + //Only used by tests....so far + public void UpdateEncapsulationField(IUDTFieldEncapsulationAttributes attributes) + { + this[attributes.FieldName].EncapsulationAttributes = attributes; + foreach ((string Name, bool Encapsulate) in attributes.MemberFlags) { - PropertyName = attributes.PropertyName, - AsTypeName = attributes.AsTypeName, - BackingField = $"{udtVariable.IdentifierName}.{udtMember.IdentifierName}", - ParameterName = attributes.ParameterName, - GenerateSetter = udtMember.IsObject, //model.ImplementSetSetterType, - GenerateLetter = !udtMember.IsObject //model.ImplementLetSetterType - }; - - return GetPropertyText(generator); + this[Name].EncapsulationAttributes.IsFlaggedToEncapsulate = Encapsulate; + } } - private string GetPropertyText(PropertyGenerator generator) + //Only used by tests....so far + public void UpdateEncapsulationField(string variableName, string propertyName, bool encapsulateFlag, string newFieldName = null) { - var propertyTextLines = generator.AllPropertyCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None); - return string.Join(Environment.NewLine, _indenter.Indent(propertyTextLines, true)); + var target = this[variableName]; + target.EncapsulationAttributes.FieldName = variableName; + target.EncapsulationAttributes.PropertyName = propertyName; + target.EncapsulationAttributes.NewFieldName = newFieldName ?? variableName; + target.EncapsulationAttributes.IsFlaggedToEncapsulate = encapsulateFlag; + this[variableName] = target; } - public EncapsulationAttributes EncapsulationAttributes(Declaration target) + //Only used by tests....so far + public void UpdateEncapsulationField(IFieldEncapsulationAttributes attributes) { - foreach ( var field in _fields) - { - if (field.Declaration == target) - { - return field.EncapsulationAttributes; - } - } - return null; + var target = this[attributes.FieldName]; + target.EncapsulationAttributes.FieldName = attributes.FieldName; + target.EncapsulationAttributes.PropertyName = attributes.PropertyName; + target.EncapsulationAttributes.NewFieldName = attributes.NewFieldName ?? attributes.FieldName; + target.EncapsulationAttributes.IsFlaggedToEncapsulate = attributes.IsFlaggedToEncapsulate; + this[attributes.FieldName] = target; } - private EncapsulateFieldDeclaration DefaultTarget => _selectedTarget; - public Declaration TargetDeclaration { - get => DefaultTarget.Declaration; - set => _selectedTarget = new EncapsulateFieldDeclaration(value); + get => _userSelectedEncapsulationField.Declaration; + set => _userSelectedEncapsulationField = _encapsulateFieldDeclarations[value]; } public string PropertyName { - get => DefaultTarget.EncapsulationAttributes.PropertyName; - set => DefaultTarget.EncapsulationAttributes.PropertyName = value; + get => _userSelectedEncapsulationField.EncapsulationAttributes.PropertyName; + set => _userSelectedEncapsulationField.EncapsulationAttributes.PropertyName = value; } public string ParameterName { - get => DefaultTarget.EncapsulationAttributes.ParameterName; - set => DefaultTarget.EncapsulationAttributes.ParameterName = value; + get => _userSelectedEncapsulationField.EncapsulationAttributes.ParameterName; + set => _userSelectedEncapsulationField.EncapsulationAttributes.ParameterName = value; } public bool ImplementLetSetterType { - get => DefaultTarget.EncapsulationAttributes.ImplementLetSetterType; - set => DefaultTarget.EncapsulationAttributes.ImplementLetSetterType = value; + get => _userSelectedEncapsulationField.EncapsulationAttributes.ImplementLetSetterType; + set => _userSelectedEncapsulationField.EncapsulationAttributes.ImplementLetSetterType = value; } public bool ImplementSetSetterType { - get => DefaultTarget.EncapsulationAttributes.ImplementSetSetterType; - set => DefaultTarget.EncapsulationAttributes.ImplementSetSetterType = value; + get => _userSelectedEncapsulationField.EncapsulationAttributes.ImplementSetSetterType; + set => _userSelectedEncapsulationField.EncapsulationAttributes.ImplementSetSetterType = value; } public bool CanImplementLet - => DefaultTarget.EncapsulationAttributes.CanImplementLet; + => _userSelectedEncapsulationField.EncapsulationAttributes.IsValueType || _userSelectedEncapsulationField.EncapsulationAttributes.IsVariantType; public bool CanImplementSet - => DefaultTarget.EncapsulationAttributes.CanImplementSet; + => !_userSelectedEncapsulationField.EncapsulationAttributes.IsValueType && _userSelectedEncapsulationField.EncapsulationAttributes.IsVariantType; } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 833b6bdd9c..1b57438bb2 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -59,24 +59,22 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) throw new InvalidDeclarationTypeException(target); } - var udtVariables = _declarationFinderProvider.DeclarationFinder - .Members(target.QualifiedName.QualifiedModuleName) + var allMemberFields = _declarationFinderProvider.DeclarationFinder + .Members(target.QualifiedModuleName) .Where(v => v.DeclarationType.Equals(DeclarationType.Variable) - && (v.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.UserDefinedType) ?? false)); + && !v.ParentDeclaration.DeclarationType.HasFlag(DeclarationType.Member)); - var udtTuples = udtVariables.Select(uv => GetUDTDefinition(uv)); + var udtFieldToTypeMap = allMemberFields + .Where(v => v.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.UserDefinedType) ?? false) + .Select(uv => CreateUDTTuple(uv)) + .ToDictionary(key => key.UDTVariable, element => (element.UserDefinedType, element.UDTMembers)); - var nonUdtVariables = _declarationFinderProvider.DeclarationFinder - .Members(target.QualifiedName.QualifiedModuleName) - .Where(v => v.DeclarationType.Equals(DeclarationType.Variable) - && !udtVariables.Contains(v) && !v.ParentDeclaration.DeclarationType.HasFlag(DeclarationType.Member)); - - var model = new EncapsulateFieldModel(target, nonUdtVariables, udtTuples, _indenter); + var model = new EncapsulateFieldModel(target, allMemberFields, udtFieldToTypeMap, _indenter); return model; } - private (Declaration UDTVariable, Declaration UserDefinedType, IEnumerable UDTMembers) GetUDTDefinition(Declaration udtVariable) + private (Declaration UDTVariable, Declaration UserDefinedType, IEnumerable UDTMembers) CreateUDTTuple(Declaration udtVariable) { var userDefinedTypeDeclaration = _declarationFinderProvider.DeclarationFinder .UserDeclarations(DeclarationType.UserDefinedType) @@ -89,6 +87,7 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) var udtMembers = _declarationFinderProvider.DeclarationFinder .UserDeclarations(DeclarationType.UserDefinedTypeMember) .Where(utm => userDefinedTypeDeclaration.IdentifierName == utm.ParentDeclaration.IdentifierName); + return (udtVariable, userDefinedTypeDeclaration, udtMembers); } @@ -96,39 +95,14 @@ protected override void RefactorImpl(EncapsulateFieldModel model) { var rewriteSession = RewritingManager.CheckOutCodePaneSession(); - var rules = new Dictionary(); - - foreach (var target in model.EncapsulationTargets) - { - if (model.TryGetUDTVariableRule(target.IdentifierName, out EncapsulateUDTVariableRule rule)) - { - rules.Add(target, rule); - } - } - - var udtVariableTargets = model.EncapsulationTargets.Where(et => rules.ContainsKey(et)).ToList(); - foreach( var udtVariable in udtVariableTargets) - { - var rule = rules[udtVariable]; - if (rule.EncapsulateAllUDTMembers) - { - foreach (var udtMember in model.GetUdtMembers(udtVariable)) - { - var udtMemberField = new EncapsulatedValueType(new EncapsulateFieldDeclaration(udtMember)); - udtMemberField = new EncapsulatedUserDefinedMemberValueType(udtMemberField, new UserDefinedTypeField(udtVariable)); - udtMemberField.EncapsulationAttributes.Encapsulate = true; - model.AddEncapsulationTarget(udtMemberField); - } - } - } + var nonUdtMemberFields = model.FlaggedEncapsulationFields + .Where(efd => efd.DeclarationType.Equals(DeclarationType.Variable)); - foreach (var target in model.EncapsulationTargets) + foreach (var nonUdtMemberField in nonUdtMemberFields) { - if (target.DeclarationType.Equals(DeclarationType.Variable)) - { - EnforceEncapsulatedVariablePrivateAccessibility(target, rewriteSession); - } - UpdateReferences(target, rewriteSession, model.EncapsulationAttributes(target).PropertyName); // model.PropertyName); + var attributes = nonUdtMemberField.EncapsulationAttributes; + EnforceEncapsulatedVariablePrivateAccessibility(nonUdtMemberField.Declaration, attributes, rewriteSession); + UpdateReferences(nonUdtMemberField.Declaration, rewriteSession, attributes.PropertyName); } InsertProperties(model, rewriteSession); @@ -141,11 +115,12 @@ protected override void RefactorImpl(EncapsulateFieldModel model) private void InsertProperties(EncapsulateFieldModel model, IRewriteSession rewriteSession) { - if (!model.EncapsulationTargets.Any()) { return; } + if (!model.FlaggedEncapsulationFields.Any()) { return; } - var qualifiedModuleName = model.EncapsulationTargets.First().QualifiedModuleName; + var qualifiedModuleName = model.FlaggedEncapsulationFields.First().Declaration.QualifiedModuleName; var carriageReturns = $"{Environment.NewLine}{Environment.NewLine}"; + var insertionTokenIndex = _declarationFinderProvider.DeclarationFinder .Members(qualifiedModuleName) .Where(d => d.DeclarationType == DeclarationType.Variable @@ -158,20 +133,20 @@ private void InsertProperties(EncapsulateFieldModel model, IRewriteSession rewri rewriter.InsertAfter(insertionTokenIndex, $"{carriageReturns}{string.Join(carriageReturns, model.PropertiesContent)}"); } - private void EnforceEncapsulatedVariablePrivateAccessibility(Declaration target, IRewriteSession rewriteSession) + private void EnforceEncapsulatedVariablePrivateAccessibility(Declaration target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession) { if (!target.DeclarationType.Equals(DeclarationType.Variable)) { return; } - if (target.Accessibility == Accessibility.Private) { return; } + if (target.Accessibility == Accessibility.Private && attributes.NewFieldName.Equals(target.IdentifierName)) { return; } var rewriter = rewriteSession.CheckOutModuleRewriter(target.QualifiedModuleName); - var newField = $"{Accessibility.Private} {target.IdentifierName} As {target.AsTypeName}"; + var newField = $"{Accessibility.Private} {attributes.NewFieldName} As {target.AsTypeName}"; - if(target.Context.TryGetAncestor(out var varList) + if (target.Context.TryGetAncestor(out var varList) && varList.ChildCount > 1) { rewriter.Remove(target); diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs new file mode 100644 index 0000000000..4e9a7e6836 --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs @@ -0,0 +1,360 @@ +using Rubberduck.Parsing; +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.EncapsulateField +{ + public interface IFieldEncapsulationAttributes + { + string FieldName { get; set; } + string NewFieldName { get; set; } + string PropertyName { get; set; } + string AsTypeName { get; set; } + string ParameterName { get; set; } + bool ImplementLetSetterType { get; set; } + bool ImplementSetSetterType { get; set; } + bool IsFlaggedToEncapsulate { get; set; } + bool IsValueType { get; set; } + bool IsVariantType { get; set; } + bool IsUserDefinedType { set; get; } + bool IsObjectType { set; get; } + bool CanImplementLet { get; set; } + bool CanImplementSet { get; set; } + } + + public interface IUDTFieldEncapsulationAttributes : IFieldEncapsulationAttributes + { + bool MemberEncapsulationFlag(string name); + bool EncapsulateAllUDTMembers { get; set; } + IEnumerable<(string Name, bool Encapsulate)> MemberFlags { get; } + } + + public class FieldEncapsulationAttributes : IFieldEncapsulationAttributes + { + private static string DEFAULT_LET_PARAMETER = "value"; + + //Only used by tests + public FieldEncapsulationAttributes() { } + + public FieldEncapsulationAttributes(Declaration target, string newFieldName = null, string parameterName = null) + { + FieldName = target.IdentifierName; + NewFieldName = newFieldName ?? target.IdentifierName; + PropertyName = target.IdentifierName; + AsTypeName = target.AsTypeName; + ParameterName = parameterName ?? DEFAULT_LET_PARAMETER; + IsFlaggedToEncapsulate = false; + IsVariantType = target.AsTypeName?.Equals(Tokens.Variant) ?? true; + IsValueType = !IsVariantType && (SymbolList.ValueTypes.Contains(target.AsTypeName) || + target.DeclarationType == DeclarationType.Enumeration); + IsObjectType = target.IsObject; + IsUserDefinedType = false; + ImplementLetSetterType = !IsObjectType && (IsUserDefinedType || IsValueType || IsVariantType); + ImplementSetSetterType = IsObjectType || !IsUserDefinedType && !IsValueType && IsVariantType; + CanImplementLet = false; + CanImplementSet = false; + } + + public FieldEncapsulationAttributes(IFieldEncapsulationAttributes attributes) + { + FieldName = attributes.FieldName; + NewFieldName = attributes.NewFieldName ?? attributes.FieldName; + PropertyName = attributes.PropertyName; + AsTypeName = attributes.AsTypeName; + ParameterName = attributes.ParameterName; + IsFlaggedToEncapsulate = attributes.IsFlaggedToEncapsulate; + IsVariantType = attributes.IsVariantType; + IsValueType = attributes.IsValueType; + IsUserDefinedType = true; + IsObjectType = attributes.IsObjectType; + ImplementLetSetterType = attributes.ImplementLetSetterType; + ImplementSetSetterType = attributes.ImplementSetSetterType; + } + + public string FieldName { get; set; } + + private string _newFieldName; + public string NewFieldName + { + get => _newFieldName ?? FieldName; + set => _newFieldName = value; + } + public string PropertyName { get; set; } + public string AsTypeName { get; set; } + public string ParameterName { get; set; } = DEFAULT_LET_PARAMETER; + + private bool? _implLet; + public bool ImplementLetSetterType + { + get => _implLet.HasValue ? _implLet.Value : IsValueType || IsVariantType || IsUserDefinedType; + set => _implLet = value; + } + + private bool? _implSet; + public bool ImplementSetSetterType + { + get => _implSet.HasValue? _implSet.Value : !(IsValueType || IsUserDefinedType) && IsVariantType; + set => _implSet = value; + } + + public bool IsFlaggedToEncapsulate { get; set; } + public bool IsValueType { set; get; } + public bool IsVariantType { set; get; } + public bool IsUserDefinedType { set; get; } + + private bool? _isObjectType; + public bool IsObjectType + { + get => _isObjectType.HasValue ? _isObjectType.Value : !(IsValueType || IsVariantType); + set => _isObjectType = value; + } + public bool CanImplementLet { get; set; } + public bool CanImplementSet { get; set; } + } + + public class UDTFieldEncapsulationAttributes : IUDTFieldEncapsulationAttributes + { + public UDTFieldEncapsulationAttributes(FieldEncapsulationAttributes attributes, IEnumerable udtMemberNames) + { + _attributes = attributes; + EncapsulateAllUDTMembers = false; + IsUserDefinedType = true; + + foreach (var udtMemberName in udtMemberNames) + { + if (!_memberEncapsulationFlags.ContainsKey(udtMemberName)) + { + _memberEncapsulationFlags.Add(udtMemberName, false); + } + } + } + + //TODO: Copy ctor may not every be needed + public UDTFieldEncapsulationAttributes(IUDTFieldEncapsulationAttributes attributes) + { + FieldName = attributes.FieldName; + NewFieldName = attributes.NewFieldName ?? attributes.FieldName; + PropertyName = attributes.PropertyName; + AsTypeName = attributes.AsTypeName; + ParameterName = attributes.ParameterName; + IsFlaggedToEncapsulate = attributes.IsFlaggedToEncapsulate; + IsVariantType = attributes.IsVariantType; + IsValueType = attributes.IsValueType; + IsUserDefinedType = true; + ImplementLetSetterType = attributes.ImplementLetSetterType; + ImplementSetSetterType = attributes.ImplementSetSetterType; + + //TODO: Dumb to have a dictionary here - it is a tuple at the moment(!?) + _memberEncapsulationFlags = attributes.MemberFlags.ToDictionary(k => k.Name, e => e.Encapsulate); + } + + private IFieldEncapsulationAttributes _attributes { set; get; } + private Dictionary _memberEncapsulationFlags = new Dictionary(); + + //Only used by tests + public void FlagUdtMemberEncapsulation(bool encapsulateFlag, params string[] names) + { + foreach (var name in names) + { + if (_memberEncapsulationFlags.ContainsKey(name)) + { + _memberEncapsulationFlags[name] = encapsulateFlag; + } + else + { + _memberEncapsulationFlags.Add(name, encapsulateFlag); + } + } + } + + public bool EncapsulateAllUDTMembers + { + set => SetEncapsulationFlagForAllMembers(value); + get => _memberEncapsulationFlags.Values.All(v => v == true); + } + + public string FieldName + { + get => _attributes.FieldName; + set => _attributes.FieldName = value; + } + + public string PropertyName + { + get => _attributes.PropertyName; + set => _attributes.PropertyName = value; + } + + public string NewFieldName + { + get => _attributes.NewFieldName; + set => _attributes.NewFieldName = value; + } + + public string AsTypeName + { + get => _attributes.AsTypeName; + set => _attributes.AsTypeName = value; + } + public string ParameterName + { + get => _attributes.ParameterName; + set => _attributes.ParameterName = value; + } + public bool ImplementLetSetterType + { + get => _attributes.ImplementLetSetterType; + set => _attributes.ImplementLetSetterType = value; + } + + public bool ImplementSetSetterType + { + get => _attributes.ImplementSetSetterType; + set => _attributes.ImplementSetSetterType = value; + } + + public bool IsFlaggedToEncapsulate + { + get => _attributes.IsFlaggedToEncapsulate; + set => _attributes.IsFlaggedToEncapsulate = value; + } + + public bool IsValueType + { + get => _attributes.IsValueType; + set => _attributes.IsValueType = value; + } + + public bool IsVariantType + { + get => _attributes.IsVariantType; + set => _attributes.IsVariantType = value; + } + + public bool IsUserDefinedType + { + get => _attributes.IsUserDefinedType; + set => _attributes.IsUserDefinedType = value; + } + + public bool IsObjectType + { + get => _attributes.IsObjectType; + set => _attributes.IsObjectType = value; + } + + public bool CanImplementLet { get; set; } + public bool CanImplementSet { get; set; } + + private void SetEncapsulationFlagForAllMembers(bool flag) + { + foreach (var key in _memberEncapsulationFlags.Keys.ToList()) + { + _memberEncapsulationFlags[key] = flag; + } + } + + public IEnumerable<(string Name, bool Encapsulate)> MemberFlags + { + get + { + var results = new List<(string Name, bool Encapsulate)>(); + foreach (var name in _memberEncapsulationFlags.Keys) + { + results.Add((name, _memberEncapsulationFlags[name])); + } + return results; + } + } + + public bool MemberEncapsulationFlag(string name) + { + return _memberEncapsulationFlags.ContainsKey(name) ? _memberEncapsulationFlags[name] : false; + } + } + + //public class UDTMemberEncapsulationAttributes : IFieldEncapsulationAttributes + //{ + // public UDTMemberEncapsulationAttributes(IFieldEncapsulationAttributes attributes) + // { + // _attributes = attributes; + // } + + // private IFieldEncapsulationAttributes _attributes { set; get; } + + // public string FieldName + // { + // get => _attributes.FieldName; + // set => _attributes.FieldName = value; + // } + + // public string PropertyName + // { + // get => _attributes.PropertyName; + // set => _attributes.PropertyName = value; + // } + + // public string NewFieldName + // { + // get => _attributes.NewFieldName; + // set => _attributes.NewFieldName = value; + // } + + // public string AsTypeName + // { + // get => _attributes.AsTypeName; + // set => _attributes.AsTypeName = value; + // } + // public string ParameterName + // { + // get => _attributes.ParameterName; + // set => _attributes.ParameterName = value; + // } + // public bool ImplementLetSetterType + // { + // get => _attributes.ImplementLetSetterType; + // set => _attributes.ImplementLetSetterType = value; + // } + + // public bool ImplementSetSetterType + // { + // get => _attributes.ImplementSetSetterType; + // set => _attributes.ImplementSetSetterType = value; + // } + // public bool IsFlaggedToEncapsulate + // { + // get => _attributes.IsFlaggedToEncapsulate; + // set => _attributes.IsFlaggedToEncapsulate = value; + // } + + // public bool IsValueType + // { + // get => _attributes.IsValueType; + // set => _attributes.IsValueType = value; + // } + + // public bool IsVariantType + // { + // get => _attributes.IsVariantType; + // set => _attributes.IsVariantType = value; + // } + + // public bool IsUserDefinedType + // { + // get => _attributes.IsUserDefinedType; + // set => _attributes.IsUserDefinedType = value; + // } + + // public bool IsObjectType + // { + // get => _attributes.IsObjectType; + // set => _attributes.IsObjectType = value; + // } + // //public bool IsObjectType => _attributes.IsObjectType; + //} +} diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index 1b30ab8e38..580e48f5e9 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -13,16 +13,18 @@ using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings.Exceptions; using Rubberduck.VBEditor.Utility; +using System.Collections.Generic; namespace RubberduckTests.Refactoring { [TestFixture] public class EncapsulateFieldTests : InteractiveRefactoringTestBase { - [Test] + [TestCase("fizz")] + [TestCase("mFizz")] [Category("Refactorings")] [Category("Encapsulate Field")] - public void EncapsulatePublicField_WithLetter() + public void EncapsulatePublicField_WithLet(string newFieldName) { //Input const string inputCode = @@ -30,22 +32,54 @@ public void EncapsulatePublicField_WithLetter() var selection = new Selection(1, 1); //Expectation - const string expectedCode = - @"Private fizz As Integer + string expectedCode = + $@"Private {newFieldName} As Integer Public Property Get Name() As Integer - Name = fizz + Name = {newFieldName} End Property Public Property Let Name(ByVal value As Integer) - fizz = value + {newFieldName} = value End Property "; - var presenterAction = SetParameters("Name", implementLet: true); + var presenterAction = SetParameters(("fizz", "Name", true, newFieldName)); var actualCode = RefactoredCode(inputCode, selection, presenterAction); Assert.AreEqual(expectedCode, actualCode); } + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulateMultipleFields() + { + //Input + const string inputCode = +@"Public fizz As Integer +Public baz As String +Public buzz As Boolean"; + + var selection = new Selection(1, 1); + + var presenterAction = SetParameters(("fizz", "FizzProp", true), ("baz", "BazProp", true), ("buzz", "BuzzProp", true)); + var actualCode = RefactoredCode(inputCode, selection, presenterAction); + StringAssert.Contains("Private fizz As Integer", actualCode); + StringAssert.Contains("Private baz As String", actualCode); + StringAssert.Contains("Private buzz As Boolean", actualCode); + StringAssert.Contains("Property Get FizzProp() As Integer", actualCode); + StringAssert.Contains("FizzProp = fizz", actualCode); + StringAssert.Contains("Let FizzProp(ByVal value As Integer)", actualCode); + StringAssert.Contains("fizz = value", actualCode); + StringAssert.Contains("Property Get BazProp() As String", actualCode); + StringAssert.Contains("BazProp = baz", actualCode); + StringAssert.Contains("Let BazProp(ByVal value As String)", actualCode); + StringAssert.Contains("baz = value", actualCode); + StringAssert.Contains("Property Get BuzzProp() As Boolean", actualCode); + StringAssert.Contains("BuzzProp = buzz", actualCode); + StringAssert.Contains("Let BuzzProp(ByVal value As Boolean)", actualCode); + StringAssert.Contains("buzz = value", actualCode); + } + [TestCase("Public")] [TestCase("Private")] [Category("Refactorings")] @@ -63,19 +97,20 @@ End Type var selection = new Selection(7, 10); //Selects 'this' declaration - var ruleTBar = new EncapsulateUDTVariableRule("this") - { - EncapsulateAllUDTMembers = false, - EncapsulateVariable = true, - }; - var attributes = new EncapsulationAttributes("this", "MyType", "TBar") + var attributes = new FieldEncapsulationAttributes() { - ImplementLetSetterType = true, - ImplementSetSetterType = false, + FieldName = "this", + PropertyName = "MyType", + AsTypeName = "TBar", + IsValueType = true, + IsFlaggedToEncapsulate = true }; - var presenterAction = SetParameters(attributes, ruleTBar); // "MyType", implementLet: true); + var thisEncapsulationAttributes = new UDTFieldEncapsulationAttributes(attributes, new string[] { "First", "Second" }); + thisEncapsulationAttributes.EncapsulateAllUDTMembers = false; + + var presenterAction = SetParameters(thisEncapsulationAttributes); var actualCode = RefactoredCode(inputCode, selection, presenterAction); StringAssert.Contains("Private this As TBar", actualCode); StringAssert.Contains("this = value", actualCode); @@ -83,11 +118,88 @@ End Type StringAssert.DoesNotContain($"this.First = value", actualCode); } + [TestCase("First")] + [TestCase("Second")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulateAllMembersFlag(string memberToEncapsulate) + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +Private this As TBar"; + + var selection = new Selection(7, 10); //Selects 'this' declaration + + + var attributes = new FieldEncapsulationAttributes() + { + FieldName = "this", + PropertyName = "MyType", + AsTypeName = "TBar", + IsFlaggedToEncapsulate = true, + IsValueType = true, + }; + + var udtEncapsulationAttributes = new UDTFieldEncapsulationAttributes(attributes, new string[] { "First", "Second" }); + udtEncapsulationAttributes.EncapsulateAllUDTMembers = true; + Assert.IsTrue(udtEncapsulationAttributes.EncapsulateAllUDTMembers); + + udtEncapsulationAttributes.FlagUdtMemberEncapsulation(false, memberToEncapsulate); + Assert.IsFalse(udtEncapsulationAttributes.EncapsulateAllUDTMembers); + + udtEncapsulationAttributes.FlagUdtMemberEncapsulation(true, memberToEncapsulate); + Assert.IsTrue(udtEncapsulationAttributes.EncapsulateAllUDTMembers); + } + + [TestCase("First")] + [TestCase("Second")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulateUserDefinedTypeMembers_Subset(string memberToEncapsulate) + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +Private this As TBar"; + + var selection = new Selection(7, 10); //Selects 'this' declaration + + + var attributes = new FieldEncapsulationAttributes() + { + FieldName = "this", + PropertyName = "MyType", + AsTypeName = "TBar", + IsFlaggedToEncapsulate = true, + IsValueType = true, + }; + + var udtAttributes = new UDTFieldEncapsulationAttributes(attributes, new string[] { "First", "Second" }); + udtAttributes.FlagUdtMemberEncapsulation(true, memberToEncapsulate); + + Assert.IsFalse(udtAttributes.EncapsulateAllUDTMembers); + + var presenterAction = SetParameters(udtAttributes); + var actualCode = RefactoredCode(inputCode, selection, presenterAction); + StringAssert.Contains($"this.{memberToEncapsulate} = value", actualCode); + StringAssert.Contains($"{memberToEncapsulate} = this.{memberToEncapsulate}", actualCode); + } + + [TestCase("Public")] [TestCase("Private")] [Category("Refactorings")] [Category("Encapsulate Field")] - public void EncapsulateUserDefinedTypeMembers(string accessibility) + public void EncapsulateUserDefinedTypeMember(string accessibility) { string inputCode = $@" @@ -100,17 +212,21 @@ End Type var selection = new Selection(7, 10); //Selects 'this' declaration - var ruleTBar = new EncapsulateUDTVariableRule("this"); - ruleTBar.EncapsulateAllUDTMembers = true; - ruleTBar.EncapsulateVariable = true; - var attributes = new EncapsulationAttributes("this", "MyType", "TBar") + var attributes = new FieldEncapsulationAttributes() { - ImplementLetSetterType = true, - ImplementSetSetterType = false, + FieldName = "this", + PropertyName = "MyType", + AsTypeName = "TBar", + IsFlaggedToEncapsulate = true, }; - var presenterAction = SetParameters(attributes, ruleTBar); // "MyType", implementLet: true, rule: ruleTBar); //, encapsulateTypeMembers: true); + var udtFieldAttributes = new UDTFieldEncapsulationAttributes(attributes, new string[] { "First", "Second" }); + udtFieldAttributes.EncapsulateAllUDTMembers = true; + + Assert.IsTrue(udtFieldAttributes.EncapsulateAllUDTMembers); + + var presenterAction = SetParameters(udtFieldAttributes); var actualCode = RefactoredCode(inputCode, selection, presenterAction); StringAssert.Contains("Private this As TBar", actualCode); StringAssert.Contains("this = value", actualCode); @@ -123,6 +239,157 @@ End Type StringAssert.DoesNotContain($"Second = Second", actualCode); } + [TestCase("Public")] + [TestCase("Private")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulateUserDefinedTypeMember_ContainsObjects(string accessibility) + { + string inputCode = +$@" +Private Type TBar + First As Class1 + Second As Long +End Type + +{accessibility} this As TBar"; + + string class1Code = +@"Option Explicit + +Public Sub Foo() +End Sub +"; + + var selection = new Selection(7, 10); //Selects 'this' declaration + + + var attributes = new FieldEncapsulationAttributes() + { + FieldName = "this", + PropertyName = "MyType", + AsTypeName = "TBar", + IsFlaggedToEncapsulate = true, + }; + + var udtFieldAttributes = new UDTFieldEncapsulationAttributes(attributes, new string[] { "First", "Second" }); + udtFieldAttributes.EncapsulateAllUDTMembers = true; + + Assert.IsTrue(udtFieldAttributes.EncapsulateAllUDTMembers); + + var presenterAction = SetParameters(udtFieldAttributes); + var actualModuleCode = RefactoredCode( + "Module1", + selection, + presenterAction, + null, + false, + ("Class1", class1Code, ComponentType.ClassModule), + ("Module1", inputCode, ComponentType.StandardModule)); + + var actualCode = actualModuleCode["Module1"]; + + StringAssert.Contains("Private this As TBar", actualCode); + StringAssert.Contains("this = value", actualCode); + StringAssert.Contains("MyType = this", actualCode); + StringAssert.Contains("Property Set First(ByVal value As Class1)", actualCode); + StringAssert.Contains("Property Get First() As Class1", actualCode); + StringAssert.Contains($"Set this.First = value", actualCode); + StringAssert.Contains($"Set First = this.First", actualCode); + StringAssert.Contains($"this.Second = value", actualCode); + StringAssert.Contains($"Second = this.Second", actualCode); + StringAssert.DoesNotContain($"Second = Second", actualCode); + } + + [TestCase("Public")] + [TestCase("Private")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulateUserDefinedTypeMember_ContainsVariant(string accessibility) + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Variant +End Type + +{accessibility} this As TBar"; + + var selection = new Selection(7, 10); //Selects 'this' declaration + + + var attributes = new FieldEncapsulationAttributes() + { + FieldName = "this", + PropertyName = "MyType", + AsTypeName = "TBar", + IsFlaggedToEncapsulate = true, + }; + + var udtFieldAttributes = new UDTFieldEncapsulationAttributes(attributes, new string[] { "First", "Second" }); + udtFieldAttributes.EncapsulateAllUDTMembers = true; + + Assert.IsTrue(udtFieldAttributes.EncapsulateAllUDTMembers); + + var presenterAction = SetParameters(udtFieldAttributes); + var actualCode = RefactoredCode(inputCode, selection, presenterAction); + StringAssert.Contains("Private this As TBar", actualCode); + StringAssert.Contains("this = value", actualCode); + StringAssert.Contains("MyType = this", actualCode); + Assert.AreEqual(actualCode.IndexOf("MyType = this"), actualCode.LastIndexOf("MyType = this")); + StringAssert.Contains($"this.First = value", actualCode); + StringAssert.Contains($"First = this.First", actualCode); + StringAssert.Contains($"IsObject", actualCode); + StringAssert.Contains($"this.Second = value", actualCode); + StringAssert.Contains($"Second = this.Second", actualCode); + StringAssert.DoesNotContain($"Second = Second", actualCode); + } + + [TestCase("Public", "Public")] + [TestCase("Private", "Private")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulateUserDefinedTypeMembersOnly(string accessibility, string expectedAccessibility) + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +{accessibility} this As TBar"; + + var selection = new Selection(7, 10); //Selects 'this' declaration + + + var attributes = new FieldEncapsulationAttributes() + { + FieldName = "this", + PropertyName = "MyType", + AsTypeName = "TBar", + IsFlaggedToEncapsulate = false, + IsValueType = true, + }; + + var udtFieldAttributes = new UDTFieldEncapsulationAttributes(attributes, new string[] { "First", "Second" }); + udtFieldAttributes.EncapsulateAllUDTMembers = true; + + Assert.IsTrue(udtFieldAttributes.EncapsulateAllUDTMembers); + + var presenterAction = SetParameters(udtFieldAttributes); + var actualCode = RefactoredCode(inputCode, selection, presenterAction); + StringAssert.Contains($"{expectedAccessibility} this As TBar", actualCode); + StringAssert.DoesNotContain("this = value", actualCode); + StringAssert.DoesNotContain("MyType = this", actualCode); + StringAssert.Contains($"this.First = value", actualCode); + StringAssert.Contains($"First = this.First", actualCode); + StringAssert.Contains($"this.Second = value", actualCode); + StringAssert.Contains($"Second = this.Second", actualCode); + StringAssert.DoesNotContain($"Second = Second", actualCode); + } + [TestCase("Public")] [TestCase("Private")] [Category("Refactorings")] @@ -145,19 +412,21 @@ End Type var selection = new Selection(4, 10); //Selects 'this' declaration - var ruleTBar = new EncapsulateUDTVariableRule("this") + var attributes = new FieldEncapsulationAttributes() { - EncapsulateAllUDTMembers = true, - EncapsulateVariable = true, + FieldName = "this", + PropertyName = "MyType", + AsTypeName = "TBar", + IsFlaggedToEncapsulate = true, + IsValueType = true, }; - var attributes = new EncapsulationAttributes("this", "MyType", "TBar") + var udtFieldAttributes = new UDTFieldEncapsulationAttributes(attributes, new string[] { "First", "Second" }) { - ImplementLetSetterType = true, - ImplementSetSetterType = false, + EncapsulateAllUDTMembers = true, }; - var presenterAction = SetParameters(attributes, ruleTBar); // "MyType", implementLet: true, rule: ruleTBar); + var presenterAction = SetParameters(udtFieldAttributes); var actualModuleCode = RefactoredCode( "Class1", selection, @@ -182,6 +451,53 @@ End Type StringAssert.DoesNotContain($"Second = Second", actualCode); } + [TestCase("Public")] + [TestCase("Private")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulateUserDefinedTypeMembers_ObjectField(string accessibility) + { + string inputCode = +$@" +Option Explicit + +{accessibility} mTheClass As Class1"; + + string classContent = +$@" +Option Explicit + +Private Sub Class_Initialize() +End Sub +"; + + var selection = new Selection(4, 10); //Selects 'mTheClass' declaration + + var attributes = new FieldEncapsulationAttributes() + { + FieldName = "mTheClass", + PropertyName = "TheClass", + AsTypeName = "Class1", + IsFlaggedToEncapsulate = true, + }; + + var presenterAction = SetParameters(attributes); + var actualModuleCode = RefactoredCode( + "Module1", + selection, + presenterAction, + null, + false, + ("Class1", classContent, ComponentType.ClassModule), + ("Module1", inputCode, ComponentType.StandardModule)); + + var actualCode = actualModuleCode["Module1"]; + + StringAssert.Contains("Private mTheClass As Class1", actualCode); + StringAssert.Contains("Set mTheClass = value", actualCode); + StringAssert.Contains("TheClass = mTheClass", actualCode); + } + [Test] [Category("Refactorings")] [Category("Encapsulate Field")] @@ -458,10 +774,11 @@ End Property Assert.AreEqual(expectedCode, actualCode); } - [Test] + [TestCase("fizz")] + [TestCase("mFizz")] [Category("Refactorings")] [Category("Encapsulate Field")] - public void EncapsulatePublicField_FieldHasReferences() + public void EncapsulatePublicField_FieldHasReferences(string newName) { //Input const string inputCode = @@ -477,15 +794,15 @@ Sub Bar(ByVal name As Integer) var selection = new Selection(1, 1); //Expectation - const string expectedCode = - @"Private fizz As Integer + string expectedCode = + $@"Private {newName} As Integer Public Property Get Name() As Integer - Name = fizz + Name = {newName} End Property Public Property Let Name(ByVal value As Integer) - fizz = value + {newName} = value End Property @@ -496,7 +813,7 @@ End Sub Sub Bar(ByVal name As Integer) End Sub"; - var presenterAction = SetParameters("Name", implementLet: true); + var presenterAction = SetParameters(("fizz", "Name", true, newName)); var actualCode = RefactoredCode(inputCode, selection, presenterAction); Assert.AreEqual(expectedCode, actualCode); } @@ -551,15 +868,16 @@ End Sub Sub Bar(ByVal v As Integer) End Sub"; - var attributes = new EncapsulationAttributes() + var attributes = new FieldEncapsulationAttributes() { + FieldName = "fizz", PropertyName = "Name", ParameterName = "value", - ImplementLetSetterType = true, - ImplementSetSetterType = false, + IsFlaggedToEncapsulate = true, + IsValueType = true, }; - var presenterAction = SetParameters(attributes); // "Name", implementLet: true); + var presenterAction = SetParameters(attributes); var actualCode = RefactoredCode( "Class1", selection, @@ -709,8 +1027,7 @@ private Func SetParameters( string propertyName, bool implementSet = false, bool implementLet = false, - string parameterName = "value", - EncapsulateUDTVariableRule rule = new EncapsulateUDTVariableRule()) + string parameterName = "value") { return model => { @@ -718,35 +1035,48 @@ private Func SetParameters( model.ParameterName = parameterName; model.ImplementLetSetterType = implementLet; model.ImplementSetSetterType = implementSet; - if (rule.VariableName != null) - { - model.AddUDTVariableRule(rule); - } return model; }; } - private Func SetParameters(EncapsulationAttributes attributes) + private Func SetParameters(FieldEncapsulationAttributes attributes) + { + return model => + { + model.UpdateEncapsulationField(attributes); + return model; + }; + } + + private Func SetParameters(IUDTFieldEncapsulationAttributes udtAttributes) + { + return model => + { + model.UpdateEncapsulationField(udtAttributes); + return model; + }; + } + + private Func SetParameters(params (string variableName, string propertyName, bool encapsulateFlag)[] namePairs) { return model => { - model.PropertyName = attributes.PropertyName; - model.ParameterName = attributes.ParameterName; - model.ImplementLetSetterType = attributes.ImplementLetSetterType; - model.ImplementSetSetterType = attributes.ImplementSetSetterType; + foreach (var pair in namePairs) + { + model.UpdateEncapsulationField(pair.variableName, pair.propertyName, pair.encapsulateFlag); + } return model; }; } - private Func SetParameters(EncapsulationAttributes attributes, EncapsulateUDTVariableRule rule) + private Func SetParameters(params (string variableName, string propertyName, bool encapsulateFlag, string newFieldName)[] tuples) { return model => { - model.PropertyName = attributes.PropertyName; - model.ParameterName = attributes.ParameterName; - model.ImplementLetSetterType = attributes.ImplementLetSetterType; - model.ImplementSetSetterType = attributes.ImplementSetSetterType; - model.AddUDTVariableRule(rule); + foreach (var tuple in tuples) + { + model.UpdateEncapsulationField(tuple.variableName, tuple.propertyName, tuple.encapsulateFlag, tuple.newFieldName); + } return model; }; } From 056ac2b1ca6a8ad6b0b7282812a4f6fae62b411a Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Fri, 8 Nov 2019 22:25:14 -0800 Subject: [PATCH 010/461] Added support for Array fields --- .../EncapsulateFieldDecorators.cs | 17 ++- .../EncapsulateField/EncapsulateFieldModel.cs | 4 + .../EncapsulateFieldRefactoring.cs | 30 ++++- .../FieldEncapsulationAttributes.cs | 34 ++++- .../Refactoring/EncapsulateFieldTests.cs | 125 +++++++++++++++++- 5 files changed, 197 insertions(+), 13 deletions(-) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs index 32c0635c9b..d6541b2bae 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs @@ -1,4 +1,5 @@ -using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Symbols; using System; using System.Collections.Generic; using System.Linq; @@ -111,4 +112,18 @@ public EncapsulateObjectType(EncapsulateFieldDeclaration declaration) EncapsulationAttributes.CanImplementSet = true; } } + + public class EncapsulateArrayType : EncapsulateFieldDeclaration + { + public EncapsulateArrayType(EncapsulateFieldDeclaration declaration) + : base(declaration.Declaration) + { + EncapsulationAttributes.CanImplementLet = false; + EncapsulationAttributes.CanImplementSet = false; + EncapsulationAttributes.IsArray = true; + EncapsulationAttributes.AsTypeName = Tokens.Variant; + EncapsulationAttributes.ImplementLetSetterType = false; + EncapsulationAttributes.ImplementSetSetterType = false; + } + } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index 93b0358d81..b827d2b03f 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -55,6 +55,10 @@ private EncapsulateFieldDeclaration DecorateDeclaration(Declaration target) { return new EncapsulateObjectType(selectedField); } + else if (selectedField.EncapsulationAttributes.IsArray) + { + return new EncapsulateArrayType(selectedField); + } return new EncapsulateValueType(selectedField); } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 1b57438bb2..aef9e39581 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -140,21 +140,43 @@ private void EnforceEncapsulatedVariablePrivateAccessibility(Declaration target, return; } - if (target.Accessibility == Accessibility.Private && attributes.NewFieldName.Equals(target.IdentifierName)) { return; } - var rewriter = rewriteSession.CheckOutModuleRewriter(target.QualifiedModuleName); - var newField = $"{Accessibility.Private} {attributes.NewFieldName} As {target.AsTypeName}"; + if (target.Accessibility == Accessibility.Private && attributes.NewFieldName.Equals(target.IdentifierName)) + { + if (!target.Context.TryGetChildContext(out _)) + { + rewriter.InsertAfter(target.Context.Stop.TokenIndex, $" {Tokens.As} {target.AsTypeName}"); + } + return; + } if (target.Context.TryGetAncestor(out var varList) && varList.ChildCount > 1) { rewriter.Remove(target); + + var arrayDeclaration = target.Context.GetText().Split(new string[] { $" {Tokens.As} " }, StringSplitOptions.None); + var arrayIdentiferAndDimension = arrayDeclaration[0].Replace(attributes.FieldName, attributes.NewFieldName); + + var newField = target.IsArray ? $"{Accessibility.Private} {arrayIdentiferAndDimension} {Tokens.As} {target.AsTypeName}" + : $"{Accessibility.Private} {attributes.NewFieldName} As {target.AsTypeName}"; + rewriter.InsertAfter(varList.Stop.TokenIndex, $"{Environment.NewLine}{newField}"); } else { - rewriter.Replace(target.Context.GetAncestor(), newField); + var identifierContext = target.Context.GetChild(); + var variableStmtContext = target.Context.GetAncestor(); + var visibilityContext = variableStmtContext.GetChild(); + + rewriter.Replace(visibilityContext, Tokens.Private); + rewriter.Replace(identifierContext, attributes.NewFieldName); + + if (!target.Context.TryGetChildContext(out _)) + { + rewriter.InsertAfter(target.Context.Stop.TokenIndex, $" {Tokens.As} {target.AsTypeName}"); + } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs index 4e9a7e6836..74663cd835 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs @@ -22,6 +22,7 @@ public interface IFieldEncapsulationAttributes bool IsValueType { get; set; } bool IsVariantType { get; set; } bool IsUserDefinedType { set; get; } + bool IsArray { set; get; } bool IsObjectType { set; get; } bool CanImplementLet { get; set; } bool CanImplementSet { get; set; } @@ -54,8 +55,9 @@ public FieldEncapsulationAttributes(Declaration target, string newFieldName = nu target.DeclarationType == DeclarationType.Enumeration); IsObjectType = target.IsObject; IsUserDefinedType = false; - ImplementLetSetterType = !IsObjectType && (IsUserDefinedType || IsValueType || IsVariantType); - ImplementSetSetterType = IsObjectType || !IsUserDefinedType && !IsValueType && IsVariantType; + IsArray = target.IsArray; + ImplementLetSetterType = UpdateFieldUsingLet(); + ImplementSetSetterType = UpdateFieldUsingSet(); CanImplementLet = false; CanImplementSet = false; } @@ -70,7 +72,8 @@ public FieldEncapsulationAttributes(IFieldEncapsulationAttributes attributes) IsFlaggedToEncapsulate = attributes.IsFlaggedToEncapsulate; IsVariantType = attributes.IsVariantType; IsValueType = attributes.IsValueType; - IsUserDefinedType = true; + IsUserDefinedType = attributes.IsUserDefinedType; + IsArray = attributes.IsArray; IsObjectType = attributes.IsObjectType; ImplementLetSetterType = attributes.ImplementLetSetterType; ImplementSetSetterType = attributes.ImplementSetSetterType; @@ -91,14 +94,14 @@ public string NewFieldName private bool? _implLet; public bool ImplementLetSetterType { - get => _implLet.HasValue ? _implLet.Value : IsValueType || IsVariantType || IsUserDefinedType; + get => _implLet.HasValue ? _implLet.Value : UpdateFieldUsingLet(); set => _implLet = value; } private bool? _implSet; public bool ImplementSetSetterType { - get => _implSet.HasValue? _implSet.Value : !(IsValueType || IsUserDefinedType) && IsVariantType; + get => _implSet.HasValue ? _implSet.Value : UpdateFieldUsingSet(); set => _implSet = value; } @@ -106,6 +109,7 @@ public bool ImplementSetSetterType public bool IsValueType { set; get; } public bool IsVariantType { set; get; } public bool IsUserDefinedType { set; get; } + public bool IsArray { set; get; } private bool? _isObjectType; public bool IsObjectType @@ -115,6 +119,12 @@ public bool IsObjectType } public bool CanImplementLet { get; set; } public bool CanImplementSet { get; set; } + + private bool UpdateFieldUsingSet() + => IsObjectType || !IsArray && !IsUserDefinedType && !IsValueType && IsVariantType; + + private bool UpdateFieldUsingLet() + => !IsObjectType && !IsArray && (IsUserDefinedType || IsValueType || IsVariantType); } public class UDTFieldEncapsulationAttributes : IUDTFieldEncapsulationAttributes @@ -123,7 +133,10 @@ public UDTFieldEncapsulationAttributes(FieldEncapsulationAttributes attributes, { _attributes = attributes; EncapsulateAllUDTMembers = false; + IsVariantType = false; + IsValueType = false; IsUserDefinedType = true; + IsArray = false; foreach (var udtMemberName in udtMemberNames) { @@ -143,9 +156,10 @@ public UDTFieldEncapsulationAttributes(IUDTFieldEncapsulationAttributes attribut AsTypeName = attributes.AsTypeName; ParameterName = attributes.ParameterName; IsFlaggedToEncapsulate = attributes.IsFlaggedToEncapsulate; - IsVariantType = attributes.IsVariantType; - IsValueType = attributes.IsValueType; + IsVariantType = false; + IsValueType = false; IsUserDefinedType = true; + IsArray = false; ImplementLetSetterType = attributes.ImplementLetSetterType; ImplementSetSetterType = attributes.ImplementSetSetterType; @@ -242,6 +256,12 @@ public bool IsUserDefinedType set => _attributes.IsUserDefinedType = value; } + public bool IsArray + { + get => _attributes.IsArray; + set => _attributes.IsArray = value; + } + public bool IsObjectType { get => _attributes.IsObjectType; diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index 580e48f5e9..b4656da3e1 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -543,7 +543,10 @@ As _ //Expectation const string expectedCode = - @"Private fizz As Integer + @"Private _ +fizz _ +As _ +Integer Public Property Get Name() As Integer Name = fizz @@ -1021,6 +1024,126 @@ End Property Assert.AreEqual(expectedCode, actualCode); } + [TestCase("Private", "mArray(5) As String", "mArray(5) As String")] + [TestCase("Public", "mArray(5) As String", "mArray(5) As String")] + [TestCase("Private", "mArray(5,2,3) As String", "mArray(5,2,3) As String")] + [TestCase("Public", "mArray(5,2,3) As String", "mArray(5,2,3) As String")] + [TestCase("Private", "mArray(1 to 10) As String", "mArray(1 to 10) As String")] + [TestCase("Public", "mArray(1 to 10) As String", "mArray(1 to 10) As String")] + [TestCase("Private", "mArray() As String", "mArray() As String")] + [TestCase("Public", "mArray() As String", "mArray() As String")] + [TestCase("Private", "mArray(5)", "mArray(5) As Variant")] + [TestCase("Public", "mArray(5)", "mArray(5) As Variant")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulateArray(string visibility, string arrayDeclaration, string expectedArrayDeclaration) + { + string inputCode = + $@"Option Explicit + +{visibility} {arrayDeclaration}"; + + var selection = new Selection(3, 8, 3, 11); + + string expectedCode = + $@"Option Explicit + +Private {expectedArrayDeclaration} + +Public Property Get MyArray() As Variant + MyArray = mArray +End Property +"; + var presenterAction = SetParameters("MyArray"); + var actualCode = RefactoredCode(inputCode, selection, presenterAction); + Assert.AreEqual(expectedCode, actualCode); + } + + [TestCase("5")] + [TestCase("5,2,3")] + [TestCase("1 to 100")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulateArray_DeclaredInList(string dimensions) + { + string inputCode = + $@"Option Explicit + +Public mArray({dimensions}) As String, anotherVar As Long, andOneMore As Variant"; + + var selection = new Selection(3, 8, 3, 11); + + string expectedCode = + $@"Option Explicit + +Public anotherVar As Long, andOneMore As Variant +Private mArray({dimensions}) As String + +Public Property Get MyArray() As Variant + MyArray = mArray +End Property +"; + var presenterAction = SetParameters("MyArray"); + var actualCode = RefactoredCode(inputCode, selection, presenterAction); + Assert.AreEqual(expectedCode, actualCode); + } + + [TestCase("Private")] + [TestCase("Public")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulateArray_newFieldName(string visibility) + { + string inputCode = + $@"Option Explicit + +{visibility} mArray(5) As String"; + + var selection = new Selection(3, 8, 3, 11); + + string expectedCode = + $@"Option Explicit + +Private xArray(5) As String + +Public Property Get MyArray() As Variant + MyArray = xArray +End Property +"; + var presenterAction = SetParameters(("mArray", "MyArray", true, "xArray")); + var actualCode = RefactoredCode(inputCode, selection, presenterAction); + Assert.AreEqual(expectedCode, actualCode); + } + + [TestCase("mArray(5) As String", "xArray(5) As String")] + [TestCase("mArray(5)", "xArray(5) As Variant")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulateArray_newFieldNameForFieldInList(string arrayDeclaration, string newArrayDeclaration) + { + string inputCode = + $@"Option Explicit + +Public {arrayDeclaration}, mNextVar As Long"; + + var selection = new Selection(3, 8, 3, 11); + + string expectedCode = + $@"Option Explicit + +Public mNextVar As Long +Private {newArrayDeclaration} + +Public Property Get MyArray() As Variant + MyArray = xArray +End Property +"; + var presenterAction = SetParameters(("mArray", "MyArray", true, "xArray")); + var actualCode = RefactoredCode(inputCode, selection, presenterAction); + Assert.AreEqual(expectedCode, actualCode); + } + + #region setup private Func SetParameters( From c3032b4dad4e9b74527dfd15302bffc5d2f001c6 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Sat, 9 Nov 2019 19:04:54 -0800 Subject: [PATCH 011/461] Added support for UDTMember arrays Significant refactoring --- .../EncapsulateFieldDecorators.cs | 119 +++---- .../EncapsulateField/EncapsulateFieldModel.cs | 197 +++++------ .../FieldEncapsulationAttributes.cs | 298 +--------------- .../Refactoring/EncapsulateFieldTests.cs | 326 ++++++++---------- 4 files changed, 302 insertions(+), 638 deletions(-) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs index d6541b2bae..4228712cbd 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs @@ -1,17 +1,20 @@ 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.EncapsulateField { - public class EncapsulateFieldDeclaration + public interface IEncapsulatedFieldDeclaration + { + Declaration Declaration { get; } + string IdentifierName { get; } + DeclarationType DeclarationType { get; } + IFieldEncapsulationAttributes EncapsulationAttributes { set; get; } + } + + public class EncapsulatedFieldDeclaration : IEncapsulatedFieldDeclaration { private Declaration _decorated; - public EncapsulateFieldDeclaration(Declaration declaration) + public EncapsulatedFieldDeclaration(Declaration declaration) { _decorated = declaration; EncapsulationAttributes = new FieldEncapsulationAttributes(_decorated); @@ -23,107 +26,87 @@ public EncapsulateFieldDeclaration(Declaration declaration) public DeclarationType DeclarationType => _decorated.DeclarationType; - public IFieldEncapsulationAttributes EncapsulationAttributes { set; get; } - } + public IFieldEncapsulationAttributes EncapsulationAttributes { set; get; } = new FieldEncapsulationAttributes(); - public class EncapsulateValueType : EncapsulateFieldDeclaration - { - public EncapsulateValueType(EncapsulateFieldDeclaration declaration) - : base(declaration.Declaration) - { - EncapsulationAttributes.CanImplementLet = true; - EncapsulationAttributes.CanImplementSet = false; - } } - public class EncapsulatedUserDefinedMemberValueType : EncapsulateValueType + public class EncapsulatedValueType : EncapsulatedFieldDeclaration { - public EncapsulatedUserDefinedMemberValueType(EncapsulateValueType declaration, EncapsulateUserDefinedType udtVariable) - : base(declaration) - { - EncapsulationAttributes.NewFieldName = $"{udtVariable.Declaration.IdentifierName}.{declaration.Declaration.IdentifierName}"; - EncapsulationAttributes.IsValueType = true; - EncapsulationAttributes.CanImplementLet = true; - EncapsulationAttributes.CanImplementSet = false; - } - - public EncapsulatedUserDefinedMemberValueType(EncapsulateVariantType declaration, EncapsulateUserDefinedType udtVariable) + public EncapsulatedValueType(Declaration declaration) : base(declaration) { - EncapsulationAttributes.NewFieldName = $"{udtVariable.Declaration.IdentifierName}.{declaration.Declaration.IdentifierName}"; - EncapsulationAttributes.IsVariantType = true; EncapsulationAttributes.CanImplementLet = true; EncapsulationAttributes.CanImplementSet = false; + EncapsulationAttributes.ImplementLetSetterType = true; + EncapsulationAttributes.ImplementSetSetterType = false; } } - public class EncapsulatedUserDefinedMemberObjectType : EncapsulateFieldDeclaration - { - public EncapsulatedUserDefinedMemberObjectType(EncapsulateObjectType declaration, EncapsulateUserDefinedType udtVariable) - : base(declaration.Declaration) - { - EncapsulationAttributes.NewFieldName = $"{udtVariable.Declaration.IdentifierName}.{declaration.Declaration.IdentifierName}"; - EncapsulationAttributes.IsObjectType = true; - EncapsulationAttributes.CanImplementLet = false; - EncapsulationAttributes.CanImplementSet = true; - } - } - - - public class EncapsulateUserDefinedType : EncapsulateFieldDeclaration + public class EncapsulatedUserDefinedType : EncapsulatedFieldDeclaration { - public EncapsulateUserDefinedType(Declaration declaration) + public EncapsulatedUserDefinedType(Declaration declaration) : base(declaration) { EncapsulationAttributes.CanImplementLet = true; EncapsulationAttributes.CanImplementSet = false; - } - - public EncapsulateUserDefinedType(EncapsulateFieldDeclaration declaration) - : base(declaration.Declaration) - { - EncapsulationAttributes.CanImplementLet = true; - EncapsulationAttributes.CanImplementSet = false; + EncapsulationAttributes.ImplementLetSetterType = true; + EncapsulationAttributes.ImplementSetSetterType = false; } } - public class EncapsulateVariantType : EncapsulateFieldDeclaration + public class EncapsulatedVariantType : EncapsulatedFieldDeclaration { - public EncapsulateVariantType(EncapsulateFieldDeclaration declaration) - : base(declaration.Declaration) - { - EncapsulationAttributes.CanImplementLet = true; - EncapsulationAttributes.CanImplementSet = true; - } - public EncapsulateVariantType(Declaration declaration) + public EncapsulatedVariantType(Declaration declaration) : base(declaration) { EncapsulationAttributes.CanImplementLet = true; EncapsulationAttributes.CanImplementSet = true; + EncapsulationAttributes.ImplementLetSetterType = true; + EncapsulationAttributes.ImplementSetSetterType = true; } } - public class EncapsulateObjectType : EncapsulateFieldDeclaration + public class EncapsulatedObjectType : EncapsulatedFieldDeclaration { - public EncapsulateObjectType(EncapsulateFieldDeclaration declaration) - : base(declaration.Declaration) + public EncapsulatedObjectType(Declaration declaration) + : base(declaration) { EncapsulationAttributes.CanImplementLet = false; EncapsulationAttributes.CanImplementSet = true; + EncapsulationAttributes.ImplementLetSetterType = false; + EncapsulationAttributes.ImplementSetSetterType = true; } } - public class EncapsulateArrayType : EncapsulateFieldDeclaration + public class EncapsulatedArrayType : EncapsulatedFieldDeclaration { - public EncapsulateArrayType(EncapsulateFieldDeclaration declaration) - : base(declaration.Declaration) + public EncapsulatedArrayType(Declaration declaration) + : base(declaration) { EncapsulationAttributes.CanImplementLet = false; EncapsulationAttributes.CanImplementSet = false; - EncapsulationAttributes.IsArray = true; - EncapsulationAttributes.AsTypeName = Tokens.Variant; EncapsulationAttributes.ImplementLetSetterType = false; EncapsulationAttributes.ImplementSetSetterType = false; + EncapsulationAttributes.AsTypeName = Tokens.Variant; } } + + public class EncapsulatedUserDefinedTypeMember : IEncapsulatedFieldDeclaration + { + private readonly IEncapsulatedFieldDeclaration _decorated; + public EncapsulatedUserDefinedTypeMember(IEncapsulatedFieldDeclaration encapsulateFieldDeclaration, EncapsulatedUserDefinedType udtVariable) + { + _decorated = encapsulateFieldDeclaration; + EncapsulationAttributes = _decorated.EncapsulationAttributes; + EncapsulationAttributes.NewFieldName = $"{udtVariable.Declaration.IdentifierName}.{encapsulateFieldDeclaration.Declaration.IdentifierName}"; + } + + public Declaration Declaration => _decorated.Declaration; + + public string IdentifierName => _decorated.IdentifierName; + + public DeclarationType DeclarationType => _decorated.DeclarationType; + + public IFieldEncapsulationAttributes EncapsulationAttributes { set; get; } + } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index b827d2b03f..244141d023 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -1,16 +1,18 @@ using System; using System.Collections.Generic; using System.Linq; -using Antlr4.Runtime; -using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.SmartIndenter; -using Rubberduck.VBEditor; namespace Rubberduck.Refactorings.EncapsulateField { - public class EncapsulateFieldModel : IRefactoringModel + public interface ISupportEncapsulateFieldTests + { + void SetMemberEncapsulationFlag(string name, bool flag); + void SetEncapsulationFieldAttributes(IUserModifiableFieldEncapsulationAttributes attributes); + } + public class EncapsulateFieldModel : IRefactoringModel, ISupportEncapsulateFieldTests { private readonly IIndenter _indenter; @@ -18,10 +20,10 @@ public class EncapsulateFieldModel : IRefactoringModel private IEnumerable UdtFields => _udtFieldToUdtDeclarationMap.Keys; private IEnumerable UdtFieldMembers(Declaration udtField) => _udtFieldToUdtDeclarationMap[udtField].Item2; - private Dictionary _encapsulateFieldDeclarations = new Dictionary(); + private Dictionary _encapsulateFieldDeclarations = new Dictionary(); - private EncapsulateFieldDeclaration _userSelectedEncapsulationField; - private Dictionary _udtVariableEncapsulationAttributes = new Dictionary(); + private IEncapsulatedFieldDeclaration _userSelectedEncapsulationField; + private Dictionary _udtVariableEncapsulationAttributes = new Dictionary(); public EncapsulateFieldModel(Declaration target, IEnumerable allMemberFields, IDictionary)> udtFieldToUdtDeclarationMap, IIndenter indenter) { @@ -35,71 +37,56 @@ public EncapsulateFieldModel(Declaration target, IEnumerable allMem AddUDTEncapsulationFields(udtFieldToUdtDeclarationMap); - this[target].EncapsulationAttributes.IsFlaggedToEncapsulate = true; + this[target].EncapsulationAttributes.EncapsulateFlag = true; TargetDeclaration = target; - //_userSelectedEncapsulationField = this[target]; } - public IEnumerable FlaggedEncapsulationFields => _encapsulateFieldDeclarations.Values.Where(v => v.EncapsulationAttributes.IsFlaggedToEncapsulate); + public IEnumerable FlaggedEncapsulationFields => _encapsulateFieldDeclarations.Values.Where(v => v.EncapsulationAttributes.EncapsulateFlag); - private EncapsulateFieldDeclaration DecorateDeclaration(Declaration target) + public IEncapsulatedFieldDeclaration this[string encapsulatedFieldIdentifier] { - //TODO: Array type fields - var selectedField = new EncapsulateFieldDeclaration(target); - - if (selectedField.EncapsulationAttributes.IsVariantType) - { - return new EncapsulateVariantType(selectedField); - } - else if (selectedField.EncapsulationAttributes.IsObjectType) - { - return new EncapsulateObjectType(selectedField); - } - else if (selectedField.EncapsulationAttributes.IsArray) + get => _encapsulateFieldDeclarations.Values.Where(efd => efd.Declaration.IdentifierName.Equals(encapsulatedFieldIdentifier)) + .FirstOrDefault(); + set { - return new EncapsulateArrayType(selectedField); + var key = _encapsulateFieldDeclarations.Keys.Where(k => k.IdentifierName.Equals(encapsulatedFieldIdentifier)) + .FirstOrDefault(); + _encapsulateFieldDeclarations[key] = value; } - return new EncapsulateValueType(selectedField); - } - - private EncapsulateFieldDeclaration DecorateUDTVariableDeclaration(Declaration target) - { - return new EncapsulateUserDefinedType(new EncapsulateFieldDeclaration(target)); } - private EncapsulateFieldDeclaration DecorateUDTMember(Declaration udtMember, EncapsulateUserDefinedType udtVariable) + public IEncapsulatedFieldDeclaration this[Declaration declaration] { - var selectedField = new EncapsulateFieldDeclaration(udtMember); - if (selectedField.EncapsulationAttributes.IsVariantType) + get { - return new EncapsulatedUserDefinedMemberValueType(new EncapsulateVariantType(selectedField), udtVariable); + if (_encapsulateFieldDeclarations.TryGetValue(declaration, out var encapsulateFieldDefinition)) + { + return encapsulateFieldDefinition; + } + return null; } - else if (selectedField.EncapsulationAttributes.IsObjectType) + set { - return new EncapsulatedUserDefinedMemberObjectType(new EncapsulateObjectType(selectedField), udtVariable); + if (_encapsulateFieldDeclarations.ContainsKey(declaration)) + { + _encapsulateFieldDeclarations[declaration] = value; + } } - return new EncapsulatedUserDefinedMemberValueType(new EncapsulateValueType(selectedField), udtVariable); } - public void AddUDTVariableAttributes(IUDTFieldEncapsulationAttributes udtFieldEncapsulationAttributes) - { - if (_udtVariableEncapsulationAttributes.TryGetValue(udtFieldEncapsulationAttributes.FieldName, out _)) - { - _udtVariableEncapsulationAttributes[udtFieldEncapsulationAttributes.FieldName] = udtFieldEncapsulationAttributes; - return; - } - _udtVariableEncapsulationAttributes.Add(udtFieldEncapsulationAttributes.FieldName, udtFieldEncapsulationAttributes); - } + //public IUserModifiableFieldEncapsulationAttributes UserEncapsulationAttributes(string fieldName) => this[fieldName].EncapsulationAttributes as IUserModifiableFieldEncapsulationAttributes; - public bool TryGetUDTVariableAttributes(string udtVariableName, out IFieldEncapsulationAttributes rule) + public IList PropertiesContent { - rule = null; - if (_udtVariableEncapsulationAttributes.ContainsKey(udtVariableName)) + get { - rule = _udtVariableEncapsulationAttributes[udtVariableName]; - return true; + var textBlocks = new List(); + foreach (var field in FlaggedEncapsulationFields) + { + textBlocks.Add(BuildPropertiesTextBlock(field.Declaration)); + } + return textBlocks; } - return false; } private void AddUDTEncapsulationFields(IDictionary)> udtFieldToTypeMap) @@ -111,65 +98,46 @@ private void AddUDTEncapsulationFields(IDictionary _encapsulateFieldDeclarations.Values.Where(efd => efd.Declaration.IdentifierName.Equals(encapsulatedFieldIdentifier)) - .FirstOrDefault(); - set + else if (target.IsObject) { - var key = _encapsulateFieldDeclarations.Keys.Where(k => k.IdentifierName.Equals(encapsulatedFieldIdentifier)) - .FirstOrDefault(); - _encapsulateFieldDeclarations[key] = value; + return new EncapsulatedObjectType(target); } + return new EncapsulatedValueType(target); } - public IEnumerable EncapsulateFieldDeclarations => _encapsulateFieldDeclarations.Values; + private IEncapsulatedFieldDeclaration DecorateUDTVariableDeclaration(Declaration target) + { + return new EncapsulatedUserDefinedType(target); + } - public void AddEncapsulationField(EncapsulateFieldDeclaration target) + private IEncapsulatedFieldDeclaration DecorateUDTMember(Declaration udtMember, EncapsulatedUserDefinedType udtVariable) { - if (_encapsulateFieldDeclarations.ContainsKey(target.Declaration)) - { - _encapsulateFieldDeclarations[target.Declaration] = target; - return; - } - _encapsulateFieldDeclarations.Add(target.Declaration, target); + return new EncapsulatedUserDefinedTypeMember(DecorateDeclaration(udtMember), udtVariable); } - public IList PropertiesContent + private void AddEncapsulationField(IEncapsulatedFieldDeclaration encapsulateFieldDeclaration) { - get + if (_encapsulateFieldDeclarations.ContainsKey(encapsulateFieldDeclaration.Declaration)) { - var textBlocks = new List(); - foreach (var field in FlaggedEncapsulationFields) - { - textBlocks.Add(BuildPropertiesTextBlock(field.Declaration)); - } - return textBlocks; + _encapsulateFieldDeclarations[encapsulateFieldDeclaration.Declaration] = encapsulateFieldDeclaration; + return; } + _encapsulateFieldDeclarations.Add(encapsulateFieldDeclaration.Declaration, encapsulateFieldDeclaration); } private string BuildPropertiesTextBlock(Declaration target) @@ -194,28 +162,31 @@ private string GetPropertyText(PropertyGenerator generator) return string.Join(Environment.NewLine, _indenter.Indent(propertyTextLines, true)); } - //private EncapsulateFieldDeclaration DefaultTarget => _userSelectedEncapsulationField; - - //Only used by tests....so far - public void UpdateEncapsulationField(IUDTFieldEncapsulationAttributes attributes) + public void SetMemberEncapsulationFlag(string name, bool flag) { - this[attributes.FieldName].EncapsulationAttributes = attributes; - foreach ((string Name, bool Encapsulate) in attributes.MemberFlags) - { - this[Name].EncapsulationAttributes.IsFlaggedToEncapsulate = Encapsulate; - } + this[name].EncapsulationAttributes.EncapsulateFlag = flag; } //Only used by tests....so far - public void UpdateEncapsulationField(string variableName, string propertyName, bool encapsulateFlag, string newFieldName = null) - { - var target = this[variableName]; - target.EncapsulationAttributes.FieldName = variableName; - target.EncapsulationAttributes.PropertyName = propertyName; - target.EncapsulationAttributes.NewFieldName = newFieldName ?? variableName; - target.EncapsulationAttributes.IsFlaggedToEncapsulate = encapsulateFlag; - this[variableName] = target; - } + public void SetEncapsulationFieldAttributes(IUserModifiableFieldEncapsulationAttributes attributes) + { + var userAttributes = this[attributes.FieldName].EncapsulationAttributes as IUserModifiableFieldEncapsulationAttributes; // = attributes; + userAttributes.FieldName = attributes.FieldName; + userAttributes.NewFieldName = attributes.NewFieldName; + userAttributes.PropertyName = attributes.PropertyName; + userAttributes.EncapsulateFlag = attributes.EncapsulateFlag; + } + + ////Only used by tests....so far + //public void UpdateEncapsulationField(string variableName, string propertyName, bool encapsulateFlag, string newFieldName = null) + //{ + // var target = this[variableName]; + // target.EncapsulationAttributes.FieldName = variableName; + // target.EncapsulationAttributes.PropertyName = propertyName; + // target.EncapsulationAttributes.NewFieldName = newFieldName ?? variableName; + // target.EncapsulationAttributes.EncapsulateFlag = encapsulateFlag; + // this[variableName] = target; + //} //Only used by tests....so far public void UpdateEncapsulationField(IFieldEncapsulationAttributes attributes) @@ -224,7 +195,7 @@ public void UpdateEncapsulationField(IFieldEncapsulationAttributes attributes) target.EncapsulationAttributes.FieldName = attributes.FieldName; target.EncapsulationAttributes.PropertyName = attributes.PropertyName; target.EncapsulationAttributes.NewFieldName = attributes.NewFieldName ?? attributes.FieldName; - target.EncapsulationAttributes.IsFlaggedToEncapsulate = attributes.IsFlaggedToEncapsulate; + target.EncapsulationAttributes.EncapsulateFlag = attributes.EncapsulateFlag; this[attributes.FieldName] = target; } @@ -242,7 +213,7 @@ public string PropertyName public string ParameterName { - get => _userSelectedEncapsulationField.EncapsulationAttributes.ParameterName; + get => _userSelectedEncapsulationField.EncapsulationAttributes.ParameterName ?? "value"; set => _userSelectedEncapsulationField.EncapsulationAttributes.ParameterName = value; } @@ -259,9 +230,9 @@ public bool ImplementSetSetterType } public bool CanImplementLet - => _userSelectedEncapsulationField.EncapsulationAttributes.IsValueType || _userSelectedEncapsulationField.EncapsulationAttributes.IsVariantType; + => _userSelectedEncapsulationField.EncapsulationAttributes.CanImplementLet; //.EncapsulationAttributes.IsValueType || _userSelectedEncapsulationField.EncapsulationAttributes.IsVariantType; public bool CanImplementSet - => !_userSelectedEncapsulationField.EncapsulationAttributes.IsValueType && _userSelectedEncapsulationField.EncapsulationAttributes.IsVariantType; + => !_userSelectedEncapsulationField.EncapsulationAttributes.CanImplementSet; //IsValueType && _userSelectedEncapsulationField.EncapsulationAttributes.IsVariantType; } } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs index 74663cd835..937d0bf19a 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs @@ -1,45 +1,31 @@ -using Rubberduck.Parsing; -using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Symbols; -using System; +using Rubberduck.Parsing.Symbols; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Rubberduck.Refactorings.EncapsulateField { - public interface IFieldEncapsulationAttributes + public interface IUserModifiableFieldEncapsulationAttributes { string FieldName { get; set; } string NewFieldName { get; set; } string PropertyName { get; set; } - string AsTypeName { get; set; } - string ParameterName { get; set; } bool ImplementLetSetterType { get; set; } bool ImplementSetSetterType { get; set; } - bool IsFlaggedToEncapsulate { get; set; } - bool IsValueType { get; set; } - bool IsVariantType { get; set; } - bool IsUserDefinedType { set; get; } - bool IsArray { set; get; } - bool IsObjectType { set; get; } - bool CanImplementLet { get; set; } - bool CanImplementSet { get; set; } + bool EncapsulateFlag { get; set; } } - public interface IUDTFieldEncapsulationAttributes : IFieldEncapsulationAttributes + public interface IFieldEncapsulationAttributes : IUserModifiableFieldEncapsulationAttributes { - bool MemberEncapsulationFlag(string name); - bool EncapsulateAllUDTMembers { get; set; } - IEnumerable<(string Name, bool Encapsulate)> MemberFlags { get; } + string AsTypeName { get; set; } + string ParameterName { get; set; } + bool CanImplementLet { get; set; } + bool CanImplementSet { get; set; } } public class FieldEncapsulationAttributes : IFieldEncapsulationAttributes { private static string DEFAULT_LET_PARAMETER = "value"; - //Only used by tests public FieldEncapsulationAttributes() { } public FieldEncapsulationAttributes(Declaration target, string newFieldName = null, string parameterName = null) @@ -49,34 +35,6 @@ public FieldEncapsulationAttributes(Declaration target, string newFieldName = nu PropertyName = target.IdentifierName; AsTypeName = target.AsTypeName; ParameterName = parameterName ?? DEFAULT_LET_PARAMETER; - IsFlaggedToEncapsulate = false; - IsVariantType = target.AsTypeName?.Equals(Tokens.Variant) ?? true; - IsValueType = !IsVariantType && (SymbolList.ValueTypes.Contains(target.AsTypeName) || - target.DeclarationType == DeclarationType.Enumeration); - IsObjectType = target.IsObject; - IsUserDefinedType = false; - IsArray = target.IsArray; - ImplementLetSetterType = UpdateFieldUsingLet(); - ImplementSetSetterType = UpdateFieldUsingSet(); - CanImplementLet = false; - CanImplementSet = false; - } - - public FieldEncapsulationAttributes(IFieldEncapsulationAttributes attributes) - { - FieldName = attributes.FieldName; - NewFieldName = attributes.NewFieldName ?? attributes.FieldName; - PropertyName = attributes.PropertyName; - AsTypeName = attributes.AsTypeName; - ParameterName = attributes.ParameterName; - IsFlaggedToEncapsulate = attributes.IsFlaggedToEncapsulate; - IsVariantType = attributes.IsVariantType; - IsValueType = attributes.IsValueType; - IsUserDefinedType = attributes.IsUserDefinedType; - IsArray = attributes.IsArray; - IsObjectType = attributes.IsObjectType; - ImplementLetSetterType = attributes.ImplementLetSetterType; - ImplementSetSetterType = attributes.ImplementSetSetterType; } public string FieldName { get; set; } @@ -91,105 +49,21 @@ public string NewFieldName public string AsTypeName { get; set; } public string ParameterName { get; set; } = DEFAULT_LET_PARAMETER; - private bool? _implLet; - public bool ImplementLetSetterType - { - get => _implLet.HasValue ? _implLet.Value : UpdateFieldUsingLet(); - set => _implLet = value; - } - - private bool? _implSet; - public bool ImplementSetSetterType - { - get => _implSet.HasValue ? _implSet.Value : UpdateFieldUsingSet(); - set => _implSet = value; - } - - public bool IsFlaggedToEncapsulate { get; set; } - public bool IsValueType { set; get; } - public bool IsVariantType { set; get; } - public bool IsUserDefinedType { set; get; } - public bool IsArray { set; get; } - - private bool? _isObjectType; - public bool IsObjectType - { - get => _isObjectType.HasValue ? _isObjectType.Value : !(IsValueType || IsVariantType); - set => _isObjectType = value; - } + public bool ImplementLetSetterType { get; set; } + public bool ImplementSetSetterType { get; set; } + public bool EncapsulateFlag { get; set; } public bool CanImplementLet { get; set; } public bool CanImplementSet { get; set; } - - private bool UpdateFieldUsingSet() - => IsObjectType || !IsArray && !IsUserDefinedType && !IsValueType && IsVariantType; - - private bool UpdateFieldUsingLet() - => !IsObjectType && !IsArray && (IsUserDefinedType || IsValueType || IsVariantType); } - public class UDTFieldEncapsulationAttributes : IUDTFieldEncapsulationAttributes + public class UDTFieldEncapsulationAttributes : IFieldEncapsulationAttributes { - public UDTFieldEncapsulationAttributes(FieldEncapsulationAttributes attributes, IEnumerable udtMemberNames) - { - _attributes = attributes; - EncapsulateAllUDTMembers = false; - IsVariantType = false; - IsValueType = false; - IsUserDefinedType = true; - IsArray = false; - - foreach (var udtMemberName in udtMemberNames) - { - if (!_memberEncapsulationFlags.ContainsKey(udtMemberName)) - { - _memberEncapsulationFlags.Add(udtMemberName, false); - } - } - } - - //TODO: Copy ctor may not every be needed - public UDTFieldEncapsulationAttributes(IUDTFieldEncapsulationAttributes attributes) - { - FieldName = attributes.FieldName; - NewFieldName = attributes.NewFieldName ?? attributes.FieldName; - PropertyName = attributes.PropertyName; - AsTypeName = attributes.AsTypeName; - ParameterName = attributes.ParameterName; - IsFlaggedToEncapsulate = attributes.IsFlaggedToEncapsulate; - IsVariantType = false; - IsValueType = false; - IsUserDefinedType = true; - IsArray = false; - ImplementLetSetterType = attributes.ImplementLetSetterType; - ImplementSetSetterType = attributes.ImplementSetSetterType; - - //TODO: Dumb to have a dictionary here - it is a tuple at the moment(!?) - _memberEncapsulationFlags = attributes.MemberFlags.ToDictionary(k => k.Name, e => e.Encapsulate); - } - - private IFieldEncapsulationAttributes _attributes { set; get; } + private IFieldEncapsulationAttributes _attributes { get; } private Dictionary _memberEncapsulationFlags = new Dictionary(); - - //Only used by tests - public void FlagUdtMemberEncapsulation(bool encapsulateFlag, params string[] names) - { - foreach (var name in names) - { - if (_memberEncapsulationFlags.ContainsKey(name)) - { - _memberEncapsulationFlags[name] = encapsulateFlag; - } - else - { - _memberEncapsulationFlags.Add(name, encapsulateFlag); - } - } - } - public bool EncapsulateAllUDTMembers + public UDTFieldEncapsulationAttributes(FieldEncapsulationAttributes attributes) //, IEnumerable udtMemberNames) { - set => SetEncapsulationFlagForAllMembers(value); - get => _memberEncapsulationFlags.Values.All(v => v == true); + _attributes = attributes; } public string FieldName @@ -232,149 +106,13 @@ public bool ImplementSetSetterType set => _attributes.ImplementSetSetterType = value; } - public bool IsFlaggedToEncapsulate + public bool EncapsulateFlag { - get => _attributes.IsFlaggedToEncapsulate; - set => _attributes.IsFlaggedToEncapsulate = value; - } - - public bool IsValueType - { - get => _attributes.IsValueType; - set => _attributes.IsValueType = value; - } - - public bool IsVariantType - { - get => _attributes.IsVariantType; - set => _attributes.IsVariantType = value; - } - - public bool IsUserDefinedType - { - get => _attributes.IsUserDefinedType; - set => _attributes.IsUserDefinedType = value; - } - - public bool IsArray - { - get => _attributes.IsArray; - set => _attributes.IsArray = value; - } - - public bool IsObjectType - { - get => _attributes.IsObjectType; - set => _attributes.IsObjectType = value; + get => _attributes.EncapsulateFlag; + set => _attributes.EncapsulateFlag = value; } public bool CanImplementLet { get; set; } public bool CanImplementSet { get; set; } - - private void SetEncapsulationFlagForAllMembers(bool flag) - { - foreach (var key in _memberEncapsulationFlags.Keys.ToList()) - { - _memberEncapsulationFlags[key] = flag; - } - } - - public IEnumerable<(string Name, bool Encapsulate)> MemberFlags - { - get - { - var results = new List<(string Name, bool Encapsulate)>(); - foreach (var name in _memberEncapsulationFlags.Keys) - { - results.Add((name, _memberEncapsulationFlags[name])); - } - return results; - } - } - - public bool MemberEncapsulationFlag(string name) - { - return _memberEncapsulationFlags.ContainsKey(name) ? _memberEncapsulationFlags[name] : false; - } } - - //public class UDTMemberEncapsulationAttributes : IFieldEncapsulationAttributes - //{ - // public UDTMemberEncapsulationAttributes(IFieldEncapsulationAttributes attributes) - // { - // _attributes = attributes; - // } - - // private IFieldEncapsulationAttributes _attributes { set; get; } - - // public string FieldName - // { - // get => _attributes.FieldName; - // set => _attributes.FieldName = value; - // } - - // public string PropertyName - // { - // get => _attributes.PropertyName; - // set => _attributes.PropertyName = value; - // } - - // public string NewFieldName - // { - // get => _attributes.NewFieldName; - // set => _attributes.NewFieldName = value; - // } - - // public string AsTypeName - // { - // get => _attributes.AsTypeName; - // set => _attributes.AsTypeName = value; - // } - // public string ParameterName - // { - // get => _attributes.ParameterName; - // set => _attributes.ParameterName = value; - // } - // public bool ImplementLetSetterType - // { - // get => _attributes.ImplementLetSetterType; - // set => _attributes.ImplementLetSetterType = value; - // } - - // public bool ImplementSetSetterType - // { - // get => _attributes.ImplementSetSetterType; - // set => _attributes.ImplementSetSetterType = value; - // } - // public bool IsFlaggedToEncapsulate - // { - // get => _attributes.IsFlaggedToEncapsulate; - // set => _attributes.IsFlaggedToEncapsulate = value; - // } - - // public bool IsValueType - // { - // get => _attributes.IsValueType; - // set => _attributes.IsValueType = value; - // } - - // public bool IsVariantType - // { - // get => _attributes.IsVariantType; - // set => _attributes.IsVariantType = value; - // } - - // public bool IsUserDefinedType - // { - // get => _attributes.IsUserDefinedType; - // set => _attributes.IsUserDefinedType = value; - // } - - // public bool IsObjectType - // { - // get => _attributes.IsObjectType; - // set => _attributes.IsObjectType = value; - // } - // //public bool IsObjectType => _attributes.IsObjectType; - //} } diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index b4656da3e1..ad3660bdf5 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -43,7 +43,7 @@ Public Property Let Name(ByVal value As Integer) {newFieldName} = value End Property "; - var presenterAction = SetParameters(("fizz", "Name", true, newFieldName)); + var presenterAction = SetParametersForSingleTarget("fizz", "Name", true, newFieldName); var actualCode = RefactoredCode(inputCode, selection, presenterAction); Assert.AreEqual(expectedCode, actualCode); } @@ -61,7 +61,12 @@ Public baz As String var selection = new Selection(1, 1); - var presenterAction = SetParameters(("fizz", "FizzProp", true), ("baz", "BazProp", true), ("buzz", "BuzzProp", true)); + var userInput = new UserInputDataObject("fizz", "FizzProp", true); + userInput.AddAttributeSet("baz", "BazProp", true); + userInput.AddAttributeSet("buzz", "BuzzProp", true); + + var presenterAction = SetParameters(userInput); + var actualCode = RefactoredCode(inputCode, selection, presenterAction); StringAssert.Contains("Private fizz As Integer", actualCode); StringAssert.Contains("Private baz As String", actualCode); @@ -97,20 +102,7 @@ End Type var selection = new Selection(7, 10); //Selects 'this' declaration - - var attributes = new FieldEncapsulationAttributes() - { - FieldName = "this", - PropertyName = "MyType", - AsTypeName = "TBar", - IsValueType = true, - IsFlaggedToEncapsulate = true - }; - - var thisEncapsulationAttributes = new UDTFieldEncapsulationAttributes(attributes, new string[] { "First", "Second" }); - thisEncapsulationAttributes.EncapsulateAllUDTMembers = false; - - var presenterAction = SetParameters(thisEncapsulationAttributes); + var presenterAction = SetParametersForSingleTarget("this", "MyType", true); var actualCode = RefactoredCode(inputCode, selection, presenterAction); StringAssert.Contains("Private this As TBar", actualCode); StringAssert.Contains("this = value", actualCode); @@ -118,44 +110,6 @@ End Type StringAssert.DoesNotContain($"this.First = value", actualCode); } - [TestCase("First")] - [TestCase("Second")] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void EncapsulateAllMembersFlag(string memberToEncapsulate) - { - string inputCode = -$@" -Private Type TBar - First As String - Second As Long -End Type - -Private this As TBar"; - - var selection = new Selection(7, 10); //Selects 'this' declaration - - - var attributes = new FieldEncapsulationAttributes() - { - FieldName = "this", - PropertyName = "MyType", - AsTypeName = "TBar", - IsFlaggedToEncapsulate = true, - IsValueType = true, - }; - - var udtEncapsulationAttributes = new UDTFieldEncapsulationAttributes(attributes, new string[] { "First", "Second" }); - udtEncapsulationAttributes.EncapsulateAllUDTMembers = true; - Assert.IsTrue(udtEncapsulationAttributes.EncapsulateAllUDTMembers); - - udtEncapsulationAttributes.FlagUdtMemberEncapsulation(false, memberToEncapsulate); - Assert.IsFalse(udtEncapsulationAttributes.EncapsulateAllUDTMembers); - - udtEncapsulationAttributes.FlagUdtMemberEncapsulation(true, memberToEncapsulate); - Assert.IsTrue(udtEncapsulationAttributes.EncapsulateAllUDTMembers); - } - [TestCase("First")] [TestCase("Second")] [Category("Refactorings")] @@ -174,27 +128,16 @@ End Type var selection = new Selection(7, 10); //Selects 'this' declaration - var attributes = new FieldEncapsulationAttributes() - { - FieldName = "this", - PropertyName = "MyType", - AsTypeName = "TBar", - IsFlaggedToEncapsulate = true, - IsValueType = true, - }; - - var udtAttributes = new UDTFieldEncapsulationAttributes(attributes, new string[] { "First", "Second" }); - udtAttributes.FlagUdtMemberEncapsulation(true, memberToEncapsulate); + var userInput = new UserInputDataObject("this", "MyType", true); + userInput.AddUDTMemberNameFlagPairs((memberToEncapsulate, true)); - Assert.IsFalse(udtAttributes.EncapsulateAllUDTMembers); + var presenterAction = SetParameters(userInput); - var presenterAction = SetParameters(udtAttributes); var actualCode = RefactoredCode(inputCode, selection, presenterAction); StringAssert.Contains($"this.{memberToEncapsulate} = value", actualCode); StringAssert.Contains($"{memberToEncapsulate} = this.{memberToEncapsulate}", actualCode); } - [TestCase("Public")] [TestCase("Private")] [Category("Refactorings")] @@ -212,22 +155,22 @@ End Type var selection = new Selection(7, 10); //Selects 'this' declaration + var userInput = new UserInputDataObject("this", "MyType", true); + userInput.AddUDTMemberNameFlagPairs(("First", true), ("Second", true)); var attributes = new FieldEncapsulationAttributes() { FieldName = "this", PropertyName = "MyType", AsTypeName = "TBar", - IsFlaggedToEncapsulate = true, + ImplementLetSetterType = true, + EncapsulateFlag = true }; - var udtFieldAttributes = new UDTFieldEncapsulationAttributes(attributes, new string[] { "First", "Second" }); - udtFieldAttributes.EncapsulateAllUDTMembers = true; - - Assert.IsTrue(udtFieldAttributes.EncapsulateAllUDTMembers); + var presenterAction = SetParameters(userInput); - var presenterAction = SetParameters(udtFieldAttributes); var actualCode = RefactoredCode(inputCode, selection, presenterAction); + StringAssert.Contains("Private this As TBar", actualCode); StringAssert.Contains("this = value", actualCode); StringAssert.Contains("MyType = this", actualCode); @@ -263,21 +206,11 @@ End Sub var selection = new Selection(7, 10); //Selects 'this' declaration + var userInput = new UserInputDataObject("this", "MyType", true); + userInput.AddUDTMemberNameFlagPairs(("First", true), ("Second", true)); - var attributes = new FieldEncapsulationAttributes() - { - FieldName = "this", - PropertyName = "MyType", - AsTypeName = "TBar", - IsFlaggedToEncapsulate = true, - }; - - var udtFieldAttributes = new UDTFieldEncapsulationAttributes(attributes, new string[] { "First", "Second" }); - udtFieldAttributes.EncapsulateAllUDTMembers = true; - - Assert.IsTrue(udtFieldAttributes.EncapsulateAllUDTMembers); + var presenterAction = SetParameters(userInput); - var presenterAction = SetParameters(udtFieldAttributes); var actualModuleCode = RefactoredCode( "Module1", selection, @@ -318,21 +251,11 @@ End Type var selection = new Selection(7, 10); //Selects 'this' declaration + var userInput = new UserInputDataObject("this", "MyType", true); + userInput.AddUDTMemberNameFlagPairs(("First", true), ("Second", true)); - var attributes = new FieldEncapsulationAttributes() - { - FieldName = "this", - PropertyName = "MyType", - AsTypeName = "TBar", - IsFlaggedToEncapsulate = true, - }; - - var udtFieldAttributes = new UDTFieldEncapsulationAttributes(attributes, new string[] { "First", "Second" }); - udtFieldAttributes.EncapsulateAllUDTMembers = true; - - Assert.IsTrue(udtFieldAttributes.EncapsulateAllUDTMembers); + var presenterAction = SetParameters(userInput); - var presenterAction = SetParameters(udtFieldAttributes); var actualCode = RefactoredCode(inputCode, selection, presenterAction); StringAssert.Contains("Private this As TBar", actualCode); StringAssert.Contains("this = value", actualCode); @@ -346,6 +269,42 @@ End Type StringAssert.DoesNotContain($"Second = Second", actualCode); } + [TestCase("Public")] + [TestCase("Private")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulateUserDefinedTypeMember_ContainsArrays(string accessibility) + { + string inputCode = +$@" +Private Type TBar + First(5) As String + Second(1 to 100) As Long + Third() As Double +End Type + +{accessibility} this As TBar"; + + var selection = new Selection(8, 10); //Selects 'this' declaration + + var userInput = new UserInputDataObject("this", "MyType", false); + userInput.AddUDTMemberNameFlagPairs(("First", true), ("Second", true), ("Third", true)); + + var presenterAction = SetParameters(userInput); + + var actualCode = RefactoredCode(inputCode, selection, presenterAction); + StringAssert.Contains($"{accessibility} this As TBar", actualCode); + StringAssert.DoesNotContain("this = value", actualCode); + StringAssert.DoesNotContain($"this.First = value", actualCode); + StringAssert.Contains($"Property Get First() As Variant", actualCode); + StringAssert.Contains($"First = this.First", actualCode); + StringAssert.DoesNotContain($"this.Second = value", actualCode); + StringAssert.Contains($"Second = this.Second", actualCode); + StringAssert.Contains($"Property Get Second() As Variant", actualCode); + StringAssert.Contains($"Third = this.Third", actualCode); + StringAssert.Contains($"Property Get Third() As Variant", actualCode); + } + [TestCase("Public", "Public")] [TestCase("Private", "Private")] [Category("Refactorings")] @@ -363,22 +322,11 @@ End Type var selection = new Selection(7, 10); //Selects 'this' declaration + var userInput = new UserInputDataObject("this", "MyType", false); + userInput.AddUDTMemberNameFlagPairs(("First", true), ("Second", true)); - var attributes = new FieldEncapsulationAttributes() - { - FieldName = "this", - PropertyName = "MyType", - AsTypeName = "TBar", - IsFlaggedToEncapsulate = false, - IsValueType = true, - }; - - var udtFieldAttributes = new UDTFieldEncapsulationAttributes(attributes, new string[] { "First", "Second" }); - udtFieldAttributes.EncapsulateAllUDTMembers = true; - - Assert.IsTrue(udtFieldAttributes.EncapsulateAllUDTMembers); + var presenterAction = SetParameters(userInput); - var presenterAction = SetParameters(udtFieldAttributes); var actualCode = RefactoredCode(inputCode, selection, presenterAction); StringAssert.Contains($"{expectedAccessibility} this As TBar", actualCode); StringAssert.DoesNotContain("this = value", actualCode); @@ -412,21 +360,11 @@ End Type var selection = new Selection(4, 10); //Selects 'this' declaration - var attributes = new FieldEncapsulationAttributes() - { - FieldName = "this", - PropertyName = "MyType", - AsTypeName = "TBar", - IsFlaggedToEncapsulate = true, - IsValueType = true, - }; + var userInput = new UserInputDataObject("this", "MyType", true); + userInput.AddUDTMemberNameFlagPairs(("First", true), ("Second", true)); - var udtFieldAttributes = new UDTFieldEncapsulationAttributes(attributes, new string[] { "First", "Second" }) - { - EncapsulateAllUDTMembers = true, - }; + var presenterAction = SetParameters(userInput); - var presenterAction = SetParameters(udtFieldAttributes); var actualModuleCode = RefactoredCode( "Class1", selection, @@ -473,15 +411,8 @@ End Sub var selection = new Selection(4, 10); //Selects 'mTheClass' declaration - var attributes = new FieldEncapsulationAttributes() - { - FieldName = "mTheClass", - PropertyName = "TheClass", - AsTypeName = "Class1", - IsFlaggedToEncapsulate = true, - }; + var presenterAction = SetParametersForSingleTarget("mTheClass", "TheClass", true); - var presenterAction = SetParameters(attributes); var actualModuleCode = RefactoredCode( "Module1", selection, @@ -816,7 +747,9 @@ End Sub Sub Bar(ByVal name As Integer) End Sub"; - var presenterAction = SetParameters(("fizz", "Name", true, newName)); + + var presenterAction = SetParametersForSingleTarget("fizz", "Name", true, newName); + var actualCode = RefactoredCode(inputCode, selection, presenterAction); Assert.AreEqual(expectedCode, actualCode); } @@ -871,16 +804,9 @@ End Sub Sub Bar(ByVal v As Integer) End Sub"; - var attributes = new FieldEncapsulationAttributes() - { - FieldName = "fizz", - PropertyName = "Name", - ParameterName = "value", - IsFlaggedToEncapsulate = true, - IsValueType = true, - }; - var presenterAction = SetParameters(attributes); + var presenterAction = SetParametersForSingleTarget("fizz", "Name", true); + var actualCode = RefactoredCode( "Class1", selection, @@ -1110,7 +1036,9 @@ Public Property Get MyArray() As Variant MyArray = xArray End Property "; - var presenterAction = SetParameters(("mArray", "MyArray", true, "xArray")); + + var presenterAction = SetParametersForSingleTarget("mArray", "MyArray", true, "xArray"); + var actualCode = RefactoredCode(inputCode, selection, presenterAction); Assert.AreEqual(expectedCode, actualCode); } @@ -1138,7 +1066,7 @@ Public Property Get MyArray() As Variant MyArray = xArray End Property "; - var presenterAction = SetParameters(("mArray", "MyArray", true, "xArray")); + var presenterAction = SetParametersForSingleTarget("mArray", "MyArray", true, "xArray"); var actualCode = RefactoredCode(inputCode, selection, presenterAction); Assert.AreEqual(expectedCode, actualCode); } @@ -1149,59 +1077,103 @@ End Property private Func SetParameters( string propertyName, bool implementSet = false, - bool implementLet = false, - string parameterName = "value") + bool implementLet = false) { return model => { model.PropertyName = propertyName; - model.ParameterName = parameterName; model.ImplementLetSetterType = implementLet; model.ImplementSetSetterType = implementSet; return model; }; } - private Func SetParameters(FieldEncapsulationAttributes attributes) - { - return model => - { - model.UpdateEncapsulationField(attributes); - return model; - }; - } + private Func SetParametersForSingleTarget(string field, string property, bool flag = true, string newFieldName = null) + => SetParameters(new UserInputDataObject(field, property, flag, newFieldName)); - private Func SetParameters(IUDTFieldEncapsulationAttributes udtAttributes) - { - return model => - { - model.UpdateEncapsulationField(udtAttributes); - return model; - }; - } - private Func SetParameters(params (string variableName, string propertyName, bool encapsulateFlag)[] namePairs) + private Func SetParameters(UserInputDataObject testInput) { return model => { - foreach (var pair in namePairs) + foreach (var testModifiedAttribute in testInput.EncapsulateFieldAttributes) { - model.UpdateEncapsulationField(pair.variableName, pair.propertyName, pair.encapsulateFlag); + var attrsInitializedByTheRefactoring = model[testModifiedAttribute.FieldName].EncapsulationAttributes as IUserModifiableFieldEncapsulationAttributes; + var testSupport = model as ISupportEncapsulateFieldTests; + + attrsInitializedByTheRefactoring.FieldName = testModifiedAttribute.FieldName; + attrsInitializedByTheRefactoring.NewFieldName = testModifiedAttribute.NewFieldName; + attrsInitializedByTheRefactoring.PropertyName = testModifiedAttribute.PropertyName; + attrsInitializedByTheRefactoring.EncapsulateFlag = testModifiedAttribute.EncapsulateFlag; + + //If the Set/Let flags have been set by a test, they override the values applied by the refactoring + if (testModifiedAttribute.ImplLet.HasValue) + { + attrsInitializedByTheRefactoring.ImplementLetSetterType = testModifiedAttribute.ImplementLetSetterType; + } + + if (testModifiedAttribute.ImplSet.HasValue) + { + attrsInitializedByTheRefactoring.ImplementSetSetterType = testModifiedAttribute.ImplementSetSetterType; + } + + testSupport.SetEncapsulationFieldAttributes(attrsInitializedByTheRefactoring); + + foreach ((string memberName, bool flag) in testInput.UDTMemberNameFlagPairs) + { + testSupport.SetMemberEncapsulationFlag(memberName, flag); + } } return model; }; } - private Func SetParameters(params (string variableName, string propertyName, bool encapsulateFlag, string newFieldName)[] tuples) + private class UserModifiableFieldEncapsulationAttributes : IUserModifiableFieldEncapsulationAttributes { - return model => + public UserModifiableFieldEncapsulationAttributes(string fieldName, string propertyName, bool encapsulationFlag = true, string newFieldName = null) { - foreach (var tuple in tuples) - { - model.UpdateEncapsulationField(tuple.variableName, tuple.propertyName, tuple.encapsulateFlag, tuple.newFieldName); - } - return model; - }; + FieldName = fieldName; + NewFieldName = newFieldName ?? fieldName; + PropertyName = propertyName; + EncapsulateFlag = encapsulationFlag; + } + + public string FieldName { get; set; } + public string NewFieldName { get; set; } + public string PropertyName { get; set; } + public bool EncapsulateFlag { get; set; } + public bool? ImplLet; + public bool ImplementLetSetterType + { + get => ImplLet.HasValue ? ImplLet.Value : false; + set => ImplLet = value; + } + + public bool? ImplSet; + public bool ImplementSetSetterType + { + get => ImplSet.HasValue? ImplSet.Value : false; + set => ImplSet = value; + } + } + + private class UserInputDataObject + { + private List _userInput = new List(); + private List<(string, bool)> _udtNameFlagPairs = new List<(string, bool)>(); + + public UserInputDataObject(string fieldName, string propertyName, bool encapsulationFlag = true, string newFieldName = null) + => _userInput.Add(new UserModifiableFieldEncapsulationAttributes(fieldName, propertyName, encapsulationFlag, newFieldName)); + + public void AddAttributeSet(string fieldName, string propertyName, bool encapsulationFlag = true, string newFieldName = null) + => _userInput.Add(new UserModifiableFieldEncapsulationAttributes(fieldName, propertyName, encapsulationFlag, newFieldName)); + + public IEnumerable EncapsulateFieldAttributes => _userInput; + + public void AddUDTMemberNameFlagPairs(params (string, bool)[] nameFlagPairs) + => _udtNameFlagPairs.AddRange(nameFlagPairs); + + public IEnumerable<(string, bool)> UDTMemberNameFlagPairs => _udtNameFlagPairs; } private static IIndenter CreateIndenter(IVBE vbe = null) From 5fc4d6543d5136134368edcab006fe4783db9aea Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Wed, 13 Nov 2019 06:49:25 -0800 Subject: [PATCH 012/461] WIP introduced extended rewriter and others Modified decorators and moved IEncapulatedFieldAttributes to be implemented by EncapsulatedFieldDeclaration class. --- .../EncapsulateFieldDeclarationExtensions.cs | 48 +++ .../EncapsulateFieldDecorators.cs | 168 +++++++--- .../EncapsulateField/EncapsulateFieldModel.cs | 31 +- .../EncapsulateFieldNewContent.cs | 86 +++++ .../EncapsulateFieldRefactoring.cs | 138 ++++---- .../EncapsulateFieldRewriter.cs | 284 +++++++++++++++++ .../FieldEncapsulationAttributes.cs | 154 +++++---- .../Refactoring/EncapsulateFieldTests.cs | 300 ++++++++++-------- 8 files changed, 873 insertions(+), 336 deletions(-) create mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationExtensions.cs create mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldNewContent.cs create mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationExtensions.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationExtensions.cs new file mode 100644 index 0000000000..d30fb6b367 --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationExtensions.cs @@ -0,0 +1,48 @@ +using Rubberduck.Parsing; +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.EncapsulateField +{ + public static class EncapsulateFieldDeclarationExtensions + { + public static bool IsVariable(this Declaration declaration) + => declaration.DeclarationType.HasFlag(DeclarationType.Variable); + + public static bool IsMemberVariable(this Declaration declaration) + => declaration.IsVariable() && !declaration.ParentDeclaration.IsMember(); + + public static bool IsLocalVariable(this Declaration declaration) + => declaration.IsVariable() && declaration.ParentDeclaration.IsMember(); + + public static bool IsLocalConstant(this Declaration declaration) + => declaration.IsConstant() && declaration.ParentDeclaration.IsMember(); + + public static bool HasPrivateAccessibility(this Declaration declaration) + => declaration.Accessibility.Equals(Accessibility.Private); + + public static bool IsMember(this Declaration declaration) + => declaration.DeclarationType.HasFlag(DeclarationType.Member); + + public static bool IsConstant(this Declaration declaration) + => declaration.DeclarationType.HasFlag(DeclarationType.Constant); + + public static bool IsDeclaredInList(this Declaration declaration) + { + return declaration.Context.TryGetAncestor(out var varList) + && varList.ChildCount > 1; + } + + public static IEnumerable AllReferences(this IEnumerable declarations) + { + return from dec in declarations + from reference in dec.References + select reference; + } + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs index 4228712cbd..6aa13c36ef 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs @@ -8,16 +8,19 @@ public interface IEncapsulatedFieldDeclaration Declaration Declaration { get; } string IdentifierName { get; } DeclarationType DeclarationType { get; } + Accessibility Accessibility { get;} IFieldEncapsulationAttributes EncapsulationAttributes { set; get; } } - public class EncapsulatedFieldDeclaration : IEncapsulatedFieldDeclaration + public class EncapsulatedFieldDeclaration : IEncapsulatedFieldDeclaration, IFieldEncapsulationAttributes { - private Declaration _decorated; + protected Declaration _decorated; + protected IFieldEncapsulationAttributes _attributes; + public EncapsulatedFieldDeclaration(Declaration declaration) { _decorated = declaration; - EncapsulationAttributes = new FieldEncapsulationAttributes(_decorated); + _attributes = new FieldEncapsulationAttributes(_decorated); } public Declaration Declaration => _decorated; @@ -26,87 +29,152 @@ public EncapsulatedFieldDeclaration(Declaration declaration) public DeclarationType DeclarationType => _decorated.DeclarationType; - public IFieldEncapsulationAttributes EncapsulationAttributes { set; get; } = new FieldEncapsulationAttributes(); + public Accessibility Accessibility => _decorated.Accessibility; + + public IFieldEncapsulationAttributes EncapsulationAttributes + { + set => _attributes = value; + get => _attributes; + } + public string AsTypeName { get => _attributes.AsTypeName; set => _attributes.AsTypeName = value; } + public string ParameterName { get => _attributes.ParameterName; set => _attributes.ParameterName = value; } + public bool CanImplementLet { get => _attributes.CanImplementLet; set => _attributes.CanImplementLet = value; } + public bool CanImplementSet { get => _attributes.CanImplementSet; set => _attributes.CanImplementSet = value; } + public string FieldName { get => _attributes.FieldName; set => _attributes.FieldName = value; } + public string NewFieldName { get => _attributes.NewFieldName; set => _attributes.NewFieldName = value; } + public string PropertyName { get => _attributes.PropertyName; set => _attributes.PropertyName = value; } + public bool ImplementLetSetterType { get => _attributes.ImplementLetSetterType; set => _attributes.ImplementLetSetterType = value; } + public bool ImplementSetSetterType { get => _attributes.ImplementSetSetterType; set => _attributes.ImplementSetSetterType = value; } + public bool EncapsulateFlag { get => _attributes.EncapsulateFlag; set => _attributes.EncapsulateFlag = value; } } - public class EncapsulatedValueType : EncapsulatedFieldDeclaration + public class EncapsulateFieldDecoratorBase : IEncapsulatedFieldDeclaration, IFieldEncapsulationAttributes { - public EncapsulatedValueType(Declaration declaration) - : base(declaration) + + private IEncapsulatedFieldDeclaration _decorated; + private IFieldEncapsulationAttributes _attributes; + public EncapsulateFieldDecoratorBase(IEncapsulatedFieldDeclaration efd) { - EncapsulationAttributes.CanImplementLet = true; - EncapsulationAttributes.CanImplementSet = false; - EncapsulationAttributes.ImplementLetSetterType = true; - EncapsulationAttributes.ImplementSetSetterType = false; + _decorated = efd; + _attributes = efd as IFieldEncapsulationAttributes; } + + public Declaration Declaration => _decorated.Declaration; + + public string IdentifierName => _decorated.IdentifierName; + + public DeclarationType DeclarationType => _decorated.DeclarationType; + + public Accessibility Accessibility => _decorated.Accessibility; + + public IFieldEncapsulationAttributes EncapsulationAttributes { get => _decorated.EncapsulationAttributes; set => _decorated.EncapsulationAttributes = value; } + public string AsTypeName { get => _attributes.AsTypeName; set => _attributes.AsTypeName = value; } + public string ParameterName { get => _attributes.ParameterName; set => _attributes.ParameterName = value; } + public bool CanImplementLet { get => _attributes.CanImplementLet; set => _attributes.CanImplementLet = value; } + public bool CanImplementSet { get => _attributes.CanImplementSet; set => _attributes.CanImplementSet = value; } + public string FieldName { get => _attributes.FieldName; set => _attributes.FieldName = value; } + public string NewFieldName { get => _attributes.NewFieldName; set => _attributes.NewFieldName = value; } + public string PropertyName { get => _attributes.PropertyName; set => _attributes.PropertyName = value; } + public bool ImplementLetSetterType { get => _attributes.ImplementLetSetterType; set => _attributes.ImplementLetSetterType = value; } + public bool ImplementSetSetterType { get => _attributes.ImplementSetSetterType; set => _attributes.ImplementSetSetterType = value; } + public bool EncapsulateFlag { get => _attributes.EncapsulateFlag; set => _attributes.EncapsulateFlag = value; } } - public class EncapsulatedUserDefinedType : EncapsulatedFieldDeclaration + public class EncapsulatedValueType : EncapsulateFieldDecoratorBase // IEncapsulatedFieldDeclaration, IFieldEncapsulationAttributes { - public EncapsulatedUserDefinedType(Declaration declaration) - : base(declaration) + private EncapsulatedValueType(IEncapsulatedFieldDeclaration efd) + : base(efd) { - EncapsulationAttributes.CanImplementLet = true; - EncapsulationAttributes.CanImplementSet = false; - EncapsulationAttributes.ImplementLetSetterType = true; - EncapsulationAttributes.ImplementSetSetterType = false; + CanImplementLet = true; + CanImplementSet = false; + ImplementLetSetterType = true; + ImplementSetSetterType = false; } + + public static IEncapsulatedFieldDeclaration Decorate(IEncapsulatedFieldDeclaration efd) + => new EncapsulatedValueType(efd); } - public class EncapsulatedVariantType : EncapsulatedFieldDeclaration + public class EncapsulatedUserDefinedType : EncapsulateFieldDecoratorBase { - public EncapsulatedVariantType(Declaration declaration) - : base(declaration) + + private EncapsulatedUserDefinedType(IEncapsulatedFieldDeclaration efd) + : base(efd) { - EncapsulationAttributes.CanImplementLet = true; - EncapsulationAttributes.CanImplementSet = true; - EncapsulationAttributes.ImplementLetSetterType = true; - EncapsulationAttributes.ImplementSetSetterType = true; + CanImplementLet = true; + CanImplementSet = false; + ImplementLetSetterType = true; + ImplementSetSetterType = false; } + + public static IEncapsulatedFieldDeclaration Decorate(IEncapsulatedFieldDeclaration efd) + => new EncapsulatedUserDefinedType(efd); } - public class EncapsulatedObjectType : EncapsulatedFieldDeclaration + public class EncapsulatedVariantType : EncapsulateFieldDecoratorBase // IEncapsulatedFieldDeclaration, IFieldEncapsulationAttributes { - public EncapsulatedObjectType(Declaration declaration) - : base(declaration) + private EncapsulatedVariantType(IEncapsulatedFieldDeclaration efd) + : base(efd) { - EncapsulationAttributes.CanImplementLet = false; - EncapsulationAttributes.CanImplementSet = true; - EncapsulationAttributes.ImplementLetSetterType = false; - EncapsulationAttributes.ImplementSetSetterType = true; + CanImplementLet = true; + CanImplementSet = true; + ImplementLetSetterType = true; + ImplementSetSetterType = true; } + + public static IEncapsulatedFieldDeclaration Decorate(IEncapsulatedFieldDeclaration efd) + => new EncapsulatedVariantType(efd); } - public class EncapsulatedArrayType : EncapsulatedFieldDeclaration + public class EncapsulatedObjectType : EncapsulateFieldDecoratorBase //IEncapsulatedFieldDeclaration, IFieldEncapsulationAttributes { - public EncapsulatedArrayType(Declaration declaration) - : base(declaration) + private EncapsulatedObjectType(IEncapsulatedFieldDeclaration efd) + : base(efd) { - EncapsulationAttributes.CanImplementLet = false; - EncapsulationAttributes.CanImplementSet = false; - EncapsulationAttributes.ImplementLetSetterType = false; - EncapsulationAttributes.ImplementSetSetterType = false; - EncapsulationAttributes.AsTypeName = Tokens.Variant; + CanImplementLet = false; + CanImplementSet = true; + ImplementLetSetterType = false; + ImplementSetSetterType = true; } + + public static IEncapsulatedFieldDeclaration Decorate(IEncapsulatedFieldDeclaration efd) + => new EncapsulatedObjectType(efd); } - public class EncapsulatedUserDefinedTypeMember : IEncapsulatedFieldDeclaration + public class EncapsulatedArrayType : EncapsulateFieldDecoratorBase //IEncapsulatedFieldDeclaration, IFieldEncapsulationAttributes { - private readonly IEncapsulatedFieldDeclaration _decorated; - public EncapsulatedUserDefinedTypeMember(IEncapsulatedFieldDeclaration encapsulateFieldDeclaration, EncapsulatedUserDefinedType udtVariable) + private EncapsulatedArrayType(IEncapsulatedFieldDeclaration efd) + : base(efd) { - _decorated = encapsulateFieldDeclaration; - EncapsulationAttributes = _decorated.EncapsulationAttributes; - EncapsulationAttributes.NewFieldName = $"{udtVariable.Declaration.IdentifierName}.{encapsulateFieldDeclaration.Declaration.IdentifierName}"; + CanImplementLet = false; + CanImplementSet = false; + ImplementLetSetterType = false; + ImplementSetSetterType = false; + AsTypeName = Tokens.Variant; } - public Declaration Declaration => _decorated.Declaration; + public static IEncapsulatedFieldDeclaration Decorate(IEncapsulatedFieldDeclaration efd) + => new EncapsulatedArrayType(efd); + } - public string IdentifierName => _decorated.IdentifierName; + public class EncapsulatedUserDefinedTypeMember : EncapsulateFieldDecoratorBase + { + private EncapsulatedUserDefinedType _udt; - public DeclarationType DeclarationType => _decorated.DeclarationType; + private EncapsulatedUserDefinedTypeMember(IEncapsulatedFieldDeclaration efd, EncapsulatedUserDefinedType udtVariable) + : base(efd) + { + _udt = udtVariable; + var decoratedAttributes = efd as IFieldEncapsulationAttributes; + CanImplementLet = decoratedAttributes.CanImplementLet; + CanImplementSet = decoratedAttributes.CanImplementSet; + ImplementLetSetterType = decoratedAttributes.ImplementLetSetterType; + ImplementSetSetterType = decoratedAttributes.ImplementSetSetterType; + NewFieldName = $"{udtVariable.Declaration.IdentifierName}.{efd.Declaration.IdentifierName}"; + } - public IFieldEncapsulationAttributes EncapsulationAttributes { set; get; } + public static IEncapsulatedFieldDeclaration Decorate(IEncapsulatedFieldDeclaration efd, EncapsulatedUserDefinedType udtVariable) + => new EncapsulatedUserDefinedTypeMember(efd, udtVariable); } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index 244141d023..a3f181ec1b 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -32,7 +32,7 @@ public EncapsulateFieldModel(Declaration target, IEnumerable allMem foreach (var field in allMemberFields.Except(UdtFields)) { - AddEncapsulationField(DecorateDeclaration(field)); + AddEncapsulationField(EncapsulateDeclaration(field)); } AddUDTEncapsulationFields(udtFieldToUdtDeclarationMap); @@ -74,8 +74,6 @@ public IEncapsulatedFieldDeclaration this[Declaration declaration] } } - //public IUserModifiableFieldEncapsulationAttributes UserEncapsulationAttributes(string fieldName) => this[fieldName].EncapsulationAttributes as IUserModifiableFieldEncapsulationAttributes; - public IList PropertiesContent { get @@ -98,36 +96,38 @@ private void AddUDTEncapsulationFields(IDictionary _userSelectedEncapsulationField.EncapsulationAttributes.PropertyName = value; } + public string NewFieldName + { + get => _userSelectedEncapsulationField.EncapsulationAttributes.NewFieldName; + set => _userSelectedEncapsulationField.EncapsulationAttributes.NewFieldName = value; + } + public string ParameterName { get => _userSelectedEncapsulationField.EncapsulationAttributes.ParameterName ?? "value"; diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldNewContent.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldNewContent.cs new file mode 100644 index 0000000000..be8690933f --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldNewContent.cs @@ -0,0 +1,86 @@ +using Rubberduck.Common; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Symbols; +using Rubberduck.VBEditor; +using Rubberduck.VBEditor.SafeComWrappers; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + public interface IEncapsulateFieldNewContentProvider + { + void AddDeclarationBlock(string declarationBlock); + void AddCodeBlock(string codeBlock); + List Declarations { get; } + List CodeBlocks { get; } + string PreCodeSectionContent { get; } + bool HasNewContent { get; } + string CodeSectionContent { get; } + string AsSingleTextBlock { get; } + int CountOfProcLines { get; } + } + + public class EncapsulateFieldNewContent : IEncapsulateFieldNewContentProvider + { + private IEnumerable SourceModuleElements { get; } + + public void AddDeclarationBlock(string declarationBlock) + { + if (declarationBlock.Length > 0) + { + Declarations.Add(declarationBlock); + } + } + + public void AddCodeBlock(string codeBlock) + { + if (codeBlock.Length > 0) + { + CodeBlocks.Add(codeBlock); + } + } + + public List Declarations { get; } = new List(); + + public List CodeBlocks { get; } = new List(); + + public string PreCodeSectionContent + { + get + { + var preCodeSectionContent = new List(Declarations); + if (preCodeSectionContent.Any()) + { + var preCodeSection = string.Join(Environment.NewLine, preCodeSectionContent); + return preCodeSection; + } + return string.Empty; + } + } + + public bool HasNewContent => Declarations.Any() || CodeBlocks.Any(); + + public string CodeSectionContent => CodeBlocks.Any() ? string.Join($"{Environment.NewLine}{Environment.NewLine}", CodeBlocks) : string.Empty; + + public string AsSingleTextBlock + { + get + { + if (!HasNewContent) { return string.Empty; } + + if (PreCodeSectionContent.Length > 0) + { + return CodeSectionContent.Length > 0 + ? $"{PreCodeSectionContent}{Environment.NewLine}{Environment.NewLine}{CodeSectionContent}" + : $"{PreCodeSectionContent}"; + } + + return $"{Environment.NewLine}{CodeSectionContent}"; + } + } + + public int CountOfProcLines => CodeSectionContent.Split(new string[] { Environment.NewLine }, StringSplitOptions.None).Count(); + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index aef9e39581..d3a8d003d0 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -19,6 +19,7 @@ public class EncapsulateFieldRefactoring : InteractiveRefactoringBase v.DeclarationType.Equals(DeclarationType.Variable) - && !v.ParentDeclaration.DeclarationType.HasFlag(DeclarationType.Member)); + _targetQMN = target.QualifiedModuleName; - var udtFieldToTypeMap = allMemberFields + var encapsulationCandiateFields = _declarationFinderProvider.DeclarationFinder + .Members(_targetQMN) + .Where(v => v.IsMemberVariable() && !v.IsWithEvents); + + var userDefinedTypeFieldToTypeDeclarationMap = encapsulationCandiateFields .Where(v => v.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.UserDefinedType) ?? false) .Select(uv => CreateUDTTuple(uv)) .ToDictionary(key => key.UDTVariable, element => (element.UserDefinedType, element.UDTMembers)); - var model = new EncapsulateFieldModel(target, allMemberFields, udtFieldToTypeMap, _indenter); + var model = new EncapsulateFieldModel(target, encapsulationCandiateFields, userDefinedTypeFieldToTypeDeclarationMap, _indenter); return model; } - private (Declaration UDTVariable, Declaration UserDefinedType, IEnumerable UDTMembers) CreateUDTTuple(Declaration udtVariable) - { - var userDefinedTypeDeclaration = _declarationFinderProvider.DeclarationFinder - .UserDeclarations(DeclarationType.UserDefinedType) - .Where(ut => ut.IdentifierName.Equals(udtVariable.AsTypeName) - && (ut.Accessibility.Equals(Accessibility.Private) - && ut.QualifiedModuleName == udtVariable.QualifiedModuleName) - || (ut.Accessibility != Accessibility.Private)) - .SingleOrDefault(); - - var udtMembers = _declarationFinderProvider.DeclarationFinder - .UserDeclarations(DeclarationType.UserDefinedTypeMember) - .Where(utm => userDefinedTypeDeclaration.IdentifierName == utm.ParentDeclaration.IdentifierName); - - return (udtVariable, userDefinedTypeDeclaration, udtMembers); - } - protected override void RefactorImpl(EncapsulateFieldModel model) { var rewriteSession = RewritingManager.CheckOutCodePaneSession(); var nonUdtMemberFields = model.FlaggedEncapsulationFields - .Where(efd => efd.DeclarationType.Equals(DeclarationType.Variable)); + .Where(encFld => encFld.Declaration.IsVariable()); + var newContent = new EncapsulateFieldNewContent(); foreach (var nonUdtMemberField in nonUdtMemberFields) { var attributes = nonUdtMemberField.EncapsulationAttributes; - EnforceEncapsulatedVariablePrivateAccessibility(nonUdtMemberField.Declaration, attributes, rewriteSession); + newContent = ModifyEncapsulatedVariable(nonUdtMemberField, attributes, rewriteSession, newContent); + UpdateReferences(nonUdtMemberField.Declaration, rewriteSession, attributes.PropertyName); } - InsertProperties(model, rewriteSession); + newContent = LoadNewPropertyContent(model, newContent); + + var moduleMembers = _declarationFinderProvider.DeclarationFinder + .Members(_targetQMN).Where(m => m.IsMember()); + + int? codeSectionStartIndex + = moduleMembers.OrderBy(c => c.Selection) + .FirstOrDefault()?.Context.Start.TokenIndex ?? null; + + var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, _targetQMN); + + rewriter.InsertNewContent(codeSectionStartIndex, newContent); if (!rewriteSession.TryRewrite()) { @@ -113,80 +111,68 @@ protected override void RefactorImpl(EncapsulateFieldModel model) } } - private void InsertProperties(EncapsulateFieldModel model, IRewriteSession rewriteSession) + private EncapsulateFieldNewContent LoadNewPropertyContent(EncapsulateFieldModel model, EncapsulateFieldNewContent newContent) { - if (!model.FlaggedEncapsulationFields.Any()) { return; } - - var qualifiedModuleName = model.FlaggedEncapsulationFields.First().Declaration.QualifiedModuleName; - - var carriageReturns = $"{Environment.NewLine}{Environment.NewLine}"; - - var insertionTokenIndex = _declarationFinderProvider.DeclarationFinder - .Members(qualifiedModuleName) - .Where(d => d.DeclarationType == DeclarationType.Variable - && !d.ParentScopeDeclaration.DeclarationType.HasFlag(DeclarationType.Member)) - .OrderBy(declaration => declaration.QualifiedSelection) - .Last().Context.Stop.TokenIndex; ; + if (!model.FlaggedEncapsulationFields.Any()) { return newContent; } - - var rewriter = rewriteSession.CheckOutModuleRewriter(qualifiedModuleName); - rewriter.InsertAfter(insertionTokenIndex, $"{carriageReturns}{string.Join(carriageReturns, model.PropertiesContent)}"); + newContent.AddCodeBlock($"{string.Join($"{Environment.NewLine}{Environment.NewLine}", model.PropertiesContent)}"); + return newContent; } - private void EnforceEncapsulatedVariablePrivateAccessibility(Declaration target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession) + private EncapsulateFieldNewContent ModifyEncapsulatedVariable(IEncapsulatedFieldDeclaration target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession, EncapsulateFieldNewContent newContent) + //private EncapsulateFieldNewContent ModifyEncapsulatedVariable(IEncapsulatedFieldDeclaration encapsulatedField, IRewriteSession rewriteSession, EncapsulateFieldNewContent newContent) { - if (!target.DeclarationType.Equals(DeclarationType.Variable)) - { - return; - } - - var rewriter = rewriteSession.CheckOutModuleRewriter(target.QualifiedModuleName); + var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, _targetQMN); if (target.Accessibility == Accessibility.Private && attributes.NewFieldName.Equals(target.IdentifierName)) { - if (!target.Context.TryGetChildContext(out _)) - { - rewriter.InsertAfter(target.Context.Stop.TokenIndex, $" {Tokens.As} {target.AsTypeName}"); - } - return; + rewriter.MakeImplicitDeclarationTypeExplicit(target.Declaration); + return newContent; } - if (target.Context.TryGetAncestor(out var varList) - && varList.ChildCount > 1) + if (target.Declaration.IsDeclaredInList()) { - rewriter.Remove(target); - - var arrayDeclaration = target.Context.GetText().Split(new string[] { $" {Tokens.As} " }, StringSplitOptions.None); - var arrayIdentiferAndDimension = arrayDeclaration[0].Replace(attributes.FieldName, attributes.NewFieldName); + var targetIdentifier = target.Declaration.Context.GetText().Replace(attributes.FieldName, attributes.NewFieldName); + var newField = target.Declaration.IsTypeSpecified ? $"{Tokens.Private} {targetIdentifier}" : $"{Tokens.Private} {targetIdentifier} {Tokens.As} {target.Declaration.AsTypeName}"; - var newField = target.IsArray ? $"{Accessibility.Private} {arrayIdentiferAndDimension} {Tokens.As} {target.AsTypeName}" - : $"{Accessibility.Private} {attributes.NewFieldName} As {target.AsTypeName}"; + rewriter.Remove(target.Declaration); - rewriter.InsertAfter(varList.Stop.TokenIndex, $"{Environment.NewLine}{newField}"); + newContent.AddDeclarationBlock(newField); } else { - var identifierContext = target.Context.GetChild(); - var variableStmtContext = target.Context.GetAncestor(); - var visibilityContext = variableStmtContext.GetChild(); - - rewriter.Replace(visibilityContext, Tokens.Private); - rewriter.Replace(identifierContext, attributes.NewFieldName); - - if (!target.Context.TryGetChildContext(out _)) - { - rewriter.InsertAfter(target.Context.Stop.TokenIndex, $" {Tokens.As} {target.AsTypeName}"); - } + rewriter.Rename(target.Declaration, attributes.NewFieldName); + rewriter.SetVariableVisiblity(target.Declaration, Accessibility.Private.TokenString()); + rewriter.MakeImplicitDeclarationTypeExplicit(target.Declaration); } + return newContent; } - private void UpdateReferences(Declaration target, IRewriteSession rewriteSession, string newName = null) + private void UpdateReferences(Declaration target, IRewriteSession rewriteSession, string propertyName) { foreach (var reference in target.References) { var rewriter = rewriteSession.CheckOutModuleRewriter(reference.QualifiedModuleName); - rewriter.Replace(reference.Context, newName ?? target.IdentifierName); + rewriter.Replace(reference.Context, propertyName ?? target.IdentifierName); } } + + private (Declaration UDTVariable, Declaration UserDefinedType, IEnumerable UDTMembers) CreateUDTTuple(Declaration udtVariable) + { + var userDefinedTypeDeclaration = _declarationFinderProvider.DeclarationFinder + .UserDeclarations(DeclarationType.UserDefinedType) + .Where(ut => ut.IdentifierName.Equals(udtVariable.AsTypeName) + && (ut.Accessibility.Equals(Accessibility.Private) + && ut.QualifiedModuleName == udtVariable.QualifiedModuleName) + || (ut.Accessibility != Accessibility.Private)) + .SingleOrDefault(); + + var udtMembers = _declarationFinderProvider.DeclarationFinder + .UserDeclarations(DeclarationType.UserDefinedTypeMember) + .Where(utm => userDefinedTypeDeclaration.IdentifierName == utm.ParentDeclaration.IdentifierName); + + return (udtVariable, userDefinedTypeDeclaration, udtMembers); + } + } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs new file mode 100644 index 0000000000..b5b2a3e971 --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs @@ -0,0 +1,284 @@ +using Antlr4.Runtime; +using Antlr4.Runtime.Misc; +using Antlr4.Runtime.Tree; +using Rubberduck.Common; +using Rubberduck.Parsing; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; +using Rubberduck.VBEditor; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + public interface IEncapsulateFieldRewriter : IModuleRewriter + { + //void RemoveDeclarations(IEnumerable allDeclarationsToRemove, IEnumerable allModuleDeclarations); + void InsertNewContent(int? codeSectionStartIndex, IEncapsulateFieldNewContentProvider newContent); + void ReplaceDescendentContext(Declaration member, string content) where T : ParserRuleContext; + void InsertBeforeDescendentContext(Declaration member, string content) where T : ParserRuleContext; + void SetMemberVisibility(Declaration member, string visibilityToken); + void SetVariableVisiblity(Declaration element, string visibilityToken); + void Rename(Declaration element, string newName); + void MakeImplicitDeclarationTypeExplicit(Declaration element); + void RemoveMemberAccess(IEnumerable memberReferences); + void RemoveMemberAccess(IdentifierReference idRef); + void RemoveWithMemberAccess(IEnumerable idReferences); + void InsertAtEndOfFile(string content); + string GetModifiedText(Declaration declaration); + } + + public class EncapsulateFieldRewriter : IEncapsulateFieldRewriter + { + public static IEncapsulateFieldRewriter CheckoutModuleRewriter(IRewriteSession rewriteSession, QualifiedModuleName qmn) + { + var rewriter = rewriteSession.CheckOutModuleRewriter(qmn); + return new EncapsulateFieldRewriter(rewriter); + } + + private IModuleRewriter _rewriter; + + public EncapsulateFieldRewriter(IModuleRewriter rewriter) + { + _rewriter = rewriter; + } + + public void InsertNewContent(int? codeSectionStartIndex, IEncapsulateFieldNewContentProvider newContent) + { + if (codeSectionStartIndex.HasValue && newContent.HasNewContent) + { + _rewriter.InsertBefore(codeSectionStartIndex.Value, $"{Environment.NewLine}{newContent.AsSingleTextBlock}"); + } + else + { + InsertAtEndOfFile($"{Environment.NewLine}{newContent.AsSingleTextBlock}"); + } + } + + public void ReplaceDescendentContext(Declaration member, string content) where T : ParserRuleContext + { + var descendentCtxt = member.Context.GetDescendent(); + if (descendentCtxt != null) + { + _rewriter.Replace(descendentCtxt, content); + } + } + + public void InsertBeforeDescendentContext(Declaration member, string content) where T : ParserRuleContext + { + var descendentCtxt = member.Context.GetDescendent(); + if (descendentCtxt != null) + { + _rewriter.InsertBefore(descendentCtxt.Start.TokenIndex, content); + } + } + + //public void RemoveDeclarations(IEnumerable allDeclarationsToRemove, IEnumerable allModuleDeclarations) + //{ + // if (allDeclarationsToRemove.Count() == 0) + // { + // return; + // } + // var original = _rewriter.GetText(); + + // var declaredInLists = allDeclarationsToRemove.Where(declaration => + // declaration.Context.Parent is VBAParser.VariableListStmtContext + // || declaration.Context.Parent is VBAParser.ConstStmtContext); + + // RemoveMany(_rewriter, allDeclarationsToRemove.Except(declaredInLists)); + + // //Handle special cases where the declarations to remove + // //are/can be declared within a declarationlist context + // if (declaredInLists.Any()) + // { + // var lookupCtxtToDeclarationListRemovals = declaredInLists.ToLookup(dec => dec.Context.Parent as ParserRuleContext); + + // foreach (var declarationsToRemoveFromList in lookupCtxtToDeclarationListRemovals) + // { + // var allDeclarationsInList = allModuleDeclarations + // .Where(dec => dec.Context?.Parent == declarationsToRemoveFromList.Key); + + // RemoveDeclarationListContent(declarationsToRemoveFromList, allDeclarationsInList); + // } + // var removeListyResult = _rewriter.GetText(); + // } + //} + + //The issues described within this method seems to have been fixed + //private void RemoveDeclarationListContent(IGrouping toRemoveFromDeclarationList, IEnumerable allDeclarationsInDeclarationList) + //{ + // //Remove the entire list + // if (toRemoveFromDeclarationList.Count() == allDeclarationsInDeclarationList.Count()) + // { + // var parentContext = toRemoveFromDeclarationList.First().Context.Parent; + // if (parentContext is VBAParser.ConstStmtContext) + // { + // _rewriter.Remove(parentContext); + // } + // else + // { + // _rewriter.Remove(parentContext.Parent); + // } + // return; + // } + + // //A subset of the declarations in the list are to be removed + // //1. Remove declarations individually + // //2. Handle special case described below + // RemoveMany(_rewriter, toRemoveFromDeclarationList); + + // //Special case: + // //If there are 'n' declarations in a list (where 'n' >= 3) and we are removing 2 to n-1 of + // //the LAST declarations, calling 'rewriter.Remove' on each declaration leaves + // //a trailing comma on the last RETAINED declaration. + // if (toRemoveFromDeclarationList.Count() >= 2 && allDeclarationsInDeclarationList.Count() >= 3) + // { + // var reversedDeclarationListElements = allDeclarationsInDeclarationList.OrderByDescending(tr => tr.Selection); + // var removedFromEndOfList = reversedDeclarationListElements.TakeWhile(rd => toRemoveFromDeclarationList.Contains(rd)); + // if (removedFromEndOfList.Count() >= 2) + // { + // var lastRetainedDeclaration = reversedDeclarationListElements.ElementAt(removedFromEndOfList.Count()); + // var tokenStart = lastRetainedDeclaration.Context.Stop.TokenIndex + 1; + // var tokenStop = removedFromEndOfList.Last().Context.Start.TokenIndex - 1; + // _rewriter.RemoveRange(tokenStart, tokenStop); + // } + // } + //} + + private static void RemoveMany(IModuleRewriter rewriter, IEnumerable declarations) + { + foreach (var dec in declarations) + { + rewriter.Remove(dec); + } + } + + public void InsertAtEndOfFile(string content) + { + if (content == string.Empty) + { + return; + } + _rewriter.InsertBefore(_rewriter.TokenStream.Size - 1, content); + } + + public string GetModifiedText(Declaration declaration) + { + return _rewriter.GetText(declaration.Context.Start.TokenIndex, declaration.Context.Stop.TokenIndex); + } + + public void SetMemberVisibility(Declaration element, string visibility) + { + if (!element.IsMember()) { return; } + + var visibilityContext = element.Context.GetChild(); + if (visibilityContext != null) + { + _rewriter.Replace(visibilityContext, visibility); + return; + } + _rewriter.InsertBefore(element.Context.Start.TokenIndex, $"{visibility} "); + } + + public void SetVariableVisiblity(Declaration element, string visibility) + { + if (!element.IsVariable()) { return; } + + var variableStmtContext = element.Context.GetAncestor(); + var visibilityContext = variableStmtContext.GetChild(); + + if (visibilityContext != null) + { + _rewriter.Replace(visibilityContext, visibility); + return; + } + _rewriter.InsertBefore(element.Context.Start.TokenIndex, $"{visibility} "); + } + + public void Rename(Declaration element, string newName) + { + var identifierContext = element.Context.GetChild(); + _rewriter.Replace(identifierContext, newName); + } + + public void MakeImplicitDeclarationTypeExplicit(Declaration element) + { + if (!element.Context.TryGetChildContext(out _)) + { + _rewriter.InsertAfter(element.Context.Stop.TokenIndex, $" {Tokens.As} {element.AsTypeName}"); + } + } + + public void RemoveMemberAccess(IEnumerable memberReferences) + { + var memberAccessExprContexts = memberReferences + .Where(rf => rf.Context.Parent is VBAParser.MemberAccessExprContext); + + foreach (var context in memberAccessExprContexts) + { + RemoveMemberAccess(context); + } + } + + public void RemoveWithMemberAccess(IEnumerable references) + { + foreach (var withMemberAccessExprContext in references.Where(rf => rf.Context.Parent is VBAParser.WithMemberAccessExprContext).Select(rf => rf.Context.Parent as VBAParser.WithMemberAccessExprContext)) + { + RemoveRange(withMemberAccessExprContext.Start.TokenIndex, withMemberAccessExprContext.Start.TokenIndex); + } + } + + public void RemoveMemberAccess(IdentifierReference idRef) + { + if (idRef.Context.Parent is VBAParser.MemberAccessExprContext maec) + { + Debug.Assert(maec.ChildCount == 3, "MemberAccessExprContext child contexts does not equal 3"); + Replace(maec, maec.children[2].GetText()); + } + } + + public bool IsDirty => _rewriter.IsDirty; + + public Selection? Selection { get => _rewriter.Selection; set => _rewriter.Selection = value; } + public Selection? SelectionOffset { get => _rewriter.SelectionOffset; set => _rewriter.SelectionOffset = value; } + + public ITokenStream TokenStream => _rewriter.TokenStream; + + public string GetText(int startTokenIndex, int stopTokenIndex) => _rewriter.GetText(startTokenIndex, stopTokenIndex); + + public string GetText() => _rewriter.GetText(); + + public void InsertAfter(int tokenIndex, string content) => _rewriter.InsertAfter(tokenIndex, content); + + public void InsertBefore(int tokenIndex, string content) => _rewriter.InsertBefore(tokenIndex, content); + + public void Remove(Declaration target) => _rewriter.Remove(target); + + public void Remove(ParserRuleContext target) => _rewriter.Remove(target); + + public void Remove(IToken target) => _rewriter.Remove(target); + + public void Remove(ITerminalNode target) => _rewriter.Remove(target); + + public void Remove(IParseTree target) => _rewriter.Remove(target); + + public void RemoveRange(int start, int stop) => _rewriter.RemoveRange(start, stop); + + public void Replace(Declaration target, string content) => _rewriter.Replace(target, content); + + public void Replace(ParserRuleContext target, string content) => _rewriter.Replace(target, content); + + public void Replace(IToken token, string content) => _rewriter.Replace(token, content); + + public void Replace(ITerminalNode target, string content) => _rewriter.Replace(target, content); + + public void Replace(IParseTree target, string content) => _rewriter.Replace(target, content); + + public void Replace(Interval tokenInterval, string content) => _rewriter.Replace(tokenInterval, content); + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs index 937d0bf19a..25aaf578b7 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs @@ -16,6 +16,7 @@ public interface IUserModifiableFieldEncapsulationAttributes public interface IFieldEncapsulationAttributes : IUserModifiableFieldEncapsulationAttributes { + //string SetGet_LHSField { get; set; } string AsTypeName { get; set; } string ParameterName { get; set; } bool CanImplementLet { get; set; } @@ -26,8 +27,23 @@ public class FieldEncapsulationAttributes : IFieldEncapsulationAttributes { private static string DEFAULT_LET_PARAMETER = "value"; + //private string _defaultBackingFieldName; + //private string _defaultPropertyName; + //private string _defaultParameterName = DEFAULT_LET_PARAMETER; + public FieldEncapsulationAttributes() { } + //public FieldEncapsulationAttributes(Declaration target) + //{ + // FieldName = target.IdentifierName; + // (string newFieldName, string propertyName) = GenerateDefaultNames(target.IdentifierName); + // SetGet_LHSField = newFieldName; + // NewFieldName = newFieldName; + // PropertyName = propertyName; + // AsTypeName = target.AsTypeName; + // ParameterName = DEFAULT_LET_PARAMETER; + //} + public FieldEncapsulationAttributes(Declaration target, string newFieldName = null, string parameterName = null) { FieldName = target.IdentifierName; @@ -37,6 +53,23 @@ public FieldEncapsulationAttributes(Declaration target, string newFieldName = nu ParameterName = parameterName ?? DEFAULT_LET_PARAMETER; } + public (string defaultField, string defaultProperty) GenerateDefaultNames(string targetName) + { + var defaultBackingFieldName = targetName + "1"; + var defaultPropertyName = string.Empty; + if (char.IsLower(targetName, 0)) + { + defaultPropertyName = $"{char.ToUpperInvariant(targetName[0]) + targetName.Substring(1, targetName.Length - 1)}"; + } + else + { + defaultPropertyName = targetName; + } + return (defaultBackingFieldName, defaultPropertyName); + } + + //private bool IsCamelCase(string value) => char.IsLower(value, 0) && char.IsUpper(value, 1); + public string FieldName { get; set; } private string _newFieldName; @@ -45,6 +78,9 @@ public string NewFieldName get => _newFieldName ?? FieldName; set => _newFieldName = value; } + + //TODO: Set BackingField to udtVariable.udtMember somehow. Otherwise, BackingField == NewField + //public string SetGet_LHSField { get; set; } public string PropertyName { get; set; } public string AsTypeName { get; set; } public string ParameterName { get; set; } = DEFAULT_LET_PARAMETER; @@ -56,63 +92,63 @@ public string NewFieldName public bool CanImplementSet { get; set; } } - public class UDTFieldEncapsulationAttributes : IFieldEncapsulationAttributes - { - private IFieldEncapsulationAttributes _attributes { get; } - private Dictionary _memberEncapsulationFlags = new Dictionary(); - - public UDTFieldEncapsulationAttributes(FieldEncapsulationAttributes attributes) //, IEnumerable udtMemberNames) - { - _attributes = attributes; - } - - public string FieldName - { - get => _attributes.FieldName; - set => _attributes.FieldName = value; - } - - public string PropertyName - { - get => _attributes.PropertyName; - set => _attributes.PropertyName = value; - } - - public string NewFieldName - { - get => _attributes.NewFieldName; - set => _attributes.NewFieldName = value; - } - - public string AsTypeName - { - get => _attributes.AsTypeName; - set => _attributes.AsTypeName = value; - } - public string ParameterName - { - get => _attributes.ParameterName; - set => _attributes.ParameterName = value; - } - public bool ImplementLetSetterType - { - get => _attributes.ImplementLetSetterType; - set => _attributes.ImplementLetSetterType = value; - } - - public bool ImplementSetSetterType - { - get => _attributes.ImplementSetSetterType; - set => _attributes.ImplementSetSetterType = value; - } - - public bool EncapsulateFlag - { - get => _attributes.EncapsulateFlag; - set => _attributes.EncapsulateFlag = value; - } - - public bool CanImplementLet { get; set; } - public bool CanImplementSet { get; set; } - } + //public class UDTFieldEncapsulationAttributesX : IFieldEncapsulationAttributes + //{ + // private IFieldEncapsulationAttributes _attributes { get; } + // private Dictionary _memberEncapsulationFlags = new Dictionary(); + + // public UDTFieldEncapsulationAttributesX(FieldEncapsulationAttributes attributes) //, IEnumerable udtMemberNames) + // { + // _attributes = attributes; + // } + + // public string FieldName + // { + // get => _attributes.FieldName; + // set => _attributes.FieldName = value; + // } + + // public string PropertyName + // { + // get => _attributes.PropertyName; + // set => _attributes.PropertyName = value; + // } + + // public string NewFieldName + // { + // get => _attributes.NewFieldName; + // set => _attributes.NewFieldName = value; + // } + + // public string AsTypeName + // { + // get => _attributes.AsTypeName; + // set => _attributes.AsTypeName = value; + // } + // public string ParameterName + // { + // get => _attributes.ParameterName; + // set => _attributes.ParameterName = value; + // } + // public bool ImplementLetSetterType + // { + // get => _attributes.ImplementLetSetterType; + // set => _attributes.ImplementLetSetterType = value; + // } + + // public bool ImplementSetSetterType + // { + // get => _attributes.ImplementSetSetterType; + // set => _attributes.ImplementSetSetterType = value; + // } + + // public bool EncapsulateFlag + // { + // get => _attributes.EncapsulateFlag; + // set => _attributes.EncapsulateFlag = value; + // } + + // public bool CanImplementLet { get; set; } + // public bool CanImplementSet { get; set; } + //} } diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index ad3660bdf5..9fa6446338 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -14,6 +14,7 @@ using Rubberduck.Refactorings.Exceptions; using Rubberduck.VBEditor.Utility; using System.Collections.Generic; +using System.Linq; namespace RubberduckTests.Refactoring { @@ -48,41 +49,117 @@ End Property Assert.AreEqual(expectedCode, actualCode); } - [Test] + [TestCase("fizz", true, "baz", true, "buzz", true)] + [TestCase("fizz", false, "baz", true, "buzz", true)] + [TestCase("fizz", false, "baz", false, "buzz", true)] [Category("Refactorings")] [Category("Encapsulate Field")] - public void EncapsulateMultipleFields() + public void EncapsulateMultipleFields( + string var1, bool var1Flag, + string var2, bool var2Flag, + string var3, bool var3Flag) { - //Input - const string inputCode = -@"Public fizz As Integer -Public baz As String -Public buzz As Boolean"; + string inputCode = +$@"Public {var1} As Integer +Public {var2} As Integer +Public {var3} As Integer"; var selection = new Selection(1, 1); - var userInput = new UserInputDataObject("fizz", "FizzProp", true); - userInput.AddAttributeSet("baz", "BazProp", true); - userInput.AddAttributeSet("buzz", "BuzzProp", true); + var userInput = new UserInputDataObject(var1, $"{var1}Prop", var1Flag); + userInput.AddAttributeSet(var2, $"{var2}Prop", var2Flag); + userInput.AddAttributeSet(var3, $"{var3}Prop", var3Flag); + + var flags = new Dictionary() + { + [var1] = var1Flag, + [var2] = var2Flag, + [var3] = var3Flag + }; var presenterAction = SetParameters(userInput); var actualCode = RefactoredCode(inputCode, selection, presenterAction); - StringAssert.Contains("Private fizz As Integer", actualCode); - StringAssert.Contains("Private baz As String", actualCode); - StringAssert.Contains("Private buzz As Boolean", actualCode); - StringAssert.Contains("Property Get FizzProp() As Integer", actualCode); - StringAssert.Contains("FizzProp = fizz", actualCode); - StringAssert.Contains("Let FizzProp(ByVal value As Integer)", actualCode); - StringAssert.Contains("fizz = value", actualCode); - StringAssert.Contains("Property Get BazProp() As String", actualCode); - StringAssert.Contains("BazProp = baz", actualCode); - StringAssert.Contains("Let BazProp(ByVal value As String)", actualCode); - StringAssert.Contains("baz = value", actualCode); - StringAssert.Contains("Property Get BuzzProp() As Boolean", actualCode); - StringAssert.Contains("BuzzProp = buzz", actualCode); - StringAssert.Contains("Let BuzzProp(ByVal value As Boolean)", actualCode); - StringAssert.Contains("buzz = value", actualCode); + + var notEncapsulated = flags.Keys.Where(k => !flags[k]) + .Select(k => k); + + var encapsulated = flags.Keys.Where(k => flags[k]) + .Select(k => k); + + foreach ( var variable in notEncapsulated) + { + StringAssert.Contains($"Public {variable} As Integer", actualCode); + } + + foreach (var variable in encapsulated) + { + StringAssert.Contains($"Private {variable} As", actualCode); + StringAssert.Contains($"{variable}Prop = {variable}", actualCode); + StringAssert.Contains($"{variable} = value", actualCode); + StringAssert.Contains($"Let {variable}Prop(ByVal value As", actualCode); + StringAssert.Contains($"Property Get {variable}Prop()", actualCode); + } + } + + [TestCase("fizz", true, "baz", true, "buzz", true, "boink", true)] + [TestCase("fizz", false, "baz", true, "buzz", true, "boink", true)] + [TestCase("fizz", false, "baz", true, "buzz", true, "boink", false)] + [TestCase("fizz", false, "baz", true, "buzz", false, "boink", false)] + [TestCase("fizz", false, "baz", false, "buzz", true, "boink", true)] + [TestCase("fizz", false, "baz", false, "buzz", false, "boink", true)] + [TestCase("fizz", false, "baz", true, "buzz", false, "boink", true)] + [TestCase("fizz", false, "baz", false, "buzz", true, "boink", true)] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulateMultipleFieldsInList( + string var1, bool var1Flag, + string var2, bool var2Flag, + string var3, bool var3Flag, + string var4, bool var4Flag) + { + string inputCode = +$@"Public {var1} As Integer, {var2} As Integer, {var3} As Integer, {var4} As Integer"; + + var selection = new Selection(1, 9); + + var userInput = new UserInputDataObject(var1, $"{var1}Prop", var1Flag); + userInput.AddAttributeSet(var2, $"{var2}Prop", var2Flag); + userInput.AddAttributeSet(var3, $"{var3}Prop", var3Flag); + userInput.AddAttributeSet(var4, $"{var4}Prop", var4Flag); + + var flags = new Dictionary() + { + [var1] = var1Flag, + [var2] = var2Flag, + [var3] = var3Flag, + [var4] = var4Flag + }; + + var presenterAction = SetParameters(userInput); + + var actualCode = RefactoredCode(inputCode, selection, presenterAction); + + var remainInList = flags.Keys.Where(k => !flags[k]) + .Select(k => $"{k} As Integer"); + + if (remainInList.Any()) + { + var declarationList = $"Public {string.Join(", ", remainInList)}"; + StringAssert.Contains(declarationList, actualCode); + } + + foreach (var key in flags.Keys) + { + if (flags[key]) + { + StringAssert.Contains($"Private {key} As", actualCode); + StringAssert.Contains($"{key}Prop = {key}", actualCode); + StringAssert.Contains($"{key} = value", actualCode); + StringAssert.Contains($"Let {key}Prop(ByVal value As", actualCode); + StringAssert.Contains($"Property Get {key}Prop()", actualCode); + } + } } [TestCase("Public")] @@ -142,7 +219,7 @@ End Type [TestCase("Private")] [Category("Refactorings")] [Category("Encapsulate Field")] - public void EncapsulateUserDefinedTypeMember(string accessibility) + public void EncapsulateUserDefinedTypeMembersAndFields(string accessibility) { string inputCode = $@" @@ -151,21 +228,19 @@ First As String Second As Long End Type +Public mFoo As String +Public mBar As Long +Private mFizz + {accessibility} this As TBar"; var selection = new Selection(7, 10); //Selects 'this' declaration var userInput = new UserInputDataObject("this", "MyType", true); userInput.AddUDTMemberNameFlagPairs(("First", true), ("Second", true)); - - var attributes = new FieldEncapsulationAttributes() - { - FieldName = "this", - PropertyName = "MyType", - AsTypeName = "TBar", - ImplementLetSetterType = true, - EncapsulateFlag = true - }; + userInput.AddAttributeSet("mFoo", "Foo", true); + userInput.AddAttributeSet("mBar", "Bar", true); + userInput.AddAttributeSet("mFizz", "Fizz", true); var presenterAction = SetParameters(userInput); @@ -180,6 +255,15 @@ End Type StringAssert.Contains($"this.Second = value", actualCode); StringAssert.Contains($"Second = this.Second", actualCode); StringAssert.DoesNotContain($"Second = Second", actualCode); + StringAssert.Contains($"Private mFoo As String", actualCode); + StringAssert.Contains($"Public Property Get Foo(", actualCode); + StringAssert.Contains($"Public Property Let Foo(", actualCode); + StringAssert.Contains($"Private mBar As Long", actualCode); + StringAssert.Contains($"Public Property Get Bar(", actualCode); + StringAssert.Contains($"Public Property Let Bar(", actualCode); + StringAssert.Contains($"Private mFizz As Variant", actualCode); + StringAssert.Contains($"Public Property Get Fizz() As Variant", actualCode); + StringAssert.Contains($"Public Property Let Fizz(", actualCode); } [TestCase("Public")] @@ -559,28 +643,9 @@ Function Bar() As Integer End Function"; var selection = new Selection(1, 1); - //Expectation - const string expectedCode = - @"Private fizz As Integer - -Public Property Get Name() As Integer - Name = fizz -End Property - -Public Property Let Name(ByVal value As Integer) - fizz = value -End Property - - -Sub Foo() -End Sub - -Function Bar() As Integer - Bar = 0 -End Function"; var presenterAction = SetParameters("Name", implementLet: true); var actualCode = RefactoredCode(inputCode, selection, presenterAction); - Assert.AreEqual(expectedCode, actualCode); + Assert.Greater(actualCode.IndexOf("Sub Foo"), actualCode.LastIndexOf("End Property")); } [Test] @@ -603,32 +668,10 @@ Property Set Foo(ByVal vall As Variant) End Property"; var selection = new Selection(1, 1); - //Expectation - const string expectedCode = - @"Private fizz As Integer - -Public Property Get Name() As Integer - Name = fizz -End Property - -Public Property Let Name(ByVal value As Integer) - fizz = value -End Property - - -Property Get Foo() As Variant - Foo = True -End Property - -Property Let Foo(ByVal vall As Variant) -End Property - -Property Set Foo(ByVal vall As Variant) -End Property"; - var presenterAction = SetParameters("Name", implementLet: true); var actualCode = RefactoredCode(inputCode, selection, presenterAction); - Assert.AreEqual(expectedCode, actualCode); + Assert.Greater(actualCode.IndexOf("fizz = value"), actualCode.IndexOf("fizz As Integer")); + Assert.Less(actualCode.IndexOf("fizz = value"), actualCode.IndexOf("Get Foo")); } [TestCase("Public fizz As Integer\r\nPublic buzz As Boolean", "Private fizz As Integer\r\nPublic buzz As Boolean", 1, 1)] @@ -727,31 +770,15 @@ Sub Bar(ByVal name As Integer) End Sub"; var selection = new Selection(1, 1); - //Expectation - string expectedCode = - $@"Private {newName} As Integer - -Public Property Get Name() As Integer - Name = {newName} -End Property - -Public Property Let Name(ByVal value As Integer) - {newName} = value -End Property - - -Sub Foo() - Name = 0 - Bar Name -End Sub - -Sub Bar(ByVal name As Integer) -End Sub"; - var presenterAction = SetParametersForSingleTarget("fizz", "Name", true, newName); var actualCode = RefactoredCode(inputCode, selection, presenterAction); - Assert.AreEqual(expectedCode, actualCode); + StringAssert.Contains($"Private {newName} As Integer", actualCode); + StringAssert.Contains("Property Get Name", actualCode); + StringAssert.Contains("Property Let Name", actualCode); + StringAssert.Contains($"Name = {newName}", actualCode); + StringAssert.Contains($"{newName} = value", actualCode); + Assert.Greater(actualCode.IndexOf("Sub Foo"), actualCode.LastIndexOf("End Property")); } [Test] @@ -778,33 +805,6 @@ Sub Bar(ByVal v As Integer) var selection = new Selection(1, 1); - //Expectation - const string expectedCode1 = - @"Private fizz As Integer - -Public Property Get Name() As Integer - Name = fizz -End Property - -Public Property Let Name(ByVal value As Integer) - fizz = value -End Property - - -Sub Foo() - Name = 1 -End Sub"; - - const string expectedCode2 = - @"Sub Foo() - Dim c As Class1 - c.Name = 0 - Bar c.Name -End Sub - -Sub Bar(ByVal v As Integer) -End Sub"; - var presenterAction = SetParametersForSingleTarget("fizz", "Name", true); var actualCode = RefactoredCode( @@ -815,8 +815,11 @@ Sub Bar(ByVal v As Integer) false, ("Class1", codeClass1, ComponentType.ClassModule), ("Class2", codeClass2, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode1, actualCode["Class1"]); - Assert.AreEqual(expectedCode2, actualCode["Class2"]); + + StringAssert.Contains("Name = 1", actualCode["Class1"]); + StringAssert.Contains("c.Name = 0", actualCode["Class2"]); + StringAssert.Contains("Bar c.Name", actualCode["Class2"]); + StringAssert.DoesNotContain("fizz", actualCode["Class2"]); } [Test] @@ -980,7 +983,11 @@ Public Property Get MyArray() As Variant MyArray = mArray End Property "; - var presenterAction = SetParameters("MyArray"); + var userInput = new UserInputDataObject("mArray", "MyArray", true, "mArray"); + //userInput.AddUDTMemberNameFlagPairs(("First", true), ("Second", true)); + + //var presenterAction = SetParameters("MyArray"); + var presenterAction = SetParameters(userInput); var actualCode = RefactoredCode(inputCode, selection, presenterAction); Assert.AreEqual(expectedCode, actualCode); } @@ -1011,7 +1018,12 @@ End Property "; var presenterAction = SetParameters("MyArray"); var actualCode = RefactoredCode(inputCode, selection, presenterAction); - Assert.AreEqual(expectedCode, actualCode); + StringAssert.Contains("Public anotherVar As Long, andOneMore As Variant", actualCode); + StringAssert.Contains($"Private mArray({dimensions}) As String", actualCode); + StringAssert.Contains("Get MyArray() As Variant", actualCode); + StringAssert.Contains("MyArray = mArray", actualCode); + StringAssert.DoesNotContain("Let MyArray", actualCode); + StringAssert.DoesNotContain("Set MyArray", actualCode); } [TestCase("Private")] @@ -1043,18 +1055,20 @@ End Property Assert.AreEqual(expectedCode, actualCode); } - [TestCase("mArray(5) As String", "xArray(5) As String")] - [TestCase("mArray(5)", "xArray(5) As Variant")] + [TestCase("mArray(5) As String, mNextVar As Long", "xArray(5) As String", 8)] + [TestCase("mNextVar As Long, mArray(5) As String", "xArray(5) As String", 27)] + [TestCase("mArray(5), mNextVar As Long", "xArray(5) As Variant", 8)] + [TestCase("mNextVar As Long, mArray(5)", "xArray(5) As Variant", 27)] [Category("Refactorings")] [Category("Encapsulate Field")] - public void EncapsulateArray_newFieldNameForFieldInList(string arrayDeclaration, string newArrayDeclaration) + public void EncapsulateArray_newFieldNameForFieldInList(string declarationList, string newArrayDeclaration, int column) { string inputCode = $@"Option Explicit -Public {arrayDeclaration}, mNextVar As Long"; +Public {declarationList}"; - var selection = new Selection(3, 8, 3, 11); + var selection = new Selection(3, column); string expectedCode = $@"Option Explicit @@ -1074,6 +1088,11 @@ End Property #region setup + private Func UserAcceptsDefaults() + { + return model => model; + } + private Func SetParameters( string propertyName, bool implementSet = false, @@ -1106,6 +1125,9 @@ private Func SetParameters(UserInp attrsInitializedByTheRefactoring.PropertyName = testModifiedAttribute.PropertyName; attrsInitializedByTheRefactoring.EncapsulateFlag = testModifiedAttribute.EncapsulateFlag; + //var check = attrsInitializedByTheRefactoring as IFieldEncapsulationAttributes; + //check.SetGet_LHSField = attrsInitializedByTheRefactoring.NewFieldName; + //If the Set/Let flags have been set by a test, they override the values applied by the refactoring if (testModifiedAttribute.ImplLet.HasValue) { @@ -1155,9 +1177,9 @@ public bool ImplementSetSetterType get => ImplSet.HasValue? ImplSet.Value : false; set => ImplSet = value; } - } + } - private class UserInputDataObject + private class UserInputDataObject { private List _userInput = new List(); private List<(string, bool)> _udtNameFlagPairs = new List<(string, bool)>(); From 625c21bd430c743ad7702717c532b419222536d3 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Sat, 16 Nov 2019 00:46:24 -0800 Subject: [PATCH 013/461] Handles presence of two variables of same UDT --- .../EncapsulateFieldDecorators.cs | 135 ++--- .../EncapsulateField/EncapsulateFieldModel.cs | 125 ++--- .../EncapsulateFieldRefactoring.cs | 9 +- .../EncapsulateFieldRewriter.cs | 159 +----- .../FieldEncapsulationAttributes.cs | 152 ++---- .../Refactoring/EncapsulateFieldTests.cs | 501 +++++++++++------- 6 files changed, 495 insertions(+), 586 deletions(-) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs index 6aa13c36ef..d7ecb425e1 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs @@ -1,5 +1,7 @@ using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; +using System; +using System.Collections.Generic; namespace Rubberduck.Refactorings.EncapsulateField { @@ -7,15 +9,16 @@ public interface IEncapsulatedFieldDeclaration { Declaration Declaration { get; } string IdentifierName { get; } + KeyValuePair TargetIDPair { set; get; } DeclarationType DeclarationType { get; } Accessibility Accessibility { get;} IFieldEncapsulationAttributes EncapsulationAttributes { set; get; } } - public class EncapsulatedFieldDeclaration : IEncapsulatedFieldDeclaration, IFieldEncapsulationAttributes + public class EncapsulatedFieldDeclaration : IEncapsulatedFieldDeclaration { protected Declaration _decorated; - protected IFieldEncapsulationAttributes _attributes; + private IFieldEncapsulationAttributes _attributes; public EncapsulatedFieldDeclaration(Declaration declaration) { @@ -37,27 +40,18 @@ public IFieldEncapsulationAttributes EncapsulationAttributes get => _attributes; } - public string AsTypeName { get => _attributes.AsTypeName; set => _attributes.AsTypeName = value; } - public string ParameterName { get => _attributes.ParameterName; set => _attributes.ParameterName = value; } - public bool CanImplementLet { get => _attributes.CanImplementLet; set => _attributes.CanImplementLet = value; } - public bool CanImplementSet { get => _attributes.CanImplementSet; set => _attributes.CanImplementSet = value; } - public string FieldName { get => _attributes.FieldName; set => _attributes.FieldName = value; } - public string NewFieldName { get => _attributes.NewFieldName; set => _attributes.NewFieldName = value; } - public string PropertyName { get => _attributes.PropertyName; set => _attributes.PropertyName = value; } - public bool ImplementLetSetterType { get => _attributes.ImplementLetSetterType; set => _attributes.ImplementLetSetterType = value; } - public bool ImplementSetSetterType { get => _attributes.ImplementSetSetterType; set => _attributes.ImplementSetSetterType = value; } - public bool EncapsulateFlag { get => _attributes.EncapsulateFlag; set => _attributes.EncapsulateFlag = value; } + public KeyValuePair TargetIDPair { get; set; } } - public class EncapsulateFieldDecoratorBase : IEncapsulatedFieldDeclaration, IFieldEncapsulationAttributes + public class EncapsulateFieldDecoratorBase : IEncapsulatedFieldDeclaration { private IEncapsulatedFieldDeclaration _decorated; - private IFieldEncapsulationAttributes _attributes; + public EncapsulateFieldDecoratorBase(IEncapsulatedFieldDeclaration efd) { _decorated = efd; - _attributes = efd as IFieldEncapsulationAttributes; + TargetIDPair = new KeyValuePair(efd.Declaration, efd.IdentifierName); } public Declaration Declaration => _decorated.Declaration; @@ -68,28 +62,24 @@ public EncapsulateFieldDecoratorBase(IEncapsulatedFieldDeclaration efd) public Accessibility Accessibility => _decorated.Accessibility; - public IFieldEncapsulationAttributes EncapsulationAttributes { get => _decorated.EncapsulationAttributes; set => _decorated.EncapsulationAttributes = value; } - public string AsTypeName { get => _attributes.AsTypeName; set => _attributes.AsTypeName = value; } - public string ParameterName { get => _attributes.ParameterName; set => _attributes.ParameterName = value; } - public bool CanImplementLet { get => _attributes.CanImplementLet; set => _attributes.CanImplementLet = value; } - public bool CanImplementSet { get => _attributes.CanImplementSet; set => _attributes.CanImplementSet = value; } - public string FieldName { get => _attributes.FieldName; set => _attributes.FieldName = value; } - public string NewFieldName { get => _attributes.NewFieldName; set => _attributes.NewFieldName = value; } - public string PropertyName { get => _attributes.PropertyName; set => _attributes.PropertyName = value; } - public bool ImplementLetSetterType { get => _attributes.ImplementLetSetterType; set => _attributes.ImplementLetSetterType = value; } - public bool ImplementSetSetterType { get => _attributes.ImplementSetSetterType; set => _attributes.ImplementSetSetterType = value; } - public bool EncapsulateFlag { get => _attributes.EncapsulateFlag; set => _attributes.EncapsulateFlag = value; } + public IFieldEncapsulationAttributes EncapsulationAttributes + { + get => _decorated.EncapsulationAttributes; + set => _decorated.EncapsulationAttributes = value; + } + + public KeyValuePair TargetIDPair { get => _decorated.TargetIDPair; set => _decorated.TargetIDPair = value; } } - public class EncapsulatedValueType : EncapsulateFieldDecoratorBase // IEncapsulatedFieldDeclaration, IFieldEncapsulationAttributes + public class EncapsulatedValueType : EncapsulateFieldDecoratorBase { private EncapsulatedValueType(IEncapsulatedFieldDeclaration efd) : base(efd) { - CanImplementLet = true; - CanImplementSet = false; - ImplementLetSetterType = true; - ImplementSetSetterType = false; + EncapsulationAttributes.CanImplementLet = true; + EncapsulationAttributes.CanImplementSet = false; + EncapsulationAttributes.ImplementLetSetterType = true; + EncapsulationAttributes.ImplementSetSetterType = false; } public static IEncapsulatedFieldDeclaration Decorate(IEncapsulatedFieldDeclaration efd) @@ -100,58 +90,58 @@ public class EncapsulatedUserDefinedType : EncapsulateFieldDecoratorBase { private EncapsulatedUserDefinedType(IEncapsulatedFieldDeclaration efd) - : base(efd) + : base(efd) { - CanImplementLet = true; - CanImplementSet = false; - ImplementLetSetterType = true; - ImplementSetSetterType = false; + EncapsulationAttributes.CanImplementLet = true; + EncapsulationAttributes.CanImplementSet = false; + EncapsulationAttributes.ImplementLetSetterType = true; + EncapsulationAttributes.ImplementSetSetterType = false; } public static IEncapsulatedFieldDeclaration Decorate(IEncapsulatedFieldDeclaration efd) => new EncapsulatedUserDefinedType(efd); } - public class EncapsulatedVariantType : EncapsulateFieldDecoratorBase // IEncapsulatedFieldDeclaration, IFieldEncapsulationAttributes + public class EncapsulatedVariantType : EncapsulateFieldDecoratorBase { private EncapsulatedVariantType(IEncapsulatedFieldDeclaration efd) - : base(efd) + : base(efd) { - CanImplementLet = true; - CanImplementSet = true; - ImplementLetSetterType = true; - ImplementSetSetterType = true; + EncapsulationAttributes.CanImplementLet = true; + EncapsulationAttributes.CanImplementSet = true; + EncapsulationAttributes.ImplementLetSetterType = true; + EncapsulationAttributes.ImplementSetSetterType = true; } public static IEncapsulatedFieldDeclaration Decorate(IEncapsulatedFieldDeclaration efd) => new EncapsulatedVariantType(efd); } - public class EncapsulatedObjectType : EncapsulateFieldDecoratorBase //IEncapsulatedFieldDeclaration, IFieldEncapsulationAttributes + public class EncapsulatedObjectType : EncapsulateFieldDecoratorBase { private EncapsulatedObjectType(IEncapsulatedFieldDeclaration efd) : base(efd) { - CanImplementLet = false; - CanImplementSet = true; - ImplementLetSetterType = false; - ImplementSetSetterType = true; + EncapsulationAttributes.CanImplementLet = false; + EncapsulationAttributes.CanImplementSet = true; + EncapsulationAttributes.ImplementLetSetterType = false; + EncapsulationAttributes.ImplementSetSetterType = true; } public static IEncapsulatedFieldDeclaration Decorate(IEncapsulatedFieldDeclaration efd) => new EncapsulatedObjectType(efd); } - public class EncapsulatedArrayType : EncapsulateFieldDecoratorBase //IEncapsulatedFieldDeclaration, IFieldEncapsulationAttributes + public class EncapsulatedArrayType : EncapsulateFieldDecoratorBase { private EncapsulatedArrayType(IEncapsulatedFieldDeclaration efd) - : base(efd) + : base(efd) { - CanImplementLet = false; - CanImplementSet = false; - ImplementLetSetterType = false; - ImplementSetSetterType = false; - AsTypeName = Tokens.Variant; + EncapsulationAttributes.CanImplementLet = false; + EncapsulationAttributes.CanImplementSet = false; + EncapsulationAttributes.ImplementLetSetterType = false; + EncapsulationAttributes.ImplementSetSetterType = false; + EncapsulationAttributes.AsTypeName = Tokens.Variant; } public static IEncapsulatedFieldDeclaration Decorate(IEncapsulatedFieldDeclaration efd) @@ -160,21 +150,34 @@ public static IEncapsulatedFieldDeclaration Decorate(IEncapsulatedFieldDeclarati public class EncapsulatedUserDefinedTypeMember : EncapsulateFieldDecoratorBase { - private EncapsulatedUserDefinedType _udt; + private IFieldEncapsulationAttributes _udtVariableAttributes; + private bool _nameResolveProperty; + private string _originalVariableName; + private EncapsulatedUserDefinedTypeMember(IEncapsulatedFieldDeclaration efd, EncapsulatedUserDefinedType udtVariable, bool propertyIdentifierRequiresNameResolution) + : base(efd) + { + _originalVariableName = udtVariable.IdentifierName; + _nameResolveProperty = propertyIdentifierRequiresNameResolution; + _udtVariableAttributes = udtVariable.EncapsulationAttributes; + + EncapsulationAttributes.NewFieldName = efd.Declaration.IdentifierName; + EncapsulationAttributes.PropertyName = BuildPropertyName(); + EncapsulationAttributes.FieldReadWriteIdentifierFunc = ()=> $"{_udtVariableAttributes.NewFieldName}.{EncapsulationAttributes.NewFieldName}"; + + efd.TargetIDPair = new KeyValuePair(efd.Declaration, $"{udtVariable.IdentifierName}.{IdentifierName}"); + } - private EncapsulatedUserDefinedTypeMember(IEncapsulatedFieldDeclaration efd, EncapsulatedUserDefinedType udtVariable) - : base(efd) + private string BuildPropertyName() { - _udt = udtVariable; - var decoratedAttributes = efd as IFieldEncapsulationAttributes; - CanImplementLet = decoratedAttributes.CanImplementLet; - CanImplementSet = decoratedAttributes.CanImplementSet; - ImplementLetSetterType = decoratedAttributes.ImplementLetSetterType; - ImplementSetSetterType = decoratedAttributes.ImplementSetSetterType; - NewFieldName = $"{udtVariable.Declaration.IdentifierName}.{efd.Declaration.IdentifierName}"; + if (_nameResolveProperty) + { + var propertyPrefix = char.ToUpper(_originalVariableName[0]) + _originalVariableName.Substring(1, _originalVariableName.Length - 1); + return $"{propertyPrefix}_{EncapsulationAttributes.FieldName}"; + } + return EncapsulationAttributes.FieldName; } - public static IEncapsulatedFieldDeclaration Decorate(IEncapsulatedFieldDeclaration efd, EncapsulatedUserDefinedType udtVariable) - => new EncapsulatedUserDefinedTypeMember(efd, udtVariable); + public static IEncapsulatedFieldDeclaration Decorate(IEncapsulatedFieldDeclaration efd, EncapsulatedUserDefinedType udtVariable, bool nameResolveProperty) + => new EncapsulatedUserDefinedTypeMember(efd, udtVariable, nameResolveProperty); } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index a3f181ec1b..336d4fe64c 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -10,7 +10,7 @@ namespace Rubberduck.Refactorings.EncapsulateField public interface ISupportEncapsulateFieldTests { void SetMemberEncapsulationFlag(string name, bool flag); - void SetEncapsulationFieldAttributes(IUserModifiableFieldEncapsulationAttributes attributes); + void SetEncapsulationFieldAttributes(string fieldName, IClientEditableFieldEncapsulationAttributes attributes); } public class EncapsulateFieldModel : IRefactoringModel, ISupportEncapsulateFieldTests { @@ -20,7 +20,7 @@ public class EncapsulateFieldModel : IRefactoringModel, ISupportEncapsulateField private IEnumerable UdtFields => _udtFieldToUdtDeclarationMap.Keys; private IEnumerable UdtFieldMembers(Declaration udtField) => _udtFieldToUdtDeclarationMap[udtField].Item2; - private Dictionary _encapsulateFieldDeclarations = new Dictionary(); + private Dictionary, IEncapsulatedFieldDeclaration> _encapsulateFieldDeclarations = new Dictionary, IEncapsulatedFieldDeclaration>(); private IEncapsulatedFieldDeclaration _userSelectedEncapsulationField; private Dictionary _udtVariableEncapsulationAttributes = new Dictionary(); @@ -32,48 +32,32 @@ public EncapsulateFieldModel(Declaration target, IEnumerable allMem foreach (var field in allMemberFields.Except(UdtFields)) { - AddEncapsulationField(EncapsulateDeclaration(field)); + var efd = EncapsulateDeclaration(field); + _encapsulateFieldDeclarations.Add(efd.TargetIDPair, efd); } AddUDTEncapsulationFields(udtFieldToUdtDeclarationMap); - this[target].EncapsulationAttributes.EncapsulateFlag = true; - TargetDeclaration = target; + var kvPair = _encapsulateFieldDeclarations.Where(efd => efd.Key.Key == target).Single(); + var selectedTarget = kvPair.Value; // _encapsulateFieldDeclarations[kvPair.Key]; + selectedTarget.EncapsulationAttributes.EncapsulateFlag = true; + _userSelectedEncapsulationField = selectedTarget; } public IEnumerable FlaggedEncapsulationFields => _encapsulateFieldDeclarations.Values.Where(v => v.EncapsulationAttributes.EncapsulateFlag); public IEncapsulatedFieldDeclaration this[string encapsulatedFieldIdentifier] { - get => _encapsulateFieldDeclarations.Values.Where(efd => efd.Declaration.IdentifierName.Equals(encapsulatedFieldIdentifier)) + get => _encapsulateFieldDeclarations.Values.Where(efd => efd.TargetIDPair.Value.Equals(encapsulatedFieldIdentifier)) .FirstOrDefault(); set { - var key = _encapsulateFieldDeclarations.Keys.Where(k => k.IdentifierName.Equals(encapsulatedFieldIdentifier)) + var key = _encapsulateFieldDeclarations.Keys.Where(k => k.Value.Equals(encapsulatedFieldIdentifier)) .FirstOrDefault(); _encapsulateFieldDeclarations[key] = value; } } - public IEncapsulatedFieldDeclaration this[Declaration declaration] - { - get - { - if (_encapsulateFieldDeclarations.TryGetValue(declaration, out var encapsulateFieldDefinition)) - { - return encapsulateFieldDefinition; - } - return null; - } - set - { - if (_encapsulateFieldDeclarations.ContainsKey(declaration)) - { - _encapsulateFieldDeclarations[declaration] = value; - } - } - } - public IList PropertiesContent { get @@ -81,7 +65,7 @@ public IList PropertiesContent var textBlocks = new List(); foreach (var field in FlaggedEncapsulationFields) { - textBlocks.Add(BuildPropertiesTextBlock(field.Declaration)); + textBlocks.Add(BuildPropertiesTextBlock(field.EncapsulationAttributes)); // as IFieldEncapsulationAttributes)); } return textBlocks; } @@ -92,12 +76,14 @@ private void AddUDTEncapsulationFields(IDictionary(udtMember.Declaration,$"{udtVariable.IdentifierName}.{udtMember.IdentifierName}"); + return EncapsulatedUserDefinedTypeMember.Decorate(udtMember, udtVariable, HasMultipleInstantiationsOfSameType(udtVariable.Declaration, targetIDPair)); } - private void AddEncapsulationField(IEncapsulatedFieldDeclaration encapsulateFieldDeclaration) + private bool HasMultipleInstantiationsOfSameType(Declaration udtVariable, KeyValuePair targetIDPair) { - if (_encapsulateFieldDeclarations.ContainsKey(encapsulateFieldDeclaration.Declaration)) - { - _encapsulateFieldDeclarations[encapsulateFieldDeclaration.Declaration] = encapsulateFieldDeclaration; - return; - } - _encapsulateFieldDeclarations.Add(encapsulateFieldDeclaration.Declaration, encapsulateFieldDeclaration); + var udt = _udtFieldToUdtDeclarationMap[udtVariable].Item1; + var otherVariableOfTheSameType = _udtFieldToUdtDeclarationMap.Keys.Where(k => k != udtVariable && _udtFieldToUdtDeclarationMap[k].Item1 == udt); + return otherVariableOfTheSameType.Any(); } - private string BuildPropertiesTextBlock(Declaration target) + private string BuildPropertiesTextBlock(IFieldEncapsulationAttributes attributes) { - var attributes = this[target].EncapsulationAttributes; var generator = new PropertyGenerator { PropertyName = attributes.PropertyName, AsTypeName = attributes.AsTypeName, - BackingField = attributes.NewFieldName, - //BackingField = attributes.SetGet_LHSField, + BackingField = attributes.FieldReadWriteIdentifier, ParameterName = attributes.ParameterName, GenerateSetter = attributes.ImplementSetSetterType, GenerateLetter = attributes.ImplementLetSetterType @@ -169,41 +151,32 @@ public void SetMemberEncapsulationFlag(string name, bool flag) } //Only used by tests....so far - public void SetEncapsulationFieldAttributes(IUserModifiableFieldEncapsulationAttributes attributes) - { - var userAttributes = this[attributes.FieldName].EncapsulationAttributes as IUserModifiableFieldEncapsulationAttributes; // = attributes; - userAttributes.FieldName = attributes.FieldName; - userAttributes.NewFieldName = attributes.NewFieldName; - userAttributes.PropertyName = attributes.PropertyName; - userAttributes.EncapsulateFlag = attributes.EncapsulateFlag; - } - - ////Only used by tests....so far - //public void UpdateEncapsulationField(string variableName, string propertyName, bool encapsulateFlag, string newFieldName = null) - //{ - // var target = this[variableName]; - // target.EncapsulationAttributes.FieldName = variableName; - // target.EncapsulationAttributes.PropertyName = propertyName; - // target.EncapsulationAttributes.NewFieldName = newFieldName ?? variableName; - // target.EncapsulationAttributes.EncapsulateFlag = encapsulateFlag; - // this[variableName] = target; - //} + public void SetEncapsulationFieldAttributes(string fieldName, IClientEditableFieldEncapsulationAttributes attributes) + { + var currentAttributes = this[fieldName].EncapsulationAttributes; // as IClientEditableFieldEncapsulationAttributes; + currentAttributes.NewFieldName = attributes.NewFieldName; + currentAttributes.PropertyName = attributes.PropertyName; + currentAttributes.EncapsulateFlag = attributes.EncapsulateFlag; + } - //Only used by tests....so far - public void UpdateEncapsulationField(IFieldEncapsulationAttributes attributes) + //This version only good for testing, fieldName could result in multiple results + public void ApplyAttributes(string fieldName, IClientEditableFieldEncapsulationAttributes clientAttributes) { - var target = this[attributes.FieldName]; - target.EncapsulationAttributes.FieldName = attributes.FieldName; - target.EncapsulationAttributes.PropertyName = attributes.PropertyName; - target.EncapsulationAttributes.NewFieldName = attributes.NewFieldName ?? attributes.FieldName; - target.EncapsulationAttributes.EncapsulateFlag = attributes.EncapsulateFlag; - this[attributes.FieldName] = target; + var encapsulatedField = this[fieldName]; + encapsulatedField.EncapsulationAttributes.NewFieldName = clientAttributes.NewFieldName; + encapsulatedField.EncapsulationAttributes.PropertyName = clientAttributes.PropertyName; + encapsulatedField.EncapsulationAttributes.ReadOnly = clientAttributes.ReadOnly; + encapsulatedField.EncapsulationAttributes.EncapsulateFlag = clientAttributes.EncapsulateFlag; } public Declaration TargetDeclaration { get => _userSelectedEncapsulationField.Declaration; - set => _userSelectedEncapsulationField = _encapsulateFieldDeclarations[value]; + set + { + var encField = new EncapsulatedFieldDeclaration(value); + _userSelectedEncapsulationField = _encapsulateFieldDeclarations[encField.TargetIDPair]; + } } public string PropertyName @@ -224,6 +197,18 @@ public string ParameterName set => _userSelectedEncapsulationField.EncapsulationAttributes.ParameterName = value; } + public bool IsReadOnly + { + get => _userSelectedEncapsulationField.EncapsulationAttributes.ReadOnly; + set => _userSelectedEncapsulationField.EncapsulationAttributes.ReadOnly = value; + } + + public bool EncapsulateFlag + { + get => _userSelectedEncapsulationField.EncapsulationAttributes.EncapsulateFlag; + set => _userSelectedEncapsulationField.EncapsulationAttributes.EncapsulateFlag = value; + } + public bool ImplementLetSetterType { get => _userSelectedEncapsulationField.EncapsulationAttributes.ImplementLetSetterType; diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index d3a8d003d0..58fd4c5487 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -1,6 +1,4 @@ -using System; -using System.Linq; -using Rubberduck.Parsing; +using System.Linq; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; @@ -89,7 +87,7 @@ protected override void RefactorImpl(EncapsulateFieldModel model) var attributes = nonUdtMemberField.EncapsulationAttributes; newContent = ModifyEncapsulatedVariable(nonUdtMemberField, attributes, rewriteSession, newContent); - UpdateReferences(nonUdtMemberField.Declaration, rewriteSession, attributes.PropertyName); + RenameReferences(nonUdtMemberField.Declaration, attributes.PropertyName ?? nonUdtMemberField.Declaration.IdentifierName, rewriteSession); } newContent = LoadNewPropertyContent(model, newContent); @@ -120,7 +118,6 @@ private EncapsulateFieldNewContent LoadNewPropertyContent(EncapsulateFieldModel } private EncapsulateFieldNewContent ModifyEncapsulatedVariable(IEncapsulatedFieldDeclaration target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession, EncapsulateFieldNewContent newContent) - //private EncapsulateFieldNewContent ModifyEncapsulatedVariable(IEncapsulatedFieldDeclaration encapsulatedField, IRewriteSession rewriteSession, EncapsulateFieldNewContent newContent) { var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, _targetQMN); @@ -148,7 +145,7 @@ private EncapsulateFieldNewContent ModifyEncapsulatedVariable(IEncapsulatedField return newContent; } - private void UpdateReferences(Declaration target, IRewriteSession rewriteSession, string propertyName) + private void RenameReferences(Declaration target, string propertyName, IRewriteSession rewriteSession) { foreach (var reference in target.References) { diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs index b5b2a3e971..b614254b1c 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs @@ -1,36 +1,22 @@ using Antlr4.Runtime; using Antlr4.Runtime.Misc; using Antlr4.Runtime.Tree; -using Rubberduck.Common; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.VBEditor; using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Rubberduck.Refactorings.EncapsulateField { public interface IEncapsulateFieldRewriter : IModuleRewriter { - //void RemoveDeclarations(IEnumerable allDeclarationsToRemove, IEnumerable allModuleDeclarations); void InsertNewContent(int? codeSectionStartIndex, IEncapsulateFieldNewContentProvider newContent); - void ReplaceDescendentContext(Declaration member, string content) where T : ParserRuleContext; - void InsertBeforeDescendentContext(Declaration member, string content) where T : ParserRuleContext; - void SetMemberVisibility(Declaration member, string visibilityToken); void SetVariableVisiblity(Declaration element, string visibilityToken); void Rename(Declaration element, string newName); void MakeImplicitDeclarationTypeExplicit(Declaration element); - void RemoveMemberAccess(IEnumerable memberReferences); - void RemoveMemberAccess(IdentifierReference idRef); - void RemoveWithMemberAccess(IEnumerable idReferences); void InsertAtEndOfFile(string content); - string GetModifiedText(Declaration declaration); } public class EncapsulateFieldRewriter : IEncapsulateFieldRewriter @@ -60,104 +46,6 @@ public void InsertNewContent(int? codeSectionStartIndex, IEncapsulateFieldNewCon } } - public void ReplaceDescendentContext(Declaration member, string content) where T : ParserRuleContext - { - var descendentCtxt = member.Context.GetDescendent(); - if (descendentCtxt != null) - { - _rewriter.Replace(descendentCtxt, content); - } - } - - public void InsertBeforeDescendentContext(Declaration member, string content) where T : ParserRuleContext - { - var descendentCtxt = member.Context.GetDescendent(); - if (descendentCtxt != null) - { - _rewriter.InsertBefore(descendentCtxt.Start.TokenIndex, content); - } - } - - //public void RemoveDeclarations(IEnumerable allDeclarationsToRemove, IEnumerable allModuleDeclarations) - //{ - // if (allDeclarationsToRemove.Count() == 0) - // { - // return; - // } - // var original = _rewriter.GetText(); - - // var declaredInLists = allDeclarationsToRemove.Where(declaration => - // declaration.Context.Parent is VBAParser.VariableListStmtContext - // || declaration.Context.Parent is VBAParser.ConstStmtContext); - - // RemoveMany(_rewriter, allDeclarationsToRemove.Except(declaredInLists)); - - // //Handle special cases where the declarations to remove - // //are/can be declared within a declarationlist context - // if (declaredInLists.Any()) - // { - // var lookupCtxtToDeclarationListRemovals = declaredInLists.ToLookup(dec => dec.Context.Parent as ParserRuleContext); - - // foreach (var declarationsToRemoveFromList in lookupCtxtToDeclarationListRemovals) - // { - // var allDeclarationsInList = allModuleDeclarations - // .Where(dec => dec.Context?.Parent == declarationsToRemoveFromList.Key); - - // RemoveDeclarationListContent(declarationsToRemoveFromList, allDeclarationsInList); - // } - // var removeListyResult = _rewriter.GetText(); - // } - //} - - //The issues described within this method seems to have been fixed - //private void RemoveDeclarationListContent(IGrouping toRemoveFromDeclarationList, IEnumerable allDeclarationsInDeclarationList) - //{ - // //Remove the entire list - // if (toRemoveFromDeclarationList.Count() == allDeclarationsInDeclarationList.Count()) - // { - // var parentContext = toRemoveFromDeclarationList.First().Context.Parent; - // if (parentContext is VBAParser.ConstStmtContext) - // { - // _rewriter.Remove(parentContext); - // } - // else - // { - // _rewriter.Remove(parentContext.Parent); - // } - // return; - // } - - // //A subset of the declarations in the list are to be removed - // //1. Remove declarations individually - // //2. Handle special case described below - // RemoveMany(_rewriter, toRemoveFromDeclarationList); - - // //Special case: - // //If there are 'n' declarations in a list (where 'n' >= 3) and we are removing 2 to n-1 of - // //the LAST declarations, calling 'rewriter.Remove' on each declaration leaves - // //a trailing comma on the last RETAINED declaration. - // if (toRemoveFromDeclarationList.Count() >= 2 && allDeclarationsInDeclarationList.Count() >= 3) - // { - // var reversedDeclarationListElements = allDeclarationsInDeclarationList.OrderByDescending(tr => tr.Selection); - // var removedFromEndOfList = reversedDeclarationListElements.TakeWhile(rd => toRemoveFromDeclarationList.Contains(rd)); - // if (removedFromEndOfList.Count() >= 2) - // { - // var lastRetainedDeclaration = reversedDeclarationListElements.ElementAt(removedFromEndOfList.Count()); - // var tokenStart = lastRetainedDeclaration.Context.Stop.TokenIndex + 1; - // var tokenStop = removedFromEndOfList.Last().Context.Start.TokenIndex - 1; - // _rewriter.RemoveRange(tokenStart, tokenStop); - // } - // } - //} - - private static void RemoveMany(IModuleRewriter rewriter, IEnumerable declarations) - { - foreach (var dec in declarations) - { - rewriter.Remove(dec); - } - } - public void InsertAtEndOfFile(string content) { if (content == string.Empty) @@ -167,24 +55,6 @@ public void InsertAtEndOfFile(string content) _rewriter.InsertBefore(_rewriter.TokenStream.Size - 1, content); } - public string GetModifiedText(Declaration declaration) - { - return _rewriter.GetText(declaration.Context.Start.TokenIndex, declaration.Context.Stop.TokenIndex); - } - - public void SetMemberVisibility(Declaration element, string visibility) - { - if (!element.IsMember()) { return; } - - var visibilityContext = element.Context.GetChild(); - if (visibilityContext != null) - { - _rewriter.Replace(visibilityContext, visibility); - return; - } - _rewriter.InsertBefore(element.Context.Start.TokenIndex, $"{visibility} "); - } - public void SetVariableVisiblity(Declaration element, string visibility) { if (!element.IsVariable()) { return; } @@ -214,37 +84,10 @@ public void MakeImplicitDeclarationTypeExplicit(Declaration element) } } - public void RemoveMemberAccess(IEnumerable memberReferences) - { - var memberAccessExprContexts = memberReferences - .Where(rf => rf.Context.Parent is VBAParser.MemberAccessExprContext); - - foreach (var context in memberAccessExprContexts) - { - RemoveMemberAccess(context); - } - } - - public void RemoveWithMemberAccess(IEnumerable references) - { - foreach (var withMemberAccessExprContext in references.Where(rf => rf.Context.Parent is VBAParser.WithMemberAccessExprContext).Select(rf => rf.Context.Parent as VBAParser.WithMemberAccessExprContext)) - { - RemoveRange(withMemberAccessExprContext.Start.TokenIndex, withMemberAccessExprContext.Start.TokenIndex); - } - } - - public void RemoveMemberAccess(IdentifierReference idRef) - { - if (idRef.Context.Parent is VBAParser.MemberAccessExprContext maec) - { - Debug.Assert(maec.ChildCount == 3, "MemberAccessExprContext child contexts does not equal 3"); - Replace(maec, maec.children[2].GetText()); - } - } - public bool IsDirty => _rewriter.IsDirty; public Selection? Selection { get => _rewriter.Selection; set => _rewriter.Selection = value; } + public Selection? SelectionOffset { get => _rewriter.SelectionOffset; set => _rewriter.SelectionOffset = value; } public ITokenStream TokenStream => _rewriter.TokenStream; diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs index 25aaf578b7..305b3554df 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs @@ -1,154 +1,88 @@ using Rubberduck.Parsing.Symbols; -using System.Collections.Generic; -using System.Linq; +using System; namespace Rubberduck.Refactorings.EncapsulateField { - public interface IUserModifiableFieldEncapsulationAttributes + public interface IClientEditableFieldEncapsulationAttributes { - string FieldName { get; set; } + string FieldName { get; } string NewFieldName { get; set; } string PropertyName { get; set; } - bool ImplementLetSetterType { get; set; } - bool ImplementSetSetterType { get; set; } + bool ReadOnly { get; set; } bool EncapsulateFlag { get; set; } } - public interface IFieldEncapsulationAttributes : IUserModifiableFieldEncapsulationAttributes + public interface IFieldEncapsulationAttributes : IClientEditableFieldEncapsulationAttributes { - //string SetGet_LHSField { get; set; } + string FieldReadWriteIdentifier { get; } string AsTypeName { get; set; } string ParameterName { get; set; } bool CanImplementLet { get; set; } bool CanImplementSet { get; set; } + bool ImplementLetSetterType { get; set; } + bool ImplementSetSetterType { get; set; } + Func FieldReadWriteIdentifierFunc { set; get; } } - public class FieldEncapsulationAttributes : IFieldEncapsulationAttributes + public struct ClientEncapsulationAttributes : IClientEditableFieldEncapsulationAttributes { - private static string DEFAULT_LET_PARAMETER = "value"; - - //private string _defaultBackingFieldName; - //private string _defaultPropertyName; - //private string _defaultParameterName = DEFAULT_LET_PARAMETER; + public ClientEncapsulationAttributes(string targetName) + { + _fieldName = targetName; + PropertyName = $"{char.ToUpperInvariant(targetName[0]) + targetName.Substring(1, targetName.Length - 1)}"; + NewFieldName = $"{targetName}1"; + ReadOnly = false; + EncapsulateFlag = false; + } - public FieldEncapsulationAttributes() { } + private string _fieldName; + public string FieldName => _fieldName; + public string NewFieldName { get; set; } + public string PropertyName { get; set; } + public bool ReadOnly { get; set; } + public bool EncapsulateFlag { get; set; } + } - //public FieldEncapsulationAttributes(Declaration target) - //{ - // FieldName = target.IdentifierName; - // (string newFieldName, string propertyName) = GenerateDefaultNames(target.IdentifierName); - // SetGet_LHSField = newFieldName; - // NewFieldName = newFieldName; - // PropertyName = propertyName; - // AsTypeName = target.AsTypeName; - // ParameterName = DEFAULT_LET_PARAMETER; - //} + public class FieldEncapsulationAttributes : IFieldEncapsulationAttributes + { + private static string DEFAULT_LET_PARAMETER = "value"; public FieldEncapsulationAttributes(Declaration target, string newFieldName = null, string parameterName = null) { + var defaults = new ClientEncapsulationAttributes(target.IdentifierName); FieldName = target.IdentifierName; - NewFieldName = newFieldName ?? target.IdentifierName; - PropertyName = target.IdentifierName; + NewFieldName = defaults.NewFieldName; + PropertyName = defaults.PropertyName; AsTypeName = target.AsTypeName; ParameterName = parameterName ?? DEFAULT_LET_PARAMETER; + FieldReadWriteIdentifierFunc = () => NewFieldName; } - public (string defaultField, string defaultProperty) GenerateDefaultNames(string targetName) - { - var defaultBackingFieldName = targetName + "1"; - var defaultPropertyName = string.Empty; - if (char.IsLower(targetName, 0)) - { - defaultPropertyName = $"{char.ToUpperInvariant(targetName[0]) + targetName.Substring(1, targetName.Length - 1)}"; - } - else - { - defaultPropertyName = targetName; - } - return (defaultBackingFieldName, defaultPropertyName); - } - //private bool IsCamelCase(string value) => char.IsLower(value, 0) && char.IsUpper(value, 1); - - public string FieldName { get; set; } + public string FieldName { get; private set; } private string _newFieldName; public string NewFieldName { - get => _newFieldName ?? FieldName; + get => EncapsulateFlag ? _newFieldName : FieldName; set => _newFieldName = value; } - //TODO: Set BackingField to udtVariable.udtMember somehow. Otherwise, BackingField == NewField - //public string SetGet_LHSField { get; set; } + public string FieldReadWriteIdentifier => FieldReadWriteIdentifierFunc(); + public Func FieldReadWriteIdentifierFunc { set; get; } public string PropertyName { get; set; } public string AsTypeName { get; set; } public string ParameterName { get; set; } = DEFAULT_LET_PARAMETER; + public bool ReadOnly { get; set; } + + private bool _implLet; + public bool ImplementLetSetterType { get => !ReadOnly && _implLet; set => _implLet = value; } + + private bool _implSet; + public bool ImplementSetSetterType { get => !ReadOnly && _implSet; set => _implSet = value; } - public bool ImplementLetSetterType { get; set; } - public bool ImplementSetSetterType { get; set; } public bool EncapsulateFlag { get; set; } public bool CanImplementLet { get; set; } public bool CanImplementSet { get; set; } } - - //public class UDTFieldEncapsulationAttributesX : IFieldEncapsulationAttributes - //{ - // private IFieldEncapsulationAttributes _attributes { get; } - // private Dictionary _memberEncapsulationFlags = new Dictionary(); - - // public UDTFieldEncapsulationAttributesX(FieldEncapsulationAttributes attributes) //, IEnumerable udtMemberNames) - // { - // _attributes = attributes; - // } - - // public string FieldName - // { - // get => _attributes.FieldName; - // set => _attributes.FieldName = value; - // } - - // public string PropertyName - // { - // get => _attributes.PropertyName; - // set => _attributes.PropertyName = value; - // } - - // public string NewFieldName - // { - // get => _attributes.NewFieldName; - // set => _attributes.NewFieldName = value; - // } - - // public string AsTypeName - // { - // get => _attributes.AsTypeName; - // set => _attributes.AsTypeName = value; - // } - // public string ParameterName - // { - // get => _attributes.ParameterName; - // set => _attributes.ParameterName = value; - // } - // public bool ImplementLetSetterType - // { - // get => _attributes.ImplementLetSetterType; - // set => _attributes.ImplementLetSetterType = value; - // } - - // public bool ImplementSetSetterType - // { - // get => _attributes.ImplementSetSetterType; - // set => _attributes.ImplementSetSetterType = value; - // } - - // public bool EncapsulateFlag - // { - // get => _attributes.EncapsulateFlag; - // set => _attributes.EncapsulateFlag = value; - // } - - // public bool CanImplementLet { get; set; } - // public bool CanImplementSet { get; set; } - //} } diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index 9fa6446338..ba3efb555d 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -44,7 +44,7 @@ Public Property Let Name(ByVal value As Integer) {newFieldName} = value End Property "; - var presenterAction = SetParametersForSingleTarget("fizz", "Name", true, newFieldName); + var presenterAction = SetParametersForSingleTarget("fizz", "Name", newFieldName: newFieldName); var actualCode = RefactoredCode(inputCode, selection, presenterAction); Assert.AreEqual(expectedCode, actualCode); } @@ -66,9 +66,9 @@ public void EncapsulateMultipleFields( var selection = new Selection(1, 1); - var userInput = new UserInputDataObject(var1, $"{var1}Prop", var1Flag); - userInput.AddAttributeSet(var2, $"{var2}Prop", var2Flag); - userInput.AddAttributeSet(var3, $"{var3}Prop", var3Flag); + var userInput = new TestInputDataObject(var1, $"{var1}Prop", var1Flag, var1); + userInput.AddAttributeSet(var2, $"{var2}Prop", var2Flag, var2); + userInput.AddAttributeSet(var3, $"{var3}Prop", var3Flag, var3); var flags = new Dictionary() { @@ -123,7 +123,7 @@ public void EncapsulateMultipleFieldsInList( var selection = new Selection(1, 9); - var userInput = new UserInputDataObject(var1, $"{var1}Prop", var1Flag); + var userInput = new TestInputDataObject(var1, $"{var1}Prop", var1Flag); userInput.AddAttributeSet(var2, $"{var2}Prop", var2Flag); userInput.AddAttributeSet(var3, $"{var3}Prop", var3Flag); userInput.AddAttributeSet(var4, $"{var4}Prop", var4Flag); @@ -153,9 +153,9 @@ public void EncapsulateMultipleFieldsInList( { if (flags[key]) { - StringAssert.Contains($"Private {key} As", actualCode); - StringAssert.Contains($"{key}Prop = {key}", actualCode); - StringAssert.Contains($"{key} = value", actualCode); + StringAssert.Contains($"Private {key}1 As", actualCode); + StringAssert.Contains($"{key}Prop = {key}1", actualCode); + StringAssert.Contains($"{key}1 = value", actualCode); StringAssert.Contains($"Let {key}Prop(ByVal value As", actualCode); StringAssert.Contains($"Property Get {key}Prop()", actualCode); } @@ -166,7 +166,7 @@ public void EncapsulateMultipleFieldsInList( [TestCase("Private")] [Category("Refactorings")] [Category("Encapsulate Field")] - public void EncapsulateUserDefinedType(string accessibility) + public void UserDefinedType_UserAcceptsDefaults(string accessibility) { string inputCode = $@" @@ -179,19 +179,93 @@ End Type var selection = new Selection(7, 10); //Selects 'this' declaration - var presenterAction = SetParametersForSingleTarget("this", "MyType", true); + var presenterAction = UserAcceptsDefaults(); var actualCode = RefactoredCode(inputCode, selection, presenterAction); - StringAssert.Contains("Private this As TBar", actualCode); - StringAssert.Contains("this = value", actualCode); - StringAssert.Contains($"MyType = this", actualCode); - StringAssert.DoesNotContain($"this.First = value", actualCode); + StringAssert.Contains("Private this1 As TBar", actualCode); + StringAssert.Contains("this1 = value", actualCode); + StringAssert.Contains($"This = this1", actualCode); + StringAssert.DoesNotContain($"this1.First1 = value", actualCode); + } + + [TestCase("Public", true, true)] + [TestCase("Private", true, true)] + [TestCase("Public", false, false)] + [TestCase("Private", false, false)] + [TestCase("Public", true, false)] + [TestCase("Private", true, false)] + [TestCase("Public", false, true)] + [TestCase("Private", false, true)] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedType_TwoInstanceVariables(string accessibility, bool encapsulateThis, bool encapsulateThat) + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +{accessibility} this As TBar +{accessibility} that As TBar"; + + var selection = new Selection(7, 10); //Selects 'this' declaration + + var userInput = new TestInputDataObject("this", "MyType", encapsulateThis); + userInput.AddAttributeSet("that", "MyOtherType", encapsulateThat); + userInput.AddUDTMemberNameFlagPairs(("this", "First", true)); + userInput.AddUDTMemberNameFlagPairs(("this", "Second", true)); + userInput.AddUDTMemberNameFlagPairs(("that", "First", true)); + userInput.AddUDTMemberNameFlagPairs(("that", "Second", true)); + + var thisDefaults = new ClientEncapsulationAttributes("this"); + var thatDefaults = new ClientEncapsulationAttributes("that"); + + var presenterAction = SetParameters(userInput); + var actualCode = RefactoredCode(inputCode, selection, presenterAction); + if (encapsulateThis) + { + StringAssert.Contains($"Private {thisDefaults.NewFieldName} As TBar", actualCode); + StringAssert.Contains($"MyType = {thisDefaults.NewFieldName}", actualCode); + StringAssert.Contains($"{thisDefaults.NewFieldName} = value", actualCode); + StringAssert.Contains($"{thisDefaults.NewFieldName}.First = value", actualCode); + StringAssert.Contains($"{thisDefaults.NewFieldName}.First = value", actualCode); + StringAssert.Contains($"{thisDefaults.NewFieldName}.Second = value", actualCode); + } + else + { + StringAssert.Contains($"{accessibility} this As TBar", actualCode); + StringAssert.Contains($"this.First = value", actualCode); + StringAssert.Contains($"this.Second = value", actualCode); + } + + if (encapsulateThat) + { + StringAssert.Contains($"Private {thatDefaults.NewFieldName} As TBar", actualCode); + StringAssert.Contains($"MyOtherType = {thatDefaults.NewFieldName}", actualCode); + StringAssert.Contains($"{thatDefaults.NewFieldName} = value", actualCode); + StringAssert.Contains($"{thatDefaults.NewFieldName}.First = value", actualCode); + StringAssert.Contains($"{thatDefaults.NewFieldName}.Second = value", actualCode); + } + else + { + StringAssert.Contains($"{accessibility} that As TBar", actualCode); + StringAssert.Contains($"that.First = value", actualCode); + StringAssert.Contains($"that.Second = value", actualCode); + } + + StringAssert.Contains($"Property Get This_First", actualCode); + StringAssert.Contains($"Property Get That_First", actualCode); + StringAssert.Contains($"Property Get This_Second", actualCode); + StringAssert.Contains($"Property Get That_Second", actualCode); } + [TestCase("First")] [TestCase("Second")] [Category("Refactorings")] [Category("Encapsulate Field")] - public void EncapsulateUserDefinedTypeMembers_Subset(string memberToEncapsulate) + public void UserDefinedTypeMembers_Subset(string memberToEncapsulate) { string inputCode = $@" @@ -205,8 +279,8 @@ End Type var selection = new Selection(7, 10); //Selects 'this' declaration - var userInput = new UserInputDataObject("this", "MyType", true); - userInput.AddUDTMemberNameFlagPairs((memberToEncapsulate, true)); + var userInput = new TestInputDataObject("this", "MyType", true, "this"); + userInput.AddUDTMemberNameFlagPairs(("this", memberToEncapsulate, true)); var presenterAction = SetParameters(userInput); @@ -219,7 +293,7 @@ End Type [TestCase("Private")] [Category("Refactorings")] [Category("Encapsulate Field")] - public void EncapsulateUserDefinedTypeMembersAndFields(string accessibility) + public void UserDefinedTypeMembersAndFields(string accessibility) { string inputCode = $@" @@ -236,11 +310,11 @@ Private mFizz var selection = new Selection(7, 10); //Selects 'this' declaration - var userInput = new UserInputDataObject("this", "MyType", true); - userInput.AddUDTMemberNameFlagPairs(("First", true), ("Second", true)); - userInput.AddAttributeSet("mFoo", "Foo", true); - userInput.AddAttributeSet("mBar", "Bar", true); - userInput.AddAttributeSet("mFizz", "Fizz", true); + var userInput = new TestInputDataObject("this", "MyType", true, "this"); + userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true)); + userInput.AddAttributeSet("mFoo", "Foo", true, "mFoo"); + userInput.AddAttributeSet("mBar", "Bar", true, "mBar"); + userInput.AddAttributeSet("mFizz", "Fizz", true, "mFizz"); var presenterAction = SetParameters(userInput); @@ -270,7 +344,58 @@ Private mFizz [TestCase("Private")] [Category("Refactorings")] [Category("Encapsulate Field")] - public void EncapsulateUserDefinedTypeMember_ContainsObjects(string accessibility) + public void UserDefinedTypeMembersAndFieldsWithTypeNameChange(string accessibility) + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +Public mFoo As String +Public mBar As Long +Private mFizz + +{accessibility} that As TBar"; + + var selection = new Selection(7, 10); //Selects 'that' declaration + + var userInput = new TestInputDataObject("that", "MyType", true, "this"); + userInput.AddUDTMemberNameFlagPairs(("that", "First", true), ("that", "Second", true)); + userInput.AddAttributeSet("mFoo", "Foo", true,"mFoo"); + userInput.AddAttributeSet("mBar", "Bar", true, "mBar"); + userInput.AddAttributeSet("mFizz", "Fizz", true, "mFizz"); + + var presenterAction = SetParameters(userInput); + + var actualCode = RefactoredCode(inputCode, selection, presenterAction); + + StringAssert.Contains("Private this As TBar", actualCode); + StringAssert.Contains("this = value", actualCode); + StringAssert.Contains("MyType = this", actualCode); + Assert.AreEqual(actualCode.IndexOf("MyType = this"), actualCode.LastIndexOf("MyType = this")); + StringAssert.Contains($"this.First = value", actualCode); + StringAssert.Contains($"First = this.First", actualCode); + StringAssert.Contains($"this.Second = value", actualCode); + StringAssert.Contains($"Second = this.Second", actualCode); + StringAssert.DoesNotContain($"Second = Second", actualCode); + StringAssert.Contains($"Private mFoo As String", actualCode); + StringAssert.Contains($"Public Property Get Foo(", actualCode); + StringAssert.Contains($"Public Property Let Foo(", actualCode); + StringAssert.Contains($"Private mBar As Long", actualCode); + StringAssert.Contains($"Public Property Get Bar(", actualCode); + StringAssert.Contains($"Public Property Let Bar(", actualCode); + StringAssert.Contains($"Private mFizz As Variant", actualCode); + StringAssert.Contains($"Public Property Get Fizz() As Variant", actualCode); + StringAssert.Contains($"Public Property Let Fizz(", actualCode); + } + + [TestCase("Public")] + [TestCase("Private")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedTypeMember_ContainsObjects(string accessibility) { string inputCode = $@" @@ -290,8 +415,9 @@ End Sub var selection = new Selection(7, 10); //Selects 'this' declaration - var userInput = new UserInputDataObject("this", "MyType", true); - userInput.AddUDTMemberNameFlagPairs(("First", true), ("Second", true)); + var userInput = new TestInputDataObject("this", "MyType", true, "this"); + + userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true)); var presenterAction = SetParameters(userInput); @@ -322,7 +448,7 @@ End Sub [TestCase("Private")] [Category("Refactorings")] [Category("Encapsulate Field")] - public void EncapsulateUserDefinedTypeMember_ContainsVariant(string accessibility) + public void UserDefinedTypeMember_ContainsVariant(string accessibility) { string inputCode = $@" @@ -335,8 +461,8 @@ End Type var selection = new Selection(7, 10); //Selects 'this' declaration - var userInput = new UserInputDataObject("this", "MyType", true); - userInput.AddUDTMemberNameFlagPairs(("First", true), ("Second", true)); + var userInput = new TestInputDataObject("this", "MyType", true, "this"); + userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true)); var presenterAction = SetParameters(userInput); @@ -357,7 +483,7 @@ End Type [TestCase("Private")] [Category("Refactorings")] [Category("Encapsulate Field")] - public void EncapsulateUserDefinedTypeMember_ContainsArrays(string accessibility) + public void UserDefinedTypeMember_ContainsArrays(string accessibility) { string inputCode = $@" @@ -371,8 +497,8 @@ End Type var selection = new Selection(8, 10); //Selects 'this' declaration - var userInput = new UserInputDataObject("this", "MyType", false); - userInput.AddUDTMemberNameFlagPairs(("First", true), ("Second", true), ("Third", true)); + var userInput = new TestInputDataObject("this", "MyType", false, "this"); + userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true), ("this", "Third", true)); var presenterAction = SetParameters(userInput); @@ -393,7 +519,7 @@ End Type [TestCase("Private", "Private")] [Category("Refactorings")] [Category("Encapsulate Field")] - public void EncapsulateUserDefinedTypeMembersOnly(string accessibility, string expectedAccessibility) + public void UserDefinedTypeMembersOnly(string accessibility, string expectedAccessibility) { string inputCode = $@" @@ -406,8 +532,8 @@ End Type var selection = new Selection(7, 10); //Selects 'this' declaration - var userInput = new UserInputDataObject("this", "MyType", false); - userInput.AddUDTMemberNameFlagPairs(("First", true), ("Second", true)); + var userInput = new TestInputDataObject("this", "MyType", false, "this"); + userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true)); var presenterAction = SetParameters(userInput); @@ -426,7 +552,7 @@ End Type [TestCase("Private")] [Category("Refactorings")] [Category("Encapsulate Field")] - public void EncapsulateUserDefinedTypeMembers_ExternallyDefinedType(string accessibility) + public void UserDefinedTypeMembers_ExternallyDefinedType(string accessibility) { string inputCode = $@" @@ -444,8 +570,8 @@ End Type var selection = new Selection(4, 10); //Selects 'this' declaration - var userInput = new UserInputDataObject("this", "MyType", true); - userInput.AddUDTMemberNameFlagPairs(("First", true), ("Second", true)); + var userInput = new TestInputDataObject("this", "MyType", true, "this"); + userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true)); var presenterAction = SetParameters(userInput); @@ -477,7 +603,7 @@ End Type [TestCase("Private")] [Category("Refactorings")] [Category("Encapsulate Field")] - public void EncapsulateUserDefinedTypeMembers_ObjectField(string accessibility) + public void UserDefinedTypeMembers_ObjectField(string accessibility) { string inputCode = $@" @@ -495,7 +621,7 @@ End Sub var selection = new Selection(4, 10); //Selects 'mTheClass' declaration - var presenterAction = SetParametersForSingleTarget("mTheClass", "TheClass", true); + var presenterAction = UserAcceptsDefaults(); var actualModuleCode = RefactoredCode( "Module1", @@ -508,9 +634,12 @@ End Sub var actualCode = actualModuleCode["Module1"]; - StringAssert.Contains("Private mTheClass As Class1", actualCode); - StringAssert.Contains("Set mTheClass = value", actualCode); - StringAssert.Contains("TheClass = mTheClass", actualCode); + var defaults = new ClientEncapsulationAttributes("mTheClass"); + + StringAssert.Contains($"Private {defaults.NewFieldName} As Class1", actualCode); + StringAssert.Contains($"Set {defaults.NewFieldName} = value", actualCode); + StringAssert.Contains($"MTheClass = {defaults.NewFieldName}", actualCode); + StringAssert.Contains($"Public Property Set {defaults.PropertyName}", actualCode); } [Test] @@ -522,7 +651,7 @@ public void EncapsulatePublicField_InvalidDeclarationType_Throws() const string inputCode = @"Public fizz As Integer"; - var presenterAction = SetParameters("Name", implementLet: true); + var presenterAction = SetParametersForSingleTarget("fizz","Name", newFieldName: "fizz"); var actualCode = RefactoredCode(inputCode, "TestModule1", DeclarationType.ProceduralModule, presenterAction, typeof(InvalidDeclarationTypeException)); Assert.AreEqual(inputCode, actualCode); } @@ -538,7 +667,7 @@ public void EncapsulatePublicField_InvalidIdentifierSelected_Throws() End Function"; var selection = new Selection(1, 19); - var presenterAction = SetParameters("Name", implementLet: true); + var presenterAction = SetParametersForSingleTarget("fizz", "Name", newFieldName: "fizz"); var actualCode = RefactoredCode(inputCode, selection, presenterAction, typeof(NoDeclarationForSelectionException)); Assert.AreEqual(inputCode, actualCode); } @@ -571,37 +700,39 @@ Public Property Let Name(ByVal value As Integer) fizz = value End Property "; - var presenterAction = SetParameters("Name", implementLet: true); + var presenterAction = SetParametersForSingleTarget("fizz", "Name", newFieldName: "fizz"); var actualCode = RefactoredCode(inputCode, selection, presenterAction); Assert.AreEqual(expectedCode, actualCode); } - [Test] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void EncapsulatePublicField_WithSetter() - { - //Input - const string inputCode = - @"Public fizz As Variant"; - var selection = new Selection(1, 1); - - //Expectation - const string expectedCode = - @"Private fizz As Variant - -Public Property Get Name() As Variant - Set Name = fizz -End Property - -Public Property Set Name(ByVal value As Variant) - Set fizz = value -End Property -"; - var presenterAction = SetParameters("Name", implementSet: true); - var actualCode = RefactoredCode(inputCode, selection, presenterAction); - Assert.AreEqual(expectedCode, actualCode); - } + //TODO: It does not seem appropriate to generate a variant property and limit + //it to either Set or Let. +// [Test] +// [Category("Refactorings")] +// [Category("Encapsulate Field")] +// public void EncapsulatePublicField_WithSetter() +// { +// //Input +// const string inputCode = +// @"Public fizz As Variant"; +// var selection = new Selection(1, 1); + +// //Expectation +// const string expectedCode = +// @"Private fizz As Variant + +//Public Property Get Name() As Variant +// Set Name = fizz +//End Property + +//Public Property Set Name(ByVal value As Variant) +// Set fizz = value +//End Property +//"; +// var presenterAction = SetParameters("Name", implementSet: true); +// var actualCode = RefactoredCode(inputCode, selection, presenterAction); +// Assert.AreEqual(expectedCode, actualCode); +// } [Test] [Category("Refactorings")] @@ -610,18 +741,18 @@ public void EncapsulatePublicField_WithOnlyGetter() { //Input const string inputCode = - @"Public fizz As Variant"; + @"Public fizz As Integer"; var selection = new Selection(1, 1); //Expectation const string expectedCode = - @"Private fizz As Variant + @"Private fizz As Integer -Public Property Get Name() As Variant +Public Property Get Name() As Integer Name = fizz End Property "; - var presenterAction = SetParameters("Name"); + var presenterAction = SetParametersForSingleTarget("fizz","Name", isReadonly: true, newFieldName: "fizz"); var actualCode = RefactoredCode(inputCode, selection, presenterAction); Assert.AreEqual(expectedCode, actualCode); } @@ -643,7 +774,8 @@ Function Bar() As Integer End Function"; var selection = new Selection(1, 1); - var presenterAction = SetParameters("Name", implementLet: true); + //var presenterAction = SetParameters("Name", implementLet: true); + var presenterAction = SetParametersForSingleTarget("fizz", "Name", newFieldName: "fizz"); var actualCode = RefactoredCode(inputCode, selection, presenterAction); Assert.Greater(actualCode.IndexOf("Sub Foo"), actualCode.LastIndexOf("End Property")); } @@ -668,7 +800,8 @@ Property Set Foo(ByVal vall As Variant) End Property"; var selection = new Selection(1, 1); - var presenterAction = SetParameters("Name", implementLet: true); + //var presenterAction = SetParameters("Name", implementLet: true); + var presenterAction = SetParametersForSingleTarget("fizz", "Name", newFieldName: "fizz"); var actualCode = RefactoredCode(inputCode, selection, presenterAction); Assert.Greater(actualCode.IndexOf("fizz = value"), actualCode.IndexOf("fizz As Integer")); Assert.Less(actualCode.IndexOf("fizz = value"), actualCode.IndexOf("Get Foo")); @@ -695,17 +828,17 @@ Public Property Let Name(ByVal value As Integer) fizz = value End Property "; - var presenterAction = SetParameters("Name", implementLet: true); + var presenterAction = SetParametersForSingleTarget("fizz", "Name", newFieldName: "fizz"); var actualCode = RefactoredCode(inputCode, selection, presenterAction); Assert.AreEqual(expectedCode, actualCode); } - [TestCase(1, 10, "Public buzz", "Private fizz As Variant", "Public fizz")] - [TestCase(2, 2, "Public fizz, _\r\nbazz", "Private buzz As Boolean", "")] - [TestCase(3, 2, "Public fizz, _\r\nbuzz", "Private bazz As Date", "Boolean, bazz As Date")] + [TestCase(1, 10, "fizz", "Public buzz", "Private fizz As Variant", "Public fizz")] + [TestCase(2, 2, "buzz", "Public fizz, _\r\nbazz", "Private buzz As Boolean", "")] + [TestCase(3, 2, "bazz", "Public fizz, _\r\nbuzz", "Private bazz As Date", "Boolean, bazz As Date")] [Category("Refactorings")] [Category("Encapsulate Field")] - public void EncapsulatePublicField_SelectedWithinDeclarationList(int rowSelection, int columnSelection, string contains1, string contains2, string doesNotContain) + public void EncapsulatePublicField_SelectedWithinDeclarationList(int rowSelection, int columnSelection, string fieldName, string contains1, string contains2, string doesNotContain) { //Input string inputCode = @@ -714,7 +847,7 @@ public void EncapsulatePublicField_SelectedWithinDeclarationList(int rowSelectio bazz As Date"; var selection = new Selection(rowSelection, columnSelection); - var presenterAction = SetParameters("Name", implementSet: true, implementLet: true); + var presenterAction = SetParametersForSingleTarget(fieldName, "Name", newFieldName: fieldName); var actualCode = RefactoredCode(inputCode, selection, presenterAction); StringAssert.Contains(contains1, actualCode); StringAssert.Contains(contains1, actualCode); @@ -746,7 +879,34 @@ Public Property Let Name(ByVal value As Integer) fizz = value End Property "; - var presenterAction = SetParameters("Name", implementLet: true); + var presenterAction = SetParametersForSingleTarget("fizz", "Name", newFieldName: "fizz"); + var actualCode = RefactoredCode(inputCode, selection, presenterAction); + Assert.AreEqual(expectedCode, actualCode); + } + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulatePrivateField_Defaults() + { + //Input + const string inputCode = + @"Private fizz As Integer"; + var selection = new Selection(1, 1); + + //Expectation + const string expectedCode = + @"Private fizz1 As Integer + +Public Property Get Fizz() As Integer + Fizz = fizz1 +End Property + +Public Property Let Fizz(ByVal value As Integer) + fizz1 = value +End Property +"; + var presenterAction = UserAcceptsDefaults(); var actualCode = RefactoredCode(inputCode, selection, presenterAction); Assert.AreEqual(expectedCode, actualCode); } @@ -770,7 +930,7 @@ Sub Bar(ByVal name As Integer) End Sub"; var selection = new Selection(1, 1); - var presenterAction = SetParametersForSingleTarget("fizz", "Name", true, newName); + var presenterAction = SetParametersForSingleTarget("fizz", "Name", newFieldName: newName); var actualCode = RefactoredCode(inputCode, selection, presenterAction); StringAssert.Contains($"Private {newName} As Integer", actualCode); @@ -822,31 +982,32 @@ Sub Bar(ByVal v As Integer) StringAssert.DoesNotContain("fizz", actualCode["Class2"]); } - [Test] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void EncapsulatePublicField_PassInTarget() - { - //Input - const string inputCode = - @"Private fizz As Integer"; - - //Expectation - const string expectedCode = - @"Private fizz As Integer - -Public Property Get Name() As Integer - Name = fizz -End Property - -Public Property Let Name(ByVal value As Integer) - fizz = value -End Property -"; - var presenterAction = SetParameters("Name", implementLet: true); - var actualCode = RefactoredCode(inputCode, "fizz", DeclarationType.Variable, presenterAction); - Assert.AreEqual(expectedCode, actualCode); - } +// [Test] +// [Category("Refactorings")] +// [Category("Encapsulate Field")] +// public void EncapsulatePublicField_PassInTarget() +// { +// //Input +// const string inputCode = +// @"Private fizz As Integer"; + +// //Expectation +// const string expectedCode = +// @"Private fizz As Integer + +//Public Property Get Name() As Integer +// Name = fizz +//End Property + +//Public Property Let Name(ByVal value As Integer) +// fizz = value +//End Property +//"; +// //var presenterAction = SetParameters("Name", implementLet: true); +// var presenterAction = SetParametersForSingleTarget("fizz", "Name", newFieldName: "fizz"); +// var actualCode = RefactoredCode(inputCode, "fizz", DeclarationType.Variable, presenterAction); +// Assert.AreEqual(expectedCode, actualCode); +// } [Test] [Category("Refactorings")] @@ -916,7 +1077,8 @@ Public Property Let Name(ByVal value As String) foo = value End Property "; - var presenterAction = SetParameters("Name", implementLet: true); + //var presenterAction = SetParameters("Name", implementLet: true); + var presenterAction = SetParametersForSingleTarget("foo", "Name", newFieldName: "foo"); var actualCode = RefactoredCode(inputCode, "foo", DeclarationType.Variable, presenterAction); Assert.AreEqual(expectedCode, actualCode); } @@ -948,7 +1110,7 @@ Public Property Let bar(ByVal value As String) Foo = value End Property "; - var presenterAction = SetParameters("bar", implementLet: true); + var presenterAction = SetParametersForSingleTarget("Foo", "bar", newFieldName: "Foo"); var actualCode = RefactoredCode(inputCode, selection, presenterAction); Assert.AreEqual(expectedCode, actualCode); } @@ -983,7 +1145,7 @@ Public Property Get MyArray() As Variant MyArray = mArray End Property "; - var userInput = new UserInputDataObject("mArray", "MyArray", true, "mArray"); + var userInput = new TestInputDataObject("mArray", "MyArray", true, "mArray"); //userInput.AddUDTMemberNameFlagPairs(("First", true), ("Second", true)); //var presenterAction = SetParameters("MyArray"); @@ -1016,7 +1178,7 @@ Public Property Get MyArray() As Variant MyArray = mArray End Property "; - var presenterAction = SetParameters("MyArray"); + var presenterAction = SetParametersForSingleTarget("mArray", "MyArray", newFieldName: "mArray"); var actualCode = RefactoredCode(inputCode, selection, presenterAction); StringAssert.Contains("Public anotherVar As Long, andOneMore As Variant", actualCode); StringAssert.Contains($"Private mArray({dimensions}) As String", actualCode); @@ -1049,7 +1211,7 @@ Public Property Get MyArray() As Variant End Property "; - var presenterAction = SetParametersForSingleTarget("mArray", "MyArray", true, "xArray"); + var presenterAction = SetParametersForSingleTarget("mArray", "MyArray", newFieldName: "xArray"); var actualCode = RefactoredCode(inputCode, selection, presenterAction); Assert.AreEqual(expectedCode, actualCode); @@ -1080,7 +1242,7 @@ Public Property Get MyArray() As Variant MyArray = xArray End Property "; - var presenterAction = SetParametersForSingleTarget("mArray", "MyArray", true, "xArray"); + var presenterAction = SetParametersForSingleTarget("mArray", "MyArray", newFieldName: "xArray"); var actualCode = RefactoredCode(inputCode, selection, presenterAction); Assert.AreEqual(expectedCode, actualCode); } @@ -1090,67 +1252,54 @@ End Property private Func UserAcceptsDefaults() { - return model => model; + return model => { model.EncapsulateFlag = true; return model; }; } - private Func SetParameters( - string propertyName, - bool implementSet = false, - bool implementLet = false) + private Func SetParametersForSingleTarget(string field, string property = null, bool? isReadonly = null, bool encapsulateFlag = true, string newFieldName = null) { - return model => - { - model.PropertyName = propertyName; - model.ImplementLetSetterType = implementLet; - model.ImplementSetSetterType = implementSet; - return model; - }; - } - - private Func SetParametersForSingleTarget(string field, string property, bool flag = true, string newFieldName = null) - => SetParameters(new UserInputDataObject(field, property, flag, newFieldName)); + var clientAttrs = new ClientEncapsulationAttributes(field); + clientAttrs.NewFieldName = newFieldName ?? clientAttrs.NewFieldName; + clientAttrs.PropertyName = property ?? clientAttrs.PropertyName; + clientAttrs.ReadOnly = isReadonly ?? clientAttrs.ReadOnly; + clientAttrs.EncapsulateFlag = encapsulateFlag; + return SetParameters(field, clientAttrs); + } - private Func SetParameters(UserInputDataObject testInput) + private Func SetParameters(TestInputDataObject testInput) { return model => { foreach (var testModifiedAttribute in testInput.EncapsulateFieldAttributes) { - var attrsInitializedByTheRefactoring = model[testModifiedAttribute.FieldName].EncapsulationAttributes as IUserModifiableFieldEncapsulationAttributes; + var attrsInitializedByTheRefactoring = model[testModifiedAttribute.FieldName].EncapsulationAttributes as IClientEditableFieldEncapsulationAttributes; var testSupport = model as ISupportEncapsulateFieldTests; - attrsInitializedByTheRefactoring.FieldName = testModifiedAttribute.FieldName; attrsInitializedByTheRefactoring.NewFieldName = testModifiedAttribute.NewFieldName; attrsInitializedByTheRefactoring.PropertyName = testModifiedAttribute.PropertyName; attrsInitializedByTheRefactoring.EncapsulateFlag = testModifiedAttribute.EncapsulateFlag; - //var check = attrsInitializedByTheRefactoring as IFieldEncapsulationAttributes; - //check.SetGet_LHSField = attrsInitializedByTheRefactoring.NewFieldName; + testSupport.SetEncapsulationFieldAttributes(testModifiedAttribute.FieldName, attrsInitializedByTheRefactoring); - //If the Set/Let flags have been set by a test, they override the values applied by the refactoring - if (testModifiedAttribute.ImplLet.HasValue) + foreach ((string instanceVariable, string memberName, bool flag) in testInput.UDTMemberNameFlagPairs) { - attrsInitializedByTheRefactoring.ImplementLetSetterType = testModifiedAttribute.ImplementLetSetterType; - } - - if (testModifiedAttribute.ImplSet.HasValue) - { - attrsInitializedByTheRefactoring.ImplementSetSetterType = testModifiedAttribute.ImplementSetSetterType; - } - - testSupport.SetEncapsulationFieldAttributes(attrsInitializedByTheRefactoring); - - foreach ((string memberName, bool flag) in testInput.UDTMemberNameFlagPairs) - { - testSupport.SetMemberEncapsulationFlag(memberName, flag); + testSupport.SetMemberEncapsulationFlag($"{instanceVariable}.{memberName}", flag); } } return model; }; } - private class UserModifiableFieldEncapsulationAttributes : IUserModifiableFieldEncapsulationAttributes + private Func SetParameters(string originalField, IClientEditableFieldEncapsulationAttributes clientEdits) + { + return model => + { + model.ApplyAttributes(originalField, clientEdits); + return model; + }; + } + + private class UserModifiableFieldEncapsulationAttributes : IClientEditableFieldEncapsulationAttributes { public UserModifiableFieldEncapsulationAttributes(string fieldName, string propertyName, bool encapsulationFlag = true, string newFieldName = null) { @@ -1164,38 +1313,36 @@ public UserModifiableFieldEncapsulationAttributes(string fieldName, string prope public string NewFieldName { get; set; } public string PropertyName { get; set; } public bool EncapsulateFlag { get; set; } - public bool? ImplLet; - public bool ImplementLetSetterType - { - get => ImplLet.HasValue ? ImplLet.Value : false; - set => ImplLet = value; - } - - public bool? ImplSet; - public bool ImplementSetSetterType - { - get => ImplSet.HasValue? ImplSet.Value : false; - set => ImplSet = value; - } + public bool ReadOnly { get; set; } } - private class UserInputDataObject + private class TestInputDataObject { - private List _userInput = new List(); - private List<(string, bool)> _udtNameFlagPairs = new List<(string, bool)>(); + private List _userInput = new List(); + private List<(string, string, bool)> _udtNameFlagPairs = new List<(string, string, bool)>(); - public UserInputDataObject(string fieldName, string propertyName, bool encapsulationFlag = true, string newFieldName = null) - => _userInput.Add(new UserModifiableFieldEncapsulationAttributes(fieldName, propertyName, encapsulationFlag, newFieldName)); + public TestInputDataObject(string fieldName, string propertyName = null, bool encapsulationFlag = true, string newFieldName = null, bool isReadOnly = false) + => AddAttributeSet(fieldName, propertyName, encapsulationFlag, newFieldName, isReadOnly); - public void AddAttributeSet(string fieldName, string propertyName, bool encapsulationFlag = true, string newFieldName = null) - => _userInput.Add(new UserModifiableFieldEncapsulationAttributes(fieldName, propertyName, encapsulationFlag, newFieldName)); + public void AddAttributeSet(string fieldName, string propertyName = null, bool encapsulationFlag = true, string newFieldName = null, bool isReadOnly = false) + { + var attrs = new ClientEncapsulationAttributes(fieldName) + { + EncapsulateFlag = encapsulationFlag, + ReadOnly = isReadOnly, + }; + attrs.PropertyName = propertyName ?? attrs.PropertyName; + attrs.NewFieldName = newFieldName ?? attrs.NewFieldName; + + _userInput.Add(attrs as IClientEditableFieldEncapsulationAttributes); + } - public IEnumerable EncapsulateFieldAttributes => _userInput; + public IEnumerable EncapsulateFieldAttributes => _userInput; - public void AddUDTMemberNameFlagPairs(params (string, bool)[] nameFlagPairs) + public void AddUDTMemberNameFlagPairs(params (string, string, bool)[] nameFlagPairs) => _udtNameFlagPairs.AddRange(nameFlagPairs); - public IEnumerable<(string, bool)> UDTMemberNameFlagPairs => _udtNameFlagPairs; + public IEnumerable<(string, string, bool)> UDTMemberNameFlagPairs => _udtNameFlagPairs; } private static IIndenter CreateIndenter(IVBE vbe = null) From c950d7d8ac0624a00faf02b8eb805f77b1bfe6e2 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Thu, 21 Nov 2019 18:40:25 -0800 Subject: [PATCH 014/461] First changes to UI to support multiple selections --- .../EncapsulateFieldView.xaml | 189 +++++++++++++++--- .../EncapsulateFieldViewModel.cs | 116 ++++++----- .../EncapsulateFieldDecorators.cs | 114 ++++++++++- .../EncapsulateField/EncapsulateFieldModel.cs | 70 ++++++- .../EncapsulateFieldRefactoring.cs | 31 +-- .../FieldEncapsulationAttributes.cs | 3 +- 6 files changed, 418 insertions(+), 105 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml index 80c6105600..56d64fabf2 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml @@ -5,8 +5,9 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:controls="clr-namespace:Rubberduck.UI.Controls" xmlns:converters="clr-namespace:Rubberduck.UI.Converters" + xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" mc:Ignorable="d" - d:DesignHeight="300" d:DesignWidth="300"> + d:DesignHeight="800" d:DesignWidth="300"> @@ -14,9 +15,11 @@ - - - + + + + + - - + --> + + + - - + + - + + + + + + + + + + + + + + + + + + + Property Name: + + + + + + + + + + + + + + + + + + Backing Variable: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs index 0cf49d7c86..05d0eec3c2 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs @@ -1,10 +1,19 @@ using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Input; +using NLog; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Refactorings.Common; using Rubberduck.Refactorings.EncapsulateField; using Rubberduck.SmartIndenter; +using Rubberduck.UI.Command; namespace Rubberduck.UI.Refactorings.EncapsulateField { @@ -19,7 +28,15 @@ public EncapsulateFieldViewModel(EncapsulateFieldModel model, RubberduckParserSt Indenter = indenter; IsLetSelected = true; - PropertyName = model.TargetDeclaration.IdentifierName; + PropertyName = model[model.TargetDeclaration].PropertyName; + + SelectAllCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), _ => ToggleSelection(true)); + DeselectAllCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), _ => ToggleSelection(false)); + + IsReadOnlyCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), _ => RefreshPreview()); + EncapsulateFlagCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), _ => RefreshPreview()); + PropertyOrFieldNameChangeCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), _ => RefreshPreview()); + BackingFieldNameChangeCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), _ => RefreshPreview()); } public Declaration TargetDeclaration @@ -28,21 +45,24 @@ public Declaration TargetDeclaration set { Model.TargetDeclaration = value; - PropertyName = value.IdentifierName; + PropertyName = Model[Model.TargetDeclaration].PropertyName; } } - private bool _expansionState = true; - public bool ExpansionState - { - get => _expansionState; - set - { - _expansionState = value; - OnPropertyChanged(); - OnExpansionStateChanged(value); - } - } + public ObservableCollection EncapsulationFields + => new ObservableCollection(Model.EncapsulationFields); + + //private bool _expansionState = true; + //public bool ExpansionState + //{ + // get => _expansionState; + // set + // { + // _expansionState = value; + // OnPropertyChanged(); + // OnExpansionStateChanged(value); + // } + //} public bool CanHaveLet => Model.CanImplementLet; public bool CanHaveSet => Model.CanImplementSet; @@ -99,14 +119,12 @@ public bool IsValidPropertyName { get { - var tokenValues = typeof(Tokens).GetFields().Select(item => item.GetValue(null)).Cast().Select(item => item); - - return TargetDeclaration != null - && !PropertyName.Equals(TargetDeclaration.IdentifierName, StringComparison.InvariantCultureIgnoreCase) - && !PropertyName.Equals(ParameterName, StringComparison.InvariantCultureIgnoreCase) - && char.IsLetter(PropertyName.FirstOrDefault()) - && !tokenValues.Contains(PropertyName, StringComparer.InvariantCultureIgnoreCase) - && PropertyName.All(c => char.IsLetterOrDigit(c) || c == '_'); + var encapsulatedField = Model[TargetDeclaration]; + + return encapsulatedField.Declaration != null + && VBAIdentifierValidator.IsValidIdentifier(encapsulatedField.PropertyName, DeclarationType.Variable) + && !encapsulatedField.PropertyName.Equals(encapsulatedField.EncapsulationAttributes.NewFieldName, StringComparison.InvariantCultureIgnoreCase) + && !encapsulatedField.PropertyName.Equals(ParameterName, StringComparison.InvariantCultureIgnoreCase); } } @@ -114,45 +132,47 @@ public bool IsValidParameterName { get { - var tokenValues = typeof(Tokens).GetFields().Select(item => item.GetValue(null)).Cast().Select(item => item); - - return TargetDeclaration != null - && !ParameterName.Equals(TargetDeclaration.IdentifierName, StringComparison.InvariantCultureIgnoreCase) - && !ParameterName.Equals(PropertyName, StringComparison.InvariantCultureIgnoreCase) - && char.IsLetter(ParameterName.FirstOrDefault()) - && !tokenValues.Contains(ParameterName, StringComparer.InvariantCultureIgnoreCase) - && ParameterName.All(c => char.IsLetterOrDigit(c) || c == '_'); + var encapsulatedField = Model[TargetDeclaration]; + + return encapsulatedField.Declaration != null + && VBAIdentifierValidator.IsValidIdentifier(encapsulatedField.PropertyName, DeclarationType.Variable) + && !encapsulatedField.EncapsulationAttributes.ParameterName.Equals(encapsulatedField.IdentifierName, StringComparison.InvariantCultureIgnoreCase) + && !encapsulatedField.EncapsulationAttributes.ParameterName.Equals(encapsulatedField.EncapsulationAttributes.PropertyName, StringComparison.InvariantCultureIgnoreCase); } } + public bool HasValidNames => IsValidPropertyName && IsValidParameterName; public string PropertyPreview { get { - if (TargetDeclaration == null) - { - return string.Empty; - } - - var previewGenerator = new PropertyGenerator - { - PropertyName = PropertyName, - AsTypeName = TargetDeclaration.AsTypeName, - BackingField = TargetDeclaration.IdentifierName, - ParameterName = ParameterName, - GenerateSetter = IsSetSelected, - GenerateLetter = IsLetSelected - }; - - var field = $"{Tokens.Private} {TargetDeclaration.IdentifierName} {Tokens.As} {TargetDeclaration.AsTypeName}{Environment.NewLine}{Environment.NewLine}"; - - var propertyText = previewGenerator.AllPropertyCode.Insert(0, field).Split(new[] { Environment.NewLine }, StringSplitOptions.None); - return string.Join(Environment.NewLine, Indenter.Indent(propertyText, true)); + return Model.NewContent.AsSingleTextBlock; } } + public CommandBase SelectAllCommand { get; } + public CommandBase DeselectAllCommand { get; } + private void ToggleSelection(bool value) + { + foreach (var item in EncapsulationFields) + { + item.EncapsulateFlag = value; + } + OnPropertyChanged(nameof(EncapsulationFields)); + OnPropertyChanged(nameof(PropertyPreview)); + } + + public CommandBase IsReadOnlyCommand { get; } + public CommandBase EncapsulateFlagCommand { get; } + public CommandBase PropertyOrFieldNameChangeCommand { get; } + public CommandBase BackingFieldNameChangeCommand { get; } + private void RefreshPreview() + { + OnPropertyChanged(nameof(PropertyPreview)); + } + public event EventHandler ExpansionStateChanged; private void OnExpansionStateChanged(bool value) => ExpansionStateChanged?.Invoke(this, value); } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs index d7ecb425e1..8a8daa6d63 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs @@ -2,6 +2,7 @@ using Rubberduck.Parsing.Symbols; using System; using System.Collections.Generic; +using System.Windows; namespace Rubberduck.Refactorings.EncapsulateField { @@ -13,6 +14,16 @@ public interface IEncapsulatedFieldDeclaration DeclarationType DeclarationType { get; } Accessibility Accessibility { get;} IFieldEncapsulationAttributes EncapsulationAttributes { set; get; } + string FieldID { get; } + bool IsReadOnly { set; get; } + bool IsEditableReadOnly { get; } + string PropertyName { set; get; } + bool IsVisibleReadWriteAccessor { set; get; } + bool EncapsulateFlag { set; get; } + Visibility ReadWriteAccessorVisibility { set; get; } + string NewFieldName { set; get; } + string ReadWriteAccessor { get; } + string AsTypeName { get; } } public class EncapsulatedFieldDeclaration : IEncapsulatedFieldDeclaration @@ -24,6 +35,7 @@ public EncapsulatedFieldDeclaration(Declaration declaration) { _decorated = declaration; _attributes = new FieldEncapsulationAttributes(_decorated); + TargetIDPair = new KeyValuePair(declaration, declaration.IdentifierName); } public Declaration Declaration => _decorated; @@ -41,12 +53,55 @@ public IFieldEncapsulationAttributes EncapsulationAttributes } public KeyValuePair TargetIDPair { get; set; } + + public string FieldID => TargetIDPair.Value; + + public bool EncapsulateFlag + { + get => _attributes.EncapsulateFlag; + set => _attributes.EncapsulateFlag = value; + } + + public bool IsReadOnly + { + get => _attributes.ReadOnly; + set => _attributes.ReadOnly = value; + } + + public bool IsEditableReadOnly => true; + + public string PropertyName + { + get => _attributes.PropertyName; + set => _attributes.PropertyName = value; + } + + public bool IsVisibleReadWriteAccessor + { + get => ReadWriteAccessorVisibility == Visibility.Visible; + set => ReadWriteAccessorVisibility = value ? Visibility.Visible : Visibility.Collapsed; + } + + public Visibility ReadWriteAccessorVisibility { set; get; } = Visibility.Visible; + + public string NewFieldName + { + get => _attributes.NewFieldName; + set => _attributes.NewFieldName = value; + } + + public string ReadWriteAccessor + { + get => _attributes.FieldReadWriteIdentifier; + } + + public string AsTypeName => _decorated.AsTypeName; } public class EncapsulateFieldDecoratorBase : IEncapsulatedFieldDeclaration { - private IEncapsulatedFieldDeclaration _decorated; + protected IEncapsulatedFieldDeclaration _decorated; public EncapsulateFieldDecoratorBase(IEncapsulatedFieldDeclaration efd) { @@ -69,6 +124,53 @@ public IFieldEncapsulationAttributes EncapsulationAttributes } public KeyValuePair TargetIDPair { get => _decorated.TargetIDPair; set => _decorated.TargetIDPair = value; } + + public string FieldID => TargetIDPair.Value; + + public bool IsReadOnly + { + get => _decorated.EncapsulationAttributes.ReadOnly; + set => _decorated.EncapsulationAttributes.ReadOnly = value; + } + + public bool EncapsulateFlag + { + get => _decorated.EncapsulateFlag; + set => _decorated.EncapsulateFlag = value; + } + + public bool IsEditableReadOnly => _decorated.IsEditableReadOnly; + + public string PropertyName + { + get => _decorated.EncapsulationAttributes.PropertyName; + set => _decorated.EncapsulationAttributes.PropertyName = value; + } + + public bool IsVisibleReadWriteAccessor + { + get => _decorated.IsVisibleReadWriteAccessor; + set => _decorated.IsVisibleReadWriteAccessor = value; + } + + public Visibility ReadWriteAccessorVisibility// { set; get; } + { + get => _decorated.ReadWriteAccessorVisibility; + set => _decorated.ReadWriteAccessorVisibility = value; + } + + public string NewFieldName + { + get => _decorated.EncapsulationAttributes.NewFieldName; + set => _decorated.EncapsulationAttributes.NewFieldName = value; + } + + public string ReadWriteAccessor + { + get => _decorated.EncapsulationAttributes.FieldReadWriteIdentifier; + } + + public string AsTypeName => _decorated.EncapsulationAttributes.AsTypeName; } public class EncapsulatedValueType : EncapsulateFieldDecoratorBase @@ -162,9 +264,17 @@ private EncapsulatedUserDefinedTypeMember(IEncapsulatedFieldDeclaration efd, Enc EncapsulationAttributes.NewFieldName = efd.Declaration.IdentifierName; EncapsulationAttributes.PropertyName = BuildPropertyName(); - EncapsulationAttributes.FieldReadWriteIdentifierFunc = ()=> $"{_udtVariableAttributes.NewFieldName}.{EncapsulationAttributes.NewFieldName}"; + EncapsulationAttributes.FieldReadWriteIdentifierFunc = () => + { + if (_udtVariableAttributes.EncapsulateFlag) + { + return $"{_udtVariableAttributes.NewFieldName}.{EncapsulationAttributes.NewFieldName}"; + } + return $"{_udtVariableAttributes.FieldName}.{EncapsulationAttributes.NewFieldName}"; + }; efd.TargetIDPair = new KeyValuePair(efd.Declaration, $"{udtVariable.IdentifierName}.{IdentifierName}"); + _decorated.IsVisibleReadWriteAccessor = false; } private string BuildPropertyName() diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index 336d4fe64c..a5dfef28ee 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -39,13 +39,19 @@ public EncapsulateFieldModel(Declaration target, IEnumerable allMem AddUDTEncapsulationFields(udtFieldToUdtDeclarationMap); var kvPair = _encapsulateFieldDeclarations.Where(efd => efd.Key.Key == target).Single(); - var selectedTarget = kvPair.Value; // _encapsulateFieldDeclarations[kvPair.Key]; + var selectedTarget = kvPair.Value; selectedTarget.EncapsulationAttributes.EncapsulateFlag = true; _userSelectedEncapsulationField = selectedTarget; } public IEnumerable FlaggedEncapsulationFields => _encapsulateFieldDeclarations.Values.Where(v => v.EncapsulationAttributes.EncapsulateFlag); + public IEnumerable EncapsulationFieldIDs + => _encapsulateFieldDeclarations.Keys.Select(k => k.Value); + + public IEnumerable EncapsulationFields + => _encapsulateFieldDeclarations.Values; + public IEncapsulatedFieldDeclaration this[string encapsulatedFieldIdentifier] { get => _encapsulateFieldDeclarations.Values.Where(efd => efd.TargetIDPair.Value.Equals(encapsulatedFieldIdentifier)) @@ -58,6 +64,18 @@ public IEncapsulatedFieldDeclaration this[string encapsulatedFieldIdentifier] } } + public IEncapsulatedFieldDeclaration this[Declaration field] + { + get => _encapsulateFieldDeclarations.Keys.Where(key => key.Key.Equals(field)).Select(kv => _encapsulateFieldDeclarations[kv]) + .Single(); + set + { + var key = _encapsulateFieldDeclarations.Keys.Where(k => k.Key.Equals(field)) + .Single(); + _encapsulateFieldDeclarations[key] = value; + } + } + public IList PropertiesContent { get @@ -65,12 +83,56 @@ public IList PropertiesContent var textBlocks = new List(); foreach (var field in FlaggedEncapsulationFields) { - textBlocks.Add(BuildPropertiesTextBlock(field.EncapsulationAttributes)); // as IFieldEncapsulationAttributes)); + textBlocks.Add(BuildPropertiesTextBlock(field.EncapsulationAttributes)); } return textBlocks; } } + public IEncapsulateFieldNewContentProvider NewContent + { + get + { + var newContent = new EncapsulateFieldNewContent(); + newContent = LoadNewDeclarationsContent(newContent); + newContent = LoadNewPropertiesContent(newContent); + return newContent; + } + } + + public EncapsulateFieldNewContent LoadNewPropertiesContent(EncapsulateFieldNewContent newContent) + { + if (!FlaggedEncapsulationFields.Any()) { return newContent; } + + newContent.AddCodeBlock($"{string.Join($"{Environment.NewLine}{Environment.NewLine}", PropertiesContent)}"); + return newContent; + } + + public EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNewContent newContent) + { + var nonUdtMemberFields = FlaggedEncapsulationFields + .Where(encFld => encFld.Declaration.IsVariable()); + + foreach (var nonUdtMemberField in nonUdtMemberFields) + { + var attributes = nonUdtMemberField.EncapsulationAttributes; + + if (nonUdtMemberField.Accessibility == Accessibility.Private && attributes.NewFieldName.Equals(nonUdtMemberField.IdentifierName)) + { + continue; + } + + if (nonUdtMemberField.Declaration.IsDeclaredInList()) + { + var targetIdentifier = nonUdtMemberField.Declaration.Context.GetText().Replace(attributes.FieldName, attributes.NewFieldName); + var newField = nonUdtMemberField.Declaration.IsTypeSpecified ? $"{Tokens.Private} {targetIdentifier}" : $"{Tokens.Private} {targetIdentifier} {Tokens.As} {nonUdtMemberField.Declaration.AsTypeName}"; + + newContent.AddDeclarationBlock(newField); + } + } + return newContent; + } + private void AddUDTEncapsulationFields(IDictionary)> udtFieldToTypeMap) { foreach (var udtField in udtFieldToTypeMap.Keys) @@ -222,9 +284,9 @@ public bool ImplementSetSetterType } public bool CanImplementLet - => _userSelectedEncapsulationField.EncapsulationAttributes.CanImplementLet; //.EncapsulationAttributes.IsValueType || _userSelectedEncapsulationField.EncapsulationAttributes.IsVariantType; + => _userSelectedEncapsulationField.EncapsulationAttributes.CanImplementLet; public bool CanImplementSet - => !_userSelectedEncapsulationField.EncapsulationAttributes.CanImplementSet; //IsValueType && _userSelectedEncapsulationField.EncapsulationAttributes.IsVariantType; + => !_userSelectedEncapsulationField.EncapsulationAttributes.CanImplementSet; } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 58fd4c5487..b6edf89c80 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -7,7 +7,6 @@ using Rubberduck.VBEditor; using Rubberduck.SmartIndenter; using Rubberduck.VBEditor.Utility; -using Environment = System.Environment; using System.Collections.Generic; namespace Rubberduck.Refactorings.EncapsulateField @@ -81,17 +80,13 @@ protected override void RefactorImpl(EncapsulateFieldModel model) var nonUdtMemberFields = model.FlaggedEncapsulationFields .Where(encFld => encFld.Declaration.IsVariable()); - var newContent = new EncapsulateFieldNewContent(); foreach (var nonUdtMemberField in nonUdtMemberFields) { var attributes = nonUdtMemberField.EncapsulationAttributes; - newContent = ModifyEncapsulatedVariable(nonUdtMemberField, attributes, rewriteSession, newContent); - + ModifyEncapsulatedVariable(nonUdtMemberField, attributes, rewriteSession); RenameReferences(nonUdtMemberField.Declaration, attributes.PropertyName ?? nonUdtMemberField.Declaration.IdentifierName, rewriteSession); } - newContent = LoadNewPropertyContent(model, newContent); - var moduleMembers = _declarationFinderProvider.DeclarationFinder .Members(_targetQMN).Where(m => m.IsMember()); @@ -101,7 +96,7 @@ protected override void RefactorImpl(EncapsulateFieldModel model) var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, _targetQMN); - rewriter.InsertNewContent(codeSectionStartIndex, newContent); + rewriter.InsertNewContent(codeSectionStartIndex, model.NewContent); if (!rewriteSession.TryRewrite()) { @@ -109,32 +104,19 @@ protected override void RefactorImpl(EncapsulateFieldModel model) } } - private EncapsulateFieldNewContent LoadNewPropertyContent(EncapsulateFieldModel model, EncapsulateFieldNewContent newContent) - { - if (!model.FlaggedEncapsulationFields.Any()) { return newContent; } - - newContent.AddCodeBlock($"{string.Join($"{Environment.NewLine}{Environment.NewLine}", model.PropertiesContent)}"); - return newContent; - } - - private EncapsulateFieldNewContent ModifyEncapsulatedVariable(IEncapsulatedFieldDeclaration target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession, EncapsulateFieldNewContent newContent) + private void ModifyEncapsulatedVariable(IEncapsulatedFieldDeclaration target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession) //, EncapsulateFieldNewContent newContent) { var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, _targetQMN); if (target.Accessibility == Accessibility.Private && attributes.NewFieldName.Equals(target.IdentifierName)) { rewriter.MakeImplicitDeclarationTypeExplicit(target.Declaration); - return newContent; + return; } if (target.Declaration.IsDeclaredInList()) { - var targetIdentifier = target.Declaration.Context.GetText().Replace(attributes.FieldName, attributes.NewFieldName); - var newField = target.Declaration.IsTypeSpecified ? $"{Tokens.Private} {targetIdentifier}" : $"{Tokens.Private} {targetIdentifier} {Tokens.As} {target.Declaration.AsTypeName}"; - rewriter.Remove(target.Declaration); - - newContent.AddDeclarationBlock(newField); } else { @@ -142,7 +124,7 @@ private EncapsulateFieldNewContent ModifyEncapsulatedVariable(IEncapsulatedField rewriter.SetVariableVisiblity(target.Declaration, Accessibility.Private.TokenString()); rewriter.MakeImplicitDeclarationTypeExplicit(target.Declaration); } - return newContent; + return; } private void RenameReferences(Declaration target, string propertyName, IRewriteSession rewriteSession) @@ -166,7 +148,8 @@ private void RenameReferences(Declaration target, string propertyName, IRewriteS var udtMembers = _declarationFinderProvider.DeclarationFinder .UserDeclarations(DeclarationType.UserDefinedTypeMember) - .Where(utm => userDefinedTypeDeclaration.IdentifierName == utm.ParentDeclaration.IdentifierName); + .Where(utm => userDefinedTypeDeclaration.IdentifierName == utm.ParentDeclaration.IdentifierName + && utm.QualifiedModuleName == userDefinedTypeDeclaration.QualifiedModuleName); return (udtVariable, userDefinedTypeDeclaration, udtMembers); } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs index 305b3554df..a3fb3a3271 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs @@ -64,11 +64,12 @@ public FieldEncapsulationAttributes(Declaration target, string newFieldName = nu private string _newFieldName; public string NewFieldName { - get => EncapsulateFlag ? _newFieldName : FieldName; + get => _newFieldName; set => _newFieldName = value; } public string FieldReadWriteIdentifier => FieldReadWriteIdentifierFunc(); + public Func FieldReadWriteIdentifierFunc { set; get; } public string PropertyName { get; set; } public string AsTypeName { get; set; } From 8c2545f6387aedc8df9495bb6566001c84c68ed4 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Thu, 21 Nov 2019 20:12:29 -0800 Subject: [PATCH 015/461] Changed encapsulated fields dictionary def --- .../EncapsulateFieldView.xaml | 2 +- .../EncapsulateFieldDecorators.cs | 19 ++--- .../EncapsulateField/EncapsulateFieldModel.cs | 75 ++++--------------- .../Refactoring/EncapsulateFieldTests.cs | 21 +++--- 4 files changed, 36 insertions(+), 81 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml index 56d64fabf2..58185f28e0 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml @@ -146,7 +146,7 @@ (efd.Declaration, $"{udtVariable.IdentifierName}.{IdentifierName}"); + efd.TargetID = $"{udtVariable.IdentifierName}.{IdentifierName}"; _decorated.IsVisibleReadWriteAccessor = false; } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index a5dfef28ee..ddf7bd19f3 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -7,12 +7,7 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface ISupportEncapsulateFieldTests - { - void SetMemberEncapsulationFlag(string name, bool flag); - void SetEncapsulationFieldAttributes(string fieldName, IClientEditableFieldEncapsulationAttributes attributes); - } - public class EncapsulateFieldModel : IRefactoringModel, ISupportEncapsulateFieldTests + public class EncapsulateFieldModel : IRefactoringModel { private readonly IIndenter _indenter; @@ -20,7 +15,7 @@ public class EncapsulateFieldModel : IRefactoringModel, ISupportEncapsulateField private IEnumerable UdtFields => _udtFieldToUdtDeclarationMap.Keys; private IEnumerable UdtFieldMembers(Declaration udtField) => _udtFieldToUdtDeclarationMap[udtField].Item2; - private Dictionary, IEncapsulatedFieldDeclaration> _encapsulateFieldDeclarations = new Dictionary, IEncapsulatedFieldDeclaration>(); + private Dictionary _encapsulateFieldDeclarations = new Dictionary(); private IEncapsulatedFieldDeclaration _userSelectedEncapsulationField; private Dictionary _udtVariableEncapsulationAttributes = new Dictionary(); @@ -33,48 +28,28 @@ public EncapsulateFieldModel(Declaration target, IEnumerable allMem foreach (var field in allMemberFields.Except(UdtFields)) { var efd = EncapsulateDeclaration(field); - _encapsulateFieldDeclarations.Add(efd.TargetIDPair, efd); + _encapsulateFieldDeclarations.Add(efd.TargetID, efd); } AddUDTEncapsulationFields(udtFieldToUdtDeclarationMap); - var kvPair = _encapsulateFieldDeclarations.Where(efd => efd.Key.Key == target).Single(); - var selectedTarget = kvPair.Value; - selectedTarget.EncapsulationAttributes.EncapsulateFlag = true; - _userSelectedEncapsulationField = selectedTarget; + this[target].EncapsulationAttributes.EncapsulateFlag = true; + _userSelectedEncapsulationField = this[target]; } public IEnumerable FlaggedEncapsulationFields => _encapsulateFieldDeclarations.Values.Where(v => v.EncapsulationAttributes.EncapsulateFlag); public IEnumerable EncapsulationFieldIDs - => _encapsulateFieldDeclarations.Keys.Select(k => k.Value); + => _encapsulateFieldDeclarations.Keys; public IEnumerable EncapsulationFields => _encapsulateFieldDeclarations.Values; - public IEncapsulatedFieldDeclaration this[string encapsulatedFieldIdentifier] - { - get => _encapsulateFieldDeclarations.Values.Where(efd => efd.TargetIDPair.Value.Equals(encapsulatedFieldIdentifier)) - .FirstOrDefault(); - set - { - var key = _encapsulateFieldDeclarations.Keys.Where(k => k.Value.Equals(encapsulatedFieldIdentifier)) - .FirstOrDefault(); - _encapsulateFieldDeclarations[key] = value; - } - } + public IEncapsulatedFieldDeclaration this[string encapsulatedFieldIdentifier] + => _encapsulateFieldDeclarations[encapsulatedFieldIdentifier]; - public IEncapsulatedFieldDeclaration this[Declaration field] - { - get => _encapsulateFieldDeclarations.Keys.Where(key => key.Key.Equals(field)).Select(kv => _encapsulateFieldDeclarations[kv]) - .Single(); - set - { - var key = _encapsulateFieldDeclarations.Keys.Where(k => k.Key.Equals(field)) - .Single(); - _encapsulateFieldDeclarations[key] = value; - } - } + public IEncapsulatedFieldDeclaration this[Declaration fieldDeclaration] + => _encapsulateFieldDeclarations.Values.Where(efd => efd.Declaration.Equals(fieldDeclaration)).Select(encapsulatedField => encapsulatedField).Single(); public IList PropertiesContent { @@ -138,14 +113,14 @@ private void AddUDTEncapsulationFields(IDictionary _userSelectedEncapsulationField.Declaration; set { var encField = new EncapsulatedFieldDeclaration(value); - _userSelectedEncapsulationField = _encapsulateFieldDeclarations[encField.TargetIDPair]; + _userSelectedEncapsulationField = _encapsulateFieldDeclarations[encField.TargetID]; } } diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index ba3efb555d..12fc1a853b 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -774,7 +774,6 @@ Function Bar() As Integer End Function"; var selection = new Selection(1, 1); - //var presenterAction = SetParameters("Name", implementLet: true); var presenterAction = SetParametersForSingleTarget("fizz", "Name", newFieldName: "fizz"); var actualCode = RefactoredCode(inputCode, selection, presenterAction); Assert.Greater(actualCode.IndexOf("Sub Foo"), actualCode.LastIndexOf("End Property")); @@ -800,7 +799,6 @@ Property Set Foo(ByVal vall As Variant) End Property"; var selection = new Selection(1, 1); - //var presenterAction = SetParameters("Name", implementLet: true); var presenterAction = SetParametersForSingleTarget("fizz", "Name", newFieldName: "fizz"); var actualCode = RefactoredCode(inputCode, selection, presenterAction); Assert.Greater(actualCode.IndexOf("fizz = value"), actualCode.IndexOf("fizz As Integer")); @@ -1077,7 +1075,6 @@ Public Property Let Name(ByVal value As String) foo = value End Property "; - //var presenterAction = SetParameters("Name", implementLet: true); var presenterAction = SetParametersForSingleTarget("foo", "Name", newFieldName: "foo"); var actualCode = RefactoredCode(inputCode, "foo", DeclarationType.Variable, presenterAction); Assert.AreEqual(expectedCode, actualCode); @@ -1146,9 +1143,7 @@ Public Property Get MyArray() As Variant End Property "; var userInput = new TestInputDataObject("mArray", "MyArray", true, "mArray"); - //userInput.AddUDTMemberNameFlagPairs(("First", true), ("Second", true)); - //var presenterAction = SetParameters("MyArray"); var presenterAction = SetParameters(userInput); var actualCode = RefactoredCode(inputCode, selection, presenterAction); Assert.AreEqual(expectedCode, actualCode); @@ -1273,17 +1268,20 @@ private Func SetParameters(TestInp foreach (var testModifiedAttribute in testInput.EncapsulateFieldAttributes) { var attrsInitializedByTheRefactoring = model[testModifiedAttribute.FieldName].EncapsulationAttributes as IClientEditableFieldEncapsulationAttributes; - var testSupport = model as ISupportEncapsulateFieldTests; attrsInitializedByTheRefactoring.NewFieldName = testModifiedAttribute.NewFieldName; attrsInitializedByTheRefactoring.PropertyName = testModifiedAttribute.PropertyName; attrsInitializedByTheRefactoring.EncapsulateFlag = testModifiedAttribute.EncapsulateFlag; - testSupport.SetEncapsulationFieldAttributes(testModifiedAttribute.FieldName, attrsInitializedByTheRefactoring); + var currentAttributes = model[testModifiedAttribute.FieldName].EncapsulationAttributes; + currentAttributes.NewFieldName = attrsInitializedByTheRefactoring.NewFieldName; + currentAttributes.PropertyName = attrsInitializedByTheRefactoring.PropertyName; + currentAttributes.EncapsulateFlag = attrsInitializedByTheRefactoring.EncapsulateFlag; + foreach ((string instanceVariable, string memberName, bool flag) in testInput.UDTMemberNameFlagPairs) { - testSupport.SetMemberEncapsulationFlag($"{instanceVariable}.{memberName}", flag); + model[$"{instanceVariable}.{memberName}"].EncapsulateFlag = flag; } } return model; @@ -1294,7 +1292,12 @@ private Func SetParameters(string { return model => { - model.ApplyAttributes(originalField, clientEdits); + var encapsulatedField = model[originalField]; + encapsulatedField.EncapsulationAttributes.NewFieldName = clientEdits.NewFieldName; + encapsulatedField.EncapsulationAttributes.PropertyName = clientEdits.PropertyName; + encapsulatedField.EncapsulationAttributes.ReadOnly = clientEdits.ReadOnly; + encapsulatedField.EncapsulationAttributes.EncapsulateFlag = clientEdits.EncapsulateFlag; + return model; }; } From eab490e380c747b66ffda9c8cf6cdf09cea35b57 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Sat, 23 Nov 2019 04:39:11 -0800 Subject: [PATCH 016/461] Formatting and Invalid Icon additions --- .../EncapsulateFieldPresenter.cs | 2 +- .../EncapsulateFieldView.xaml | 289 +++++++++++------- 2 files changed, 179 insertions(+), 112 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldPresenter.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldPresenter.cs index 5ef12d6d46..b3629e3577 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldPresenter.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldPresenter.cs @@ -6,7 +6,7 @@ namespace Rubberduck.UI.Refactorings.EncapsulateField internal class EncapsulateFieldPresenter : RefactoringPresenterBase, IEncapsulateFieldPresenter { private static readonly DialogData DialogData = - DialogData.Create(RubberduckUI.EncapsulateField_Caption, 305, 667); + DialogData.Create(RubberduckUI.EncapsulateField_Caption, 800, 800); public EncapsulateFieldPresenter(EncapsulateFieldModel model, IRefactoringDialogFactory dialogFactory) : base(DialogData, model, dialogFactory) { } diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml index 58185f28e0..611260f496 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml @@ -1,35 +1,53 @@  + mc:Ignorable="d" + d:DesignHeight="800" + d:DesignWidth="800"> - + + + + + - - - - - + + + + + + + + + + - - + - + @@ -41,7 +59,8 @@ - + @@ -59,9 +78,10 @@ Margin="0,-10,-8,0" HorizontalAlignment="Right" VerticalAlignment="Top" - Visibility="{Binding IsValidPropertyName, Converter={StaticResource BoolToHiddenVisibility}}"/> + Visibility="{Binding IsValidPropertyName, Converter={StaticResource BoolToHiddenVisibility}}" /> - + @@ -79,7 +99,7 @@ Margin="0,-10,-8,0" HorizontalAlignment="Right" VerticalAlignment="Top" - Visibility="{Binding IsValidParameterName, Converter={StaticResource BoolToHiddenVisibility}}"/> + Visibility="{Binding IsValidParameterName, Converter={StaticResource BoolToHiddenVisibility}}" /> --> - + - - + + - + Margin="5,0,0,5"> - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + Property Name: - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + Backing Variable: - - - - - - - - - - - + + + + + + + + + + + + HorizontalAlignment="Right" + Margin="5,0,0,0" + MinWidth="100"> @@ -251,38 +315,41 @@ Text="{Binding PropertyPreview,Mode=OneWay}"/> --> - + + FontFamily="Courier New " + ShowLineNumbers="False" + HorizontalScrollBarVisibility="Auto" + VerticalScrollBarVisibility="Auto" + MinHeight="200" + IsReadOnly="True" + Text="{Binding PropertyPreview,Mode=OneWay}" /> - - - - - - - + + - From 6847bd8512e6acead82ce403f6a54edbb18ca65a Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Sat, 23 Nov 2019 05:15:30 -0800 Subject: [PATCH 017/461] Introduced ViewableEncapsulatedField --- .../EncapsulateFieldViewModel.cs | 73 +++++++++++++------ .../ViewableEncapsulatedField.cs | 73 +++++++++++++++++++ 2 files changed, 125 insertions(+), 21 deletions(-) create mode 100644 Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs index 05d0eec3c2..d93f37e5fb 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs @@ -20,12 +20,13 @@ namespace Rubberduck.UI.Refactorings.EncapsulateField public class EncapsulateFieldViewModel : RefactoringViewModelBase { public RubberduckParserState State { get; } - public IIndenter Indenter { get; } + //public IIndenter Indenter { get; } - public EncapsulateFieldViewModel(EncapsulateFieldModel model, RubberduckParserState state, IIndenter indenter) : base(model) + + public EncapsulateFieldViewModel(EncapsulateFieldModel model, RubberduckParserState state/*, IIndenter indenter*/) : base(model) { State = state; - Indenter = indenter; + //Indenter = indenter; IsLetSelected = true; PropertyName = model[model.TargetDeclaration].PropertyName; @@ -39,6 +40,8 @@ public EncapsulateFieldViewModel(EncapsulateFieldModel model, RubberduckParserSt BackingFieldNameChangeCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), _ => RefreshPreview()); } + public IEncapsulatedFieldViewData SelectedValue { set; get; } + public Declaration TargetDeclaration { get => Model.TargetDeclaration; @@ -49,22 +52,49 @@ public Declaration TargetDeclaration } } - public ObservableCollection EncapsulationFields - => new ObservableCollection(Model.EncapsulationFields); - - //private bool _expansionState = true; - //public bool ExpansionState - //{ - // get => _expansionState; - // set - // { - // _expansionState = value; - // OnPropertyChanged(); - // OnExpansionStateChanged(value); - // } - //} - - public bool CanHaveLet => Model.CanImplementLet; + public ObservableCollection EncapsulationFields + { + get + { + var flaggedFields = Model.EncapsulationFields.Where(efd => efd.EncapsulateFlag) + .OrderBy(efd => efd.Declaration.IdentifierName); + + var orderedFields = Model.EncapsulationFields.Except(flaggedFields) + .OrderBy(efd => efd.Declaration.IdentifierName); + + var viewableFields = new ObservableCollection(); + foreach (var efd in flaggedFields.Concat(orderedFields)) + { + viewableFields.Add(new ViewableEncapsulatedField(efd)); + } + //TODO: Trying to reset the scroll to the top using SelectedValue is not working...Remove or fix + SelectedValue = viewableFields.FirstOrDefault(); + return viewableFields; + } + } + + public bool TargetsHaveValidEncapsulationSettings + { + get + { + return Model.EncapsulationFields.Where(efd => efd.EncapsulateFlag) + .Any(ff => ff.HasValidEncapsulationAttributes == false); + } + } + + //private bool _expansionState = true; + //public bool ExpansionState + //{ + // get => _expansionState; + // set + // { + // _expansionState = value; + // OnPropertyChanged(); + // OnExpansionStateChanged(value); + // } + //} + + public bool CanHaveLet => Model.CanImplementLet; public bool CanHaveSet => Model.CanImplementSet; public bool IsLetSelected @@ -160,8 +190,7 @@ private void ToggleSelection(bool value) { item.EncapsulateFlag = value; } - OnPropertyChanged(nameof(EncapsulationFields)); - OnPropertyChanged(nameof(PropertyPreview)); + RefreshPreview(); } public CommandBase IsReadOnlyCommand { get; } @@ -170,7 +199,9 @@ private void ToggleSelection(bool value) public CommandBase BackingFieldNameChangeCommand { get; } private void RefreshPreview() { + OnPropertyChanged(nameof(EncapsulationFields)); OnPropertyChanged(nameof(PropertyPreview)); + OnPropertyChanged(nameof(SelectedValue)); } public event EventHandler ExpansionStateChanged; diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs new file mode 100644 index 0000000000..08256a126d --- /dev/null +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs @@ -0,0 +1,73 @@ +using Rubberduck.Refactorings.EncapsulateField; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; + +namespace Rubberduck.UI.Refactorings.EncapsulateField +{ + public interface IEncapsulatedFieldViewData + { + string TargetID { get; set; } + string PropertyName { set; get; } + string NewFieldName { set; get; } + bool EncapsulateFlag { set; get; } + bool IsReadOnly { set; get; } + bool CanBeReadWrite { get; } + bool IsEditableReadWriteFieldIdentifier { get; } + Visibility FieldNameVisibility { get; } + Visibility PropertyNameVisibility { get; } + bool HasValidEncapsulationAttributes { get; } + string AsTypeName { get; } + } + + public class ViewableEncapsulatedField : IEncapsulatedFieldViewData + { + private IEncapsulatedFieldDeclaration _efd; + public ViewableEncapsulatedField(IEncapsulatedFieldDeclaration efd) + { + _efd = efd; + } + + public Visibility FieldNameVisibility => _efd.IsUDTMember || !_efd.EncapsulateFlag ? Visibility.Collapsed : Visibility.Visible; + public Visibility PropertyNameVisibility => !_efd.EncapsulateFlag ? Visibility.Collapsed : Visibility.Visible; + public bool HasValidEncapsulationAttributes => _efd.HasValidEncapsulationAttributes; + public string TargetID { get => _efd.TargetID; set => _efd.TargetID = value; } + public bool IsReadOnly { get => _efd.IsReadOnly; set => _efd.IsReadOnly = value; } + public bool CanBeReadWrite => _efd.CanBeReadWrite; + public string PropertyName { get => _efd.PropertyName; set => _efd.PropertyName = value; } + public bool IsEditableReadWriteFieldIdentifier { get => !_efd.IsUDTMember; } // set => _efd.IsEditableReadWriteFieldIdentifier = value; } + public bool EncapsulateFlag { get => _efd.EncapsulateFlag; set => _efd.EncapsulateFlag = value; } + public string NewFieldName { get => _efd.NewFieldName; set => _efd.NewFieldName = value; } + //TODO: Change name of AsTypeName property to FieldDescriptor(?) -> and does it belong on IEncapsulatedField? + public string AsTypeName + { + //(Variable: Integer Array) + //(Variable: Long) + //(UserDefinedType Member: Long) + get + { + var prefix = string.Empty; + + var descriptor = string.Empty; + if (_efd.IsUDTMember) + { + prefix = "UserDefinedType"; + } + else + { + prefix = "Variable"; + } + + descriptor = $"{prefix}: {_efd.Declaration.AsTypeName}"; + if (_efd.Declaration.IsArray) + { + descriptor = $"{descriptor} Array"; + } + return descriptor; + } + } + } +} From 810a70e49ab17ff9df58dbfc329a696164af33f8 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Sat, 23 Nov 2019 05:16:43 -0800 Subject: [PATCH 018/461] Corrected default field rename bug --- .../EncapsulateField/FieldEncapsulationAttributes.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs index a3fb3a3271..22dd8ddcbe 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs @@ -30,7 +30,7 @@ public ClientEncapsulationAttributes(string targetName) { _fieldName = targetName; PropertyName = $"{char.ToUpperInvariant(targetName[0]) + targetName.Substring(1, targetName.Length - 1)}"; - NewFieldName = $"{targetName}1"; + NewFieldName = $"{char.ToLowerInvariant(targetName[0]) + targetName.Substring(1, targetName.Length - 1)}1"; ReadOnly = false; EncapsulateFlag = false; } From 4b907f623729be15dc723e40183c3b3faafa48a8 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Sat, 23 Nov 2019 05:18:23 -0800 Subject: [PATCH 019/461] Relocated view-support content --- .../EncapsulateFieldDecorators.cs | 87 ++++++++++++------- 1 file changed, 54 insertions(+), 33 deletions(-) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs index eff2632111..9e4ffa08c1 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs @@ -1,5 +1,6 @@ using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; +using Rubberduck.Refactorings.Common; using System; using System.Collections.Generic; using System.Windows; @@ -15,14 +16,15 @@ public interface IEncapsulatedFieldDeclaration Accessibility Accessibility { get;} IFieldEncapsulationAttributes EncapsulationAttributes { set; get; } bool IsReadOnly { set; get; } - bool IsEditableReadOnly { get; } + bool CanBeReadWrite { set; get; } string PropertyName { set; get; } - bool IsVisibleReadWriteAccessor { set; get; } + string FieldReadWriteIdentifier { get; } bool EncapsulateFlag { set; get; } - Visibility ReadWriteAccessorVisibility { set; get; } string NewFieldName { set; get; } - string ReadWriteAccessor { get; } string AsTypeName { get; } + bool IsUDTMember { set; get; } + bool HasValidEncapsulationAttributes { get; } + Func HasConflictsValidationFunc { set; get; } } public class EncapsulatedFieldDeclaration : IEncapsulatedFieldDeclaration @@ -34,7 +36,7 @@ public EncapsulatedFieldDeclaration(Declaration declaration) { _decorated = declaration; _attributes = new FieldEncapsulationAttributes(_decorated); - TargetIDPair = new KeyValuePair(declaration, declaration.IdentifierName); + TargetID = declaration.IdentifierName; } public Declaration Declaration => _decorated; @@ -45,14 +47,23 @@ public EncapsulatedFieldDeclaration(Declaration declaration) public Accessibility Accessibility => _decorated.Accessibility; + public bool HasValidEncapsulationAttributes + { + get + { + return Declaration != null + && VBAIdentifierValidator.IsValidIdentifier(PropertyName, DeclarationType.Variable) + && !EncapsulationAttributes.PropertyName.Equals(FieldReadWriteIdentifier, StringComparison.InvariantCultureIgnoreCase) + && !EncapsulationAttributes.ParameterName.Equals(EncapsulationAttributes.PropertyName, StringComparison.InvariantCultureIgnoreCase); + } + } + public IFieldEncapsulationAttributes EncapsulationAttributes { set => _attributes = value; get => _attributes; } - public KeyValuePair TargetIDPair { get; set; } - public string TargetID { get; set; } public bool EncapsulateFlag @@ -67,7 +78,7 @@ public bool IsReadOnly set => _attributes.ReadOnly = value; } - public bool IsEditableReadOnly => true; + public bool CanBeReadWrite { set; get; } = true; public string PropertyName { @@ -75,13 +86,7 @@ public string PropertyName set => _attributes.PropertyName = value; } - public bool IsVisibleReadWriteAccessor - { - get => ReadWriteAccessorVisibility == Visibility.Visible; - set => ReadWriteAccessorVisibility = value ? Visibility.Visible : Visibility.Collapsed; - } - - public Visibility ReadWriteAccessorVisibility { set; get; } = Visibility.Visible; + public bool IsEditableReadWriteFieldIdentifier { set; get; } = true; public string NewFieldName { @@ -89,12 +94,16 @@ public string NewFieldName set => _attributes.NewFieldName = value; } - public string ReadWriteAccessor + public string FieldReadWriteIdentifier { get => _attributes.FieldReadWriteIdentifier; } - public string AsTypeName => _decorated.AsTypeName; + public string AsTypeName => _decorated.AsTypeName; + + public bool IsUDTMember { set; get; } = false; + + public Func HasConflictsValidationFunc { set; get; } } public class EncapsulateFieldDecoratorBase : IEncapsulatedFieldDeclaration @@ -128,7 +137,7 @@ public string TargetID set => _decorated.TargetID = value; } - public bool IsReadOnly + public bool IsReadOnly { get => _decorated.EncapsulationAttributes.ReadOnly; set => _decorated.EncapsulationAttributes.ReadOnly = value; @@ -140,7 +149,11 @@ public bool EncapsulateFlag set => _decorated.EncapsulateFlag = value; } - public bool IsEditableReadOnly => _decorated.IsEditableReadOnly; + public bool CanBeReadWrite + { + get => _decorated.CanBeReadWrite; + set => _decorated.CanBeReadWrite = value; + } public string PropertyName { @@ -148,30 +161,37 @@ public string PropertyName set => _decorated.EncapsulationAttributes.PropertyName = value; } - public bool IsVisibleReadWriteAccessor + public string NewFieldName { - get => _decorated.IsVisibleReadWriteAccessor; - set => _decorated.IsVisibleReadWriteAccessor = value; + get => _decorated.EncapsulationAttributes.NewFieldName; + set => _decorated.EncapsulationAttributes.NewFieldName = value; } - public Visibility ReadWriteAccessorVisibility// { set; get; } + public string FieldReadWriteIdentifier + => _decorated.EncapsulationAttributes.FieldReadWriteIdentifier; + + public string AsTypeName => _decorated.EncapsulationAttributes.AsTypeName; + + public bool IsUDTMember { - get => _decorated.ReadWriteAccessorVisibility; - set => _decorated.ReadWriteAccessorVisibility = value; + get => _decorated.IsUDTMember; + set => _decorated.IsUDTMember = value; } - public string NewFieldName + public Func HasConflictsValidationFunc { - get => _decorated.EncapsulationAttributes.NewFieldName; - set => _decorated.EncapsulationAttributes.NewFieldName = value; + get => _decorated.HasConflictsValidationFunc; + set => _decorated.HasConflictsValidationFunc = value; } - public string ReadWriteAccessor + public bool HasValidEncapsulationAttributes { - get => _decorated.EncapsulationAttributes.FieldReadWriteIdentifier; + get + { + return _decorated.HasValidEncapsulationAttributes + && !(HasConflictsValidationFunc != null ? HasConflictsValidationFunc(_decorated) : false); + } } - - public string AsTypeName => _decorated.EncapsulationAttributes.AsTypeName; } public class EncapsulatedValueType : EncapsulateFieldDecoratorBase @@ -245,6 +265,7 @@ private EncapsulatedArrayType(IEncapsulatedFieldDeclaration efd) EncapsulationAttributes.ImplementLetSetterType = false; EncapsulationAttributes.ImplementSetSetterType = false; EncapsulationAttributes.AsTypeName = Tokens.Variant; + CanBeReadWrite = false; } public static IEncapsulatedFieldDeclaration Decorate(IEncapsulatedFieldDeclaration efd) @@ -275,7 +296,7 @@ private EncapsulatedUserDefinedTypeMember(IEncapsulatedFieldDeclaration efd, Enc }; efd.TargetID = $"{udtVariable.IdentifierName}.{IdentifierName}"; - _decorated.IsVisibleReadWriteAccessor = false; + efd.IsUDTMember = true; } private string BuildPropertyName() From c98a001c4f8ef9983382ac407285149418fd1614 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Sun, 24 Nov 2019 05:42:10 -0800 Subject: [PATCH 020/461] Improved validation and encapsulate as UDT --- .../EncapsulateFieldViewModel.cs | 4 +- .../EncapsulateFieldDecorators.cs | 128 +------------ .../EncapsulateField/EncapsulateFieldModel.cs | 32 +++- .../EncapsulateFieldRefactoring.cs | 38 +++- .../EncapsulateFieldValidator.cs | 71 +++++++ .../EncapsulatedFieldDeclaration.cs | 124 ++++++++++++ .../EncapsulateField/EncapsulationUDT.cs | 54 ++++++ .../FieldEncapsulationAttributes.cs | 4 +- .../EncapsulatedFieldTests.cs | 178 ++++++++++++++++++ .../Refactoring/EncapsulateFieldTests.cs | 58 +++++- 10 files changed, 538 insertions(+), 153 deletions(-) create mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs create mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs create mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulationUDT.cs create mode 100644 RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs index d93f37e5fb..002a2c2843 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs @@ -145,6 +145,8 @@ public string ParameterName } } + public IEncapsulateFieldNamesValidator RefactoringValidator { set; get; } + public bool IsValidPropertyName { get @@ -166,7 +168,7 @@ public bool IsValidParameterName return encapsulatedField.Declaration != null && VBAIdentifierValidator.IsValidIdentifier(encapsulatedField.PropertyName, DeclarationType.Variable) - && !encapsulatedField.EncapsulationAttributes.ParameterName.Equals(encapsulatedField.IdentifierName, StringComparison.InvariantCultureIgnoreCase) + && !encapsulatedField.EncapsulationAttributes.ParameterName.Equals(encapsulatedField.Declaration.IdentifierName, StringComparison.InvariantCultureIgnoreCase) && !encapsulatedField.EncapsulationAttributes.ParameterName.Equals(encapsulatedField.EncapsulationAttributes.PropertyName, StringComparison.InvariantCultureIgnoreCase); } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs index 9e4ffa08c1..2087df0932 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs @@ -7,124 +7,18 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface IEncapsulatedFieldDeclaration - { - Declaration Declaration { get; } - string IdentifierName { get; } - string TargetID { get; set; } - DeclarationType DeclarationType { get; } - Accessibility Accessibility { get;} - IFieldEncapsulationAttributes EncapsulationAttributes { set; get; } - bool IsReadOnly { set; get; } - bool CanBeReadWrite { set; get; } - string PropertyName { set; get; } - string FieldReadWriteIdentifier { get; } - bool EncapsulateFlag { set; get; } - string NewFieldName { set; get; } - string AsTypeName { get; } - bool IsUDTMember { set; get; } - bool HasValidEncapsulationAttributes { get; } - Func HasConflictsValidationFunc { set; get; } - } - - public class EncapsulatedFieldDeclaration : IEncapsulatedFieldDeclaration - { - protected Declaration _decorated; - private IFieldEncapsulationAttributes _attributes; - - public EncapsulatedFieldDeclaration(Declaration declaration) - { - _decorated = declaration; - _attributes = new FieldEncapsulationAttributes(_decorated); - TargetID = declaration.IdentifierName; - } - - public Declaration Declaration => _decorated; - - public string IdentifierName => _decorated.IdentifierName; - - public DeclarationType DeclarationType => _decorated.DeclarationType; - - public Accessibility Accessibility => _decorated.Accessibility; - - public bool HasValidEncapsulationAttributes - { - get - { - return Declaration != null - && VBAIdentifierValidator.IsValidIdentifier(PropertyName, DeclarationType.Variable) - && !EncapsulationAttributes.PropertyName.Equals(FieldReadWriteIdentifier, StringComparison.InvariantCultureIgnoreCase) - && !EncapsulationAttributes.ParameterName.Equals(EncapsulationAttributes.PropertyName, StringComparison.InvariantCultureIgnoreCase); - } - } - - public IFieldEncapsulationAttributes EncapsulationAttributes - { - set => _attributes = value; - get => _attributes; - } - - public string TargetID { get; set; } - - public bool EncapsulateFlag - { - get => _attributes.EncapsulateFlag; - set => _attributes.EncapsulateFlag = value; - } - - public bool IsReadOnly - { - get => _attributes.ReadOnly; - set => _attributes.ReadOnly = value; - } - - public bool CanBeReadWrite { set; get; } = true; - - public string PropertyName - { - get => _attributes.PropertyName; - set => _attributes.PropertyName = value; - } - - public bool IsEditableReadWriteFieldIdentifier { set; get; } = true; - - public string NewFieldName - { - get => _attributes.NewFieldName; - set => _attributes.NewFieldName = value; - } - - public string FieldReadWriteIdentifier - { - get => _attributes.FieldReadWriteIdentifier; - } - - public string AsTypeName => _decorated.AsTypeName; - - public bool IsUDTMember { set; get; } = false; - - public Func HasConflictsValidationFunc { set; get; } - } - public class EncapsulateFieldDecoratorBase : IEncapsulatedFieldDeclaration { - protected IEncapsulatedFieldDeclaration _decorated; public EncapsulateFieldDecoratorBase(IEncapsulatedFieldDeclaration efd) { _decorated = efd; - TargetID = efd.IdentifierName; + TargetID = efd.Declaration.IdentifierName; } public Declaration Declaration => _decorated.Declaration; - public string IdentifierName => _decorated.IdentifierName; - - public DeclarationType DeclarationType => _decorated.DeclarationType; - - public Accessibility Accessibility => _decorated.Accessibility; - public IFieldEncapsulationAttributes EncapsulationAttributes { get => _decorated.EncapsulationAttributes; @@ -178,20 +72,8 @@ public bool IsUDTMember set => _decorated.IsUDTMember = value; } - public Func HasConflictsValidationFunc - { - get => _decorated.HasConflictsValidationFunc; - set => _decorated.HasConflictsValidationFunc = value; - } - - public bool HasValidEncapsulationAttributes - { - get - { - return _decorated.HasValidEncapsulationAttributes - && !(HasConflictsValidationFunc != null ? HasConflictsValidationFunc(_decorated) : false); - } - } + public bool HasValidEncapsulationAttributes + => _decorated.HasValidEncapsulationAttributes; } public class EncapsulatedValueType : EncapsulateFieldDecoratorBase @@ -280,7 +162,7 @@ public class EncapsulatedUserDefinedTypeMember : EncapsulateFieldDecoratorBase private EncapsulatedUserDefinedTypeMember(IEncapsulatedFieldDeclaration efd, EncapsulatedUserDefinedType udtVariable, bool propertyIdentifierRequiresNameResolution) : base(efd) { - _originalVariableName = udtVariable.IdentifierName; + _originalVariableName = udtVariable.Declaration.IdentifierName; _nameResolveProperty = propertyIdentifierRequiresNameResolution; _udtVariableAttributes = udtVariable.EncapsulationAttributes; @@ -295,7 +177,7 @@ private EncapsulatedUserDefinedTypeMember(IEncapsulatedFieldDeclaration efd, Enc return $"{_udtVariableAttributes.FieldName}.{EncapsulationAttributes.NewFieldName}"; }; - efd.TargetID = $"{udtVariable.IdentifierName}.{IdentifierName}"; + efd.TargetID = $"{udtVariable.Declaration.IdentifierName}.{Declaration.IdentifierName}"; efd.IsUDTMember = true; } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index ddf7bd19f3..5d5cfc82ba 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -3,6 +3,7 @@ using System.Linq; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; +using Rubberduck.Refactorings.Common; using Rubberduck.SmartIndenter; namespace Rubberduck.Refactorings.EncapsulateField @@ -10,6 +11,7 @@ namespace Rubberduck.Refactorings.EncapsulateField public class EncapsulateFieldModel : IRefactoringModel { private readonly IIndenter _indenter; + private readonly IEncapsulateFieldNamesValidator _validator; private IDictionary)> _udtFieldToUdtDeclarationMap = new Dictionary)>(); private IEnumerable UdtFields => _udtFieldToUdtDeclarationMap.Keys; @@ -20,9 +22,10 @@ public class EncapsulateFieldModel : IRefactoringModel private IEncapsulatedFieldDeclaration _userSelectedEncapsulationField; private Dictionary _udtVariableEncapsulationAttributes = new Dictionary(); - public EncapsulateFieldModel(Declaration target, IEnumerable allMemberFields, IDictionary)> udtFieldToUdtDeclarationMap, IIndenter indenter) + public EncapsulateFieldModel(Declaration target, IEnumerable allMemberFields, IDictionary)> udtFieldToUdtDeclarationMap, IIndenter indenter, IEncapsulateFieldNamesValidator validator) { _indenter = indenter; + _validator = validator; _udtFieldToUdtDeclarationMap = udtFieldToUdtDeclarationMap; foreach (var field in allMemberFields.Except(UdtFields)) @@ -51,6 +54,8 @@ public IEncapsulatedFieldDeclaration this[string encapsulatedFieldIdentifier] public IEncapsulatedFieldDeclaration this[Declaration fieldDeclaration] => _encapsulateFieldDeclarations.Values.Where(efd => efd.Declaration.Equals(fieldDeclaration)).Select(encapsulatedField => encapsulatedField).Single(); + public bool EncapsulateWithUserDefinedType { set; get; } + public IList PropertiesContent { get @@ -88,11 +93,24 @@ public EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNew var nonUdtMemberFields = FlaggedEncapsulationFields .Where(encFld => encFld.Declaration.IsVariable()); + if (EncapsulateWithUserDefinedType) + { + var udt = new EncapsulationUDT(); + foreach (var nonUdtMemberField in nonUdtMemberFields) + { + udt.AddMember(nonUdtMemberField); + } + newContent.AddDeclarationBlock(udt.DeclarationAndField); + + //TODO: handle selected UDTs + return newContent; + } + foreach (var nonUdtMemberField in nonUdtMemberFields) { var attributes = nonUdtMemberField.EncapsulationAttributes; - if (nonUdtMemberField.Accessibility == Accessibility.Private && attributes.NewFieldName.Equals(nonUdtMemberField.IdentifierName)) + if (nonUdtMemberField.Declaration.Accessibility == Accessibility.Private && attributes.NewFieldName.Equals(nonUdtMemberField.Declaration.IdentifierName)) { continue; } @@ -127,7 +145,7 @@ private void AddUDTEncapsulationFields(IDictionary(udtMember.Declaration,$"{udtVariable.IdentifierName}.{udtMember.IdentifierName}"); + var targetIDPair = new KeyValuePair(udtMember.Declaration,$"{udtVariable.Declaration.IdentifierName}.{udtMember.Declaration.IdentifierName}"); return EncapsulatedUserDefinedTypeMember.Decorate(udtMember, udtVariable, HasMultipleInstantiationsOfSameType(udtVariable.Declaration, targetIDPair)); } @@ -167,7 +185,7 @@ private string BuildPropertiesTextBlock(IFieldEncapsulationAttributes attributes { PropertyName = attributes.PropertyName, AsTypeName = attributes.AsTypeName, - BackingField = attributes.FieldReadWriteIdentifier, + BackingField = EncapsulateWithUserDefinedType ? $"this.{attributes.PropertyName}" : attributes.FieldReadWriteIdentifier, ParameterName = attributes.ParameterName, GenerateSetter = attributes.ImplementSetSetterType, GenerateLetter = attributes.ImplementLetSetterType @@ -187,7 +205,7 @@ public Declaration TargetDeclaration get => _userSelectedEncapsulationField.Declaration; set { - var encField = new EncapsulatedFieldDeclaration(value); + var encField = new EncapsulatedFieldDeclaration(value, _validator); _userSelectedEncapsulationField = _encapsulateFieldDeclarations[encField.TargetID]; } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index b6edf89c80..4e035c5ca3 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -17,6 +17,7 @@ public class EncapsulateFieldRefactoring : InteractiveRefactoringBase v.IsMemberVariable() && !v.IsWithEvents); - var userDefinedTypeFieldToTypeDeclarationMap = encapsulationCandiateFields + var userDefinedTypeFieldToTypeDeclarationMap = encapsulationCandidateFields .Where(v => v.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.UserDefinedType) ?? false) .Select(uv => CreateUDTTuple(uv)) .ToDictionary(key => key.UDTVariable, element => (element.UserDefinedType, element.UDTMembers)); - var model = new EncapsulateFieldModel(target, encapsulationCandiateFields, userDefinedTypeFieldToTypeDeclarationMap, _indenter); + var model = new EncapsulateFieldModel + (target, + encapsulationCandidateFields, + userDefinedTypeFieldToTypeDeclarationMap, + _indenter, + _validator); return model; } @@ -77,14 +84,19 @@ protected override void RefactorImpl(EncapsulateFieldModel model) { var rewriteSession = RewritingManager.CheckOutCodePaneSession(); + if (model.EncapsulateWithUserDefinedType) + { + //create UDT and add to new Content of Declaration Section + } + var nonUdtMemberFields = model.FlaggedEncapsulationFields .Where(encFld => encFld.Declaration.IsVariable()); foreach (var nonUdtMemberField in nonUdtMemberFields) { var attributes = nonUdtMemberField.EncapsulationAttributes; - ModifyEncapsulatedVariable(nonUdtMemberField, attributes, rewriteSession); - RenameReferences(nonUdtMemberField.Declaration, attributes.PropertyName ?? nonUdtMemberField.Declaration.IdentifierName, rewriteSession); + ModifyEncapsulatedVariable(nonUdtMemberField, attributes, rewriteSession, model.EncapsulateWithUserDefinedType); + RenameReferences(nonUdtMemberField, attributes.PropertyName ?? nonUdtMemberField.Declaration.IdentifierName, rewriteSession); } var moduleMembers = _declarationFinderProvider.DeclarationFinder @@ -104,11 +116,17 @@ protected override void RefactorImpl(EncapsulateFieldModel model) } } - private void ModifyEncapsulatedVariable(IEncapsulatedFieldDeclaration target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession) //, EncapsulateFieldNewContent newContent) + private void ModifyEncapsulatedVariable(IEncapsulatedFieldDeclaration target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession, bool asUDT = false) //, EncapsulateFieldNewContent newContent) { var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, _targetQMN); - if (target.Accessibility == Accessibility.Private && attributes.NewFieldName.Equals(target.IdentifierName)) + if (asUDT) + { + rewriter.Remove(target.Declaration); + return; + } + + if (target.Declaration.Accessibility == Accessibility.Private && attributes.NewFieldName.Equals(target.Declaration.IdentifierName)) { rewriter.MakeImplicitDeclarationTypeExplicit(target.Declaration); return; @@ -127,12 +145,12 @@ private void ModifyEncapsulatedVariable(IEncapsulatedFieldDeclaration target, IF return; } - private void RenameReferences(Declaration target, string propertyName, IRewriteSession rewriteSession) + private void RenameReferences(IEncapsulatedFieldDeclaration efd, string propertyName, IRewriteSession rewriteSession) { - foreach (var reference in target.References) + foreach (var reference in efd.Declaration.References) { var rewriter = rewriteSession.CheckOutModuleRewriter(reference.QualifiedModuleName); - rewriter.Replace(reference.Context, propertyName ?? target.IdentifierName); + rewriter.Replace(reference.Context, propertyName ?? efd.Declaration.IdentifierName); } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs new file mode 100644 index 0000000000..e9b90f61ef --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -0,0 +1,71 @@ +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.Refactorings.Common; +using Rubberduck.VBEditor; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + public interface IEncapsulateFieldNamesValidator + { + bool HasValidEncapsulationAttributes(IEncapsulatedFieldDeclaration encapsulatedField); + bool HasValidEncapsulationAttributes(IEnumerable newMembers); + bool IsConflictingMemberName(string identifier, QualifiedModuleName qmn, DeclarationType declarationType); + } + + public class EncapsulateFieldNamesValidator : IEncapsulateFieldNamesValidator + { + private readonly IDeclarationFinderProvider _declarationFinderProvider; + public EncapsulateFieldNamesValidator(IDeclarationFinderProvider declarationFinderProvider) + { + _declarationFinderProvider = declarationFinderProvider; + } + + public bool HasValidEncapsulationAttributes(IEncapsulatedFieldDeclaration encapsulatedField) + { + var internalChecks = HasValidIdentifiers(encapsulatedField) + && !HasInternalNameConflicts(encapsulatedField); + + var external = _declarationFinderProvider.DeclarationFinder + .FindNewDeclarationNameConflicts(encapsulatedField.NewFieldName, encapsulatedField.Declaration); + + //if the collision is the target, then ignore + if (external.Count() == 1 && external.First() == encapsulatedField.Declaration) + { + return internalChecks; + } + return internalChecks && !external.Any(); + } + + public bool HasValidEncapsulationAttributes(IEnumerable newMembers) + { + return newMembers.Any(nm => !HasValidIdentifiers(nm)); + } + + public bool IsConflictingMemberName(string memberName, QualifiedModuleName qmn, DeclarationType declarationType) + { + var members = _declarationFinderProvider.DeclarationFinder.Members(qmn); + return members.Any(m => m.IdentifierName.Equals(memberName, StringComparison.CurrentCultureIgnoreCase)); + } + + private bool HasValidIdentifiers(IEncapsulatedFieldDeclaration encapsulatedField) + { + var attributes = encapsulatedField.EncapsulationAttributes; + return VBAIdentifierValidator.IsValidIdentifier(attributes.NewFieldName, encapsulatedField.Declaration.DeclarationType) + && VBAIdentifierValidator.IsValidIdentifier(attributes.PropertyName, encapsulatedField.Declaration.DeclarationType) + && VBAIdentifierValidator.IsValidIdentifier(attributes.ParameterName, encapsulatedField.Declaration.DeclarationType); + } + + private bool HasInternalNameConflicts(IEncapsulatedFieldDeclaration encapsulatedField) + { + var attributes = encapsulatedField.EncapsulationAttributes; + return attributes.PropertyName.Equals(attributes.NewFieldName, StringComparison.InvariantCultureIgnoreCase) + || attributes.PropertyName.Equals(attributes.ParameterName, StringComparison.InvariantCultureIgnoreCase) + || attributes.NewFieldName.Equals(attributes.ParameterName, StringComparison.InvariantCultureIgnoreCase); + } + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs new file mode 100644 index 0000000000..58c1bb0030 --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs @@ -0,0 +1,124 @@ +using Rubberduck.Parsing.Symbols; +using Rubberduck.Refactorings.Common; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + public interface IEncapsulatedFieldDeclaration + { + Declaration Declaration { get; } + string TargetID { get; set; } + IFieldEncapsulationAttributes EncapsulationAttributes { set; get; } + bool IsReadOnly { set; get; } + bool CanBeReadWrite { set; get; } + string PropertyName { set; get; } + string FieldReadWriteIdentifier { get; } + bool EncapsulateFlag { set; get; } + string NewFieldName { set; get; } + string AsTypeName { get; } + bool IsUDTMember { set; get; } + bool HasValidEncapsulationAttributes { get; } + } + + public class EncapsulatedFieldDeclaration : IEncapsulatedFieldDeclaration + { + protected Declaration _decorated; + private IFieldEncapsulationAttributes _attributes; + private IEncapsulateFieldNamesValidator _validator; + + public EncapsulatedFieldDeclaration(Declaration declaration, IEncapsulateFieldNamesValidator validator) + { + _decorated = declaration; + _attributes = new FieldEncapsulationAttributes(_decorated); + _validator = validator; + TargetID = declaration.IdentifierName; + SetNonConflictingEncapsulationAttributes(); + } + + private void SetNonConflictingEncapsulationAttributes() + { + var isValid = _validator.HasValidEncapsulationAttributes(this); + if (!isValid) + { + var attributes = new ClientEncapsulationAttributes(Declaration.IdentifierName); + if (IsConflictingAttributes(attributes)) + { + var hasConflict = true; + for (var idx = 2; idx < 9 && hasConflict; idx++) + { + attributes = new ClientEncapsulationAttributes($"{Declaration.IdentifierName}{idx}"); + hasConflict = IsConflictingAttributes(attributes); + } + NewFieldName = attributes.NewFieldName; + PropertyName = attributes.PropertyName; + } + } + } + + private bool IsConflictingAttributes(ClientEncapsulationAttributes attributes) + { + var isConflictingFieldName = _validator.IsConflictingMemberName(attributes.NewFieldName, Declaration.QualifiedModuleName, Declaration.DeclarationType); + var isConflictingPropertyName = _validator.IsConflictingMemberName(attributes.PropertyName, Declaration.QualifiedModuleName, DeclarationType.Member); + return isConflictingFieldName || isConflictingPropertyName; + } + + public Declaration Declaration => _decorated; + + public bool HasValidEncapsulationAttributes + { + get + { + return _validator.HasValidEncapsulationAttributes(this); + } + } + + public IFieldEncapsulationAttributes EncapsulationAttributes + { + set => _attributes = value; + get => _attributes; + } + + public string TargetID { get; set; } + + public bool EncapsulateFlag + { + get => _attributes.EncapsulateFlag; + set => _attributes.EncapsulateFlag = value; + } + + public bool IsReadOnly + { + get => _attributes.ReadOnly; + set => _attributes.ReadOnly = value; + } + + public bool CanBeReadWrite { set; get; } = true; + + public string PropertyName + { + get => _attributes.PropertyName; + set => _attributes.PropertyName = value; + } + + public bool IsEditableReadWriteFieldIdentifier { set; get; } = true; + + public string NewFieldName + { + get => _attributes.NewFieldName; + set => _attributes.NewFieldName = value; + } + + public string FieldReadWriteIdentifier + { + get => _attributes.FieldReadWriteIdentifier; + } + + public string AsTypeName => _decorated.AsTypeName; + + public bool IsUDTMember { set; get; } = false; + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationUDT.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationUDT.cs new file mode 100644 index 0000000000..996c2c7bd7 --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationUDT.cs @@ -0,0 +1,54 @@ +using Rubberduck.Parsing.Symbols; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + public class EncapsulationUDT + { + private const string _typeIdentifier = "This_Type"; + private const string _fieldName = "this"; + + private List _members; + + public EncapsulationUDT() + { + _members = new List(); + } + + public void AddMember(IEncapsulatedFieldDeclaration field) + { + _members.Add(field); + } + + public string FieldDeclaration + => $"Private {_fieldName} As {_typeIdentifier}"; + + public string DeclarationAndField + { + get + { + var members = new List(); + foreach (var member in _members) + { + var declaration = $"{Capitalize(member.PropertyName)} As {member.Declaration.AsTypeName}"; + members.Add(declaration); + } + return +$@"Private Type {_typeIdentifier} + {string.Join(Environment.NewLine, members)} +End Type + +{FieldDeclaration}{Environment.NewLine}"; + } + } + + private string Capitalize(string input) + { + return $"{char.ToUpperInvariant(input[0]) + input.Substring(1, input.Length - 1)}"; + } + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs index 22dd8ddcbe..c00c1d90ff 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs @@ -17,8 +17,8 @@ public interface IFieldEncapsulationAttributes : IClientEditableFieldEncapsulati string FieldReadWriteIdentifier { get; } string AsTypeName { get; set; } string ParameterName { get; set; } - bool CanImplementLet { get; set; } - bool CanImplementSet { get; set; } + bool CanImplementLet { get; set; } //TODO: Can these go away? + bool CanImplementSet { get; set; } //TODO: Can these go away? bool ImplementLetSetterType { get; set; } bool ImplementSetSetterType { get; set; } Func FieldReadWriteIdentifierFunc { set; get; } diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs new file mode 100644 index 0000000000..90a2fdb971 --- /dev/null +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs @@ -0,0 +1,178 @@ +using System; +using NUnit.Framework; +using Moq; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Refactorings; +using Rubberduck.Refactorings.EncapsulateField; +using Rubberduck.VBEditor; +using RubberduckTests.Mocks; +using Rubberduck.SmartIndenter; +using Rubberduck.VBEditor.SafeComWrappers; +using Rubberduck.VBEditor.SafeComWrappers.Abstract; +using Rubberduck.Parsing.VBA; +using Rubberduck.Refactorings.Exceptions; +using Rubberduck.VBEditor.Utility; +using System.Collections.Generic; +using System.Linq; + +namespace RubberduckTests.Refactoring.EncapsulateField +{ + [TestFixture] + public class EncapsulatedFieldTests //: InteractiveRefactoringTestBase + { + [TestCase("fizz", "_fizz", false)] + [TestCase("fizz", "Fizz", false)] //Property name default is 'Fizz' + [TestCase("fizz", "mFizz", true)] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void NewFieldNameAttributeValidations_Internal(string originalFieldName, string newFieldName, bool expectedResult) + { + string inputCode = +$@"Public {originalFieldName} As String"; + + var selection = new Selection(1, 1); + var encapsulatedField = RetrieveEncapsulatedField(inputCode, originalFieldName); + + encapsulatedField.NewFieldName = newFieldName; + + Assert.AreEqual(expectedResult, encapsulatedField.HasValidEncapsulationAttributes); + } + + [TestCase("fizz", "_Fizz", false)] + [TestCase("fizz", "Fizz1", false)] //field is defaulted is 'fizz1' + [TestCase("fizz", "FizzProp", true)] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void PropertyNameAttributeValidations_Internal(string originalFieldName, string newPropertyName, bool expectedResult) + { + string inputCode = +$@"Public {originalFieldName} As String"; + + var selection = new Selection(1, 1); + var encapsulatedField = RetrieveEncapsulatedField(inputCode, originalFieldName); + + encapsulatedField.PropertyName = newPropertyName; + + Assert.AreEqual(expectedResult, encapsulatedField.HasValidEncapsulationAttributes); + } + + [TestCase("fizz", "Name", false)] + [TestCase("fizz", "mName", false)] + [TestCase("fizz", "fizz1", true)] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void FieldNameAttributeValidation_External(string originalFieldName, string newFieldName, bool expectedResult) + { + string inputCode = +$@"Public {originalFieldName} As String + + Private mName As String + + Public Property Get Name() As String + Name = mName + End Property + + Public Property Let Name(ByVal value As String) + mName = value + End Property + "; + var selection = new Selection(1, 1); + var encapsulatedField = RetrieveEncapsulatedField(inputCode, originalFieldName); + + encapsulatedField.NewFieldName = newFieldName; + + Assert.AreEqual(expectedResult, encapsulatedField.HasValidEncapsulationAttributes); + } + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void FieldNameAttributeValidation_DefaultsToAvailableFieldName() + { + string inputCode = +$@"Public fizz As String + + 'fizz1 is the intial default name for encapsulating 'fizz' + Private fizz1 As String + + Public Property Get Name() As String + Name = fizz1 + End Property + + Public Property Let Name(ByVal value As String) + fizz1 = value + End Property + "; + var encapsulatedField = RetrieveEncapsulatedField(inputCode, "fizz"); + Assert.AreEqual(true, encapsulatedField.HasValidEncapsulationAttributes); + } + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void FieldNameAttributeValidation_DefaultsToAvailablePropertyName() + { + string inputCode = +$@"Public fizz As String + + Private fizzle As String + + 'fizz1 is the intial default name for encapsulating 'fizz' + Public Property Get Fizz1() As String + Fizz1 = fizzle + End Property + + Public Property Let Fizz1(ByVal value As String) + fizzle = value + End Property + "; + var encapsulatedField = RetrieveEncapsulatedField(inputCode, "fizz"); + Assert.AreEqual(true, encapsulatedField.HasValidEncapsulationAttributes); + } + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void CreateUDT() + { + string inputCode = +$@"Public fizz As String"; + + var encapsulatedField = RetrieveEncapsulatedField(inputCode, "fizz"); + + var udtTest = new EncapsulationUDT(); + udtTest.AddMember(encapsulatedField); + var result = udtTest.DeclarationAndField; + StringAssert.Contains("Fizz As String", result); + } + + private IEncapsulatedFieldDeclaration RetrieveEncapsulatedField(string inputCode, string fieldName)//, Selection selection) //, Func presenterAdjustment, Type expectedException = null, bool executeViaActiveSelection = false) + { + var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; + + var selectedComponentName = vbe.SelectedVBComponent.Name; + + var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); + using (state) + { + var module = state.DeclarationFinder.UserDeclarations(DeclarationType.Module) + .Single(declaration => declaration.IdentifierName == selectedComponentName) + .QualifiedModuleName; + + var match = state.DeclarationFinder.MatchName(fieldName).Single(); + return new EncapsulatedFieldDeclaration(match, new EncapsulateFieldNamesValidator(state)) as IEncapsulatedFieldDeclaration; + } + } + + private ClientEncapsulationAttributes UserModifiedEncapsulationAttributes(string field, string property = null, bool? isReadonly = null, bool encapsulateFlag = true, string newFieldName = null) + { + var clientAttrs = new ClientEncapsulationAttributes(field); + clientAttrs.NewFieldName = newFieldName ?? clientAttrs.NewFieldName; + clientAttrs.PropertyName = property ?? clientAttrs.PropertyName; + clientAttrs.ReadOnly = isReadonly ?? clientAttrs.ReadOnly; + clientAttrs.EncapsulateFlag = encapsulateFlag; + return clientAttrs; + } + } +} diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index 12fc1a853b..21e6c5ec0b 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -882,6 +882,22 @@ End Property Assert.AreEqual(expectedCode, actualCode); } + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulatePrivateFieldAsUDT() + { + //Input + const string inputCode = + @"Private fizz As Integer"; + var selection = new Selection(1, 1); + + var presenterAction = SetParametersForSingleTarget("fizz", "Name", asUDT: true); + var actualCode = RefactoredCode(inputCode, selection, presenterAction); + StringAssert.Contains("Name As Integer", actualCode); + StringAssert.Contains("this.Name = value", actualCode); + } + [Test] [Category("Refactorings")] [Category("Encapsulate Field")] @@ -909,6 +925,23 @@ End Property Assert.AreEqual(expectedCode, actualCode); } + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulatePrivateField_DefaultsAsUDT() + { + const string inputCode = + @"Private fizz As Integer"; + + var selection = new Selection(1, 1); + + var presenterAction = UserAcceptsDefaults(asUDT: true); + var actualCode = RefactoredCode(inputCode, selection, presenterAction); + StringAssert.Contains("Fizz As Integer", actualCode); + StringAssert.Contains("this As This_Type", actualCode); + StringAssert.Contains("this.Fizz = value", actualCode); + } + [TestCase("fizz")] [TestCase("mFizz")] [Category("Refactorings")] @@ -1242,23 +1275,28 @@ End Property Assert.AreEqual(expectedCode, actualCode); } - #region setup - private Func UserAcceptsDefaults() - { - return model => { model.EncapsulateFlag = true; return model; }; - } - - private Func SetParametersForSingleTarget(string field, string property = null, bool? isReadonly = null, bool encapsulateFlag = true, string newFieldName = null) + private ClientEncapsulationAttributes UserModifiedEncapsulationAttributes(string field, string property = null, bool? isReadonly = null, bool encapsulateFlag = true, string newFieldName = null) { var clientAttrs = new ClientEncapsulationAttributes(field); clientAttrs.NewFieldName = newFieldName ?? clientAttrs.NewFieldName; clientAttrs.PropertyName = property ?? clientAttrs.PropertyName; clientAttrs.ReadOnly = isReadonly ?? clientAttrs.ReadOnly; clientAttrs.EncapsulateFlag = encapsulateFlag; + return clientAttrs; + } + + private Func UserAcceptsDefaults(bool asUDT = false) + { + return model => { model.EncapsulateFlag = true; model.EncapsulateWithUserDefinedType = asUDT; return model; }; + } + + private Func SetParametersForSingleTarget(string field, string property = null, bool? isReadonly = null, bool encapsulateFlag = true, string newFieldName = null, bool asUDT = false) + { + var clientAttrs = UserModifiedEncapsulationAttributes(field, property, isReadonly, encapsulateFlag, newFieldName); - return SetParameters(field, clientAttrs); + return SetParameters(field, clientAttrs, asUDT); } private Func SetParameters(TestInputDataObject testInput) @@ -1278,7 +1316,6 @@ private Func SetParameters(TestInp currentAttributes.PropertyName = attrsInitializedByTheRefactoring.PropertyName; currentAttributes.EncapsulateFlag = attrsInitializedByTheRefactoring.EncapsulateFlag; - foreach ((string instanceVariable, string memberName, bool flag) in testInput.UDTMemberNameFlagPairs) { model[$"{instanceVariable}.{memberName}"].EncapsulateFlag = flag; @@ -1288,7 +1325,7 @@ private Func SetParameters(TestInp }; } - private Func SetParameters(string originalField, IClientEditableFieldEncapsulationAttributes clientEdits) + private Func SetParameters(string originalField, IClientEditableFieldEncapsulationAttributes clientEdits, bool asUDT = false) { return model => { @@ -1298,6 +1335,7 @@ private Func SetParameters(string encapsulatedField.EncapsulationAttributes.ReadOnly = clientEdits.ReadOnly; encapsulatedField.EncapsulationAttributes.EncapsulateFlag = clientEdits.EncapsulateFlag; + model.EncapsulateWithUserDefinedType = asUDT; return model; }; } From ddf726ad8c25f75f32a2944fe74f4cc2c6d16ddd Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Sun, 24 Nov 2019 15:51:23 -0800 Subject: [PATCH 021/461] Added option to encapsulate within a UDT --- .../EncapsulateField/EncapsulateFieldView.xaml | 9 ++++++--- .../EncapsulateFieldViewModel.cs | 10 ++++++++++ .../EncapsulateField/EncapsulateFieldModel.cs | 5 +++-- .../EncapsulateFieldNewContent.cs | 4 +++- .../EncapsulateField/EncapsulationUDT.cs | 17 ++++++++++------- .../EncapsulateField/EncapsulatedFieldTests.cs | 9 +++++++-- 6 files changed, 39 insertions(+), 15 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml index 611260f496..914b58f745 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml @@ -84,9 +84,12 @@ VerticalAlignment="Top"> - + - - - - UpdatePreview()); } - public IEncapsulatedFieldViewData SelectedValue { set; get; } - public ObservableCollection EncapsulationFields { get @@ -56,6 +44,10 @@ public ObservableCollection EncapsulationFields } } + public IEncapsulatedFieldViewData SelectedValue { set; get; } + + public bool HideEncapsulateAsUDTFields => !EncapsulateAsUDT; + public bool EncapsulateAsUDT { get => Model.EncapsulateWithUDT; @@ -63,6 +55,7 @@ public bool EncapsulateAsUDT { Model.EncapsulateWithUDT = value; UpdatePreview(); + OnPropertyChanged(nameof(HideEncapsulateAsUDTFields)); } } @@ -86,28 +79,16 @@ public string EncapsulateAsUDT_FieldName } } - public bool TargetsHaveValidEncapsulationSettings - { - get - { - return Model.EncapsulationFields.Where(efd => efd.EncapsulateFlag) - .Any(ff => ff.HasValidEncapsulationAttributes == false); - } - } - + public bool TargetsHaveValidEncapsulationSettings + => Model.EncapsulationFields.Where(efd => efd.EncapsulateFlag) + .Any(ff => !ff.HasValidEncapsulationAttributes); public IEncapsulateFieldNamesValidator RefactoringValidator { set; get; } //TODO: hook the validation scheme backup public bool HasValidNames => true; - public string PropertyPreview - { - get - { - return Model.NewContent.AsSingleTextBlock; - } - } + public string PropertyPreview => Model.PreviewRefactoring(); public CommandBase SelectAllCommand { get; } public CommandBase DeselectAllCommand { get; } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index bbf00648e8..f5dde87247 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -15,6 +15,7 @@ public class EncapsulateFieldModel : IRefactoringModel private readonly IIndenter _indenter; private readonly IEncapsulateFieldNamesValidator _validator; + private readonly Func _previewFunc; private IDictionary)> _udtFieldToUdtDeclarationMap = new Dictionary)>(); private IEnumerable UdtFields => _udtFieldToUdtDeclarationMap.Keys; @@ -22,11 +23,12 @@ public class EncapsulateFieldModel : IRefactoringModel private Dictionary _encapsulateFieldDeclarations = new Dictionary(); - public EncapsulateFieldModel(Declaration target, IEnumerable allMemberFields, IDictionary)> udtFieldToUdtDeclarationMap, IIndenter indenter, IEncapsulateFieldNamesValidator validator) + public EncapsulateFieldModel(Declaration target, IEnumerable allMemberFields, IDictionary)> udtFieldToUdtDeclarationMap, IIndenter indenter, IEncapsulateFieldNamesValidator validator, Func previewFunc) { _indenter = indenter; _validator = validator; _udtFieldToUdtDeclarationMap = udtFieldToUdtDeclarationMap; + _previewFunc = previewFunc; foreach (var field in allMemberFields.Except(UdtFields)) { @@ -72,25 +74,37 @@ public IList PropertiesContent } } - public IEncapsulateFieldNewContentProvider NewContent + public string PreviewRefactoring() { - get - { - var newContent = new EncapsulateFieldNewContent(); - newContent = LoadNewDeclarationsContent(newContent); - newContent = LoadNewPropertiesContent(newContent); - return newContent; - } + return _previewFunc(this); } - public EncapsulateFieldNewContent LoadNewPropertiesContent(EncapsulateFieldNewContent newContent) + public IEncapsulateFieldNewContentProvider NewContent(string postScript = null) + { + var newContent = new EncapsulateFieldNewContent(); + newContent = LoadNewDeclarationsContent(newContent); + newContent = LoadNewPropertiesContent(newContent, postScript); + return newContent; + } + + public EncapsulateFieldNewContent LoadNewPropertiesContent(EncapsulateFieldNewContent newContent, string postScript) { if (!FlaggedEncapsulationFields.Any()) { return newContent; } newContent.AddCodeBlock($"{string.Join($"{Environment.NewLine}{Environment.NewLine}", PropertiesContent)}"); + if (postScript?.Length > 0) + { + newContent.AddCodeBlock(postScript); + } return newContent; } + public IEncapsulateFieldNewContentProvider NewContentPostscript(IEncapsulateFieldNewContentProvider newContent, string postScript) + { + newContent.AddCodeBlock($"{Environment.NewLine}{postScript}"); + return newContent as IEncapsulateFieldNewContentProvider; + } + public EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNewContent newContent) { var nonUdtMemberFields = FlaggedEncapsulationFields diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 25b48aa741..c637744abc 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -8,6 +8,7 @@ using Rubberduck.SmartIndenter; using Rubberduck.VBEditor.Utility; using System.Collections.Generic; +using System; namespace Rubberduck.Refactorings.EncapsulateField { @@ -20,13 +21,13 @@ public class EncapsulateFieldRefactoring : InteractiveRefactoringBase CreateUDTTuple(uv)) .ToDictionary(key => key.UDTVariable, element => (element.UserDefinedType, element.UDTMembers)); - var model = new EncapsulateFieldModel - (target, - encapsulationCandidateFields, - userDefinedTypeFieldToTypeDeclarationMap, + var model = new EncapsulateFieldModel + (target, + encapsulationCandidateFields, + userDefinedTypeFieldToTypeDeclarationMap, _indenter, - _validator); + _validator, + PreviewRewrite); return model; } protected override void RefactorImpl(EncapsulateFieldModel model) { - var rewriteSession = RewritingManager.CheckOutCodePaneSession(); + var rewriteSession = RefactorRewrite(model, RewritingManager.CheckOutCodePaneSession()); + var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, _targetQMN); + + rewriter.InsertNewContent(CodeSectionStartIndex, model.NewContent()); + + if (!rewriteSession.TryRewrite()) + { + throw new RewriteFailedException(rewriteSession); + } + } + + private string PreviewRewrite(EncapsulateFieldModel model) + { + var scratchPadRewriteSession = RefactorRewrite(model, RewritingManager.CheckOutCodePaneSession()); + + var previewRewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(scratchPadRewriteSession, _targetQMN); + + var newContent = model.NewContent("'<===== No Changes below this line =====>"); + + previewRewriter.InsertNewContent(CodeSectionStartIndex, newContent); + + var preview = previewRewriter.GetText(); + + return preview; + } + + private IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) + { var nonUdtMemberFields = model.FlaggedEncapsulationFields .Where(encFld => encFld.Declaration.IsVariable()); @@ -94,24 +123,21 @@ protected override void RefactorImpl(EncapsulateFieldModel model) RenameReferences(nonUdtMemberField, attributes.PropertyName ?? nonUdtMemberField.Declaration.IdentifierName, rewriteSession); } - var moduleMembers = _declarationFinderProvider.DeclarationFinder - .Members(_targetQMN).Where(m => m.IsMember()); - - int? codeSectionStartIndex - = moduleMembers.OrderBy(c => c.Selection) - .FirstOrDefault()?.Context.Start.TokenIndex ?? null; - - var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, _targetQMN); + return rewriteSession; + } - rewriter.InsertNewContent(codeSectionStartIndex, model.NewContent); + private int? CodeSectionStartIndex + { + get + { + var moduleMembers = _declarationFinderProvider.DeclarationFinder + .Members(_targetQMN).Where(m => m.IsMember()); - var modifiedAndNewConent = codeSectionStartIndex.HasValue - ? rewriter.GetText(1, codeSectionStartIndex.Value - 1) - : rewriter.GetText(); + int? codeSectionStartIndex + = moduleMembers.OrderBy(c => c.Selection) + .FirstOrDefault()?.Context.Start.TokenIndex ?? null; - if (!rewriteSession.TryRewrite()) - { - throw new RewriteFailedException(rewriteSession); + return codeSectionStartIndex; } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs index b614254b1c..ad7fa9427e 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs @@ -36,13 +36,14 @@ public EncapsulateFieldRewriter(IModuleRewriter rewriter) public void InsertNewContent(int? codeSectionStartIndex, IEncapsulateFieldNewContentProvider newContent) { + var allContent = newContent.AsSingleTextBlock; if (codeSectionStartIndex.HasValue && newContent.HasNewContent) { - _rewriter.InsertBefore(codeSectionStartIndex.Value, $"{Environment.NewLine}{newContent.AsSingleTextBlock}"); + _rewriter.InsertBefore(codeSectionStartIndex.Value, $"{Environment.NewLine}{allContent}"); } else { - InsertAtEndOfFile($"{Environment.NewLine}{newContent.AsSingleTextBlock}"); + InsertAtEndOfFile($"{Environment.NewLine}{allContent}"); } } From e7f9eeec37d2533a44f8c87b92b2526486798961 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Wed, 27 Nov 2019 15:04:08 -0800 Subject: [PATCH 029/461] Handle encapsulating udt fields in the uber UDT --- .../EncapsulateFieldDecorators.cs | 7 + .../EncapsulateField/EncapsulateFieldModel.cs | 38 +- .../EncapsulateFieldRefactoring.cs | 14 +- .../EncapsulateFieldValidator.cs | 185 +++++-- .../EncapsulatedFieldDeclaration.cs | 44 +- .../FieldEncapsulationAttributes.cs | 10 +- ...enerator.cs => UDTDeclarationGenerator.cs} | 8 +- .../EncapsulateField/EncapsulateAsUDTTests.cs | 71 +++ .../EncapsulateFieldValidatorTests.cs | 129 +++++ .../EncapsulatedFieldTests.cs | 18 +- .../EncapsulateField/TestSupport.cs | 152 ++++++ .../Refactoring/EncapsulateFieldTests.cs | 458 +++++++++++------- 12 files changed, 869 insertions(+), 265 deletions(-) rename Rubberduck.Refactorings/EncapsulateField/{UDTGenerator.cs => UDTDeclarationGenerator.cs} (85%) create mode 100644 RubberduckTests/Refactoring/EncapsulateField/EncapsulateAsUDTTests.cs create mode 100644 RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs create mode 100644 RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs index ca1bf70d37..75069008d3 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs @@ -1,6 +1,7 @@ using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.Refactorings.Common; +using Rubberduck.VBEditor; using System; using System.Collections.Generic; using System.Windows; @@ -19,6 +20,8 @@ public EncapsulateFieldDecoratorBase(IEncapsulatedFieldDeclaration efd) public Declaration Declaration => _decorated.Declaration; + public DeclarationType DeclarationType => _decorated.DeclarationType; + public IFieldEncapsulationAttributes EncapsulationAttributes { get => _decorated.EncapsulationAttributes; @@ -70,6 +73,10 @@ public bool IsUDTMember public bool HasValidEncapsulationAttributes => _decorated.HasValidEncapsulationAttributes; + + public QualifiedModuleName QualifiedModuleName => _decorated.QualifiedModuleName; + + public IEnumerable References => _decorated.References; } public class EncapsulatedValueType : EncapsulateFieldDecoratorBase diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index f5dde87247..54b0f4e817 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -41,7 +41,8 @@ public EncapsulateFieldModel(Declaration target, IEnumerable allMem this[target].EncapsulationAttributes.EncapsulateFlag = true; } - public IEnumerable FlaggedEncapsulationFields => _encapsulateFieldDeclarations.Values.Where(v => v.EncapsulationAttributes.EncapsulateFlag); + public IEnumerable FlaggedEncapsulationFields + => _encapsulateFieldDeclarations.Values.Where(v => v.EncapsulationAttributes.EncapsulateFlag); public IEnumerable EncapsulationFieldIDs => _encapsulateFieldDeclarations.Keys; @@ -68,12 +69,34 @@ public IList PropertiesContent var textBlocks = new List(); foreach (var field in FlaggedEncapsulationFields) { + if (EncapsulateWithUDT && field is EncapsulatedUserDefinedTypeMember) + { + continue; + } textBlocks.Add(BuildPropertiesTextBlock(field.EncapsulationAttributes)); } return textBlocks; } } + public string EncapsulateInUDT_UDTMemberProperty(IEncapsulatedFieldDeclaration udtMember) + { + var parentField = _udtMemberTargetIDToParentMap[udtMember.TargetID]; + var generator = new PropertyGenerator + { + PropertyName = udtMember.PropertyName, + AsTypeName = udtMember.AsTypeName, + BackingField = $"{EncapsulateWithUDT_FieldName}.{parentField.PropertyName}.{udtMember.PropertyName}", + + ParameterName = udtMember.EncapsulationAttributes.ParameterName, + GenerateSetter = udtMember.EncapsulationAttributes.ImplementSetSetterType, + GenerateLetter = udtMember.EncapsulationAttributes.ImplementLetSetterType + }; + + var propertyTextLines = generator.AllPropertyCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None); + return string.Join(Environment.NewLine, _indenter.Indent(propertyTextLines, true)); + } + public string PreviewRefactoring() { return _previewFunc(this); @@ -94,7 +117,7 @@ public EncapsulateFieldNewContent LoadNewPropertiesContent(EncapsulateFieldNewCo newContent.AddCodeBlock($"{string.Join($"{Environment.NewLine}{Environment.NewLine}", PropertiesContent)}"); if (postScript?.Length > 0) { - newContent.AddCodeBlock(postScript); + newContent.AddCodeBlock($"{postScript}{Environment.NewLine}{Environment.NewLine}"); } return newContent; } @@ -112,7 +135,7 @@ public EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNew if (EncapsulateWithUDT) { - var udt = new UDTGenerator(EncapsulateWithUDT_TypeIdentifier, _indenter); + var udt = new UDTDeclarationGenerator(EncapsulateWithUDT_TypeIdentifier, _indenter); foreach (var nonUdtMemberField in nonUdtMemberFields) { udt.AddMember(nonUdtMemberField); @@ -120,7 +143,12 @@ public EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNew newContent.AddDeclarationBlock(udt.TypeDeclarationBlock); newContent.AddDeclarationBlock(udt.FieldDeclaration(EncapsulateWithUDT_FieldName)); - //TODO: handle selected UDTs + var udtMemberFields = FlaggedEncapsulationFields.Where(efd => efd.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)); + foreach ( var udtMember in udtMemberFields) + { + newContent.AddCodeBlock(EncapsulateInUDT_UDTMemberProperty(udtMember)); + } + return newContent; } @@ -144,6 +172,7 @@ public EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNew return newContent; } + private Dictionary _udtMemberTargetIDToParentMap { get; } = new Dictionary(); private void AddUDTEncapsulationFields(IDictionary)> udtFieldToTypeMap) { foreach (var udtField in udtFieldToTypeMap.Keys) @@ -157,6 +186,7 @@ private void AddUDTEncapsulationFields(IDictionary CreateUDTTuple(uv)) .ToDictionary(key => key.UDTVariable, element => (element.UserDefinedType, element.UDTMembers)); - var model = new EncapsulateFieldModel - (target, + Model = new EncapsulateFieldModel( + target, encapsulationCandidateFields, userDefinedTypeFieldToTypeDeclarationMap, _indenter, _validator, PreviewRewrite); - return model; + return Model; } + private IEnumerable FlaggedFields() => Model?.FlaggedEncapsulationFields ?? Enumerable.Empty(); + protected override void RefactorImpl(EncapsulateFieldModel model) { + Model = model; var rewriteSession = RefactorRewrite(model, RewritingManager.CheckOutCodePaneSession()); var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, _targetQMN); diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs index e9b90f61ef..e8a0df0278 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -1,7 +1,10 @@ -using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Refactorings.Common; using Rubberduck.VBEditor; +using Rubberduck.VBEditor.SafeComWrappers; using System; using System.Collections.Generic; using System.Linq; @@ -10,62 +13,186 @@ namespace Rubberduck.Refactorings.EncapsulateField { + //public interface IDeclarationFacade + //{ + // DeclarationType DeclarationType { get; } + // string IdentifierName { get;} + // string AsTypeName { get; } + // Accessibility Accessibility { get; } + // QualifiedModuleName QualifiedModuleName { get; } + // IEnumerable References { get; } + //} + + //public struct WrappedDeclaration : IDeclarationFacade + //{ + // public WrappedDeclaration(Declaration declaration) + // { + // DeclarationType = declaration.DeclarationType; + // IdentifierName = declaration.IdentifierName; + // Accessibility = declaration.Accessibility; + // References = declaration.References; + // AsTypeName = declaration.AsTypeName; + // QualifiedModuleName = declaration.QualifiedModuleName; + // } + + // public DeclarationType DeclarationType { set; get; } + // public string IdentifierName { set; get; } + // public string AsTypeName { set; get; } + // public Accessibility Accessibility { set; get; } + // public QualifiedModuleName QualifiedModuleName { set; get; } + // public IEnumerable References { set; get; } + //} + + //public struct ProposedDeclaration : IDeclarationFacade + //{ + + // public ProposedDeclaration(IEncapsulatedFieldDeclaration efd, DeclarationType declarationType) + // { + // DeclarationType = declarationType; + // IdentifierName = efd.PropertyName; + // Accessibility = Accessibility.Public; + // References = efd.References; + // if (declarationType.Equals(DeclarationType.Variable)) + // { + // IdentifierName = efd.NewFieldName; + // Accessibility = Accessibility.Private; + // References = Enumerable.Empty(); + // } + // AsTypeName = efd.AsTypeName; + // QualifiedModuleName = efd.QualifiedModuleName; + // } + + // public DeclarationType DeclarationType { set; get; } + // public string IdentifierName { set; get; } + // public string AsTypeName { set; get; } + // public Accessibility Accessibility { set; get; } + // public QualifiedModuleName QualifiedModuleName { set; get; } + // public IEnumerable References { set; get; } + //} + public interface IEncapsulateFieldNamesValidator { - bool HasValidEncapsulationAttributes(IEncapsulatedFieldDeclaration encapsulatedField); - bool HasValidEncapsulationAttributes(IEnumerable newMembers); - bool IsConflictingMemberName(string identifier, QualifiedModuleName qmn, DeclarationType declarationType); + bool HasValidEncapsulationAttributes(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, Predicate ignore); } public class EncapsulateFieldNamesValidator : IEncapsulateFieldNamesValidator { private readonly IDeclarationFinderProvider _declarationFinderProvider; - public EncapsulateFieldNamesValidator(IDeclarationFinderProvider declarationFinderProvider) + private Func> _selectedFieldsRetriever; + public EncapsulateFieldNamesValidator(IDeclarationFinderProvider declarationFinderProvider, Func> selectedFieldsRetriever = null) { _declarationFinderProvider = declarationFinderProvider; + _selectedFieldsRetriever = selectedFieldsRetriever; + } + + private DeclarationFinder DeclarationFinder => _declarationFinderProvider.DeclarationFinder; + + public bool HasValidEncapsulationAttributes(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, Predicate ignore) + { + var isSelfConsistent = HasValidIdentifiers(attributes) + && !HasInternalNameConflicts(attributes); + + if (!isSelfConsistent) { return false; } + + + if (!attributes.FieldNameIsExemptFromValidation) + { + if (HasNewFieldNameConflicts(attributes, qmn, ignore)) { return false; } + } + + if (HasNewPropertyNameConflicts(attributes, qmn, ignore)) { return false; } + + return true; } - public bool HasValidEncapsulationAttributes(IEncapsulatedFieldDeclaration encapsulatedField) + public bool HasNewPropertyNameConflicts(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, Predicate ignoreThisDeclaration) { - var internalChecks = HasValidIdentifiers(encapsulatedField) - && !HasInternalNameConflicts(encapsulatedField); + Predicate IsInSearchScope = null; + Predicate IsPrivateInOtherModule = (Declaration dec) => dec.QualifiedModuleName != qmn && dec.Accessibility.Equals(Accessibility.Private); + if (qmn.ComponentType == ComponentType.ClassModule) + { + IsInSearchScope = (Declaration dec) => dec.QualifiedModuleName == qmn; + } + else + { + IsInSearchScope = (Declaration dec) => dec.QualifiedModuleName.ProjectId == qmn.ProjectId; + } - var external = _declarationFinderProvider.DeclarationFinder - .FindNewDeclarationNameConflicts(encapsulatedField.NewFieldName, encapsulatedField.Declaration); + var identifierMatches = DeclarationFinder.MatchName(attributes.PropertyName) + .Where(match => IsInSearchScope(match) + && !ignoreThisDeclaration(match) + && !IsPrivateInOtherModule(match) + && !IsEnumOrUDTMemberDeclaration(match) + && !match.IsLocalVariable()).ToList(); - //if the collision is the target, then ignore - if (external.Count() == 1 && external.First() == encapsulatedField.Declaration) + var candidates = new List(); + var candidateMatches = new List(); + var fields = _selectedFieldsRetriever is null ? Enumerable.Empty() : _selectedFieldsRetriever(); + foreach (var efd in fields) { - return internalChecks; + var matches = candidates.Where(c => c.PropertyName.EqualsVBAIdentifier(efd.PropertyName)); + if (matches.Any()) + { + candidateMatches.Add(efd); + } + candidates.Add(efd); } - return internalChecks && !external.Any(); + + return identifierMatches.Any() || candidateMatches.Any(); + } + + //FieldNames are always Private, so only look within the same module as the field to encapsulate + public bool HasNewFieldNameConflicts(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, Predicate ignoreThisDeclaration) + { + var identifierMatches = DeclarationFinder.MatchName(attributes.NewFieldName) + .Where(match => match.QualifiedModuleName == qmn + && !ignoreThisDeclaration(match) + && !IsEnumOrUDTMemberDeclaration(match) + && !match.IsLocalVariable()).ToList(); + + var candidates = new List(); + var candidateMatches = new List(); + var fields = _selectedFieldsRetriever is null + ? Enumerable.Empty() + : _selectedFieldsRetriever(); + + foreach (var efd in fields) + { + var matches = candidates.Where(c => c.NewFieldName.EqualsVBAIdentifier(efd.NewFieldName)); + if (matches.Where(m => m.TargetID != efd.TargetID).Any()) + { + candidateMatches.Add(efd); + } + candidates.Add(efd); + } + + return identifierMatches.Any() || candidateMatches.Any(); } - public bool HasValidEncapsulationAttributes(IEnumerable newMembers) + private bool IsEnumOrUDTMemberDeclaration(Declaration candidate) { - return newMembers.Any(nm => !HasValidIdentifiers(nm)); + return candidate.DeclarationType == DeclarationType.EnumerationMember + || candidate.DeclarationType == DeclarationType.UserDefinedTypeMember; } - public bool IsConflictingMemberName(string memberName, QualifiedModuleName qmn, DeclarationType declarationType) + private bool UsesScopeResolution(Antlr4.Runtime.RuleContext ruleContext) { - var members = _declarationFinderProvider.DeclarationFinder.Members(qmn); - return members.Any(m => m.IdentifierName.Equals(memberName, StringComparison.CurrentCultureIgnoreCase)); + return (ruleContext is VBAParser.WithMemberAccessExprContext) + || (ruleContext is VBAParser.MemberAccessExprContext); } - private bool HasValidIdentifiers(IEncapsulatedFieldDeclaration encapsulatedField) + private bool HasValidIdentifiers(IFieldEncapsulationAttributes attributes) { - var attributes = encapsulatedField.EncapsulationAttributes; - return VBAIdentifierValidator.IsValidIdentifier(attributes.NewFieldName, encapsulatedField.Declaration.DeclarationType) - && VBAIdentifierValidator.IsValidIdentifier(attributes.PropertyName, encapsulatedField.Declaration.DeclarationType) - && VBAIdentifierValidator.IsValidIdentifier(attributes.ParameterName, encapsulatedField.Declaration.DeclarationType); + return VBAIdentifierValidator.IsValidIdentifier(attributes.NewFieldName, DeclarationType.Variable) + && VBAIdentifierValidator.IsValidIdentifier(attributes.PropertyName, DeclarationType.Property) + && VBAIdentifierValidator.IsValidIdentifier(attributes.ParameterName, DeclarationType.Parameter); } - private bool HasInternalNameConflicts(IEncapsulatedFieldDeclaration encapsulatedField) + private bool HasInternalNameConflicts(IFieldEncapsulationAttributes attributes) { - var attributes = encapsulatedField.EncapsulationAttributes; - return attributes.PropertyName.Equals(attributes.NewFieldName, StringComparison.InvariantCultureIgnoreCase) - || attributes.PropertyName.Equals(attributes.ParameterName, StringComparison.InvariantCultureIgnoreCase) - || attributes.NewFieldName.Equals(attributes.ParameterName, StringComparison.InvariantCultureIgnoreCase); + return attributes.PropertyName.EqualsVBAIdentifier(attributes.NewFieldName) + || attributes.PropertyName.EqualsVBAIdentifier(attributes.ParameterName) + || attributes.NewFieldName.EqualsVBAIdentifier(attributes.ParameterName); } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs index cd851d141c..8c57fe9805 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs @@ -1,5 +1,6 @@ using Rubberduck.Parsing.Symbols; using Rubberduck.Refactorings.Common; +using Rubberduck.VBEditor; using System; using System.Collections.Generic; using System.Linq; @@ -11,6 +12,7 @@ namespace Rubberduck.Refactorings.EncapsulateField public interface IEncapsulatedFieldDeclaration { Declaration Declaration { get; } + DeclarationType DeclarationType { get; } string TargetID { get; set; } IFieldEncapsulationAttributes EncapsulationAttributes { set; get; } bool IsReadOnly { set; get; } @@ -21,6 +23,8 @@ public interface IEncapsulatedFieldDeclaration string AsTypeName { get; } bool IsUDTMember { set; get; } bool HasValidEncapsulationAttributes { get; } + QualifiedModuleName QualifiedModuleName { get; } + IEnumerable References { get; } } public class EncapsulatedFieldDeclaration : IEncapsulatedFieldDeclaration @@ -35,45 +39,25 @@ public EncapsulatedFieldDeclaration(Declaration declaration, IEncapsulateFieldNa _attributes = new FieldEncapsulationAttributes(_decorated); _validator = validator; TargetID = declaration.IdentifierName; - SetNonConflictingEncapsulationIdentifiers(); - } - private void SetNonConflictingEncapsulationIdentifiers() - { - var isValid = _validator.HasValidEncapsulationAttributes(this); - if (!isValid) + + var isValidAttributeSet = _validator.HasValidEncapsulationAttributes(_attributes, declaration.QualifiedModuleName, (Declaration dec) => dec.Equals(_decorated)); + for (var idx = 2; idx < 9 && !isValidAttributeSet; idx++) { - var clientAttributes = ClientEditableAttributes(Declaration); - if (IsConflictingAttributes(clientAttributes)) - { - var hasConflict = true; - for (var idx = 2; idx < 9 && hasConflict; idx++) - { - clientAttributes.ModifyEncapsulationIdentifiers($"{Declaration.IdentifierName}{idx}"); - hasConflict = IsConflictingAttributes(clientAttributes); - } - PropertyName = clientAttributes.PropertyName; - } + _attributes.NewFieldName = $"{declaration.IdentifierName}{idx}"; + isValidAttributeSet = _validator.HasValidEncapsulationAttributes(_attributes, declaration.QualifiedModuleName, (Declaration dec) => dec.Equals(_decorated)); } } - private IFieldEncapsulationAttributes ClientEditableAttributes(Declaration declaration) - => new FieldEncapsulationAttributes(declaration); - - private bool IsConflictingAttributes(IFieldEncapsulationAttributes attributes) - { - var isConflictingFieldName = _validator.IsConflictingMemberName(attributes.NewFieldName, Declaration.QualifiedModuleName, Declaration.DeclarationType); - var isConflictingPropertyName = _validator.IsConflictingMemberName(attributes.PropertyName, Declaration.QualifiedModuleName, DeclarationType.Member); - return isConflictingFieldName || isConflictingPropertyName; - } - public Declaration Declaration => _decorated; + public DeclarationType DeclarationType => _decorated.DeclarationType; + public bool HasValidEncapsulationAttributes { get { - return _validator.HasValidEncapsulationAttributes(this); + return _validator.HasValidEncapsulationAttributes(EncapsulationAttributes, QualifiedModuleName, (Declaration dec) => dec.Equals(_decorated)); } } @@ -115,5 +99,9 @@ public string NewFieldName public string AsTypeName => _decorated.AsTypeName; public bool IsUDTMember { set; get; } = false; + + public QualifiedModuleName QualifiedModuleName => Declaration.QualifiedModuleName; + + public IEnumerable References => Declaration.References; } } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs index 2c3324a766..5a4b70c8f8 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs @@ -10,13 +10,13 @@ public interface IFieldEncapsulationAttributes string PropertyName { get; set; } bool ReadOnly { get; set; } bool EncapsulateFlag { get; set; } - void ModifyEncapsulationIdentifiers(string fieldName); - string NewFieldName { get; } + string NewFieldName { set; get; } string FieldReferenceExpression { get; } string AsTypeName { get; set; } string ParameterName { get;} bool ImplementLetSetterType { get; set; } bool ImplementSetSetterType { get; set; } + bool FieldNameIsExemptFromValidation { get; } } public class FieldEncapsulationAttributes : IFieldEncapsulationAttributes @@ -32,11 +32,6 @@ public FieldEncapsulationAttributes(Declaration target) private EncapsulationIdentifiers _fieldAndProperty; - public void ModifyEncapsulationIdentifiers(string newFieldName) - { - _fieldAndProperty = new EncapsulationIdentifiers(newFieldName); - } - public string TargetName { private set; get; } public string NewFieldName @@ -66,5 +61,6 @@ public string PropertyName private bool _implSet; public bool ImplementSetSetterType { get => !ReadOnly && _implSet; set => _implSet = value; } + public bool FieldNameIsExemptFromValidation => NewFieldName.EqualsVBAIdentifier(TargetName); } } diff --git a/Rubberduck.Refactorings/EncapsulateField/UDTGenerator.cs b/Rubberduck.Refactorings/EncapsulateField/UDTDeclarationGenerator.cs similarity index 85% rename from Rubberduck.Refactorings/EncapsulateField/UDTGenerator.cs rename to Rubberduck.Refactorings/EncapsulateField/UDTDeclarationGenerator.cs index 86cc690480..2a0ce7846a 100644 --- a/Rubberduck.Refactorings/EncapsulateField/UDTGenerator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/UDTDeclarationGenerator.cs @@ -9,20 +9,20 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public class UDTGenerator + public class UDTDeclarationGenerator { private readonly string _typeIdentifier = "This_Type"; private readonly IIndenter _indenter; private List _members; - public UDTGenerator(string typeIdentifier, IIndenter indenter) + public UDTDeclarationGenerator(string typeIdentifier, IIndenter indenter) :this(indenter) { _typeIdentifier = typeIdentifier; } - public UDTGenerator(IIndenter indenter) + public UDTDeclarationGenerator(IIndenter indenter) { _indenter = indenter; _members = new List(); @@ -47,7 +47,7 @@ public string TypeDeclarationBlock foreach (var member in _members) { - var declaration = $"{member.PropertyName.Capitalize()} As {member.AsTypeName}"; + var declaration = $"{member.PropertyName} As {member.AsTypeName}"; members.Add(declaration); } diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateAsUDTTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateAsUDTTests.cs new file mode 100644 index 0000000000..bcfd56e208 --- /dev/null +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateAsUDTTests.cs @@ -0,0 +1,71 @@ +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RubberduckTests.Refactoring.EncapsulateField +{ + [TestFixture] + public class EncapsulateAsUDTTests + { + private EncapsulateFieldTestSupport Support { get; } = new EncapsulateFieldTestSupport(); + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedType_MultipleFields_ToNewUDT() + { + string inputCode = +$@" +Public fo|o As Long +Public bar As String +Public foobar As Byte +"; + + var userInput = new UserInputDataObject("foo", encapsulationFlag: true); + userInput.AddAttributeSet("bar", encapsulationFlag: true); + userInput.AddAttributeSet("foobar", encapsulationFlag: true); + userInput.EncapsulateAsUDT = true; + + var presenterAction = Support.SetParameters(userInput); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.Contains("Private this As This_Type", actualCode); + StringAssert.Contains("Private Type This_Type", actualCode); + StringAssert.Contains("Foo As Long", actualCode); + StringAssert.Contains("Bar As String", actualCode); + StringAssert.Contains("Foobar As Byte", actualCode); + } + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedType_MultipleFieldsWithUDT_ToNewUDT() + { + string inputCode = +$@" + +Private Type TBar + First As Long + Second As String +End Type + +Public fo|o As Long +Public myBar As TBar +"; + + var userInput = new UserInputDataObject("foo", encapsulationFlag: true); + userInput.AddAttributeSet("myBar", encapsulationFlag: true); + userInput.AddUDTMemberNameFlagPairs(("myBar", "First", true), ("myBar", "Second", true)); + userInput.EncapsulateAsUDT = true; + + var presenterAction = Support.SetParameters(userInput); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.Contains("this.MyBar.First = value", actualCode); + StringAssert.Contains("First = this.MyBar.First", actualCode); + StringAssert.Contains("this.MyBar.Second = value", actualCode); + StringAssert.Contains("Second = this.MyBar.Second", actualCode); + } + } +} diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs new file mode 100644 index 0000000000..66b35953fc --- /dev/null +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs @@ -0,0 +1,129 @@ +using NUnit.Framework; +using Moq; +using Rubberduck.Refactorings.EncapsulateField; +using RubberduckTests.Mocks; +using Rubberduck.SmartIndenter; +using Rubberduck.VBEditor.SafeComWrappers.Abstract; +using System.Linq; +using System.Collections.Generic; +using Rubberduck.VBEditor; +using Rubberduck.Refactorings; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.VBA; +using Rubberduck.VBEditor.Utility; +using Rubberduck.Parsing.Symbols; + +namespace RubberduckTests.Refactoring.EncapsulateField +{ + [TestFixture] + public class EncapsulateFieldValidatorTests + { + //private EncapsulateFieldTestSupport Support { get; } = new EncapsulateFieldTestSupport(); + + [TestCase("Number")] + [TestCase("Test")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulateMultipleFields_PropertyNameConflicts(string modifiedPropertyName) + { + string inputCode = +$@"Public fizz As Integer +Public bazz As Integer +Public buzz As Integer +Private mTest As Integer + +Public Property Get Test() As Integer + Test = mTest +End Property"; + + var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; + var selectedComponentName = vbe.SelectedVBComponent.Name; + + var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); + using (state) + { + var mockFizz = CreateEncapsulatedFieldMock("fizz", "Integer", vbe.SelectedVBComponent, modifiedPropertyName); + var mockBazz = CreateEncapsulatedFieldMock("bazz", "Integer", vbe.SelectedVBComponent, "Whole"); + var mockBuzz = CreateEncapsulatedFieldMock("buzz", "Integer", vbe.SelectedVBComponent, modifiedPropertyName); + + var validator = new EncapsulateFieldNamesValidator( + state, + () => new List() + { + mockFizz, + mockBazz, + mockBuzz + }); + + Assert.IsTrue(validator.HasNewPropertyNameConflicts(mockFizz.EncapsulationAttributes, mockFizz.QualifiedModuleName, (Declaration dec) => false)); + } + } + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulateMultipleFields_UDTConflicts() + { + string inputCode = +$@" +Private Type TBar + First As Long + Second As String +End Type + +Public this As TBar + +Public that As TBar +"; + + var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; + var selectedComponentName = vbe.SelectedVBComponent.Name; + + var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); + using (state) + { + var thisField = CreateEncapsulatedFieldMock("this.First", "Long", vbe.SelectedVBComponent, "First"); + var thatField = CreateEncapsulatedFieldMock("that.First", "String", vbe.SelectedVBComponent, "First"); + + var validator = new EncapsulateFieldNamesValidator( + state, + () => new List() + { + thisField, + thatField, + }); + + + Assert.IsTrue(validator.HasNewPropertyNameConflicts(thisField.EncapsulationAttributes, thisField.QualifiedModuleName, (Declaration dec) => false)); + } + } + + private IEncapsulatedFieldDeclaration CreateEncapsulatedFieldMock(string targetID, string asTypeName, IVBComponent component, string modifiedPropertyName = null, bool encapsulateFlag = true ) + { + var identifiers = new EncapsulationIdentifiers(targetID); + var attributesMock = CreateAttributesMock(targetID, asTypeName, modifiedPropertyName); + + var mock = new Mock(); + mock.SetupGet(m => m.TargetID).Returns(identifiers.TargetFieldName); + mock.SetupGet(m => m.NewFieldName).Returns(identifiers.Field); + mock.SetupGet(m => m.PropertyName).Returns(modifiedPropertyName ?? identifiers.Property); + mock.SetupGet(m => m.AsTypeName).Returns(asTypeName); + mock.SetupGet(m => m.EncapsulateFlag).Returns(encapsulateFlag); + mock.SetupGet(m => m.EncapsulationAttributes).Returns(attributesMock); + mock.SetupGet(m => m.QualifiedModuleName).Returns(new QualifiedModuleName(component)); + return mock.Object; + } + + private IFieldEncapsulationAttributes CreateAttributesMock(string targetID, string asTypeName, string modifiedPropertyName = null, bool encapsulateFlag = true) + { + var identifiers = new EncapsulationIdentifiers(targetID); + var mock = new Mock(); + mock.SetupGet(m => m.TargetName).Returns(identifiers.TargetFieldName); + mock.SetupGet(m => m.NewFieldName).Returns(identifiers.Field); + mock.SetupGet(m => m.PropertyName).Returns(modifiedPropertyName ?? identifiers.Property); + mock.SetupGet(m => m.AsTypeName).Returns(asTypeName); + mock.SetupGet(m => m.EncapsulateFlag).Returns(encapsulateFlag); + return mock.Object; + } + } +} diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs index 1542dc976d..dcc67356a5 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs @@ -1,19 +1,9 @@ -using System; -using NUnit.Framework; +using NUnit.Framework; using Moq; -using Rubberduck.Parsing.Rewriter; -using Rubberduck.Parsing.Symbols; -using Rubberduck.Refactorings; using Rubberduck.Refactorings.EncapsulateField; -using Rubberduck.VBEditor; using RubberduckTests.Mocks; using Rubberduck.SmartIndenter; -using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; -using Rubberduck.Parsing.VBA; -using Rubberduck.Refactorings.Exceptions; -using Rubberduck.VBEditor.Utility; -using System.Collections.Generic; using System.Linq; namespace RubberduckTests.Refactoring.EncapsulateField @@ -132,7 +122,7 @@ public void CreateUDT() mock.SetupGet(m => m.AsTypeName).Returns("String"); mock.SetupGet(m => m.PropertyName).Returns("Fizz"); - var newUserDefinedType = new UDTGenerator(CreateIndenter()); + var newUserDefinedType = new UDTDeclarationGenerator(CreateIndenter()); newUserDefinedType.AddMember(mock.Object); var result = newUserDefinedType.TypeDeclarationBlock; @@ -150,10 +140,6 @@ private IEncapsulatedFieldDeclaration RetrieveEncapsulatedField(string inputCode var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); using (state) { - var module = state.DeclarationFinder.UserDeclarations(DeclarationType.Module) - .Single(declaration => declaration.IdentifierName == selectedComponentName) - .QualifiedModuleName; - var match = state.DeclarationFinder.MatchName(fieldName).Single(); return new EncapsulatedFieldDeclaration(match, new EncapsulateFieldNamesValidator(state)) as IEncapsulatedFieldDeclaration; } diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs new file mode 100644 index 0000000000..b6b255b270 --- /dev/null +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -0,0 +1,152 @@ +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.VBA; +using Rubberduck.Refactorings; +using Rubberduck.Refactorings.EncapsulateField; +using Rubberduck.SmartIndenter; +using Rubberduck.VBEditor; +using Rubberduck.VBEditor.SafeComWrappers.Abstract; +using Rubberduck.VBEditor.Utility; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RubberduckTests.Refactoring.EncapsulateField +{ + public class EncapsulateFieldTestSupport : InteractiveRefactoringTestBase + { + private TestEncapsulationAttributes UserModifiedEncapsulationAttributes(string field, string property = null, bool? isReadonly = null, bool encapsulateFlag = true) + { + var testAttrs = new TestEncapsulationAttributes(field, encapsulateFlag, isReadonly ?? false); + if (property != null) + { + testAttrs.PropertyName = property; + } + return testAttrs; + } + + public Func UserAcceptsDefaults(bool asUDT = false) + { + return model => { model.EncapsulateWithUDT = asUDT; return model; }; + } + + public Func SetParametersForSingleTarget(string field, string property = null, bool? isReadonly = null, bool encapsulateFlag = true, bool asUDT = false) + { + var clientAttrs = UserModifiedEncapsulationAttributes(field, property, isReadonly, encapsulateFlag); + + return SetParameters(field, clientAttrs, asUDT); + } + + public Func SetParameters(UserInputDataObject userModifications) + { + return model => + { + model.EncapsulateWithUDT = userModifications.EncapsulateAsUDT; + foreach (var testModifiedAttribute in userModifications.EncapsulateFieldAttributes) + { + var attrsInitializedByTheRefactoring = model[testModifiedAttribute.TargetFieldName].EncapsulationAttributes; + + attrsInitializedByTheRefactoring.PropertyName = testModifiedAttribute.PropertyName; + attrsInitializedByTheRefactoring.EncapsulateFlag = testModifiedAttribute.EncapsulateFlag; + + var currentAttributes = model[testModifiedAttribute.TargetFieldName].EncapsulationAttributes; + currentAttributes.PropertyName = attrsInitializedByTheRefactoring.PropertyName; + currentAttributes.EncapsulateFlag = attrsInitializedByTheRefactoring.EncapsulateFlag; + + foreach ((string instanceVariable, string memberName, bool flag) in userModifications.UDTMemberNameFlagPairs) + { + model[$"{instanceVariable}.{memberName}"].EncapsulateFlag = flag; + } + } + return model; + }; + } + + public Func SetParameters(string originalField, TestEncapsulationAttributes attrs, bool asUDT = false) + { + return model => + { + var encapsulatedField = model[originalField]; + encapsulatedField.EncapsulationAttributes.PropertyName = attrs.PropertyName; + encapsulatedField.EncapsulationAttributes.ReadOnly = attrs.IsReadOnly; + encapsulatedField.EncapsulationAttributes.EncapsulateFlag = attrs.EncapsulateFlag; + + model.EncapsulateWithUDT = asUDT; + return model; + }; + } + + public string RefactoredCode(CodeString codeString, Func presenterAdjustment, Type expectedException = null, bool executeViaActiveSelection = false) + => RefactoredCode(codeString.Code, codeString.CaretPosition.ToOneBased(), presenterAdjustment, expectedException, executeViaActiveSelection); + + public static IIndenter CreateIndenter(IVBE vbe = null) + { + return new Indenter(vbe, () => Settings.IndenterSettingsTests.GetMockIndenterSettings()); + } + + protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) + { + var indenter = CreateIndenter(); //The refactoring only uses method independent of the VBE instance. + var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); + return new EncapsulateFieldRefactoring(state, indenter, factory, rewritingManager, selectionService, selectedDeclarationProvider); + } + } + + public class TestEncapsulationAttributes + { + public TestEncapsulationAttributes(string fieldName, bool encapsulationFlag = true, bool isReadOnly = false) + { + _identifiers = new EncapsulationIdentifiers(fieldName); + EncapsulateFlag = encapsulationFlag; + IsReadOnly = isReadOnly; + } + + private EncapsulationIdentifiers _identifiers; + public string TargetFieldName => _identifiers.TargetFieldName; + + public string NewFieldName + { + get => _identifiers.Field; + set => _identifiers.Field = value; + } + public string PropertyName + { + get => _identifiers.Property; + set => _identifiers.Property = value; + } + public bool EncapsulateFlag { get; set; } + public bool IsReadOnly { get; set; } + } + + public class UserInputDataObject + { + private List _userInput = new List(); + private List<(string, string, bool)> _udtNameFlagPairs = new List<(string, string, bool)>(); + + public UserInputDataObject(string fieldName, string propertyName = null, bool encapsulationFlag = true, bool isReadOnly = false) + => AddAttributeSet(fieldName, propertyName, encapsulationFlag, isReadOnly); + + public void AddAttributeSet(string fieldName, string propertyName = null, bool encapsulationFlag = true, bool isReadOnly = false) + { + var attrs = new TestEncapsulationAttributes(fieldName, encapsulationFlag, isReadOnly); + attrs.PropertyName = propertyName ?? attrs.PropertyName; + + _userInput.Add(attrs); + } + + public bool EncapsulateAsUDT { set; get; } + + public TestEncapsulationAttributes this[string fieldName] + => EncapsulateFieldAttributes.Where(efa => efa.TargetFieldName == fieldName).Single(); + + + public IEnumerable EncapsulateFieldAttributes => _userInput; + + public void AddUDTMemberNameFlagPairs(params (string, string, bool)[] nameFlagPairs) + => _udtNameFlagPairs.AddRange(nameFlagPairs); + + public IEnumerable<(string, string, bool)> UDTMemberNameFlagPairs => _udtNameFlagPairs; + } + +} diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index 7ecbbc317b..74618eab2a 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -15,12 +15,16 @@ using Rubberduck.VBEditor.Utility; using System.Collections.Generic; using System.Linq; +using Rubberduck.Parsing.Grammar; -namespace RubberduckTests.Refactoring +namespace RubberduckTests.Refactoring.EncapsulateField { + [TestFixture] public class EncapsulateFieldTests : InteractiveRefactoringTestBase { + private EncapsulateFieldTestSupport Support { get; } = new EncapsulateFieldTestSupport(); + [TestCase("fizz", true, "baz", true, "buzz", true)] [TestCase("fizz", false, "baz", true, "buzz", true)] [TestCase("fizz", false, "baz", false, "buzz", true)] @@ -49,7 +53,7 @@ public void EncapsulateMultipleFields( [var3] = var3Flag }; - var presenterAction = SetParameters(userInput); + var presenterAction = Support.SetParameters(userInput); var actualCode = RefactoredCode(inputCode, selection, presenterAction); @@ -108,7 +112,7 @@ public void EncapsulateMultipleFieldsInList( [var4] = var4Flag }; - var presenterAction = SetParameters(userInput); + var presenterAction = Support.SetParameters(userInput); var actualCode = RefactoredCode(inputCode, selection, presenterAction); @@ -134,6 +138,32 @@ public void EncapsulateMultipleFieldsInList( } } +// [Test] +// [Category("Refactorings")] +// [Category("Encapsulate Field")] +// public void UserDefinedType_MultipleFieldsToNewUDT() +// { +// string inputCode = +//$@" +//Public fo|o As Long +//Public bar As String +//Public foobar As Byte +//"; + +// var userInput = new UserInputDataObject("foo", encapsulationFlag: true); +// userInput.AddAttributeSet("bar", encapsulationFlag: true); +// userInput.AddAttributeSet("foobar", encapsulationFlag: true); +// userInput.EncapsulateAsUDT = true; + +// var presenterAction = Support.SetParameters(userInput); +// var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); +// StringAssert.Contains("Private this As This_Type", actualCode); +// StringAssert.Contains("Private Type This_Type", actualCode); +// StringAssert.Contains("Foo As Long", actualCode); +// StringAssert.Contains("Bar As String", actualCode); +// StringAssert.Contains("Foobar As Byte", actualCode); +// } + [TestCase("Public")] [TestCase("Private")] [Category("Refactorings")] @@ -150,14 +180,55 @@ End Type {accessibility} th|is As TBar"; - var presenterAction = UserAcceptsDefaults(); - var actualCode = RefactoredCode(inputCode.ToCodeString(), presenterAction); + var presenterAction = Support.UserAcceptsDefaults(); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.Contains("Private this1 As TBar", actualCode); StringAssert.Contains("this1 = value", actualCode); StringAssert.Contains($"This = this1", actualCode); StringAssert.DoesNotContain($"this1.First1 = value", actualCode); } + + [TestCase("Public")] + [TestCase("Private")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedType_UserAcceptsDefaults_ToUDTInstances(string accessibility) + { + string selectionModule = "ClassInput"; + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +{accessibility} th|is As TBar + +Private that As TBar"; + + string otherModule = "OtherModule"; + string moduleCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +{accessibility} this As TBar + +Private that As TBar"; + + + var presenterAdjustment = Support.UserAcceptsDefaults(); + var codeString = inputCode.ToCodeString(); + var actualCode = RefactoredCode(selectionModule, codeString.CaretPosition.ToOneBased(), presenterAdjustment, null, false, (selectionModule, codeString.Code, ComponentType.ClassModule), (otherModule, moduleCode, ComponentType.StandardModule) ); + StringAssert.Contains("Private this1 As TBar", actualCode[selectionModule]); + StringAssert.Contains("this1 = value", actualCode[selectionModule]); + StringAssert.Contains($"This = this1", actualCode[selectionModule]); + StringAssert.DoesNotContain($"this1.First1 = value", actualCode[selectionModule]); + } + [TestCase("Public", true, true)] [TestCase("Private", true, true)] [TestCase("Public", false, false)] @@ -190,8 +261,8 @@ End Type var expectedThis = new EncapsulationIdentifiers("this") { Property = "MyType"}; var expectedThat = new EncapsulationIdentifiers("that") { Property = "MyOtherType"}; - var presenterAction = SetParameters(userInput); - var actualCode = RefactoredCode(inputCode.ToCodeString(), presenterAction); + var presenterAction = Support.SetParameters(userInput); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); if (encapsulateThis) { StringAssert.Contains($"Private {expectedThis.Field} As TBar", actualCode); @@ -249,9 +320,9 @@ End Type var userInput = new UserInputDataObject("this", "MyType", true); userInput.AddUDTMemberNameFlagPairs(("this", memberToEncapsulate, true)); - var presenterAction = SetParameters(userInput); + var presenterAction = Support.SetParameters(userInput); - var actualCode = RefactoredCode(inputCode.ToCodeString(), presenterAction); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.Contains($"this.{memberToEncapsulate} = value", actualCode); StringAssert.Contains($"{memberToEncapsulate} = this.{memberToEncapsulate}", actualCode); } @@ -276,9 +347,9 @@ End Type userInput.AddUDTMemberNameFlagPairs(("this", "First", true)); userInput.AddUDTMemberNameFlagPairs(("this", "Second", true)); - var presenterAction = SetParameters(userInput); + var presenterAction = Support.SetParameters(userInput); - var actualCode = RefactoredCode(inputCode.ToCodeString(), presenterAction); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.Contains("this.First = value", actualCode); StringAssert.Contains($"First = this.First", actualCode); StringAssert.Contains("this.Second = value", actualCode); @@ -311,9 +382,9 @@ Private mFizz userInput.AddAttributeSet("mBar", "Bar", true); userInput.AddAttributeSet("mFizz", "Fizz", true); - var presenterAction = SetParameters(userInput); + var presenterAction = Support.SetParameters(userInput); - var actualCode = RefactoredCode(inputCode.ToCodeString(), presenterAction); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.Contains("Private this As TBar", actualCode); StringAssert.Contains("this = value", actualCode); @@ -361,7 +432,7 @@ End Sub userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true)); - var presenterAction = SetParameters(userInput); + var presenterAction = Support.SetParameters(userInput); var codeString = inputCode.ToCodeString(); var actualModuleCode = RefactoredCode( @@ -405,9 +476,9 @@ End Type var userInput = new UserInputDataObject("this", "MyType", true); userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true)); - var presenterAction = SetParameters(userInput); + var presenterAction = Support.SetParameters(userInput); - var actualCode = RefactoredCode(inputCode.ToCodeString(), presenterAction); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.Contains("Private this As TBar", actualCode); StringAssert.Contains("this = value", actualCode); StringAssert.Contains("MyType = this", actualCode); @@ -439,9 +510,9 @@ End Type var userInput = new UserInputDataObject("this", "MyType", false); userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true), ("this", "Third", true)); - var presenterAction = SetParameters(userInput); + var presenterAction = Support.SetParameters(userInput); - var actualCode = RefactoredCode(inputCode.ToCodeString(), presenterAction); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.Contains($"{accessibility} this As TBar", actualCode); StringAssert.DoesNotContain("this = value", actualCode); StringAssert.DoesNotContain($"this.First = value", actualCode); @@ -472,9 +543,9 @@ End Type var userInput = new UserInputDataObject("this", "MyType", false); userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true)); - var presenterAction = SetParameters(userInput); + var presenterAction = Support.SetParameters(userInput); - var actualCode = RefactoredCode(inputCode.ToCodeString(), presenterAction); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.Contains($"{expectedAccessibility} this As TBar", actualCode); StringAssert.DoesNotContain("this = value", actualCode); StringAssert.DoesNotContain("MyType = this", actualCode); @@ -508,7 +579,7 @@ End Type var userInput = new UserInputDataObject("this", "MyType", true); userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true)); - var presenterAction = SetParameters(userInput); + var presenterAction = Support.SetParameters(userInput); var codeString = inputCode.ToCodeString(); var actualModuleCode = RefactoredCode( @@ -555,7 +626,7 @@ Private Sub Class_Initialize() End Sub "; - var presenterAction = UserAcceptsDefaults(); + var presenterAction = Support.UserAcceptsDefaults(); var codeString = inputCode.ToCodeString(); var actualModuleCode = RefactoredCode( @@ -585,7 +656,7 @@ public void EncapsulatePublicField_InvalidDeclarationType_Throws() const string inputCode = @"Public fizz As Integer"; - var presenterAction = SetParametersForSingleTarget("fizz", "Name"); + var presenterAction = Support.SetParametersForSingleTarget("fizz", "Name"); var actualCode = RefactoredCode(inputCode, "TestModule1", DeclarationType.ProceduralModule, presenterAction, typeof(InvalidDeclarationTypeException)); Assert.AreEqual(inputCode, actualCode); } @@ -599,7 +670,7 @@ public void EncapsulatePublicField_InvalidIdentifierSelected_Throws() @"Public Function fiz|z() As Integer End Function"; - var presenterAction = SetParametersForSingleTarget("fizz", "Name"); + var presenterAction = Support.SetParametersForSingleTarget("fizz", "Name"); var codeString = inputCode.ToCodeString(); var actualCode = RefactoredCode(codeString.Code, codeString.CaretPosition.ToOneBased(), presenterAction, typeof(NoDeclarationForSelectionException)); @@ -630,8 +701,8 @@ Public Property Let Name(ByVal value As Integer) fizz = value End Property "; - var presenterAction = SetParametersForSingleTarget("fizz", "Name"); - var actualCode = RefactoredCode(inputCode.ToCodeString(), presenterAction); + var presenterAction = Support.SetParametersForSingleTarget("fizz", "Name"); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); Assert.AreEqual(expectedCode, actualCode); } @@ -651,8 +722,8 @@ Public Property Get Name() As Integer Name = fizz End Property "; - var presenterAction = SetParametersForSingleTarget("fizz", "Name", isReadonly: true); - var actualCode = RefactoredCode(inputCode.ToCodeString(), presenterAction); + var presenterAction = Support.SetParametersForSingleTarget("fizz", "Name", isReadonly: true); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); Assert.AreEqual(expectedCode, actualCode); } @@ -671,9 +742,9 @@ Function Bar() As Integer Bar = 0 End Function"; - var presenterAction = SetParametersForSingleTarget("fizz", "Name"); + var presenterAction = Support.SetParametersForSingleTarget("fizz", "Name"); - var actualCode = RefactoredCode(inputCode.ToCodeString(), presenterAction); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); Assert.Greater(actualCode.IndexOf("Sub Foo"), actualCode.LastIndexOf("End Property")); } @@ -695,9 +766,9 @@ End Property Property Set Foo(ByVal vall As Variant) End Property"; - var presenterAction = SetParametersForSingleTarget("fizz", "Name"); + var presenterAction = Support.SetParametersForSingleTarget("fizz", "Name"); - var actualCode = RefactoredCode(inputCode.ToCodeString(), presenterAction); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); Assert.Greater(actualCode.IndexOf("fizz = value"), actualCode.IndexOf("fizz As Integer")); Assert.Less(actualCode.IndexOf("fizz = value"), actualCode.IndexOf("Get Foo")); } @@ -721,8 +792,8 @@ Public Property Let Name(ByVal value As Integer) fizz = value End Property "; - var presenterAction = SetParametersForSingleTarget("fizz", "Name"); - var actualCode = RefactoredCode(inputCode.ToCodeString(), presenterAction); + var presenterAction = Support.SetParametersForSingleTarget("fizz", "Name"); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); Assert.AreEqual(expectedCode, actualCode); } @@ -739,7 +810,7 @@ public void EncapsulatePublicField_SelectedWithinDeclarationList(int rowSelectio bazz As Date"; var selection = new Selection(rowSelection, columnSelection); - var presenterAction = SetParametersForSingleTarget(fieldName, "Name"); + var presenterAction = Support.SetParametersForSingleTarget(fieldName, "Name"); var actualCode = RefactoredCode(inputCode, selection, presenterAction); StringAssert.Contains(contains1, actualCode); StringAssert.Contains(contains1, actualCode); @@ -768,11 +839,48 @@ Public Property Let Name(ByVal value As Integer) fizz = value End Property "; - var presenterAction = SetParametersForSingleTarget("fizz", "Name"); - var actualCode = RefactoredCode(inputCode.ToCodeString(), presenterAction); + var presenterAction = Support.SetParametersForSingleTarget("fizz", "Name"); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); Assert.AreEqual(expectedCode, actualCode); } + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulatePrivateField_NameConflict() + { + const string inputCode = + @"Private fizz As String +Private mName As String + +Public Property Get Name() As String + Name = mName +End Property + +Public Property Let Name(ByVal value As String) + mName = value +End Property +"; + var fieldName = "fizz"; + var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; + + var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); + using (state) + { + IEncapsulatedFieldDeclaration efd = null; + var fields = new List(); + var validator = new EncapsulateFieldNamesValidator(state, () => fields); + + var match = state.DeclarationFinder.MatchName(fieldName).Single(); + efd = new EncapsulatedFieldDeclaration(match, validator); + fields.Add(efd); + efd.PropertyName = "Name"; + + var hasConflict = !validator.HasValidEncapsulationAttributes(efd.EncapsulationAttributes, efd.QualifiedModuleName, (Declaration dec) => match.Equals(dec)); + Assert.IsTrue(hasConflict); + } + } + [Test] [Category("Refactorings")] [Category("Encapsulate Field")] @@ -781,8 +889,8 @@ public void EncapsulatePrivateFieldAsUDT() const string inputCode = @"|Private fizz As Integer"; - var presenterAction = SetParametersForSingleTarget("fizz", "Name", asUDT: true); - var actualCode = RefactoredCode(inputCode.ToCodeString(), presenterAction); + var presenterAction = Support.SetParametersForSingleTarget("fizz", "Name", asUDT: true); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.Contains("Name As Integer", actualCode); StringAssert.Contains("this.Name = value", actualCode); } @@ -806,8 +914,8 @@ Public Property Let Fizz(ByVal value As Integer) fizz1 = value End Property "; - var presenterAction = UserAcceptsDefaults(); - var actualCode = RefactoredCode(inputCode.ToCodeString(), presenterAction); + var presenterAction = Support.UserAcceptsDefaults(); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); Assert.AreEqual(expectedCode, actualCode); } @@ -819,8 +927,8 @@ public void EncapsulatePrivateField_DefaultsAsUDT() const string inputCode = @"|Private fizz As Integer"; - var presenterAction = UserAcceptsDefaults(asUDT: true); - var actualCode = RefactoredCode(inputCode.ToCodeString(), presenterAction); + var presenterAction = Support.UserAcceptsDefaults(asUDT: true); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.Contains("Fizz As Integer", actualCode); StringAssert.Contains("this As This_Type", actualCode); StringAssert.Contains("this.Fizz = value", actualCode); @@ -842,11 +950,11 @@ End Sub Sub Bar(ByVal name As Integer) End Sub"; - var presenterAction = SetParametersForSingleTarget("fizz", "Name"); + var presenterAction = Support.SetParametersForSingleTarget("fizz", "Name"); var enapsulationIdentifiers = new EncapsulationIdentifiers("fizz") { Property = "Name" }; - var actualCode = RefactoredCode(inputCode.ToCodeString(), presenterAction); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.AreEqualIgnoringCase(enapsulationIdentifiers.Field, "fizz"); StringAssert.Contains($"Private {enapsulationIdentifiers.Field} As Integer", actualCode); StringAssert.Contains("Property Get Name", actualCode); @@ -876,7 +984,7 @@ End Sub Sub Bar(ByVal v As Integer) End Sub"; - var presenterAction = SetParametersForSingleTarget("fizz", "Name", true); + var presenterAction = Support.SetParametersForSingleTarget("fizz", "Name", true); var class1CodeString = codeClass1.ToCodeString(); var actualCode = RefactoredCode( @@ -932,7 +1040,7 @@ public void EncapsulateField_ModelIsNull() Func presenterAction = model => null; var codeString = inputCode.ToCodeString(); - var actualCode = RefactoredCode(codeString, presenterAction, typeof(InvalidRefactoringModelException)); + var actualCode = Support.RefactoredCode(codeString, presenterAction, typeof(InvalidRefactoringModelException)); Assert.AreEqual(codeString.Code, actualCode); } @@ -959,7 +1067,7 @@ Public Property Let Name(ByVal value As String) foo = value End Property "; - var presenterAction = SetParametersForSingleTarget("foo", "Name"); + var presenterAction = Support.SetParametersForSingleTarget("foo", "Name"); var actualCode = RefactoredCode(inputCode, "foo", DeclarationType.Variable, presenterAction); Assert.AreEqual(expectedCode, actualCode); } @@ -987,8 +1095,8 @@ Public Property Let bar(ByVal value As String) Foo = value End Property "; - var presenterAction = SetParametersForSingleTarget("Foo", "bar"); - var actualCode = RefactoredCode(inputCode.ToCodeString(), presenterAction); + var presenterAction = Support.SetParametersForSingleTarget("Foo", "bar"); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); Assert.AreEqual(expectedCode, actualCode); } @@ -1024,7 +1132,7 @@ End Property "; var userInput = new UserInputDataObject("mArray", "MyArray", true); - var presenterAction = SetParameters(userInput); + var presenterAction = Support.SetParameters(userInput); var actualCode = RefactoredCode(inputCode, selection, presenterAction); Assert.AreEqual(expectedCode, actualCode); } @@ -1053,7 +1161,7 @@ Public Property Get MyArray() As Variant MyArray = mArray End Property "; - var presenterAction = SetParametersForSingleTarget("mArray", "MyArray"); + var presenterAction = Support.SetParametersForSingleTarget("mArray", "MyArray"); var actualCode = RefactoredCode(inputCode, selection, presenterAction); StringAssert.Contains("Public anotherVar As Long, andOneMore As Variant", actualCode); StringAssert.Contains($"Private mArray({dimensions}) As String", actualCode); @@ -1086,135 +1194,141 @@ Public Property Get MyArray() As Variant MyArray = mArray End Property "; - var presenterAction = SetParametersForSingleTarget("mArray", "MyArray"); - var actualCode = RefactoredCode(inputCode.ToCodeString(), presenterAction); + var presenterAction = Support.SetParametersForSingleTarget("mArray", "MyArray"); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); Assert.AreEqual(expectedCode, actualCode); } #region setup - private TestEncapsulationAttributes UserModifiedEncapsulationAttributes(string field, string property = null, bool? isReadonly = null, bool encapsulateFlag = true) - { - var testAttrs = new TestEncapsulationAttributes(field, encapsulateFlag, isReadonly ?? false); - if (property != null) - { - testAttrs.PropertyName = property; - } - return testAttrs; - } - - private Func UserAcceptsDefaults(bool asUDT = false) - { - return model => {model.EncapsulateWithUDT = asUDT; return model; }; - } - - private Func SetParametersForSingleTarget(string field, string property = null, bool? isReadonly = null, bool encapsulateFlag = true, bool asUDT = false) - { - var clientAttrs = UserModifiedEncapsulationAttributes(field, property, isReadonly, encapsulateFlag); - - return SetParameters(field, clientAttrs, asUDT); - } - - private Func SetParameters(UserInputDataObject userModifications) - { - return model => - { - foreach (var testModifiedAttribute in userModifications.EncapsulateFieldAttributes) - { - var attrsInitializedByTheRefactoring = model[testModifiedAttribute.TargetFieldName].EncapsulationAttributes; - - attrsInitializedByTheRefactoring.PropertyName = testModifiedAttribute.PropertyName; - attrsInitializedByTheRefactoring.EncapsulateFlag = testModifiedAttribute.EncapsulateFlag; - - var currentAttributes = model[testModifiedAttribute.TargetFieldName].EncapsulationAttributes; - currentAttributes.PropertyName = attrsInitializedByTheRefactoring.PropertyName; - currentAttributes.EncapsulateFlag = attrsInitializedByTheRefactoring.EncapsulateFlag; - - foreach ((string instanceVariable, string memberName, bool flag) in userModifications.UDTMemberNameFlagPairs) - { - model[$"{instanceVariable}.{memberName}"].EncapsulateFlag = flag; - } - } - return model; - }; - } - - private Func SetParameters(string originalField, TestEncapsulationAttributes attrs, bool asUDT = false) - { - return model => - { - var encapsulatedField = model[originalField]; - encapsulatedField.EncapsulationAttributes.PropertyName = attrs.PropertyName; - encapsulatedField.EncapsulationAttributes.ReadOnly = attrs.IsReadOnly; - encapsulatedField.EncapsulationAttributes.EncapsulateFlag = attrs.EncapsulateFlag; - - model.EncapsulateWithUDT = asUDT; - return model; - }; - } - - private class TestEncapsulationAttributes - { - public TestEncapsulationAttributes(string fieldName, bool encapsulationFlag = true, bool isReadOnly = false) - { - _identifiers = new EncapsulationIdentifiers(fieldName); - EncapsulateFlag = encapsulationFlag; - IsReadOnly = isReadOnly; - } - - private EncapsulationIdentifiers _identifiers; - public string TargetFieldName => _identifiers.TargetFieldName; - - public string NewFieldName - { - get => _identifiers.Field; - set => _identifiers.Field = value; - } - public string PropertyName - { - get => _identifiers.Property; - set => _identifiers.Property = value; - } - public bool EncapsulateFlag { get; set; } - public bool IsReadOnly { get; set; } - } - - private class UserInputDataObject - { - private List _userInput = new List(); - private List<(string, string, bool)> _udtNameFlagPairs = new List<(string, string, bool)>(); - - public UserInputDataObject(string fieldName, string propertyName = null, bool encapsulationFlag = true, bool isReadOnly = false) - => AddAttributeSet(fieldName, propertyName, encapsulationFlag, isReadOnly); - - public void AddAttributeSet(string fieldName, string propertyName = null, bool encapsulationFlag = true, bool isReadOnly = false) - { - var attrs = new TestEncapsulationAttributes(fieldName, encapsulationFlag, isReadOnly); - attrs.PropertyName = propertyName ?? attrs.PropertyName; - - _userInput.Add(attrs); - } - - public TestEncapsulationAttributes this[string fieldName] - => EncapsulateFieldAttributes.Where(efa => efa.TargetFieldName == fieldName).Single(); - - - public IEnumerable EncapsulateFieldAttributes => _userInput; - - public void AddUDTMemberNameFlagPairs(params (string, string, bool)[] nameFlagPairs) - => _udtNameFlagPairs.AddRange(nameFlagPairs); - - public IEnumerable<(string, string, bool)> UDTMemberNameFlagPairs => _udtNameFlagPairs; - } - - private string RefactoredCode(CodeString codeString, Func presenterAdjustment, Type expectedException = null, bool executeViaActiveSelection = false) - => RefactoredCode(codeString.Code, codeString.CaretPosition.ToOneBased(), presenterAdjustment, expectedException, executeViaActiveSelection); - - private static IIndenter CreateIndenter(IVBE vbe = null) + //private TestEncapsulationAttributes UserModifiedEncapsulationAttributes(string field, string property = null, bool? isReadonly = null, bool encapsulateFlag = true) + //{ + // var testAttrs = new TestEncapsulationAttributes(field, encapsulateFlag, isReadonly ?? false); + // if (property != null) + // { + // testAttrs.PropertyName = property; + // } + // return testAttrs; + //} + + //private Func UserAcceptsDefaults(bool asUDT = false) + //{ + // return model => {model.EncapsulateWithUDT = asUDT; return model; }; + //} + + //private Func Support.SetParametersForSingleTarget(string field, string property = null, bool? isReadonly = null, bool encapsulateFlag = true, bool asUDT = false) + //{ + // var clientAttrs = UserModifiedEncapsulationAttributes(field, property, isReadonly, encapsulateFlag); + + // return Support.SetParameters(field, clientAttrs, asUDT); + //} + + //public Func Support.SetParameters(UserInputDataObject userModifications) + //{ + // return model => + // { + // foreach (var testModifiedAttribute in userModifications.EncapsulateFieldAttributes) + // { + // var attrsInitializedByTheRefactoring = model[testModifiedAttribute.TargetFieldName].EncapsulationAttributes; + + // attrsInitializedByTheRefactoring.PropertyName = testModifiedAttribute.PropertyName; + // attrsInitializedByTheRefactoring.EncapsulateFlag = testModifiedAttribute.EncapsulateFlag; + + // var currentAttributes = model[testModifiedAttribute.TargetFieldName].EncapsulationAttributes; + // currentAttributes.PropertyName = attrsInitializedByTheRefactoring.PropertyName; + // currentAttributes.EncapsulateFlag = attrsInitializedByTheRefactoring.EncapsulateFlag; + + // foreach ((string instanceVariable, string memberName, bool flag) in userModifications.UDTMemberNameFlagPairs) + // { + // model[$"{instanceVariable}.{memberName}"].EncapsulateFlag = flag; + // } + // } + // return model; + // }; + //} + + //private Func Support.SetParameters(string originalField, TestEncapsulationAttributes attrs, bool asUDT = false) + //{ + // return model => + // { + // var encapsulatedField = model[originalField]; + // encapsulatedField.EncapsulationAttributes.PropertyName = attrs.PropertyName; + // encapsulatedField.EncapsulationAttributes.ReadOnly = attrs.IsReadOnly; + // encapsulatedField.EncapsulationAttributes.EncapsulateFlag = attrs.EncapsulateFlag; + + // model.EncapsulateWithUDT = asUDT; + // return model; + // }; + //} + + //public class TestEncapsulationAttributes + //{ + // public TestEncapsulationAttributes(string fieldName, bool encapsulationFlag = true, bool isReadOnly = false) + // { + // _identifiers = new EncapsulationIdentifiers(fieldName); + // EncapsulateFlag = encapsulationFlag; + // IsReadOnly = isReadOnly; + // } + + // private EncapsulationIdentifiers _identifiers; + // public string TargetFieldName => _identifiers.TargetFieldName; + + // public string NewFieldName + // { + // get => _identifiers.Field; + // set => _identifiers.Field = value; + // } + // public string PropertyName + // { + // get => _identifiers.Property; + // set => _identifiers.Property = value; + // } + // public bool EncapsulateFlag { get; set; } + // public bool IsReadOnly { get; set; } + //} + + //public class UserInputDataObject + //{ + // private List _userInput = new List(); + // private List<(string, string, bool)> _udtNameFlagPairs = new List<(string, string, bool)>(); + + // public UserInputDataObject(string fieldName, string propertyName = null, bool encapsulationFlag = true, bool isReadOnly = false) + // => AddAttributeSet(fieldName, propertyName, encapsulationFlag, isReadOnly); + + // public void AddAttributeSet(string fieldName, string propertyName = null, bool encapsulationFlag = true, bool isReadOnly = false) + // { + // var attrs = new TestEncapsulationAttributes(fieldName, encapsulationFlag, isReadOnly); + // attrs.PropertyName = propertyName ?? attrs.PropertyName; + + // _userInput.Add(attrs); + // } + + // public TestEncapsulationAttributes this[string fieldName] + // => EncapsulateFieldAttributes.Where(efa => efa.TargetFieldName == fieldName).Single(); + + + // public IEnumerable EncapsulateFieldAttributes => _userInput; + + // public void AddUDTMemberNameFlagPairs(params (string, string, bool)[] nameFlagPairs) + // => _udtNameFlagPairs.AddRange(nameFlagPairs); + + // public IEnumerable<(string, string, bool)> UDTMemberNameFlagPairs => _udtNameFlagPairs; + //} + + //private string Support.RefactoredCode(CodeString codeString, Func presenterAdjustment, Type expectedException = null, bool executeViaActiveSelection = false) + // => Support.RefactoredCode(codeString.Code, codeString.CaretPosition.ToOneBased(), presenterAdjustment, expectedException, executeViaActiveSelection); + + public static IIndenter CreateIndenter(IVBE vbe = null) { return new Indenter(vbe, () => Settings.IndenterSettingsTests.GetMockIndenterSettings()); } + //protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) + //{ + // var indenter = CreateIndenter(); //The refactoring only uses method independent of the VBE instance. + // var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); + // return new EncapsulateFieldRefactoring(state, indenter, factory, rewritingManager, selectionService, selectedDeclarationProvider); + //} protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) { var indenter = CreateIndenter(); //The refactoring only uses method independent of the VBE instance. From e2b1211e471b2609ff0aec3bca458fd4457b3d0a Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Wed, 27 Nov 2019 17:03:25 -0800 Subject: [PATCH 030/461] Reorganzing the tests --- .../EncapsulateField/EncapsulateAsUDTTests.cs | 497 ++++++++++++- .../EncapsulateField/TestSupport.cs | 8 +- .../Refactoring/EncapsulateFieldTests.cs | 654 +----------------- 3 files changed, 513 insertions(+), 646 deletions(-) diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateAsUDTTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateAsUDTTests.cs index bcfd56e208..1ceee9d2ec 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateAsUDTTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateAsUDTTests.cs @@ -1,4 +1,10 @@ using NUnit.Framework; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.VBA; +using Rubberduck.Refactorings; +using Rubberduck.Refactorings.EncapsulateField; +using Rubberduck.VBEditor.SafeComWrappers; +using Rubberduck.VBEditor.Utility; using System; using System.Collections.Generic; using System.Linq; @@ -8,10 +14,494 @@ namespace RubberduckTests.Refactoring.EncapsulateField { [TestFixture] - public class EncapsulateAsUDTTests + public class EncapsulateAsUDTTests : InteractiveRefactoringTestBase { private EncapsulateFieldTestSupport Support { get; } = new EncapsulateFieldTestSupport(); + [TestCase("Public")] + [TestCase("Private")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedType_UserAcceptsDefaults(string accessibility) + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +{accessibility} th|is As TBar"; + + + var presenterAction = Support.UserAcceptsDefaults(); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.Contains("Private this1 As TBar", actualCode); + StringAssert.Contains("this1 = value", actualCode); + StringAssert.Contains($"This = this1", actualCode); + StringAssert.DoesNotContain($"this1.First1 = value", actualCode); + } + + + [TestCase("Public")] + [TestCase("Private")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedType_UserAcceptsDefaults_ToUDTInstances(string accessibility) + { + string selectionModule = "ClassInput"; + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +{accessibility} th|is As TBar + +Private that As TBar"; + + string otherModule = "OtherModule"; + string moduleCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +{accessibility} this As TBar + +Private that As TBar"; + + + var presenterAdjustment = Support.UserAcceptsDefaults(); + var codeString = inputCode.ToCodeString(); + var actualCode = RefactoredCode(selectionModule, codeString.CaretPosition.ToOneBased(), presenterAdjustment, null, false, (selectionModule, codeString.Code, ComponentType.ClassModule), (otherModule, moduleCode, ComponentType.StandardModule)); + StringAssert.Contains("Private this1 As TBar", actualCode[selectionModule]); + StringAssert.Contains("this1 = value", actualCode[selectionModule]); + StringAssert.Contains($"This = this1", actualCode[selectionModule]); + StringAssert.DoesNotContain($"this1.First1 = value", actualCode[selectionModule]); + } + + [TestCase("Public", true, true)] + [TestCase("Private", true, true)] + [TestCase("Public", false, false)] + [TestCase("Private", false, false)] + [TestCase("Public", true, false)] + [TestCase("Private", true, false)] + [TestCase("Public", false, true)] + [TestCase("Private", false, true)] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedType_TwoInstanceVariables(string accessibility, bool encapsulateThis, bool encapsulateThat) + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +{accessibility} th|is As TBar +{accessibility} that As TBar"; + + var userInput = new UserInputDataObject("this", "MyType", encapsulateThis); + userInput.AddAttributeSet("that", "MyOtherType", encapsulateThat); + userInput.AddUDTMemberNameFlagPairs(("this", "First", true)); + userInput.AddUDTMemberNameFlagPairs(("this", "Second", true)); + userInput.AddUDTMemberNameFlagPairs(("that", "First", true)); + userInput.AddUDTMemberNameFlagPairs(("that", "Second", true)); + + var expectedThis = new EncapsulationIdentifiers("this") { Property = "MyType" }; + var expectedThat = new EncapsulationIdentifiers("that") { Property = "MyOtherType" }; + + var presenterAction = Support.SetParameters(userInput); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + if (encapsulateThis) + { + StringAssert.Contains($"Private {expectedThis.Field} As TBar", actualCode); + StringAssert.Contains($"MyType = {expectedThis.Field}", actualCode); + StringAssert.Contains($"{expectedThis.Field} = value", actualCode); + StringAssert.Contains($"{expectedThis.Field}.First = value", actualCode); + StringAssert.Contains($"{expectedThis.Field}.First = value", actualCode); + StringAssert.Contains($"{expectedThis.Field}.Second = value", actualCode); + } + else + { + StringAssert.Contains($"{accessibility} this As TBar", actualCode); + StringAssert.Contains($"this.First = value", actualCode); + StringAssert.Contains($"this.Second = value", actualCode); + } + + if (encapsulateThat) + { + StringAssert.Contains($"Private {expectedThat.Field} As TBar", actualCode); + StringAssert.Contains($"MyOtherType = {expectedThat.Field}", actualCode); + StringAssert.Contains($"{expectedThat.Field} = value", actualCode); + StringAssert.Contains($"{expectedThat.Field}.First = value", actualCode); + StringAssert.Contains($"{expectedThat.Field}.Second = value", actualCode); + } + else + { + StringAssert.Contains($"{accessibility} that As TBar", actualCode); + StringAssert.Contains($"that.First = value", actualCode); + StringAssert.Contains($"that.Second = value", actualCode); + } + + StringAssert.Contains($"Property Get This_First", actualCode); + StringAssert.Contains($"Property Get That_First", actualCode); + StringAssert.Contains($"Property Get This_Second", actualCode); + StringAssert.Contains($"Property Get That_Second", actualCode); + } + + + [TestCase("First")] + [TestCase("Second")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedTypeMembers_Subset(string memberToEncapsulate) + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +Private th|is As TBar"; + + + var userInput = new UserInputDataObject("this", "MyType", true); + userInput.AddUDTMemberNameFlagPairs(("this", memberToEncapsulate, true)); + + var presenterAction = Support.SetParameters(userInput); + + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.Contains($"this.{memberToEncapsulate} = value", actualCode); + StringAssert.Contains($"{memberToEncapsulate} = this.{memberToEncapsulate}", actualCode); + } + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedTypeMembers_OnlyEncapsulateUDTMembers() + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +Private th|is As TBar"; + + + var userInput = new UserInputDataObject("this"); + userInput["this"].EncapsulateFlag = false; + userInput.AddUDTMemberNameFlagPairs(("this", "First", true)); + userInput.AddUDTMemberNameFlagPairs(("this", "Second", true)); + + var presenterAction = Support.SetParameters(userInput); + + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.Contains("this.First = value", actualCode); + StringAssert.Contains($"First = this.First", actualCode); + StringAssert.Contains("this.Second = value", actualCode); + StringAssert.Contains($"Second = this.Second", actualCode); + } + + [TestCase("Public")] + [TestCase("Private")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedTypeMembersAndFields(string accessibility) + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +Public mFoo As String +Public mBar As Long +Private mFizz + +{accessibility} t|his As TBar"; + + + var userInput = new UserInputDataObject("this", "MyType", true); + userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true)); + userInput.AddAttributeSet("mFoo", "Foo", true); + userInput.AddAttributeSet("mBar", "Bar", true); + userInput.AddAttributeSet("mFizz", "Fizz", true); + + var presenterAction = Support.SetParameters(userInput); + + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + + StringAssert.Contains("Private this As TBar", actualCode); + StringAssert.Contains("this = value", actualCode); + StringAssert.Contains("MyType = this", actualCode); + Assert.AreEqual(actualCode.IndexOf("MyType = this"), actualCode.LastIndexOf("MyType = this")); + StringAssert.Contains($"this.First = value", actualCode); + StringAssert.Contains($"First = this.First", actualCode); + StringAssert.Contains($"this.Second = value", actualCode); + StringAssert.Contains($"Second = this.Second", actualCode); + StringAssert.DoesNotContain($"Second = Second", actualCode); + StringAssert.Contains($"Private mFoo As String", actualCode); + StringAssert.Contains($"Public Property Get Foo(", actualCode); + StringAssert.Contains($"Public Property Let Foo(", actualCode); + StringAssert.Contains($"Private mBar As Long", actualCode); + StringAssert.Contains($"Public Property Get Bar(", actualCode); + StringAssert.Contains($"Public Property Let Bar(", actualCode); + StringAssert.Contains($"Private mFizz As Variant", actualCode); + StringAssert.Contains($"Public Property Get Fizz() As Variant", actualCode); + StringAssert.Contains($"Public Property Let Fizz(", actualCode); + } + + [TestCase("Public")] + [TestCase("Private")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedTypeMember_ContainsObjects(string accessibility) + { + string inputCode = +$@" +Private Type TBar + First As Class1 + Second As Long +End Type + +{accessibility} th|is As TBar"; + + string class1Code = +@"Option Explicit + +Public Sub Foo() +End Sub +"; + + var userInput = new UserInputDataObject("this", "MyType", true); + + userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true)); + + var presenterAction = Support.SetParameters(userInput); + + var codeString = inputCode.ToCodeString(); + var actualModuleCode = RefactoredCode( + "Module1", + codeString.CaretPosition.ToOneBased(), + presenterAction, + null, + false, + ("Class1", class1Code, ComponentType.ClassModule), + ("Module1", codeString.Code, ComponentType.StandardModule)); + + var actualCode = actualModuleCode["Module1"]; + + StringAssert.Contains("Private this As TBar", actualCode); + StringAssert.Contains("this = value", actualCode); + StringAssert.Contains("MyType = this", actualCode); + StringAssert.Contains("Property Set First(ByVal value As Class1)", actualCode); + StringAssert.Contains("Property Get First() As Class1", actualCode); + StringAssert.Contains($"Set this.First = value", actualCode); + StringAssert.Contains($"Set First = this.First", actualCode); + StringAssert.Contains($"this.Second = value", actualCode); + StringAssert.Contains($"Second = this.Second", actualCode); + StringAssert.DoesNotContain($"Second = Second", actualCode); + } + + [TestCase("Public")] + [TestCase("Private")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedTypeMember_ContainsVariant(string accessibility) + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Variant +End Type + +{accessibility} th|is As TBar"; + + var userInput = new UserInputDataObject("this", "MyType", true); + userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true)); + + var presenterAction = Support.SetParameters(userInput); + + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.Contains("Private this As TBar", actualCode); + StringAssert.Contains("this = value", actualCode); + StringAssert.Contains("MyType = this", actualCode); + Assert.AreEqual(actualCode.IndexOf("MyType = this"), actualCode.LastIndexOf("MyType = this")); + StringAssert.Contains($"this.First = value", actualCode); + StringAssert.Contains($"First = this.First", actualCode); + StringAssert.Contains($"IsObject", actualCode); + StringAssert.Contains($"this.Second = value", actualCode); + StringAssert.Contains($"Second = this.Second", actualCode); + StringAssert.DoesNotContain($"Second = Second", actualCode); + } + + [TestCase("Public")] + [TestCase("Private")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedTypeMember_ContainsArrays(string accessibility) + { + string inputCode = +$@" +Private Type TBar + First(5) As String + Second(1 to 100) As Long + Third() As Double +End Type + +{accessibility} t|his As TBar"; + + var userInput = new UserInputDataObject("this", "MyType", false); + userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true), ("this", "Third", true)); + + var presenterAction = Support.SetParameters(userInput); + + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.Contains($"{accessibility} this As TBar", actualCode); + StringAssert.DoesNotContain("this = value", actualCode); + StringAssert.DoesNotContain($"this.First = value", actualCode); + StringAssert.Contains($"Property Get First() As Variant", actualCode); + StringAssert.Contains($"First = this.First", actualCode); + StringAssert.DoesNotContain($"this.Second = value", actualCode); + StringAssert.Contains($"Second = this.Second", actualCode); + StringAssert.Contains($"Property Get Second() As Variant", actualCode); + StringAssert.Contains($"Third = this.Third", actualCode); + StringAssert.Contains($"Property Get Third() As Variant", actualCode); + } + + [TestCase("Public", "Public")] + [TestCase("Private", "Private")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedTypeMembersOnly(string accessibility, string expectedAccessibility) + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +{accessibility} th|is As TBar"; + + var userInput = new UserInputDataObject("this", "MyType", false); + userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true)); + + var presenterAction = Support.SetParameters(userInput); + + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.Contains($"{expectedAccessibility} this As TBar", actualCode); + StringAssert.DoesNotContain("this = value", actualCode); + StringAssert.DoesNotContain("MyType = this", actualCode); + StringAssert.Contains($"this.First = value", actualCode); + StringAssert.Contains($"First = this.First", actualCode); + StringAssert.Contains($"this.Second = value", actualCode); + StringAssert.Contains($"Second = this.Second", actualCode); + StringAssert.DoesNotContain($"Second = Second", actualCode); + } + + [TestCase("Public")] + [TestCase("Private")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedTypeMembers_ExternallyDefinedType(string accessibility) + { + string inputCode = +$@" +Option Explicit + +{accessibility} th|is As TBar"; + + string typeDefinition = +$@" +Public Type TBar + First As String + Second As Long +End Type +"; + + var userInput = new UserInputDataObject("this", "MyType", true); + userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true)); + + var presenterAction = Support.SetParameters(userInput); + + var codeString = inputCode.ToCodeString(); + var actualModuleCode = RefactoredCode( + "Class1", + codeString.CaretPosition.ToOneBased(), + presenterAction, + null, + false, + ("Class1", codeString.Code, ComponentType.ClassModule), + ("Module1", typeDefinition, ComponentType.StandardModule)); + + Assert.AreEqual(typeDefinition, actualModuleCode["Module1"]); + + + var actualCode = actualModuleCode["Class1"]; + StringAssert.Contains("Private this As TBar", actualCode); + StringAssert.Contains("this = value", actualCode); + StringAssert.Contains("MyType = this", actualCode); + Assert.AreEqual(actualCode.IndexOf("MyType = this"), actualCode.LastIndexOf("MyType = this")); + StringAssert.Contains($"this.First = value", actualCode); + StringAssert.Contains($"First = this.First", actualCode); + StringAssert.Contains($"this.Second = value", actualCode); + StringAssert.Contains($"Second = this.Second", actualCode); + StringAssert.DoesNotContain($"Second = Second", actualCode); + } + + [TestCase("Public")] + [TestCase("Private")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedTypeMembers_ObjectField(string accessibility) + { + string inputCode = +$@" +Option Explicit + +{accessibility} mThe|Class As Class1"; + + string classContent = +$@" +Option Explicit + +Private Sub Class_Initialize() +End Sub +"; + + var presenterAction = Support.UserAcceptsDefaults(); + + var codeString = inputCode.ToCodeString(); + var actualModuleCode = RefactoredCode( + "Module1", + codeString.CaretPosition.ToOneBased(), + presenterAction, + null, + false, + ("Class1", classContent, ComponentType.ClassModule), + ("Module1", codeString.Code, ComponentType.StandardModule)); + + var actualCode = actualModuleCode["Module1"]; + + var defaults = new EncapsulationIdentifiers("mTheClass"); + + StringAssert.Contains($"Private {defaults.Field} As Class1", actualCode); + StringAssert.Contains($"Set {defaults.Field} = value", actualCode); + StringAssert.Contains($"MTheClass = {defaults.Field}", actualCode); + StringAssert.Contains($"Public Property Set {defaults.Property}", actualCode); + } + [Test] [Category("Refactorings")] [Category("Encapsulate Field")] @@ -67,5 +557,10 @@ Public myBar As TBar StringAssert.Contains("this.MyBar.Second = value", actualCode); StringAssert.Contains("Second = this.MyBar.Second", actualCode); } + + protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) + { + return Support.SupportTestRefactoring(rewritingManager, state, factory, selectionService); + } } } diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index b6b255b270..0fc81e5068 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -85,12 +85,17 @@ public static IIndenter CreateIndenter(IVBE vbe = null) return new Indenter(vbe, () => Settings.IndenterSettingsTests.GetMockIndenterSettings()); } - protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) + public IRefactoring SupportTestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) { var indenter = CreateIndenter(); //The refactoring only uses method independent of the VBE instance. var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); return new EncapsulateFieldRefactoring(state, indenter, factory, rewritingManager, selectionService, selectedDeclarationProvider); } + + protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) + { + return SupportTestRefactoring(rewritingManager, state, factory, selectionService); + } } public class TestEncapsulationAttributes @@ -148,5 +153,4 @@ public void AddUDTMemberNameFlagPairs(params (string, string, bool)[] nameFlagPa public IEnumerable<(string, string, bool)> UDTMemberNameFlagPairs => _udtNameFlagPairs; } - } diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index 74618eab2a..95b53943f9 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -124,6 +124,10 @@ public void EncapsulateMultipleFieldsInList( var declarationList = $"Public {string.Join(", ", remainInList)}"; StringAssert.Contains(declarationList, actualCode); } + else + { + StringAssert.DoesNotContain($"Public {Environment.NewLine}", actualCode); + } foreach (var key in flags.Keys) { @@ -138,516 +142,6 @@ public void EncapsulateMultipleFieldsInList( } } -// [Test] -// [Category("Refactorings")] -// [Category("Encapsulate Field")] -// public void UserDefinedType_MultipleFieldsToNewUDT() -// { -// string inputCode = -//$@" -//Public fo|o As Long -//Public bar As String -//Public foobar As Byte -//"; - -// var userInput = new UserInputDataObject("foo", encapsulationFlag: true); -// userInput.AddAttributeSet("bar", encapsulationFlag: true); -// userInput.AddAttributeSet("foobar", encapsulationFlag: true); -// userInput.EncapsulateAsUDT = true; - -// var presenterAction = Support.SetParameters(userInput); -// var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); -// StringAssert.Contains("Private this As This_Type", actualCode); -// StringAssert.Contains("Private Type This_Type", actualCode); -// StringAssert.Contains("Foo As Long", actualCode); -// StringAssert.Contains("Bar As String", actualCode); -// StringAssert.Contains("Foobar As Byte", actualCode); -// } - - [TestCase("Public")] - [TestCase("Private")] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void UserDefinedType_UserAcceptsDefaults(string accessibility) - { - string inputCode = -$@" -Private Type TBar - First As String - Second As Long -End Type - -{accessibility} th|is As TBar"; - - - var presenterAction = Support.UserAcceptsDefaults(); - var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - StringAssert.Contains("Private this1 As TBar", actualCode); - StringAssert.Contains("this1 = value", actualCode); - StringAssert.Contains($"This = this1", actualCode); - StringAssert.DoesNotContain($"this1.First1 = value", actualCode); - } - - - [TestCase("Public")] - [TestCase("Private")] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void UserDefinedType_UserAcceptsDefaults_ToUDTInstances(string accessibility) - { - string selectionModule = "ClassInput"; - string inputCode = -$@" -Private Type TBar - First As String - Second As Long -End Type - -{accessibility} th|is As TBar - -Private that As TBar"; - - string otherModule = "OtherModule"; - string moduleCode = -$@" -Private Type TBar - First As String - Second As Long -End Type - -{accessibility} this As TBar - -Private that As TBar"; - - - var presenterAdjustment = Support.UserAcceptsDefaults(); - var codeString = inputCode.ToCodeString(); - var actualCode = RefactoredCode(selectionModule, codeString.CaretPosition.ToOneBased(), presenterAdjustment, null, false, (selectionModule, codeString.Code, ComponentType.ClassModule), (otherModule, moduleCode, ComponentType.StandardModule) ); - StringAssert.Contains("Private this1 As TBar", actualCode[selectionModule]); - StringAssert.Contains("this1 = value", actualCode[selectionModule]); - StringAssert.Contains($"This = this1", actualCode[selectionModule]); - StringAssert.DoesNotContain($"this1.First1 = value", actualCode[selectionModule]); - } - - [TestCase("Public", true, true)] - [TestCase("Private", true, true)] - [TestCase("Public", false, false)] - [TestCase("Private", false, false)] - [TestCase("Public", true, false)] - [TestCase("Private", true, false)] - [TestCase("Public", false, true)] - [TestCase("Private", false, true)] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void UserDefinedType_TwoInstanceVariables(string accessibility, bool encapsulateThis, bool encapsulateThat) - { - string inputCode = -$@" -Private Type TBar - First As String - Second As Long -End Type - -{accessibility} th|is As TBar -{accessibility} that As TBar"; - - var userInput = new UserInputDataObject("this", "MyType", encapsulateThis); - userInput.AddAttributeSet("that", "MyOtherType", encapsulateThat); - userInput.AddUDTMemberNameFlagPairs(("this", "First", true)); - userInput.AddUDTMemberNameFlagPairs(("this", "Second", true)); - userInput.AddUDTMemberNameFlagPairs(("that", "First", true)); - userInput.AddUDTMemberNameFlagPairs(("that", "Second", true)); - - var expectedThis = new EncapsulationIdentifiers("this") { Property = "MyType"}; - var expectedThat = new EncapsulationIdentifiers("that") { Property = "MyOtherType"}; - - var presenterAction = Support.SetParameters(userInput); - var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - if (encapsulateThis) - { - StringAssert.Contains($"Private {expectedThis.Field} As TBar", actualCode); - StringAssert.Contains($"MyType = {expectedThis.Field}", actualCode); - StringAssert.Contains($"{expectedThis.Field} = value", actualCode); - StringAssert.Contains($"{expectedThis.Field}.First = value", actualCode); - StringAssert.Contains($"{expectedThis.Field}.First = value", actualCode); - StringAssert.Contains($"{expectedThis.Field}.Second = value", actualCode); - } - else - { - StringAssert.Contains($"{accessibility} this As TBar", actualCode); - StringAssert.Contains($"this.First = value", actualCode); - StringAssert.Contains($"this.Second = value", actualCode); - } - - if (encapsulateThat) - { - StringAssert.Contains($"Private {expectedThat.Field} As TBar", actualCode); - StringAssert.Contains($"MyOtherType = {expectedThat.Field}", actualCode); - StringAssert.Contains($"{expectedThat.Field} = value", actualCode); - StringAssert.Contains($"{expectedThat.Field}.First = value", actualCode); - StringAssert.Contains($"{expectedThat.Field}.Second = value", actualCode); - } - else - { - StringAssert.Contains($"{accessibility} that As TBar", actualCode); - StringAssert.Contains($"that.First = value", actualCode); - StringAssert.Contains($"that.Second = value", actualCode); - } - - StringAssert.Contains($"Property Get This_First", actualCode); - StringAssert.Contains($"Property Get That_First", actualCode); - StringAssert.Contains($"Property Get This_Second", actualCode); - StringAssert.Contains($"Property Get That_Second", actualCode); - } - - - [TestCase("First")] - [TestCase("Second")] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void UserDefinedTypeMembers_Subset(string memberToEncapsulate) - { - string inputCode = -$@" -Private Type TBar - First As String - Second As Long -End Type - -Private th|is As TBar"; - - - var userInput = new UserInputDataObject("this", "MyType", true); - userInput.AddUDTMemberNameFlagPairs(("this", memberToEncapsulate, true)); - - var presenterAction = Support.SetParameters(userInput); - - var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - StringAssert.Contains($"this.{memberToEncapsulate} = value", actualCode); - StringAssert.Contains($"{memberToEncapsulate} = this.{memberToEncapsulate}", actualCode); - } - - [Test] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void UserDefinedTypeMembers_OnlyEncapsulateUDTMembers() - { - string inputCode = -$@" -Private Type TBar - First As String - Second As Long -End Type - -Private th|is As TBar"; - - - var userInput = new UserInputDataObject("this"); - userInput["this"].EncapsulateFlag = false; - userInput.AddUDTMemberNameFlagPairs(("this", "First", true)); - userInput.AddUDTMemberNameFlagPairs(("this", "Second", true)); - - var presenterAction = Support.SetParameters(userInput); - - var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - StringAssert.Contains("this.First = value", actualCode); - StringAssert.Contains($"First = this.First", actualCode); - StringAssert.Contains("this.Second = value", actualCode); - StringAssert.Contains($"Second = this.Second", actualCode); - } - - [TestCase("Public")] - [TestCase("Private")] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void UserDefinedTypeMembersAndFields(string accessibility) - { - string inputCode = -$@" -Private Type TBar - First As String - Second As Long -End Type - -Public mFoo As String -Public mBar As Long -Private mFizz - -{accessibility} t|his As TBar"; - - - var userInput = new UserInputDataObject("this", "MyType", true); - userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true)); - userInput.AddAttributeSet("mFoo", "Foo", true); - userInput.AddAttributeSet("mBar", "Bar", true); - userInput.AddAttributeSet("mFizz", "Fizz", true); - - var presenterAction = Support.SetParameters(userInput); - - var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - - StringAssert.Contains("Private this As TBar", actualCode); - StringAssert.Contains("this = value", actualCode); - StringAssert.Contains("MyType = this", actualCode); - Assert.AreEqual(actualCode.IndexOf("MyType = this"), actualCode.LastIndexOf("MyType = this")); - StringAssert.Contains($"this.First = value", actualCode); - StringAssert.Contains($"First = this.First", actualCode); - StringAssert.Contains($"this.Second = value", actualCode); - StringAssert.Contains($"Second = this.Second", actualCode); - StringAssert.DoesNotContain($"Second = Second", actualCode); - StringAssert.Contains($"Private mFoo As String", actualCode); - StringAssert.Contains($"Public Property Get Foo(", actualCode); - StringAssert.Contains($"Public Property Let Foo(", actualCode); - StringAssert.Contains($"Private mBar As Long", actualCode); - StringAssert.Contains($"Public Property Get Bar(", actualCode); - StringAssert.Contains($"Public Property Let Bar(", actualCode); - StringAssert.Contains($"Private mFizz As Variant", actualCode); - StringAssert.Contains($"Public Property Get Fizz() As Variant", actualCode); - StringAssert.Contains($"Public Property Let Fizz(", actualCode); - } - - [TestCase("Public")] - [TestCase("Private")] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void UserDefinedTypeMember_ContainsObjects(string accessibility) - { - string inputCode = -$@" -Private Type TBar - First As Class1 - Second As Long -End Type - -{accessibility} th|is As TBar"; - - string class1Code = -@"Option Explicit - -Public Sub Foo() -End Sub -"; - - var userInput = new UserInputDataObject("this", "MyType", true); - - userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true)); - - var presenterAction = Support.SetParameters(userInput); - - var codeString = inputCode.ToCodeString(); - var actualModuleCode = RefactoredCode( - "Module1", - codeString.CaretPosition.ToOneBased(), - presenterAction, - null, - false, - ("Class1", class1Code, ComponentType.ClassModule), - ("Module1", codeString.Code, ComponentType.StandardModule)); - - var actualCode = actualModuleCode["Module1"]; - - StringAssert.Contains("Private this As TBar", actualCode); - StringAssert.Contains("this = value", actualCode); - StringAssert.Contains("MyType = this", actualCode); - StringAssert.Contains("Property Set First(ByVal value As Class1)", actualCode); - StringAssert.Contains("Property Get First() As Class1", actualCode); - StringAssert.Contains($"Set this.First = value", actualCode); - StringAssert.Contains($"Set First = this.First", actualCode); - StringAssert.Contains($"this.Second = value", actualCode); - StringAssert.Contains($"Second = this.Second", actualCode); - StringAssert.DoesNotContain($"Second = Second", actualCode); - } - - [TestCase("Public")] - [TestCase("Private")] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void UserDefinedTypeMember_ContainsVariant(string accessibility) - { - string inputCode = -$@" -Private Type TBar - First As String - Second As Variant -End Type - -{accessibility} th|is As TBar"; - - var userInput = new UserInputDataObject("this", "MyType", true); - userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true)); - - var presenterAction = Support.SetParameters(userInput); - - var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - StringAssert.Contains("Private this As TBar", actualCode); - StringAssert.Contains("this = value", actualCode); - StringAssert.Contains("MyType = this", actualCode); - Assert.AreEqual(actualCode.IndexOf("MyType = this"), actualCode.LastIndexOf("MyType = this")); - StringAssert.Contains($"this.First = value", actualCode); - StringAssert.Contains($"First = this.First", actualCode); - StringAssert.Contains($"IsObject", actualCode); - StringAssert.Contains($"this.Second = value", actualCode); - StringAssert.Contains($"Second = this.Second", actualCode); - StringAssert.DoesNotContain($"Second = Second", actualCode); - } - - [TestCase("Public")] - [TestCase("Private")] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void UserDefinedTypeMember_ContainsArrays(string accessibility) - { - string inputCode = -$@" -Private Type TBar - First(5) As String - Second(1 to 100) As Long - Third() As Double -End Type - -{accessibility} t|his As TBar"; - - var userInput = new UserInputDataObject("this", "MyType", false); - userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true), ("this", "Third", true)); - - var presenterAction = Support.SetParameters(userInput); - - var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - StringAssert.Contains($"{accessibility} this As TBar", actualCode); - StringAssert.DoesNotContain("this = value", actualCode); - StringAssert.DoesNotContain($"this.First = value", actualCode); - StringAssert.Contains($"Property Get First() As Variant", actualCode); - StringAssert.Contains($"First = this.First", actualCode); - StringAssert.DoesNotContain($"this.Second = value", actualCode); - StringAssert.Contains($"Second = this.Second", actualCode); - StringAssert.Contains($"Property Get Second() As Variant", actualCode); - StringAssert.Contains($"Third = this.Third", actualCode); - StringAssert.Contains($"Property Get Third() As Variant", actualCode); - } - - [TestCase("Public", "Public")] - [TestCase("Private", "Private")] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void UserDefinedTypeMembersOnly(string accessibility, string expectedAccessibility) - { - string inputCode = -$@" -Private Type TBar - First As String - Second As Long -End Type - -{accessibility} th|is As TBar"; - - var userInput = new UserInputDataObject("this", "MyType", false); - userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true)); - - var presenterAction = Support.SetParameters(userInput); - - var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - StringAssert.Contains($"{expectedAccessibility} this As TBar", actualCode); - StringAssert.DoesNotContain("this = value", actualCode); - StringAssert.DoesNotContain("MyType = this", actualCode); - StringAssert.Contains($"this.First = value", actualCode); - StringAssert.Contains($"First = this.First", actualCode); - StringAssert.Contains($"this.Second = value", actualCode); - StringAssert.Contains($"Second = this.Second", actualCode); - StringAssert.DoesNotContain($"Second = Second", actualCode); - } - - [TestCase("Public")] - [TestCase("Private")] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void UserDefinedTypeMembers_ExternallyDefinedType(string accessibility) - { - string inputCode = -$@" -Option Explicit - -{accessibility} th|is As TBar"; - - string typeDefinition = -$@" -Public Type TBar - First As String - Second As Long -End Type -"; - - var userInput = new UserInputDataObject("this", "MyType", true); - userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true)); - - var presenterAction = Support.SetParameters(userInput); - - var codeString = inputCode.ToCodeString(); - var actualModuleCode = RefactoredCode( - "Class1", - codeString.CaretPosition.ToOneBased(), - presenterAction, - null, - false, - ("Class1", codeString.Code, ComponentType.ClassModule), - ("Module1", typeDefinition, ComponentType.StandardModule)); - - Assert.AreEqual(typeDefinition, actualModuleCode["Module1"]); - - - var actualCode = actualModuleCode["Class1"]; - StringAssert.Contains("Private this As TBar", actualCode); - StringAssert.Contains("this = value", actualCode); - StringAssert.Contains("MyType = this", actualCode); - Assert.AreEqual(actualCode.IndexOf("MyType = this"), actualCode.LastIndexOf("MyType = this")); - StringAssert.Contains($"this.First = value", actualCode); - StringAssert.Contains($"First = this.First", actualCode); - StringAssert.Contains($"this.Second = value", actualCode); - StringAssert.Contains($"Second = this.Second", actualCode); - StringAssert.DoesNotContain($"Second = Second", actualCode); - } - - [TestCase("Public")] - [TestCase("Private")] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void UserDefinedTypeMembers_ObjectField(string accessibility) - { - string inputCode = -$@" -Option Explicit - -{accessibility} mThe|Class As Class1"; - - string classContent = -$@" -Option Explicit - -Private Sub Class_Initialize() -End Sub -"; - - var presenterAction = Support.UserAcceptsDefaults(); - - var codeString = inputCode.ToCodeString(); - var actualModuleCode = RefactoredCode( - "Module1", - codeString.CaretPosition.ToOneBased(), - presenterAction, - null, - false, - ("Class1", classContent, ComponentType.ClassModule), - ("Module1", codeString.Code, ComponentType.StandardModule)); - - var actualCode = actualModuleCode["Module1"]; - - var defaults = new EncapsulationIdentifiers("mTheClass"); - - StringAssert.Contains($"Private {defaults.Field} As Class1", actualCode); - StringAssert.Contains($"Set {defaults.Field} = value", actualCode); - StringAssert.Contains($"MTheClass = {defaults.Field}", actualCode); - StringAssert.Contains($"Public Property Set {defaults.Property}", actualCode); - } - [Test] [Category("Refactorings")] [Category("Encapsulate Field")] @@ -1199,143 +693,17 @@ End Property Assert.AreEqual(expectedCode, actualCode); } - #region setup - - //private TestEncapsulationAttributes UserModifiedEncapsulationAttributes(string field, string property = null, bool? isReadonly = null, bool encapsulateFlag = true) - //{ - // var testAttrs = new TestEncapsulationAttributes(field, encapsulateFlag, isReadonly ?? false); - // if (property != null) - // { - // testAttrs.PropertyName = property; - // } - // return testAttrs; - //} - - //private Func UserAcceptsDefaults(bool asUDT = false) - //{ - // return model => {model.EncapsulateWithUDT = asUDT; return model; }; - //} - - //private Func Support.SetParametersForSingleTarget(string field, string property = null, bool? isReadonly = null, bool encapsulateFlag = true, bool asUDT = false) - //{ - // var clientAttrs = UserModifiedEncapsulationAttributes(field, property, isReadonly, encapsulateFlag); - - // return Support.SetParameters(field, clientAttrs, asUDT); - //} - - //public Func Support.SetParameters(UserInputDataObject userModifications) - //{ - // return model => - // { - // foreach (var testModifiedAttribute in userModifications.EncapsulateFieldAttributes) - // { - // var attrsInitializedByTheRefactoring = model[testModifiedAttribute.TargetFieldName].EncapsulationAttributes; - - // attrsInitializedByTheRefactoring.PropertyName = testModifiedAttribute.PropertyName; - // attrsInitializedByTheRefactoring.EncapsulateFlag = testModifiedAttribute.EncapsulateFlag; - - // var currentAttributes = model[testModifiedAttribute.TargetFieldName].EncapsulationAttributes; - // currentAttributes.PropertyName = attrsInitializedByTheRefactoring.PropertyName; - // currentAttributes.EncapsulateFlag = attrsInitializedByTheRefactoring.EncapsulateFlag; - - // foreach ((string instanceVariable, string memberName, bool flag) in userModifications.UDTMemberNameFlagPairs) - // { - // model[$"{instanceVariable}.{memberName}"].EncapsulateFlag = flag; - // } - // } - // return model; - // }; - //} - - //private Func Support.SetParameters(string originalField, TestEncapsulationAttributes attrs, bool asUDT = false) - //{ - // return model => - // { - // var encapsulatedField = model[originalField]; - // encapsulatedField.EncapsulationAttributes.PropertyName = attrs.PropertyName; - // encapsulatedField.EncapsulationAttributes.ReadOnly = attrs.IsReadOnly; - // encapsulatedField.EncapsulationAttributes.EncapsulateFlag = attrs.EncapsulateFlag; - - // model.EncapsulateWithUDT = asUDT; - // return model; - // }; - //} - - //public class TestEncapsulationAttributes - //{ - // public TestEncapsulationAttributes(string fieldName, bool encapsulationFlag = true, bool isReadOnly = false) - // { - // _identifiers = new EncapsulationIdentifiers(fieldName); - // EncapsulateFlag = encapsulationFlag; - // IsReadOnly = isReadOnly; - // } - - // private EncapsulationIdentifiers _identifiers; - // public string TargetFieldName => _identifiers.TargetFieldName; - - // public string NewFieldName - // { - // get => _identifiers.Field; - // set => _identifiers.Field = value; - // } - // public string PropertyName - // { - // get => _identifiers.Property; - // set => _identifiers.Property = value; - // } - // public bool EncapsulateFlag { get; set; } - // public bool IsReadOnly { get; set; } - //} - - //public class UserInputDataObject - //{ - // private List _userInput = new List(); - // private List<(string, string, bool)> _udtNameFlagPairs = new List<(string, string, bool)>(); - - // public UserInputDataObject(string fieldName, string propertyName = null, bool encapsulationFlag = true, bool isReadOnly = false) - // => AddAttributeSet(fieldName, propertyName, encapsulationFlag, isReadOnly); - - // public void AddAttributeSet(string fieldName, string propertyName = null, bool encapsulationFlag = true, bool isReadOnly = false) - // { - // var attrs = new TestEncapsulationAttributes(fieldName, encapsulationFlag, isReadOnly); - // attrs.PropertyName = propertyName ?? attrs.PropertyName; - - // _userInput.Add(attrs); - // } - - // public TestEncapsulationAttributes this[string fieldName] - // => EncapsulateFieldAttributes.Where(efa => efa.TargetFieldName == fieldName).Single(); - - - // public IEnumerable EncapsulateFieldAttributes => _userInput; - - // public void AddUDTMemberNameFlagPairs(params (string, string, bool)[] nameFlagPairs) - // => _udtNameFlagPairs.AddRange(nameFlagPairs); - - // public IEnumerable<(string, string, bool)> UDTMemberNameFlagPairs => _udtNameFlagPairs; - //} - - //private string Support.RefactoredCode(CodeString codeString, Func presenterAdjustment, Type expectedException = null, bool executeViaActiveSelection = false) - // => Support.RefactoredCode(codeString.Code, codeString.CaretPosition.ToOneBased(), presenterAdjustment, expectedException, executeViaActiveSelection); - - public static IIndenter CreateIndenter(IVBE vbe = null) + protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) { - return new Indenter(vbe, () => Settings.IndenterSettingsTests.GetMockIndenterSettings()); + return Support.SupportTestRefactoring(rewritingManager, state, factory, selectionService); + //var indenter = CreateIndenter(); //The refactoring only uses method independent of the VBE instance. + //var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); + //return new EncapsulateFieldRefactoring(state, indenter, factory, rewritingManager, selectionService, selectedDeclarationProvider); } - //protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) + //private static IIndenter CreateIndenter(IVBE vbe = null) //{ - // var indenter = CreateIndenter(); //The refactoring only uses method independent of the VBE instance. - // var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); - // return new EncapsulateFieldRefactoring(state, indenter, factory, rewritingManager, selectionService, selectedDeclarationProvider); + // return new Indenter(vbe, () => Settings.IndenterSettingsTests.GetMockIndenterSettings()); //} - protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) - { - var indenter = CreateIndenter(); //The refactoring only uses method independent of the VBE instance. - var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); - return new EncapsulateFieldRefactoring(state, indenter, factory, rewritingManager, selectionService, selectedDeclarationProvider); - } - - #endregion } } From 6fc8cca41984686d19d1a4f0fb8a2546ebb42c9c Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Wed, 27 Nov 2019 17:03:47 -0800 Subject: [PATCH 031/461] Rewriter 'Remove' workaround --- .../EncapsulateFieldRefactoring.cs | 18 +++++-- .../RewriterRemoveWorkaround.cs | 54 +++++++++++++++++++ 2 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 Rubberduck.Refactorings/EncapsulateField/RewriterRemoveWorkaround.cs diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 66b00fad27..dc233219a0 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -9,6 +9,7 @@ using Rubberduck.VBEditor.Utility; using System.Collections.Generic; using System; +using Rubberduck.Parsing; namespace Rubberduck.Refactorings.EncapsulateField { @@ -92,6 +93,8 @@ protected override void RefactorImpl(EncapsulateFieldModel model) var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, _targetQMN); + RewriterRemoveWorkAround.RemoveDeclarationsFromVariableLists(rewriter); + rewriter.InsertNewContent(CodeSectionStartIndex, model.NewContent()); if (!rewriteSession.TryRewrite()) @@ -106,12 +109,20 @@ private string PreviewRewrite(EncapsulateFieldModel model) var previewRewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(scratchPadRewriteSession, _targetQMN); + RewriterRemoveWorkAround.RemoveDeclarationsFromVariableLists(previewRewriter); + var newContent = model.NewContent("'<===== No Changes below this line =====>"); previewRewriter.InsertNewContent(CodeSectionStartIndex, newContent); var preview = previewRewriter.GetText(); + var counter = 0; + while ( counter++ < 10 && preview.Contains($"{Environment.NewLine}{Environment.NewLine}{Environment.NewLine}")) + { + preview = preview.Replace($"{Environment.NewLine}{Environment.NewLine}{Environment.NewLine}", $"{Environment.NewLine}{Environment.NewLine}"); + } + return preview; } @@ -151,7 +162,8 @@ private void ModifyEncapsulatedVariable(IEncapsulatedFieldDeclaration target, IF if (asUDT) { - rewriter.Remove(target.Declaration); + RewriterRemoveWorkAround.Remove(target.Declaration, rewriter); + //rewriter.Remove(target.Declaration); return; } @@ -163,7 +175,8 @@ private void ModifyEncapsulatedVariable(IEncapsulatedFieldDeclaration target, IF if (target.Declaration.IsDeclaredInList()) { - rewriter.Remove(target.Declaration); + RewriterRemoveWorkAround.Remove(target.Declaration, rewriter); + //rewriter.Remove(target.Declaration); } else { @@ -200,6 +213,5 @@ private void RenameReferences(IEncapsulatedFieldDeclaration efd, string property return (udtVariable, userDefinedTypeDeclaration, udtMembers); } - } } diff --git a/Rubberduck.Refactorings/EncapsulateField/RewriterRemoveWorkaround.cs b/Rubberduck.Refactorings/EncapsulateField/RewriterRemoveWorkaround.cs new file mode 100644 index 0000000000..e5e4b7e8df --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/RewriterRemoveWorkaround.cs @@ -0,0 +1,54 @@ +using Rubberduck.Parsing; +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.EncapsulateField +{ + //If all variables are removed from a list one by one the + //Accessiblity token is left behind + public static class RewriterRemoveWorkAround + { + private static Dictionary> RemovedVariables { set; get; } = new Dictionary>(); + + public static void Remove(Declaration target, IEncapsulateFieldRewriter rewriter) + { + var varList = target.Context.GetAncestor(); + if (varList.children.Where(ch => ch is VBAParser.VariableSubStmtContext).Count() == 1) + { + rewriter.Remove(target); + return; + } + + if (!RemovedVariables.ContainsKey(varList)) + { + RemovedVariables.Add(varList, new HashSet()); + } + RemovedVariables[varList].Add(target); + } + + public static void RemoveDeclarationsFromVariableLists(IEncapsulateFieldRewriter rewriter) + { + foreach (var key in RemovedVariables.Keys) + { + var variables = key.children.Where(ch => ch is VBAParser.VariableSubStmtContext); + if (variables.Count() == RemovedVariables[key].Count) + { + rewriter.Remove(key.Parent); + } + else + { + foreach (var dec in RemovedVariables[key]) + { + rewriter.Remove(dec); + } + } + } + RemovedVariables = new Dictionary>(); + } + } +} From d12884faa38af2950b66d4124d03742fc8f2ef0a Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Wed, 27 Nov 2019 20:33:33 -0800 Subject: [PATCH 032/461] Arrays are readony --- .../EncapsulateField/EncapsulateFieldDecorators.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs index 75069008d3..0d1e224615 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs @@ -141,6 +141,7 @@ private EncapsulatedArrayType(IEncapsulatedFieldDeclaration efd) EncapsulationAttributes.ImplementSetSetterType = false; EncapsulationAttributes.AsTypeName = Tokens.Variant; CanBeReadWrite = false; + IsReadOnly = true; } public static IEncapsulatedFieldDeclaration Decorate(IEncapsulatedFieldDeclaration efd) From 98cdab63e677f095b2e5d4378aec7bc896770717 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Wed, 27 Nov 2019 20:34:24 -0800 Subject: [PATCH 033/461] minor --- .../Refactoring/EncapsulateField/TestSupport.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index 0fc81e5068..bf6bac5927 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -80,11 +80,6 @@ public Func SetParameters(string o public string RefactoredCode(CodeString codeString, Func presenterAdjustment, Type expectedException = null, bool executeViaActiveSelection = false) => RefactoredCode(codeString.Code, codeString.CaretPosition.ToOneBased(), presenterAdjustment, expectedException, executeViaActiveSelection); - public static IIndenter CreateIndenter(IVBE vbe = null) - { - return new Indenter(vbe, () => Settings.IndenterSettingsTests.GetMockIndenterSettings()); - } - public IRefactoring SupportTestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) { var indenter = CreateIndenter(); //The refactoring only uses method independent of the VBE instance. @@ -92,6 +87,11 @@ public IRefactoring SupportTestRefactoring(IRewritingManager rewritingManager, R return new EncapsulateFieldRefactoring(state, indenter, factory, rewritingManager, selectionService, selectedDeclarationProvider); } + private static IIndenter CreateIndenter(IVBE vbe = null) + { + return new Indenter(vbe, () => Settings.IndenterSettingsTests.GetMockIndenterSettings()); + } + protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) { return SupportTestRefactoring(rewritingManager, state, factory, selectionService); From 47067c74f04b701b24a353769931e82019c5ff5b Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Wed, 27 Nov 2019 20:36:02 -0800 Subject: [PATCH 034/461] Return number of conflicts rather than T/F --- .../EncapsulateFieldValidator.cs | 16 ++-- .../EncapsulateFieldValidatorTests.cs | 74 +++++++++++++++++-- 2 files changed, 77 insertions(+), 13 deletions(-) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs index e8a0df0278..cd24e1f46f 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -97,18 +97,18 @@ public bool HasValidEncapsulationAttributes(IFieldEncapsulationAttributes attrib if (!attributes.FieldNameIsExemptFromValidation) { - if (HasNewFieldNameConflicts(attributes, qmn, ignore)) { return false; } + if (HasNewFieldNameConflicts(attributes, qmn, ignore) > 0) { return false; } } - if (HasNewPropertyNameConflicts(attributes, qmn, ignore)) { return false; } + if (HasNewPropertyNameConflicts(attributes, qmn, ignore) > 0) { return false; } return true; } - public bool HasNewPropertyNameConflicts(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, Predicate ignoreThisDeclaration) + public int HasNewPropertyNameConflicts(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, Predicate ignoreThisDeclaration) { + Predicate IsPrivateAccessiblityInOtherModule = (Declaration dec) => dec.QualifiedModuleName != qmn && dec.Accessibility.Equals(Accessibility.Private); Predicate IsInSearchScope = null; - Predicate IsPrivateInOtherModule = (Declaration dec) => dec.QualifiedModuleName != qmn && dec.Accessibility.Equals(Accessibility.Private); if (qmn.ComponentType == ComponentType.ClassModule) { IsInSearchScope = (Declaration dec) => dec.QualifiedModuleName == qmn; @@ -121,7 +121,7 @@ public bool HasNewPropertyNameConflicts(IFieldEncapsulationAttributes attributes var identifierMatches = DeclarationFinder.MatchName(attributes.PropertyName) .Where(match => IsInSearchScope(match) && !ignoreThisDeclaration(match) - && !IsPrivateInOtherModule(match) + && !IsPrivateAccessiblityInOtherModule(match) && !IsEnumOrUDTMemberDeclaration(match) && !match.IsLocalVariable()).ToList(); @@ -138,11 +138,11 @@ public bool HasNewPropertyNameConflicts(IFieldEncapsulationAttributes attributes candidates.Add(efd); } - return identifierMatches.Any() || candidateMatches.Any(); + return identifierMatches.Count() + candidateMatches.Count(); } //FieldNames are always Private, so only look within the same module as the field to encapsulate - public bool HasNewFieldNameConflicts(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, Predicate ignoreThisDeclaration) + public int HasNewFieldNameConflicts(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, Predicate ignoreThisDeclaration) { var identifierMatches = DeclarationFinder.MatchName(attributes.NewFieldName) .Where(match => match.QualifiedModuleName == qmn @@ -166,7 +166,7 @@ public bool HasNewFieldNameConflicts(IFieldEncapsulationAttributes attributes, Q candidates.Add(efd); } - return identifierMatches.Any() || candidateMatches.Any(); + return identifierMatches.Count() + candidateMatches.Count(); } private bool IsEnumOrUDTMemberDeclaration(Declaration candidate) diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs index 66b35953fc..d6f84f539d 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs @@ -12,13 +12,14 @@ using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.Utility; using Rubberduck.Parsing.Symbols; +using System; namespace RubberduckTests.Refactoring.EncapsulateField { [TestFixture] - public class EncapsulateFieldValidatorTests + public class EncapsulateFieldValidatorTests : InteractiveRefactoringTestBase { - //private EncapsulateFieldTestSupport Support { get; } = new EncapsulateFieldTestSupport(); + private EncapsulateFieldTestSupport Support { get; } = new EncapsulateFieldTestSupport(); [TestCase("Number")] [TestCase("Test")] @@ -55,7 +56,7 @@ Public Property Get Test() As Integer mockBuzz }); - Assert.IsTrue(validator.HasNewPropertyNameConflicts(mockFizz.EncapsulationAttributes, mockFizz.QualifiedModuleName, (Declaration dec) => false)); + Assert.Less(0, validator.HasNewPropertyNameConflicts(mockFizz.EncapsulationAttributes, mockFizz.QualifiedModuleName, (Declaration dec) => false)); } } @@ -77,7 +78,23 @@ Public that As TBar "; var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; - var selectedComponentName = vbe.SelectedVBComponent.Name; + CreateAndParse(vbe, ThisTest); + //var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; + //var selectedComponentName = vbe.SelectedVBComponent.Name; + + void ThisTest(IDeclarationFinderProvider declarationProviderProvider) + { + var userInput = new UserInputDataObject("this", encapsulationFlag: true); + userInput.AddAttributeSet("that", encapsulationFlag: true); + userInput.AddUDTMemberNameFlagPairs(("this", "First", true)); + userInput.AddUDTMemberNameFlagPairs(("that", "First", true)); + + var presenterAction = Support.SetParameters(userInput); + + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + encapsulatedWholeNumber.EncapsulationAttributes.PropertyName = "LongValue"; + Assert.Less(0, validator.HasNewPropertyNameConflicts(encapsulatedWholeNumber.EncapsulationAttributes, encapsulatedWholeNumber.QualifiedModuleName, (Declaration dec) => dec.Equals(encapsulatedWholeNumber.Declaration))); + } var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); using (state) @@ -94,7 +111,49 @@ Public that As TBar }); - Assert.IsTrue(validator.HasNewPropertyNameConflicts(thisField.EncapsulationAttributes, thisField.QualifiedModuleName, (Declaration dec) => false)); + Assert.Less(0 ,validator.HasNewPropertyNameConflicts(thisField.EncapsulationAttributes, thisField.QualifiedModuleName, (Declaration dec) => false)); + } + } + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void PropertyNameConflictsWithModuleVariable() + { + string inputCode = +$@" +Public longValue As Long + +Public wholeNumber As String +"; + var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; + CreateAndParse(vbe, ThisTest); + + void ThisTest(IDeclarationFinderProvider declarationProviderProvider) + { + var wholeNumber = declarationProviderProvider.DeclarationFinder.MatchName("wholeNumber").Single(); + var longValue = declarationProviderProvider.DeclarationFinder.MatchName("longValue").Single(); + + var fields = new List(); + + var validator = new EncapsulateFieldNamesValidator(declarationProviderProvider, () => fields); + + var encapsulatedWholeNumber = new EncapsulatedFieldDeclaration(wholeNumber, validator); + var encapsulatedLongValue = new EncapsulatedFieldDeclaration(longValue, validator); + fields.Add(new EncapsulatedFieldDeclaration(wholeNumber, validator)); + fields.Add(new EncapsulatedFieldDeclaration(longValue, validator)); + + encapsulatedWholeNumber.EncapsulationAttributes.PropertyName = "LongValue"; + Assert.Less(0, validator.HasNewPropertyNameConflicts(encapsulatedWholeNumber.EncapsulationAttributes, encapsulatedWholeNumber.QualifiedModuleName, (Declaration dec) => dec.Equals(encapsulatedWholeNumber.Declaration))); + } + } + + private void CreateAndParse(IVBE vbe, Action theTest) + { + //var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); + var state = MockParser.CreateAndParse(vbe); + using (state) + { + theTest(state as IDeclarationFinderProvider); } } @@ -125,5 +184,10 @@ private IFieldEncapsulationAttributes CreateAttributesMock(string targetID, stri mock.SetupGet(m => m.EncapsulateFlag).Returns(encapsulateFlag); return mock.Object; } + + protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) + { + return Support.SupportTestRefactoring(rewritingManager, state, factory, selectionService); + } } } From c385e031b5b97ecd1fcddfe76cad081dc6610b5b Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Thu, 28 Nov 2019 10:19:18 -0800 Subject: [PATCH 035/461] Migration to encapsulation strategies --- .../EncapsulateFieldViewModel.cs | 2 +- .../ViewableEncapsulatedField.cs | 9 +- .../EncapsulateFieldDeclarationFactory.cs | 72 ++++++ .../EncapsulateFieldDecorators.cs | 179 ++++---------- .../EncapsulateField/EncapsulateFieldModel.cs | 233 ++++++------------ .../EncapsulateFieldRefactoring.cs | 111 +-------- .../EncapsulateFieldValidator.cs | 16 +- .../EncapsulatedFieldDeclaration.cs | 37 ++- .../EncapsulateWithBackingFields.cs | 126 ++++++++++ .../EncapsulateWithBackingUserDefinedType.cs | 130 ++++++++++ .../Strategies/EncapsulationStrategiesBase.cs | 102 ++++++++ .../UDTDeclarationGenerator.cs | 25 +- .../EncapsulateFieldValidatorTests.cs | 38 +-- .../EncapsulatedFieldTests.cs | 10 +- .../Refactoring/EncapsulateFieldTests.cs | 6 +- 15 files changed, 629 insertions(+), 467 deletions(-) create mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs create mode 100644 Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs create mode 100644 Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs create mode 100644 Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs index 813f84e4e1..8ee8d1a9e8 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs @@ -27,7 +27,7 @@ public ObservableCollection EncapsulationFields { get { - var flaggedFields = Model.EncapsulationFields.Where(efd => efd.EncapsulateFlag) + var flaggedFields = Model.FlaggedEncapsulationFields //.Where(efd => efd.EncapsulateFlag) .OrderBy(efd => efd.Declaration.IdentifierName); var orderedFields = Model.EncapsulationFields.Except(flaggedFields) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs index 17a94ddc56..f0232b9bbb 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs @@ -10,7 +10,7 @@ namespace Rubberduck.UI.Refactorings.EncapsulateField { public interface IEncapsulatedFieldViewData { - string TargetID { get; set; } + string TargetID { get; } // set; } string PropertyName { set; get; } string NewFieldName { get; } // { set; get; } bool EncapsulateFlag { set; get; } @@ -25,8 +25,8 @@ public interface IEncapsulatedFieldViewData public class ViewableEncapsulatedField : IEncapsulatedFieldViewData { - private IEncapsulatedFieldDeclaration _efd; - public ViewableEncapsulatedField(IEncapsulatedFieldDeclaration efd) + private IEncapsulateFieldCandidate _efd; + public ViewableEncapsulatedField(IEncapsulateFieldCandidate efd) { _efd = efd; } @@ -34,7 +34,8 @@ public ViewableEncapsulatedField(IEncapsulatedFieldDeclaration efd) public Visibility FieldNameVisibility => _efd.IsUDTMember || !_efd.EncapsulateFlag ? Visibility.Collapsed : Visibility.Visible; public Visibility PropertyNameVisibility => !_efd.EncapsulateFlag ? Visibility.Collapsed : Visibility.Visible; public bool HasValidEncapsulationAttributes => _efd.HasValidEncapsulationAttributes; - public string TargetID { get => _efd.TargetID; set => _efd.TargetID = value; } + public string TargetID { get => _efd.TargetID; } + //set => _efd.TargetID = value; } public bool IsReadOnly { get => _efd.IsReadOnly; set => _efd.IsReadOnly = value; } public bool CanBeReadWrite => _efd.CanBeReadWrite; public string PropertyName { get => _efd.PropertyName; set => _efd.PropertyName = value; } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs new file mode 100644 index 0000000000..4ed5f13ca1 --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs @@ -0,0 +1,72 @@ +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Symbols; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + public class EncapsulateFieldDeclarationFactory + { + public static IEncapsulateFieldCandidate EncapsulateDeclaration(Declaration target, IEncapsulateFieldNamesValidator validator) + { + var candidate = new EncapsulateFieldCandidate(target, validator); + + if (target.IsArray) + { + candidate.EncapsulationAttributes.ImplementLetSetterType = false; + candidate.EncapsulationAttributes.ImplementSetSetterType = false; + candidate.EncapsulationAttributes.AsTypeName = Tokens.Variant; + candidate.CanBeReadWrite = false; + candidate.IsReadOnly = true; + return candidate; + } + else if (target.AsTypeName.Equals(Tokens.Variant)) + { + candidate.EncapsulationAttributes.ImplementLetSetterType = true; + candidate.EncapsulationAttributes.ImplementSetSetterType = true; + return candidate; + } + else if (target.IsObject) + { + candidate.EncapsulationAttributes.ImplementLetSetterType = false; + candidate.EncapsulationAttributes.ImplementSetSetterType = true; + return candidate; + } + else if (target.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.UserDefinedType) ?? false) + { + candidate.EncapsulationAttributes.ImplementLetSetterType = true; + candidate.EncapsulationAttributes.ImplementSetSetterType = false; + return candidate; + } + else if (target.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)) + { + //TODO: This may need to pass back thru using it's AsTypeName + candidate.EncapsulationAttributes.ImplementLetSetterType = true; + candidate.EncapsulationAttributes.ImplementSetSetterType = false; + return candidate; + } + + candidate.EncapsulationAttributes.ImplementLetSetterType = true; + candidate.EncapsulationAttributes.ImplementSetSetterType = false; + return candidate; + } + + //public static IEncapsulatedFieldDeclaration EncapsulateDeclaration(Declaration udtMember, IEncapsulatedFieldDeclaration instantiatingField, IEncapsulateFieldNamesValidator validator) + //{ + // var targetIDPair = new KeyValuePair(udtMember, $"{instantiatingField.Declaration.IdentifierName}.{udtMember.IdentifierName}"); + // var encapsulatedUdtMember = EncapsulateDeclaration(udtMember, validator); + // return EncapsulatedUserDefinedTypeMember.Decorate(encapsulatedUdtMember, instantiatingField, false); // HasMultipleInstantiationsOfSameType(instantiatingField.Declaration, targetIDPair)); + //} + + // private bool HasMultipleInstantiationsOfSameType(Declaration udtVariable, KeyValuePair targetIDPair) + // { + // var udt = _udtFieldToUdtDeclarationMap[udtVariable].Item1; + // var otherVariableOfTheSameType = _udtFieldToUdtDeclarationMap.Keys.Where(k => k != udtVariable && _udtFieldToUdtDeclarationMap[k].Item1 == udt); + // return otherVariableOfTheSameType.Any(); + // } + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs index 0d1e224615..541e452926 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs @@ -8,176 +8,91 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public class EncapsulateFieldDecoratorBase : IEncapsulatedFieldDeclaration + public class EncapsulatedUserDefinedTypeMember : IEncapsulateFieldCandidate //: EncapsulateFieldDecoratorBase { - protected IEncapsulatedFieldDeclaration _decorated; - - public EncapsulateFieldDecoratorBase(IEncapsulatedFieldDeclaration efd) + private IEncapsulateFieldCandidate _candidate; + private IFieldEncapsulationAttributes _udtVariableAttributes; + private bool _nameResolveProperty; + private string _originalVariableName; + private string _targetID; + public EncapsulatedUserDefinedTypeMember(IEncapsulateFieldCandidate candidate, IEncapsulateFieldCandidate udtVariable, bool propertyIdentifierRequiresNameResolution) { - _decorated = efd; - TargetID = efd.Declaration.IdentifierName; - } + _candidate = candidate; + _originalVariableName = udtVariable.Declaration.IdentifierName; + _nameResolveProperty = propertyIdentifierRequiresNameResolution; + _udtVariableAttributes = udtVariable.EncapsulationAttributes; - public Declaration Declaration => _decorated.Declaration; + EncapsulationAttributes.PropertyName = BuildPropertyName(); + if (EncapsulationAttributes is FieldEncapsulationAttributes fea) + { + fea.FieldReferenceExpressionFunc = + () => { var prefix = _udtVariableAttributes.EncapsulateFlag + ? _udtVariableAttributes.NewFieldName + : _udtVariableAttributes.TargetName; - public DeclarationType DeclarationType => _decorated.DeclarationType; + return $"{prefix}.{EncapsulationAttributes.NewFieldName}"; + }; + } - public IFieldEncapsulationAttributes EncapsulationAttributes - { - get => _decorated.EncapsulationAttributes; - set => _decorated.EncapsulationAttributes = value; + _targetID = $"{udtVariable.Declaration.IdentifierName}.{Declaration.IdentifierName}"; + candidate.IsUDTMember = true; } - public string TargetID + public Declaration Declaration => _candidate.Declaration; + + public DeclarationType DeclarationType => _candidate.DeclarationType; + + public IFieldEncapsulationAttributes EncapsulationAttributes { - get => _decorated.TargetID; - set => _decorated.TargetID = value; + get => _candidate.EncapsulationAttributes; + set => _candidate.EncapsulationAttributes = value; } public bool IsReadOnly { - get => _decorated.EncapsulationAttributes.ReadOnly; - set => _decorated.EncapsulationAttributes.ReadOnly = value; + get => _candidate.EncapsulationAttributes.ReadOnly; + set => _candidate.EncapsulationAttributes.ReadOnly = value; } public bool EncapsulateFlag { - get => _decorated.EncapsulateFlag; - set => _decorated.EncapsulateFlag = value; + get => _candidate.EncapsulateFlag; + set => _candidate.EncapsulateFlag = value; } public bool CanBeReadWrite { - get => _decorated.CanBeReadWrite; - set => _decorated.CanBeReadWrite = value; + get => _candidate.CanBeReadWrite; + set => _candidate.CanBeReadWrite = value; } public string PropertyName { - get => _decorated.EncapsulationAttributes.PropertyName; - set => _decorated.EncapsulationAttributes.PropertyName = value; + get => _candidate.EncapsulationAttributes.PropertyName; + set => _candidate.EncapsulationAttributes.PropertyName = value; } public string NewFieldName { - get => _decorated.EncapsulationAttributes.NewFieldName; + get => _candidate.EncapsulationAttributes.NewFieldName; } - public string AsTypeName => _decorated.EncapsulationAttributes.AsTypeName; + public string AsTypeName => _candidate.EncapsulationAttributes.AsTypeName; public bool IsUDTMember { - get => _decorated.IsUDTMember; - set => _decorated.IsUDTMember = value; - } - - public bool HasValidEncapsulationAttributes - => _decorated.HasValidEncapsulationAttributes; - - public QualifiedModuleName QualifiedModuleName => _decorated.QualifiedModuleName; - - public IEnumerable References => _decorated.References; - } - - public class EncapsulatedValueType : EncapsulateFieldDecoratorBase - { - private EncapsulatedValueType(IEncapsulatedFieldDeclaration efd) - : base(efd) - { - EncapsulationAttributes.ImplementLetSetterType = true; - EncapsulationAttributes.ImplementSetSetterType = false; - } - - public static IEncapsulatedFieldDeclaration Decorate(IEncapsulatedFieldDeclaration efd) - => new EncapsulatedValueType(efd); - } - - public class EncapsulatedUserDefinedType : EncapsulateFieldDecoratorBase - { - - private EncapsulatedUserDefinedType(IEncapsulatedFieldDeclaration efd) - : base(efd) - { - EncapsulationAttributes.ImplementLetSetterType = true; - EncapsulationAttributes.ImplementSetSetterType = false; - } - - public static IEncapsulatedFieldDeclaration Decorate(IEncapsulatedFieldDeclaration efd) - => new EncapsulatedUserDefinedType(efd); - } - - public class EncapsulatedVariantType : EncapsulateFieldDecoratorBase - { - private EncapsulatedVariantType(IEncapsulatedFieldDeclaration efd) - : base(efd) - { - EncapsulationAttributes.ImplementLetSetterType = true; - EncapsulationAttributes.ImplementSetSetterType = true; - } - - public static IEncapsulatedFieldDeclaration Decorate(IEncapsulatedFieldDeclaration efd) - => new EncapsulatedVariantType(efd); - } - - public class EncapsulatedObjectType : EncapsulateFieldDecoratorBase - { - private EncapsulatedObjectType(IEncapsulatedFieldDeclaration efd) - : base(efd) - { - EncapsulationAttributes.ImplementLetSetterType = false; - EncapsulationAttributes.ImplementSetSetterType = true; + get => _candidate.IsUDTMember; + set => _candidate.IsUDTMember = value; } - public static IEncapsulatedFieldDeclaration Decorate(IEncapsulatedFieldDeclaration efd) - => new EncapsulatedObjectType(efd); - } - - public class EncapsulatedArrayType : EncapsulateFieldDecoratorBase - { - private EncapsulatedArrayType(IEncapsulatedFieldDeclaration efd) - : base(efd) - { - EncapsulationAttributes.ImplementLetSetterType = false; - EncapsulationAttributes.ImplementSetSetterType = false; - EncapsulationAttributes.AsTypeName = Tokens.Variant; - CanBeReadWrite = false; - IsReadOnly = true; - } + public bool HasValidEncapsulationAttributes + => _candidate.HasValidEncapsulationAttributes; - public static IEncapsulatedFieldDeclaration Decorate(IEncapsulatedFieldDeclaration efd) - => new EncapsulatedArrayType(efd); - } + public QualifiedModuleName QualifiedModuleName => _candidate.QualifiedModuleName; - public class EncapsulatedUserDefinedTypeMember : EncapsulateFieldDecoratorBase - { - private IFieldEncapsulationAttributes _udtVariableAttributes; - private bool _nameResolveProperty; - private string _originalVariableName; - private EncapsulatedUserDefinedTypeMember(IEncapsulatedFieldDeclaration efd, EncapsulatedUserDefinedType udtVariable, bool propertyIdentifierRequiresNameResolution) - : base(efd) - { - _originalVariableName = udtVariable.Declaration.IdentifierName; - _nameResolveProperty = propertyIdentifierRequiresNameResolution; - _udtVariableAttributes = udtVariable.EncapsulationAttributes; - - EncapsulationAttributes.PropertyName = BuildPropertyName(); - if (EncapsulationAttributes is FieldEncapsulationAttributes fea) - { - fea.FieldReferenceExpressionFunc = - () => { var prefix = _udtVariableAttributes.EncapsulateFlag - ? _udtVariableAttributes.NewFieldName - : _udtVariableAttributes.TargetName; - - return $"{prefix}.{EncapsulationAttributes.NewFieldName}"; - }; - } - - efd.TargetID = $"{udtVariable.Declaration.IdentifierName}.{Declaration.IdentifierName}"; - efd.IsUDTMember = true; - } + public IEnumerable References => _candidate.References; - public static IEncapsulatedFieldDeclaration Decorate(IEncapsulatedFieldDeclaration efd, EncapsulatedUserDefinedType udtVariable, bool nameResolveProperty) - => new EncapsulatedUserDefinedTypeMember(efd, udtVariable, nameResolveProperty); + public string TargetID => _targetID; private string BuildPropertyName() { diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index 54b0f4e817..5f1953ef3c 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -3,8 +3,11 @@ using System.Linq; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings.Common; +using Rubberduck.Refactorings.EncapsulateField.Strategies; using Rubberduck.SmartIndenter; +using Rubberduck.VBEditor; namespace Rubberduck.Refactorings.EncapsulateField { @@ -14,210 +17,112 @@ public class EncapsulateFieldModel : IRefactoringModel private const string DEFAULT_ENCAPSULATION_UDT_FIELD_IDENTIFIER = "this"; private readonly IIndenter _indenter; + private readonly IDeclarationFinderProvider _declarationFinderProvider; private readonly IEncapsulateFieldNamesValidator _validator; private readonly Func _previewFunc; + private QualifiedModuleName _targetQMN; private IDictionary)> _udtFieldToUdtDeclarationMap = new Dictionary)>(); private IEnumerable UdtFields => _udtFieldToUdtDeclarationMap.Keys; private IEnumerable UdtFieldMembers(Declaration udtField) => _udtFieldToUdtDeclarationMap[udtField].Item2; - private Dictionary _encapsulateFieldDeclarations = new Dictionary(); + private Dictionary _candidates = new Dictionary(); - public EncapsulateFieldModel(Declaration target, IEnumerable allMemberFields, IDictionary)> udtFieldToUdtDeclarationMap, IIndenter indenter, IEncapsulateFieldNamesValidator validator, Func previewFunc) + public EncapsulateFieldModel(Declaration target, IDeclarationFinderProvider declarationFinderProvider, /*IEnumerable allMemberFields, IDictionary)> udtFieldToUdtDeclarationMap,*/ IIndenter indenter, IEncapsulateFieldNamesValidator validator, Func previewFunc) { + _declarationFinderProvider = declarationFinderProvider; _indenter = indenter; _validator = validator; - _udtFieldToUdtDeclarationMap = udtFieldToUdtDeclarationMap; _previewFunc = previewFunc; + _targetQMN = target.QualifiedModuleName; - foreach (var field in allMemberFields.Except(UdtFields)) + var encapsulationCandidateFields = _declarationFinderProvider.DeclarationFinder + .Members(_targetQMN) + .Where(v => v.IsMemberVariable() && !v.IsWithEvents); + + _udtFieldToUdtDeclarationMap = encapsulationCandidateFields + .Where(v => v.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.UserDefinedType) ?? false) + .Select(uv => CreateUDTTuple(uv)) + .ToDictionary(key => key.UDTVariable, element => (element.UserDefinedType, element.UDTMembers)); + + foreach (var field in encapsulationCandidateFields.Except(UdtFields)) { var efd = EncapsulateDeclaration(field); - _encapsulateFieldDeclarations.Add(efd.TargetID, efd); + _candidates.Add(efd.TargetID, efd); } - AddUDTEncapsulationFields(udtFieldToUdtDeclarationMap); + AddUDTEncapsulationFields(_udtFieldToUdtDeclarationMap); this[target].EncapsulationAttributes.EncapsulateFlag = true; - } - - public IEnumerable FlaggedEncapsulationFields - => _encapsulateFieldDeclarations.Values.Where(v => v.EncapsulationAttributes.EncapsulateFlag); - public IEnumerable EncapsulationFieldIDs - => _encapsulateFieldDeclarations.Keys; - - public IEnumerable EncapsulationFields - => _encapsulateFieldDeclarations.Values; + //Maybe this should be passed in + EncapsulationStrategy = new EncapsulateWithBackingFields(_targetQMN, _indenter); + } - public IEncapsulatedFieldDeclaration this[string encapsulatedFieldIdentifier] - => _encapsulateFieldDeclarations[encapsulatedFieldIdentifier]; + public IEnumerable FlaggedEncapsulationFields + => _candidates.Values.Where(v => v.EncapsulationAttributes.EncapsulateFlag); - public IEncapsulatedFieldDeclaration this[Declaration fieldDeclaration] - => _encapsulateFieldDeclarations.Values.Where(efd => efd.Declaration.Equals(fieldDeclaration)).Select(encapsulatedField => encapsulatedField).Single(); + public IEnumerable EncapsulationFields + => _candidates.Values; - public bool EncapsulateWithUDT { set; get; } + public IEncapsulateFieldCandidate this[string encapsulatedFieldIdentifier] + => _candidates[encapsulatedFieldIdentifier]; - public string EncapsulateWithUDT_TypeIdentifier { set; get; } = DEFAULT_ENCAPSULATION_UDT_IDENTIFIER; + public IEncapsulateFieldCandidate this[Declaration fieldDeclaration] + => _candidates.Values.Where(efd => efd.Declaration.Equals(fieldDeclaration)).Select(encapsulatedField => encapsulatedField).Single(); - public string EncapsulateWithUDT_FieldName { set; get; } = DEFAULT_ENCAPSULATION_UDT_FIELD_IDENTIFIER; + public IEncapsulateFieldStrategy EncapsulationStrategy { set; get; } - public IList PropertiesContent + public bool EncapsulateWithUDT { - get + set { - var textBlocks = new List(); - foreach (var field in FlaggedEncapsulationFields) - { - if (EncapsulateWithUDT && field is EncapsulatedUserDefinedTypeMember) - { - continue; - } - textBlocks.Add(BuildPropertiesTextBlock(field.EncapsulationAttributes)); - } - return textBlocks; + EncapsulationStrategy = value + ? new EncapsulateWithBackingUserDefinedType(_targetQMN, _indenter) as IEncapsulateFieldStrategy + : new EncapsulateWithBackingFields(_targetQMN, _indenter) as IEncapsulateFieldStrategy; + //This probably should go - or be in the ctor + EncapsulationStrategy.UdtMemberTargetIDToParentMap = _udtMemberTargetIDToParentMap; } - } - public string EncapsulateInUDT_UDTMemberProperty(IEncapsulatedFieldDeclaration udtMember) - { - var parentField = _udtMemberTargetIDToParentMap[udtMember.TargetID]; - var generator = new PropertyGenerator - { - PropertyName = udtMember.PropertyName, - AsTypeName = udtMember.AsTypeName, - BackingField = $"{EncapsulateWithUDT_FieldName}.{parentField.PropertyName}.{udtMember.PropertyName}", + get => EncapsulationStrategy is EncapsulateWithBackingUserDefinedType; + } - ParameterName = udtMember.EncapsulationAttributes.ParameterName, - GenerateSetter = udtMember.EncapsulationAttributes.ImplementSetSetterType, - GenerateLetter = udtMember.EncapsulationAttributes.ImplementLetSetterType - }; + //What to do with these as far as IStrategy goes - only here to support the view model + public string EncapsulateWithUDT_TypeIdentifier { set; get; } = DEFAULT_ENCAPSULATION_UDT_IDENTIFIER; - var propertyTextLines = generator.AllPropertyCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None); - return string.Join(Environment.NewLine, _indenter.Indent(propertyTextLines, true)); - } + public string EncapsulateWithUDT_FieldName { set; get; } = DEFAULT_ENCAPSULATION_UDT_FIELD_IDENTIFIER; public string PreviewRefactoring() { return _previewFunc(this); } - public IEncapsulateFieldNewContentProvider NewContent(string postScript = null) - { - var newContent = new EncapsulateFieldNewContent(); - newContent = LoadNewDeclarationsContent(newContent); - newContent = LoadNewPropertiesContent(newContent, postScript); - return newContent; - } - - public EncapsulateFieldNewContent LoadNewPropertiesContent(EncapsulateFieldNewContent newContent, string postScript) - { - if (!FlaggedEncapsulationFields.Any()) { return newContent; } - - newContent.AddCodeBlock($"{string.Join($"{Environment.NewLine}{Environment.NewLine}", PropertiesContent)}"); - if (postScript?.Length > 0) - { - newContent.AddCodeBlock($"{postScript}{Environment.NewLine}{Environment.NewLine}"); - } - return newContent; - } - - public IEncapsulateFieldNewContentProvider NewContentPostscript(IEncapsulateFieldNewContentProvider newContent, string postScript) - { - newContent.AddCodeBlock($"{Environment.NewLine}{postScript}"); - return newContent as IEncapsulateFieldNewContentProvider; - } - - public EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNewContent newContent) - { - var nonUdtMemberFields = FlaggedEncapsulationFields - .Where(encFld => encFld.Declaration.IsVariable()); - - if (EncapsulateWithUDT) - { - var udt = new UDTDeclarationGenerator(EncapsulateWithUDT_TypeIdentifier, _indenter); - foreach (var nonUdtMemberField in nonUdtMemberFields) - { - udt.AddMember(nonUdtMemberField); - } - newContent.AddDeclarationBlock(udt.TypeDeclarationBlock); - newContent.AddDeclarationBlock(udt.FieldDeclaration(EncapsulateWithUDT_FieldName)); - - var udtMemberFields = FlaggedEncapsulationFields.Where(efd => efd.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)); - foreach ( var udtMember in udtMemberFields) - { - newContent.AddCodeBlock(EncapsulateInUDT_UDTMemberProperty(udtMember)); - } - - return newContent; - } - - foreach (var nonUdtMemberField in nonUdtMemberFields) - { - var attributes = nonUdtMemberField.EncapsulationAttributes; - - if (nonUdtMemberField.Declaration.Accessibility == Accessibility.Private && attributes.NewFieldName.Equals(nonUdtMemberField.Declaration.IdentifierName)) - { - continue; - } - - if (nonUdtMemberField.Declaration.IsDeclaredInList()) - { - var targetIdentifier = nonUdtMemberField.Declaration.Context.GetText().Replace(attributes.TargetName, attributes.NewFieldName); - var newField = nonUdtMemberField.Declaration.IsTypeSpecified ? $"{Tokens.Private} {targetIdentifier}" : $"{Tokens.Private} {targetIdentifier} {Tokens.As} {nonUdtMemberField.Declaration.AsTypeName}"; - - newContent.AddDeclarationBlock(newField); - } - } - return newContent; - } - - private Dictionary _udtMemberTargetIDToParentMap { get; } = new Dictionary(); + private Dictionary _udtMemberTargetIDToParentMap { get; } = new Dictionary(); private void AddUDTEncapsulationFields(IDictionary)> udtFieldToTypeMap) { foreach (var udtField in udtFieldToTypeMap.Keys) { - var udtEncapsulation = DecorateUDTVariableDeclaration(udtField); - _encapsulateFieldDeclarations.Add(udtEncapsulation.TargetID, udtEncapsulation); + var udtEncapsulation = EncapsulateDeclaration(udtField); + _candidates.Add(udtEncapsulation.TargetID, udtEncapsulation); foreach (var udtMember in UdtFieldMembers(udtField)) { var encapsulatedUdtMember = EncapsulateDeclaration(udtMember); - encapsulatedUdtMember = DecorateUDTMember(encapsulatedUdtMember, udtEncapsulation as EncapsulatedUserDefinedType); - _encapsulateFieldDeclarations.Add(encapsulatedUdtMember.TargetID, encapsulatedUdtMember); + encapsulatedUdtMember = DecorateUDTMember(encapsulatedUdtMember, udtEncapsulation as IEncapsulateFieldCandidate); + _candidates.Add(encapsulatedUdtMember.TargetID, encapsulatedUdtMember); _udtMemberTargetIDToParentMap.Add(encapsulatedUdtMember.TargetID, udtEncapsulation); } } } - private IEncapsulatedFieldDeclaration EncapsulateDeclaration(Declaration target) - { - var encapsulated = new EncapsulatedFieldDeclaration(target, _validator); - if (target.IsArray) - { - return EncapsulatedArrayType.Decorate(encapsulated); - } - else if (target.AsTypeName.Equals(Tokens.Variant)) - { - return EncapsulatedVariantType.Decorate(encapsulated); - } - else if (target.IsObject) - { - return EncapsulatedObjectType.Decorate(encapsulated); - } - return EncapsulatedValueType.Decorate(encapsulated); - } + private IEncapsulateFieldCandidate EncapsulateDeclaration(Declaration target) + => EncapsulateFieldDeclarationFactory.EncapsulateDeclaration(target, _validator); - private IEncapsulatedFieldDeclaration DecorateUDTVariableDeclaration(Declaration target) - { - return EncapsulatedUserDefinedType.Decorate(new EncapsulatedFieldDeclaration(target, _validator)); - } - - private IEncapsulatedFieldDeclaration DecorateUDTMember(IEncapsulatedFieldDeclaration udtMember, EncapsulatedUserDefinedType udtVariable) + private IEncapsulateFieldCandidate DecorateUDTMember(IEncapsulateFieldCandidate udtMember, IEncapsulateFieldCandidate udtVariable) { var targetIDPair = new KeyValuePair(udtMember.Declaration,$"{udtVariable.Declaration.IdentifierName}.{udtMember.Declaration.IdentifierName}"); - return EncapsulatedUserDefinedTypeMember.Decorate(udtMember, udtVariable, HasMultipleInstantiationsOfSameType(udtVariable.Declaration, targetIDPair)); + return new EncapsulatedUserDefinedTypeMember(udtMember, udtVariable, HasMultipleInstantiationsOfSameType(udtVariable.Declaration, targetIDPair)); } private bool HasMultipleInstantiationsOfSameType(Declaration udtVariable, KeyValuePair targetIDPair) @@ -227,22 +132,22 @@ private bool HasMultipleInstantiationsOfSameType(Declaration udtVariable, KeyVal return otherVariableOfTheSameType.Any(); } - private string BuildPropertiesTextBlock(IFieldEncapsulationAttributes attributes) + private (Declaration UDTVariable, Declaration UserDefinedType, IEnumerable UDTMembers) CreateUDTTuple(Declaration udtVariable) { - var generator = new PropertyGenerator - { - PropertyName = attributes.PropertyName, - AsTypeName = attributes.AsTypeName, - BackingField = EncapsulateWithUDT - ? $"{EncapsulateWithUDT_FieldName}.{attributes.PropertyName}" - : attributes.FieldReferenceExpression, - ParameterName = attributes.ParameterName, - GenerateSetter = attributes.ImplementSetSetterType, - GenerateLetter = attributes.ImplementLetSetterType - }; - - var propertyTextLines = generator.AllPropertyCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None); - return string.Join(Environment.NewLine, _indenter.Indent(propertyTextLines, true)); + var userDefinedTypeDeclaration = _declarationFinderProvider.DeclarationFinder + .UserDeclarations(DeclarationType.UserDefinedType) + .Where(ut => ut.IdentifierName.Equals(udtVariable.AsTypeName) + && (ut.Accessibility.Equals(Accessibility.Private) + && ut.QualifiedModuleName == udtVariable.QualifiedModuleName) + || (ut.Accessibility != Accessibility.Private)) + .SingleOrDefault(); + + var udtMembers = _declarationFinderProvider.DeclarationFinder + .UserDeclarations(DeclarationType.UserDefinedTypeMember) + .Where(utm => userDefinedTypeDeclaration.IdentifierName == utm.ParentDeclaration.IdentifierName + && utm.QualifiedModuleName == userDefinedTypeDeclaration.QualifiedModuleName); + + return (udtVariable, userDefinedTypeDeclaration, udtMembers); } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index dc233219a0..858c4c142e 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -64,19 +64,9 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) _targetQMN = target.QualifiedModuleName; - var encapsulationCandidateFields = _declarationFinderProvider.DeclarationFinder - .Members(_targetQMN) - .Where(v => v.IsMemberVariable() && !v.IsWithEvents); - - var userDefinedTypeFieldToTypeDeclarationMap = encapsulationCandidateFields - .Where(v => v.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.UserDefinedType) ?? false) - .Select(uv => CreateUDTTuple(uv)) - .ToDictionary(key => key.UDTVariable, element => (element.UserDefinedType, element.UDTMembers)); - Model = new EncapsulateFieldModel( target, - encapsulationCandidateFields, - userDefinedTypeFieldToTypeDeclarationMap, + _declarationFinderProvider, _indenter, _validator, PreviewRewrite); @@ -84,18 +74,16 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) return Model; } - private IEnumerable FlaggedFields() => Model?.FlaggedEncapsulationFields ?? Enumerable.Empty(); + //Get rid of Model property after improving the validator ctor + private IEnumerable FlaggedFields() => Model?.FlaggedEncapsulationFields ?? Enumerable.Empty(); protected override void RefactorImpl(EncapsulateFieldModel model) { - Model = model; - var rewriteSession = RefactorRewrite(model, RewritingManager.CheckOutCodePaneSession()); - - var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, _targetQMN); + //Model = model; + var strategy = model.EncapsulationStrategy; - RewriterRemoveWorkAround.RemoveDeclarationsFromVariableLists(rewriter); - - rewriter.InsertNewContent(CodeSectionStartIndex, model.NewContent()); + var rewriteSession = strategy.RefactorRewrite(model, RewritingManager.CheckOutCodePaneSession()); + strategy.InsertNewContent(CodeSectionStartIndex, model, rewriteSession); if (!rewriteSession.TryRewrite()) { @@ -105,16 +93,12 @@ protected override void RefactorImpl(EncapsulateFieldModel model) private string PreviewRewrite(EncapsulateFieldModel model) { - var scratchPadRewriteSession = RefactorRewrite(model, RewritingManager.CheckOutCodePaneSession()); - - var previewRewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(scratchPadRewriteSession, _targetQMN); - - RewriterRemoveWorkAround.RemoveDeclarationsFromVariableLists(previewRewriter); - - var newContent = model.NewContent("'<===== No Changes below this line =====>"); + var strategy = model.EncapsulationStrategy; + var scratchPadRewriteSession = strategy.RefactorRewrite(model, RewritingManager.CheckOutCodePaneSession()); - previewRewriter.InsertNewContent(CodeSectionStartIndex, newContent); + strategy.InsertNewContent(CodeSectionStartIndex, model, scratchPadRewriteSession, true); + var previewRewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(scratchPadRewriteSession, _targetQMN); var preview = previewRewriter.GetText(); var counter = 0; @@ -126,21 +110,6 @@ private string PreviewRewrite(EncapsulateFieldModel model) return preview; } - private IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) - { - var nonUdtMemberFields = model.FlaggedEncapsulationFields - .Where(encFld => encFld.Declaration.IsVariable()); - - foreach (var nonUdtMemberField in nonUdtMemberFields) - { - var attributes = nonUdtMemberField.EncapsulationAttributes; - ModifyEncapsulatedVariable(nonUdtMemberField, attributes, rewriteSession, model.EncapsulateWithUDT); - RenameReferences(nonUdtMemberField, attributes.PropertyName ?? nonUdtMemberField.Declaration.IdentifierName, rewriteSession); - } - - return rewriteSession; - } - private int? CodeSectionStartIndex { get @@ -155,63 +124,5 @@ private int? CodeSectionStartIndex return codeSectionStartIndex; } } - - private void ModifyEncapsulatedVariable(IEncapsulatedFieldDeclaration target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession, bool asUDT = false) //, EncapsulateFieldNewContent newContent) - { - var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, _targetQMN); - - if (asUDT) - { - RewriterRemoveWorkAround.Remove(target.Declaration, rewriter); - //rewriter.Remove(target.Declaration); - return; - } - - if (target.Declaration.Accessibility == Accessibility.Private && attributes.NewFieldName.Equals(target.Declaration.IdentifierName)) - { - rewriter.MakeImplicitDeclarationTypeExplicit(target.Declaration); - return; - } - - if (target.Declaration.IsDeclaredInList()) - { - RewriterRemoveWorkAround.Remove(target.Declaration, rewriter); - //rewriter.Remove(target.Declaration); - } - else - { - rewriter.Rename(target.Declaration, attributes.NewFieldName); - rewriter.SetVariableVisiblity(target.Declaration, Accessibility.Private.TokenString()); - rewriter.MakeImplicitDeclarationTypeExplicit(target.Declaration); - } - return; - } - - private void RenameReferences(IEncapsulatedFieldDeclaration efd, string propertyName, IRewriteSession rewriteSession) - { - foreach (var reference in efd.Declaration.References) - { - var rewriter = rewriteSession.CheckOutModuleRewriter(reference.QualifiedModuleName); - rewriter.Replace(reference.Context, propertyName ?? efd.Declaration.IdentifierName); - } - } - - private (Declaration UDTVariable, Declaration UserDefinedType, IEnumerable UDTMembers) CreateUDTTuple(Declaration udtVariable) - { - var userDefinedTypeDeclaration = _declarationFinderProvider.DeclarationFinder - .UserDeclarations(DeclarationType.UserDefinedType) - .Where(ut => ut.IdentifierName.Equals(udtVariable.AsTypeName) - && (ut.Accessibility.Equals(Accessibility.Private) - && ut.QualifiedModuleName == udtVariable.QualifiedModuleName) - || (ut.Accessibility != Accessibility.Private)) - .SingleOrDefault(); - - var udtMembers = _declarationFinderProvider.DeclarationFinder - .UserDeclarations(DeclarationType.UserDefinedTypeMember) - .Where(utm => userDefinedTypeDeclaration.IdentifierName == utm.ParentDeclaration.IdentifierName - && utm.QualifiedModuleName == userDefinedTypeDeclaration.QualifiedModuleName); - - return (udtVariable, userDefinedTypeDeclaration, udtMembers); - } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs index cd24e1f46f..bca50a8335 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -78,8 +78,8 @@ public interface IEncapsulateFieldNamesValidator public class EncapsulateFieldNamesValidator : IEncapsulateFieldNamesValidator { private readonly IDeclarationFinderProvider _declarationFinderProvider; - private Func> _selectedFieldsRetriever; - public EncapsulateFieldNamesValidator(IDeclarationFinderProvider declarationFinderProvider, Func> selectedFieldsRetriever = null) + private Func> _selectedFieldsRetriever; + public EncapsulateFieldNamesValidator(IDeclarationFinderProvider declarationFinderProvider, Func> selectedFieldsRetriever = null) { _declarationFinderProvider = declarationFinderProvider; _selectedFieldsRetriever = selectedFieldsRetriever; @@ -125,9 +125,9 @@ public int HasNewPropertyNameConflicts(IFieldEncapsulationAttributes attributes, && !IsEnumOrUDTMemberDeclaration(match) && !match.IsLocalVariable()).ToList(); - var candidates = new List(); - var candidateMatches = new List(); - var fields = _selectedFieldsRetriever is null ? Enumerable.Empty() : _selectedFieldsRetriever(); + var candidates = new List(); + var candidateMatches = new List(); + var fields = _selectedFieldsRetriever is null ? Enumerable.Empty() : _selectedFieldsRetriever(); foreach (var efd in fields) { var matches = candidates.Where(c => c.PropertyName.EqualsVBAIdentifier(efd.PropertyName)); @@ -150,10 +150,10 @@ public int HasNewFieldNameConflicts(IFieldEncapsulationAttributes attributes, Qu && !IsEnumOrUDTMemberDeclaration(match) && !match.IsLocalVariable()).ToList(); - var candidates = new List(); - var candidateMatches = new List(); + var candidates = new List(); + var candidateMatches = new List(); var fields = _selectedFieldsRetriever is null - ? Enumerable.Empty() + ? Enumerable.Empty() : _selectedFieldsRetriever(); foreach (var efd in fields) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs index 8c57fe9805..0762d04662 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs @@ -9,11 +9,11 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface IEncapsulatedFieldDeclaration + public interface IEncapsulateFieldCandidate { Declaration Declaration { get; } DeclarationType DeclarationType { get; } - string TargetID { get; set; } + string TargetID { get; } IFieldEncapsulationAttributes EncapsulationAttributes { set; get; } bool IsReadOnly { set; get; } bool CanBeReadWrite { set; get; } @@ -27,39 +27,34 @@ public interface IEncapsulatedFieldDeclaration IEnumerable References { get; } } - public class EncapsulatedFieldDeclaration : IEncapsulatedFieldDeclaration + public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate { - protected Declaration _decorated; + protected Declaration _target; private IFieldEncapsulationAttributes _attributes; private IEncapsulateFieldNamesValidator _validator; - public EncapsulatedFieldDeclaration(Declaration declaration, IEncapsulateFieldNamesValidator validator) + public EncapsulateFieldCandidate(Declaration declaration, IEncapsulateFieldNamesValidator validator) { - _decorated = declaration; - _attributes = new FieldEncapsulationAttributes(_decorated); + _target = declaration; + _attributes = new FieldEncapsulationAttributes(_target); _validator = validator; - TargetID = declaration.IdentifierName; + //TargetID = declaration.IdentifierName; - var isValidAttributeSet = _validator.HasValidEncapsulationAttributes(_attributes, declaration.QualifiedModuleName, (Declaration dec) => dec.Equals(_decorated)); + var isValidAttributeSet = _validator.HasValidEncapsulationAttributes(_attributes, declaration.QualifiedModuleName, (Declaration dec) => dec.Equals(_target)); for (var idx = 2; idx < 9 && !isValidAttributeSet; idx++) { _attributes.NewFieldName = $"{declaration.IdentifierName}{idx}"; - isValidAttributeSet = _validator.HasValidEncapsulationAttributes(_attributes, declaration.QualifiedModuleName, (Declaration dec) => dec.Equals(_decorated)); + isValidAttributeSet = _validator.HasValidEncapsulationAttributes(_attributes, declaration.QualifiedModuleName, (Declaration dec) => dec.Equals(_target)); } } - public Declaration Declaration => _decorated; + public Declaration Declaration => _target; - public DeclarationType DeclarationType => _decorated.DeclarationType; + public DeclarationType DeclarationType => _target.DeclarationType; - public bool HasValidEncapsulationAttributes - { - get - { - return _validator.HasValidEncapsulationAttributes(EncapsulationAttributes, QualifiedModuleName, (Declaration dec) => dec.Equals(_decorated)); - } - } + public bool HasValidEncapsulationAttributes + => _validator.HasValidEncapsulationAttributes(EncapsulationAttributes, QualifiedModuleName, (Declaration dec) => dec.Equals(_target)); public IFieldEncapsulationAttributes EncapsulationAttributes { @@ -67,7 +62,7 @@ public IFieldEncapsulationAttributes EncapsulationAttributes get => _attributes; } - public string TargetID { get; set; } + public virtual string TargetID => _target.IdentifierName; public bool EncapsulateFlag { @@ -96,7 +91,7 @@ public string NewFieldName get => _attributes.NewFieldName; } - public string AsTypeName => _decorated.AsTypeName; + public string AsTypeName => _target.AsTypeName; public bool IsUDTMember { set; get; } = false; diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs new file mode 100644 index 0000000000..6223caecbe --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs @@ -0,0 +1,126 @@ +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; +using Rubberduck.SmartIndenter; +using Rubberduck.VBEditor; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField.Strategies +{ + public class EncapsulateWithBackingFields : EncapsulateFieldStrategiesBase + { + public EncapsulateWithBackingFields(QualifiedModuleName qmn, IIndenter indenter) + : base(qmn, indenter) + { + + } + + protected override void ModifyEncapsulatedVariable(IEncapsulateFieldCandidate target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession) //, bool asUDT = false) //, EncapsulateFieldNewContent newContent) + { + var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); + + if (target.Declaration.Accessibility == Accessibility.Private && attributes.NewFieldName.Equals(target.Declaration.IdentifierName)) + { + rewriter.MakeImplicitDeclarationTypeExplicit(target.Declaration); + return; + } + + if (target.Declaration.IsDeclaredInList()) + { + RewriterRemoveWorkAround.Remove(target.Declaration, rewriter); + //rewriter.Remove(target.Declaration); + } + else + { + rewriter.Rename(target.Declaration, attributes.NewFieldName); + rewriter.SetVariableVisiblity(target.Declaration, Accessibility.Private.TokenString()); + rewriter.MakeImplicitDeclarationTypeExplicit(target.Declaration); + } + return; + } + + protected override EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNewContent newContent, IEnumerable FlaggedEncapsulationFields) + { + var nonUdtMemberFields = FlaggedEncapsulationFields + .Where(encFld => encFld.Declaration.IsVariable()); + + //if (EncapsulateWithUDT) + //{ + // var udt = new UDTDeclarationGenerator(EncapsulateWithUDT_TypeIdentifier, _indenter); + // foreach (var nonUdtMemberField in nonUdtMemberFields) + // { + // udt.AddMember(nonUdtMemberField); + // } + // newContent.AddDeclarationBlock(udt.TypeDeclarationBlock); + // newContent.AddDeclarationBlock(udt.FieldDeclaration(EncapsulateWithUDT_FieldName)); + + // var udtMemberFields = FlaggedEncapsulationFields.Where(efd => efd.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)); + // foreach (var udtMember in udtMemberFields) + // { + // newContent.AddCodeBlock(EncapsulateInUDT_UDTMemberProperty(udtMember)); + // } + + // return newContent; + //} + + foreach (var nonUdtMemberField in nonUdtMemberFields) + { + var attributes = nonUdtMemberField.EncapsulationAttributes; + + if (nonUdtMemberField.Declaration.Accessibility == Accessibility.Private && attributes.NewFieldName.Equals(nonUdtMemberField.Declaration.IdentifierName)) + { + continue; + } + + if (nonUdtMemberField.Declaration.IsDeclaredInList()) + { + var targetIdentifier = nonUdtMemberField.Declaration.Context.GetText().Replace(attributes.TargetName, attributes.NewFieldName); + var newField = nonUdtMemberField.Declaration.IsTypeSpecified ? $"{Tokens.Private} {targetIdentifier}" : $"{Tokens.Private} {targetIdentifier} {Tokens.As} {nonUdtMemberField.Declaration.AsTypeName}"; + + newContent.AddDeclarationBlock(newField); + } + } + return newContent; + } + + protected override IList PropertiesContent(IEnumerable flaggedEncapsulationFields) + { + //get + //{ + var textBlocks = new List(); + foreach (var field in flaggedEncapsulationFields) + { + //if (/*EncapsulateWithUDT &&*/ field is EncapsulatedUserDefinedTypeMember) + //{ + // continue; + //} + textBlocks.Add(BuildPropertiesTextBlock(field.EncapsulationAttributes)); + } + return textBlocks; + //} + } + + private string BuildPropertiesTextBlock(IFieldEncapsulationAttributes attributes) + { + var generator = new PropertyGenerator + { + PropertyName = attributes.PropertyName, + AsTypeName = attributes.AsTypeName, + //BackingField = EncapsulateWithUDT + // ? $"{EncapsulateWithUDT_FieldName}.{attributes.PropertyName}" + // : attributes.FieldReferenceExpression, + BackingField = attributes.FieldReferenceExpression, + ParameterName = attributes.ParameterName, + GenerateSetter = attributes.ImplementSetSetterType, + GenerateLetter = attributes.ImplementLetSetterType + }; + + var propertyTextLines = generator.AllPropertyCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None); + return string.Join(Environment.NewLine, Indenter.Indent(propertyTextLines, true)); + } + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs new file mode 100644 index 0000000000..05201bc01b --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs @@ -0,0 +1,130 @@ +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; +using Rubberduck.SmartIndenter; +using Rubberduck.VBEditor; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField.Strategies +{ + public class EncapsulateWithBackingUserDefinedType : EncapsulateFieldStrategiesBase + { + public EncapsulateWithBackingUserDefinedType(QualifiedModuleName qmn, IIndenter indenter) + : base(qmn, indenter) { } + + private const string DEFAULT_TYPE_IDENTIFIER = "This_Type"; + private const string DEFAULT_FIELD_IDENTIFIER = "this"; + + public string TypeIdentifier { set; get; } = DEFAULT_TYPE_IDENTIFIER; + + public string FieldName { set; get; } = DEFAULT_FIELD_IDENTIFIER; + + protected override void ModifyEncapsulatedVariable(IEncapsulateFieldCandidate target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession) //, bool asUDT = false) //, EncapsulateFieldNewContent newContent) + { + var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); + + RewriterRemoveWorkAround.Remove(target.Declaration, rewriter); + return; + } + + protected override EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNewContent newContent, IEnumerable FlaggedEncapsulationFields) + { + var nonUdtMemberFields = FlaggedEncapsulationFields + .Where(encFld => encFld.Declaration.IsVariable()); + + //if (EncapsulateWithUDT) + //{ + var udt = new UDTDeclarationGenerator(TypeIdentifier); //, _indenter); + foreach (var nonUdtMemberField in nonUdtMemberFields) + { + udt.AddMember(nonUdtMemberField); + } + newContent.AddDeclarationBlock(udt.TypeDeclarationBlock(Indenter)); + newContent.AddDeclarationBlock(udt.FieldDeclaration(FieldName)); + + var udtMemberFields = FlaggedEncapsulationFields.Where(efd => efd.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)); + foreach (var udtMember in udtMemberFields) + { + newContent.AddCodeBlock(EncapsulateInUDT_UDTMemberProperty(udtMember)); + } + + return newContent; + //} + + //foreach (var nonUdtMemberField in nonUdtMemberFields) + //{ + // var attributes = nonUdtMemberField.EncapsulationAttributes; + + // if (nonUdtMemberField.Declaration.Accessibility == Accessibility.Private && attributes.NewFieldName.Equals(nonUdtMemberField.Declaration.IdentifierName)) + // { + // continue; + // } + + // if (nonUdtMemberField.Declaration.IsDeclaredInList()) + // { + // var targetIdentifier = nonUdtMemberField.Declaration.Context.GetText().Replace(attributes.TargetName, attributes.NewFieldName); + // var newField = nonUdtMemberField.Declaration.IsTypeSpecified ? $"{Tokens.Private} {targetIdentifier}" : $"{Tokens.Private} {targetIdentifier} {Tokens.As} {nonUdtMemberField.Declaration.AsTypeName}"; + + // newContent.AddDeclarationBlock(newField); + // } + //} + //return newContent; + } + + protected override IList PropertiesContent(IEnumerable flaggedEncapsulationFields) + { + //get + //{ + var textBlocks = new List(); + foreach (var field in flaggedEncapsulationFields) + { + if (/*EncapsulateWithUDT &&*/ field is EncapsulatedUserDefinedTypeMember) + { + continue; + } + textBlocks.Add(BuildPropertiesTextBlock(field.EncapsulationAttributes)); + } + return textBlocks; + //} + } + + protected string BuildPropertiesTextBlock(IFieldEncapsulationAttributes attributes) + { + var generator = new PropertyGenerator + { + PropertyName = attributes.PropertyName, + AsTypeName = attributes.AsTypeName, + BackingField = //EncapsulateWithUDT + $"{FieldName}.{attributes.PropertyName}", + //: attributes.FieldReferenceExpression, + ParameterName = attributes.ParameterName, + GenerateSetter = attributes.ImplementSetSetterType, + GenerateLetter = attributes.ImplementLetSetterType + }; + + var propertyTextLines = generator.AllPropertyCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None); + return string.Join(Environment.NewLine, Indenter.Indent(propertyTextLines, true)); + } + + private string EncapsulateInUDT_UDTMemberProperty(IEncapsulateFieldCandidate udtMember) + { + var parentField = UdtMemberTargetIDToParentMap[udtMember.TargetID]; + var generator = new PropertyGenerator + { + PropertyName = udtMember.PropertyName, + AsTypeName = udtMember.AsTypeName, + BackingField = $"{FieldName}.{parentField.PropertyName}.{udtMember.PropertyName}", + + ParameterName = udtMember.EncapsulationAttributes.ParameterName, + GenerateSetter = udtMember.EncapsulationAttributes.ImplementSetSetterType, + GenerateLetter = udtMember.EncapsulationAttributes.ImplementLetSetterType + }; + + var propertyTextLines = generator.AllPropertyCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None); + return string.Join(Environment.NewLine, Indenter.Indent(propertyTextLines, true)); + } + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs new file mode 100644 index 0000000000..4e6fd423a6 --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs @@ -0,0 +1,102 @@ +using Rubberduck.Parsing.Rewriter; +using Rubberduck.SmartIndenter; +using Rubberduck.VBEditor; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField.Strategies +{ + public interface IEncapsulateFieldStrategy + { + IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession); + void InsertNewContent(int? codeSectionStartIndex, EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool includePreviewMessage = false); + Dictionary UdtMemberTargetIDToParentMap { get; set; } + } + + public abstract class EncapsulateFieldStrategiesBase : IEncapsulateFieldStrategy + { + public EncapsulateFieldStrategiesBase(QualifiedModuleName qmn, IIndenter indenter) + { + TargetQMN = qmn; + Indenter = indenter; + } + + protected QualifiedModuleName TargetQMN {private set; get;} + + protected IIndenter Indenter { private set; get; } + + public IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) + { + var nonUdtMemberFields = model.FlaggedEncapsulationFields + .Where(encFld => encFld.Declaration.IsVariable()); + + foreach (var nonUdtMemberField in nonUdtMemberFields) + { + var attributes = nonUdtMemberField.EncapsulationAttributes; + ModifyEncapsulatedVariable(nonUdtMemberField, attributes, rewriteSession); //, model.EncapsulateWithUDT); + RenameReferences(nonUdtMemberField, attributes.PropertyName ?? nonUdtMemberField.Declaration.IdentifierName, rewriteSession); + } + + var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); + RewriterRemoveWorkAround.RemoveDeclarationsFromVariableLists(rewriter); + + return rewriteSession; + } + + public Dictionary UdtMemberTargetIDToParentMap { get; set; } + + public void InsertNewContent(int? codeSectionStartIndex, EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool includePreviewMessage = false) + { + var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); + + //var newContent = model.NewContent(); + + var newContent1 = new EncapsulateFieldNewContent(); + newContent1 = LoadNewDeclarationsContent(newContent1, model.FlaggedEncapsulationFields); + + if (includePreviewMessage) + { + var postScript = "'<===== No Changes below this line =====>"; + newContent1 = LoadNewPropertiesContent(newContent1, model.FlaggedEncapsulationFields, postScript); + } + else + { + newContent1 = LoadNewPropertiesContent(newContent1, model.FlaggedEncapsulationFields); + } + + rewriter.InsertNewContent(codeSectionStartIndex, newContent1); + + } + + protected abstract void ModifyEncapsulatedVariable(IEncapsulateFieldCandidate target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession); //, EncapsulateFieldNewContent newContent) + + protected abstract EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNewContent newContent, IEnumerable FlaggedEncapsulationFields); + + protected abstract IList PropertiesContent(IEnumerable flaggedEncapsulationFields); + + private EncapsulateFieldNewContent LoadNewPropertiesContent(EncapsulateFieldNewContent newContent, IEnumerable FlaggedEncapsulationFields, string postScript = null) + { + if (!FlaggedEncapsulationFields.Any()) { return newContent; } + + var theContent = string.Join($"{Environment.NewLine}{Environment.NewLine}", PropertiesContent(FlaggedEncapsulationFields)); + newContent.AddCodeBlock(theContent); + if (postScript?.Length > 0) + { + newContent.AddCodeBlock($"{postScript}{Environment.NewLine}{Environment.NewLine}"); + } + return newContent; + } + + private void RenameReferences(IEncapsulateFieldCandidate efd, string propertyName, IRewriteSession rewriteSession) + { + foreach (var reference in efd.Declaration.References) + { + var rewriter = rewriteSession.CheckOutModuleRewriter(reference.QualifiedModuleName); + rewriter.Replace(reference.Context, propertyName ?? efd.Declaration.IdentifierName); + } + } + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/UDTDeclarationGenerator.cs b/Rubberduck.Refactorings/EncapsulateField/UDTDeclarationGenerator.cs index 2a0ce7846a..cf46db7652 100644 --- a/Rubberduck.Refactorings/EncapsulateField/UDTDeclarationGenerator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/UDTDeclarationGenerator.cs @@ -14,23 +14,24 @@ public class UDTDeclarationGenerator private readonly string _typeIdentifier = "This_Type"; private readonly IIndenter _indenter; - private List _members; + private List _members; - public UDTDeclarationGenerator(string typeIdentifier, IIndenter indenter) - :this(indenter) + public UDTDeclarationGenerator(string typeIdentifier) //, IIndenter indenter) + : this() + //:this(indenter) { _typeIdentifier = typeIdentifier; } - public UDTDeclarationGenerator(IIndenter indenter) + public UDTDeclarationGenerator() //IIndenter indenter) { - _indenter = indenter; - _members = new List(); + //_indenter = indenter; + _members = new List(); } public string AsTypeName => _typeIdentifier; - public void AddMember(IEncapsulatedFieldDeclaration field) + public void AddMember(IEncapsulateFieldCandidate field) { _members.Add(field); } @@ -38,10 +39,10 @@ public void AddMember(IEncapsulatedFieldDeclaration field) public string FieldDeclaration(string identifier, Accessibility accessibility = Accessibility.Private) => $"{accessibility} {identifier} {Tokens.As} {_typeIdentifier}"; - public string TypeDeclarationBlock + public string TypeDeclarationBlock(IIndenter indenter) { - get - { + //get + //{ var members = new List(); members.Add($"{Tokens.Private} {Tokens.Type} {_typeIdentifier}"); @@ -53,8 +54,8 @@ public string TypeDeclarationBlock members.Add("End Type"); - return string.Join(Environment.NewLine, _indenter.Indent(members, true)); - } + return string.Join(Environment.NewLine, indenter.Indent(members, true)); + //} } } } diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs index d6f84f539d..4e3ed2d2f8 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs @@ -49,7 +49,7 @@ Public Property Get Test() As Integer var validator = new EncapsulateFieldNamesValidator( state, - () => new List() + () => new List() { mockFizz, mockBazz, @@ -84,16 +84,20 @@ Public that As TBar void ThisTest(IDeclarationFinderProvider declarationProviderProvider) { - var userInput = new UserInputDataObject("this", encapsulationFlag: true); - userInput.AddAttributeSet("that", encapsulationFlag: true); - userInput.AddUDTMemberNameFlagPairs(("this", "First", true)); - userInput.AddUDTMemberNameFlagPairs(("that", "First", true)); + var declarationThis = declarationProviderProvider.DeclarationFinder.MatchName("this").Single(); + var declarationThat = declarationProviderProvider.DeclarationFinder.MatchName("that").Single(); + var declarationTBar = declarationProviderProvider.DeclarationFinder.MatchName("TBar").Single(); + var declarationFirst = declarationProviderProvider.DeclarationFinder.MatchName("First").Single(); - var presenterAction = Support.SetParameters(userInput); + var fields = new List(); - var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - encapsulatedWholeNumber.EncapsulationAttributes.PropertyName = "LongValue"; - Assert.Less(0, validator.HasNewPropertyNameConflicts(encapsulatedWholeNumber.EncapsulationAttributes, encapsulatedWholeNumber.QualifiedModuleName, (Declaration dec) => dec.Equals(encapsulatedWholeNumber.Declaration))); + + var validator = new EncapsulateFieldNamesValidator(declarationProviderProvider, () => fields); + + var encapsulatedThis = new EncapsulateFieldCandidate(declarationThis, validator); + var encapsulatedThat = new EncapsulateFieldCandidate(declarationThat, validator); + fields.Add(encapsulatedThis); + fields.Add(encapsulatedThat); } var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); @@ -104,7 +108,7 @@ void ThisTest(IDeclarationFinderProvider declarationProviderProvider) var validator = new EncapsulateFieldNamesValidator( state, - () => new List() + () => new List() { thisField, thatField, @@ -133,14 +137,14 @@ void ThisTest(IDeclarationFinderProvider declarationProviderProvider) var wholeNumber = declarationProviderProvider.DeclarationFinder.MatchName("wholeNumber").Single(); var longValue = declarationProviderProvider.DeclarationFinder.MatchName("longValue").Single(); - var fields = new List(); + var fields = new List(); var validator = new EncapsulateFieldNamesValidator(declarationProviderProvider, () => fields); - var encapsulatedWholeNumber = new EncapsulatedFieldDeclaration(wholeNumber, validator); - var encapsulatedLongValue = new EncapsulatedFieldDeclaration(longValue, validator); - fields.Add(new EncapsulatedFieldDeclaration(wholeNumber, validator)); - fields.Add(new EncapsulatedFieldDeclaration(longValue, validator)); + var encapsulatedWholeNumber = new EncapsulateFieldCandidate(wholeNumber, validator); + var encapsulatedLongValue = new EncapsulateFieldCandidate(longValue, validator); + fields.Add(new EncapsulateFieldCandidate(wholeNumber, validator)); + fields.Add(new EncapsulateFieldCandidate(longValue, validator)); encapsulatedWholeNumber.EncapsulationAttributes.PropertyName = "LongValue"; Assert.Less(0, validator.HasNewPropertyNameConflicts(encapsulatedWholeNumber.EncapsulationAttributes, encapsulatedWholeNumber.QualifiedModuleName, (Declaration dec) => dec.Equals(encapsulatedWholeNumber.Declaration))); @@ -157,12 +161,12 @@ private void CreateAndParse(IVBE vbe, Action theTest } } - private IEncapsulatedFieldDeclaration CreateEncapsulatedFieldMock(string targetID, string asTypeName, IVBComponent component, string modifiedPropertyName = null, bool encapsulateFlag = true ) + private IEncapsulateFieldCandidate CreateEncapsulatedFieldMock(string targetID, string asTypeName, IVBComponent component, string modifiedPropertyName = null, bool encapsulateFlag = true ) { var identifiers = new EncapsulationIdentifiers(targetID); var attributesMock = CreateAttributesMock(targetID, asTypeName, modifiedPropertyName); - var mock = new Mock(); + var mock = new Mock(); mock.SetupGet(m => m.TargetID).Returns(identifiers.TargetFieldName); mock.SetupGet(m => m.NewFieldName).Returns(identifiers.Field); mock.SetupGet(m => m.PropertyName).Returns(modifiedPropertyName ?? identifiers.Property); diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs index dcc67356a5..a44fb1a502 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs @@ -118,20 +118,20 @@ public void PropertyNameChange_UniqueParamName() public void CreateUDT() { - var mock = new Mock(); + var mock = new Mock(); mock.SetupGet(m => m.AsTypeName).Returns("String"); mock.SetupGet(m => m.PropertyName).Returns("Fizz"); - var newUserDefinedType = new UDTDeclarationGenerator(CreateIndenter()); + var newUserDefinedType = new UDTDeclarationGenerator(); newUserDefinedType.AddMember(mock.Object); - var result = newUserDefinedType.TypeDeclarationBlock; + var result = newUserDefinedType.TypeDeclarationBlock(CreateIndenter()); StringAssert.Contains("Private Type This_Type", result); StringAssert.Contains(" Fizz As String", result); StringAssert.Contains("End Type", result); } - private IEncapsulatedFieldDeclaration RetrieveEncapsulatedField(string inputCode, string fieldName) + private IEncapsulateFieldCandidate RetrieveEncapsulatedField(string inputCode, string fieldName) { var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; @@ -141,7 +141,7 @@ private IEncapsulatedFieldDeclaration RetrieveEncapsulatedField(string inputCode using (state) { var match = state.DeclarationFinder.MatchName(fieldName).Single(); - return new EncapsulatedFieldDeclaration(match, new EncapsulateFieldNamesValidator(state)) as IEncapsulatedFieldDeclaration; + return new EncapsulateFieldCandidate(match, new EncapsulateFieldNamesValidator(state)) as IEncapsulateFieldCandidate; } } diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index 95b53943f9..902f5b6141 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -361,12 +361,12 @@ End Property var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); using (state) { - IEncapsulatedFieldDeclaration efd = null; - var fields = new List(); + IEncapsulateFieldCandidate efd = null; + var fields = new List(); var validator = new EncapsulateFieldNamesValidator(state, () => fields); var match = state.DeclarationFinder.MatchName(fieldName).Single(); - efd = new EncapsulatedFieldDeclaration(match, validator); + efd = new EncapsulateFieldCandidate(match, validator); fields.Add(efd); efd.PropertyName = "Name"; From 0069e04c4444ea8c082f6e0d25c5a90d4735df6e Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Fri, 29 Nov 2019 15:02:34 -0800 Subject: [PATCH 036/461] WIP refactoring More code moved to strategies --- .../EncapsulateFieldDeclarationExtensions.cs | 3 + .../EncapsulateFieldDeclarationFactory.cs | 107 +++++++++++++--- .../EncapsulateFieldDecorators.cs | 82 +++++++----- .../EncapsulateField/EncapsulateFieldModel.cs | 96 ++++---------- .../EncapsulateFieldRefactoring.cs | 33 +---- .../EncapsulateFieldRewriter.cs | 15 +++ .../EncapsulateFieldValidator.cs | 26 ++-- .../EncapsulatedFieldDeclaration.cs | 64 +++++++-- .../EncapsulationFieldGroup.cs | 19 +++ .../FieldEncapsulationAttributes.cs | 86 ++++++++++++- .../EncapsulateWithBackingFields.cs | 49 ++----- .../EncapsulateWithBackingUserDefinedType.cs | 85 ++++++------ .../Strategies/EncapsulationStrategiesBase.cs | 121 +++++++++++++++--- .../EncapsulateField/EncapsulateAsUDTTests.cs | 27 +++- .../EncapsulateFieldValidatorTests.cs | 8 +- .../Refactoring/EncapsulateFieldTests.cs | 2 +- 16 files changed, 533 insertions(+), 290 deletions(-) create mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulationFieldGroup.cs diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationExtensions.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationExtensions.cs index d30fb6b367..1ac6f64b38 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationExtensions.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationExtensions.cs @@ -32,6 +32,9 @@ public static bool IsMember(this Declaration declaration) public static bool IsConstant(this Declaration declaration) => declaration.DeclarationType.HasFlag(DeclarationType.Constant); + public static bool IsUserDefinedTypeField(this Declaration declaration) + => declaration.IsMemberVariable() && (declaration.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.UserDefinedType) ?? false); + public static bool IsDeclaredInList(this Declaration declaration) { return declaration.Context.TryGetAncestor(out var varList) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs index 4ed5f13ca1..45ab4e8827 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs @@ -1,18 +1,83 @@ using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.VBEditor; using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Rubberduck.Refactorings.EncapsulateField { - public class EncapsulateFieldDeclarationFactory + public class EncapsulationCandidateFactory { - public static IEncapsulateFieldCandidate EncapsulateDeclaration(Declaration target, IEncapsulateFieldNamesValidator validator) + private readonly IDeclarationFinderProvider _declarationFinderProvider; + private IDictionary)> _udtFieldToUdtDeclarationMap = new Dictionary)>(); + private QualifiedModuleName _targetQMN; + private readonly IEncapsulateFieldNamesValidator _validator; + private IEnumerable _candidateFields; + private bool _useNewStructure; + + public EncapsulationCandidateFactory(IDeclarationFinderProvider declarationFinderProvider, IEncapsulateFieldNamesValidator validator) + { + + _declarationFinderProvider = declarationFinderProvider; + _validator = validator; + + _useNewStructure = File.Exists("C:\\Users\\Brian\\Documents\\UseNewUDTStructure.txt"); + } + + public IEncapsulateFieldCandidate CreateProposedField(string identifier, string asTypeName, QualifiedModuleName qmn, IEncapsulateFieldNamesValidator validator) + { + var unselectableAttributes = new UnselectableField(identifier, asTypeName, qmn, validator); + return new EncapsulateFieldCandidate(unselectableAttributes, validator); + } + + public IEnumerable CreateEncapsulationCandidates(IEnumerable candidateFields) { + _candidateFields = candidateFields; + + _udtFieldToUdtDeclarationMap = candidateFields + .Where(v => v.IsUserDefinedTypeField()) + .Select(uv => CreateUDTTuple(uv)) + .ToDictionary(key => key.UDTVariable, element => (element.UserDefinedType, element.UDTMembers)); + + var candidates = new List(); + foreach (var field in candidateFields) + { + candidates.Add(EncapsulateDeclaration(field, _validator)); + } + return candidates; + } + + public IEncapsulateFieldCandidate EncapsulateDeclaration(Declaration target, IEncapsulateFieldNamesValidator validator) + { + if (target.IsUserDefinedTypeField()) + { + var udtCandidate = new EncapsulatedUserDefinedTypeField(target, validator); + udtCandidate.EncapsulationAttributes.ImplementLetSetterType = true; + udtCandidate.EncapsulationAttributes.ImplementSetSetterType = false; + + if (_useNewStructure) + { + var udtMembers = new List(); + + foreach (var member in _udtFieldToUdtDeclarationMap[target].Item2) + { + var udtMemberCandidate = EncapsulateDeclaration(member, validator); + var udtMember = new EncapsulatedUserDefinedTypeMember(udtMemberCandidate, udtCandidate, HasMultipleFieldsOfSameUserDefinedType(udtCandidate)); + udtMembers.Add(udtMember); + } + + udtCandidate.Members = udtMembers.Cast().ToList(); + } + + return udtCandidate; + } + var candidate = new EncapsulateFieldCandidate(target, validator); if (target.IsArray) @@ -36,12 +101,6 @@ public static IEncapsulateFieldCandidate EncapsulateDeclaration(Declaration targ candidate.EncapsulationAttributes.ImplementSetSetterType = true; return candidate; } - else if (target.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.UserDefinedType) ?? false) - { - candidate.EncapsulationAttributes.ImplementLetSetterType = true; - candidate.EncapsulationAttributes.ImplementSetSetterType = false; - return candidate; - } else if (target.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)) { //TODO: This may need to pass back thru using it's AsTypeName @@ -55,18 +114,24 @@ public static IEncapsulateFieldCandidate EncapsulateDeclaration(Declaration targ return candidate; } - //public static IEncapsulatedFieldDeclaration EncapsulateDeclaration(Declaration udtMember, IEncapsulatedFieldDeclaration instantiatingField, IEncapsulateFieldNamesValidator validator) - //{ - // var targetIDPair = new KeyValuePair(udtMember, $"{instantiatingField.Declaration.IdentifierName}.{udtMember.IdentifierName}"); - // var encapsulatedUdtMember = EncapsulateDeclaration(udtMember, validator); - // return EncapsulatedUserDefinedTypeMember.Decorate(encapsulatedUdtMember, instantiatingField, false); // HasMultipleInstantiationsOfSameType(instantiatingField.Declaration, targetIDPair)); - //} - - // private bool HasMultipleInstantiationsOfSameType(Declaration udtVariable, KeyValuePair targetIDPair) - // { - // var udt = _udtFieldToUdtDeclarationMap[udtVariable].Item1; - // var otherVariableOfTheSameType = _udtFieldToUdtDeclarationMap.Keys.Where(k => k != udtVariable && _udtFieldToUdtDeclarationMap[k].Item1 == udt); - // return otherVariableOfTheSameType.Any(); - // } + private (Declaration UDTVariable, Declaration UserDefinedType, IEnumerable UDTMembers) CreateUDTTuple(Declaration udtVariable) + { + var userDefinedTypeDeclaration = _declarationFinderProvider.DeclarationFinder + .UserDeclarations(DeclarationType.UserDefinedType) + .Where(ut => ut.IdentifierName.Equals(udtVariable.AsTypeName) + && (ut.Accessibility.Equals(Accessibility.Private) + && ut.QualifiedModuleName == udtVariable.QualifiedModuleName) + || (ut.Accessibility != Accessibility.Private)) + .SingleOrDefault(); + + var udtMembers = _declarationFinderProvider.DeclarationFinder + .UserDeclarations(DeclarationType.UserDefinedTypeMember) + .Where(utm => userDefinedTypeDeclaration == utm.ParentDeclaration); + + return (udtVariable, userDefinedTypeDeclaration, udtMembers); + } + + private bool HasMultipleFieldsOfSameUserDefinedType(IEncapsulateFieldCandidate udtCandidate) + => _candidateFields.Any(fld => fld != udtCandidate.Declaration && udtCandidate.AsTypeName.Equals(fld.AsTypeName)); } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs index 541e452926..24baece520 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs @@ -4,40 +4,56 @@ using Rubberduck.VBEditor; using System; using System.Collections.Generic; +using System.Linq; using System.Windows; namespace Rubberduck.Refactorings.EncapsulateField { + public class EncapsulatedUserDefinedTypeField : EncapsulateFieldCandidate + { + public List Members { set; get; } + public EncapsulatedUserDefinedTypeField(Declaration declaration, IEncapsulateFieldNamesValidator validator) + : base(declaration, validator) + { + } + } + public class EncapsulatedUserDefinedTypeMember : IEncapsulateFieldCandidate //: EncapsulateFieldDecoratorBase { private IEncapsulateFieldCandidate _candidate; - private IFieldEncapsulationAttributes _udtVariableAttributes; - private bool _nameResolveProperty; - private string _originalVariableName; - private string _targetID; - public EncapsulatedUserDefinedTypeMember(IEncapsulateFieldCandidate candidate, IEncapsulateFieldCandidate udtVariable, bool propertyIdentifierRequiresNameResolution) + public EncapsulatedUserDefinedTypeMember(IEncapsulateFieldCandidate candidate, IEncapsulateFieldCandidate udtVariable, bool propertyNameRequiresParentIdentiier) { _candidate = candidate; - _originalVariableName = udtVariable.Declaration.IdentifierName; - _nameResolveProperty = propertyIdentifierRequiresNameResolution; - _udtVariableAttributes = udtVariable.EncapsulationAttributes; + Parent = udtVariable; + NameResolveProperty = propertyNameRequiresParentIdentiier; + + EncapsulationAttributes.PropertyName = NameResolveProperty + ? $"{Parent.IdentifierName.Capitalize()}_{IdentifierName}" + : IdentifierName; - EncapsulationAttributes.PropertyName = BuildPropertyName(); - if (EncapsulationAttributes is FieldEncapsulationAttributes fea) + //var fea = EncapsulationAttributes as FieldEncapsulationAttributes; + (EncapsulationAttributes as FieldEncapsulationAttributes).FieldReferenceExpressionFunc = () => AsWithMemberExpression; + candidate.IsUDTMember = true; + } + + public string AsWithMemberExpression + { + get { - fea.FieldReferenceExpressionFunc = - () => { var prefix = _udtVariableAttributes.EncapsulateFlag - ? _udtVariableAttributes.NewFieldName - : _udtVariableAttributes.TargetName; + var prefix = Parent.EncapsulateFlag + ? Parent.NewFieldName + : Parent.IdentifierName; - return $"{prefix}.{EncapsulationAttributes.NewFieldName}"; - }; + return $"{prefix}.{NewFieldName}"; } - - _targetID = $"{udtVariable.Declaration.IdentifierName}.{Declaration.IdentifierName}"; - candidate.IsUDTMember = true; } + public IEncapsulateFieldCandidate Parent { private set; get; } + + public bool NameResolveProperty { set; get; } + + public bool IsExistingDeclaration => _candidate.IsExistingDeclaration; + public Declaration Declaration => _candidate.Declaration; public DeclarationType DeclarationType => _candidate.DeclarationType; @@ -92,16 +108,24 @@ public bool HasValidEncapsulationAttributes public IEnumerable References => _candidate.References; - public string TargetID => _targetID; + public string TargetID => $"{Parent.IdentifierName}.{IdentifierName}"; - private string BuildPropertyName() - { - if (_nameResolveProperty) - { - var propertyPrefix = char.ToUpper(_originalVariableName[0]) + _originalVariableName.Substring(1, _originalVariableName.Length - 1); - return $"{propertyPrefix}_{EncapsulationAttributes.TargetName}"; - } - return EncapsulationAttributes.TargetName; - } + public string IdentifierName => _candidate.IdentifierName; + + public string ParameterName => _candidate.ParameterName;// throw new NotImplementedException(); + + public string FieldReferenceExpression => _candidate.FieldReferenceExpression; // throw new NotImplementedException(); + + public bool ImplementLetSetterType { get => _candidate.ImplementLetSetterType; /*throw new NotImplementedException();*/ set => _candidate.ImplementLetSetterType = value; } // throw new NotImplementedException(); } + public bool ImplementSetSetterType { get => _candidate.ImplementSetSetterType; /*throw new NotImplementedException();*/ set => _candidate.ImplementSetSetterType = value; } // throw new NotImplementedException(); } + + //private string BuildPropertyName() => NameResolveProperty ? $"{Parent.IdentifierName.Capitalize()}_{IdentifierName}" : IdentifierName; + //{ + // if (NameResolveProperty) + // { + // return $"{Parent.IdentifierName.Capitalize()}_{IdentifierName}"; + // } + // return IdentifierName; + //} } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index 5f1953ef3c..748c8b8156 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; @@ -22,9 +23,9 @@ public class EncapsulateFieldModel : IRefactoringModel private readonly Func _previewFunc; private QualifiedModuleName _targetQMN; + private bool _useNewStructure; + private IDictionary)> _udtFieldToUdtDeclarationMap = new Dictionary)>(); - private IEnumerable UdtFields => _udtFieldToUdtDeclarationMap.Keys; - private IEnumerable UdtFieldMembers(Declaration udtField) => _udtFieldToUdtDeclarationMap[udtField].Item2; private Dictionary _candidates = new Dictionary(); @@ -36,39 +37,25 @@ public EncapsulateFieldModel(Declaration target, IDeclarationFinderProvider decl _previewFunc = previewFunc; _targetQMN = target.QualifiedModuleName; - var encapsulationCandidateFields = _declarationFinderProvider.DeclarationFinder - .Members(_targetQMN) - .Where(v => v.IsMemberVariable() && !v.IsWithEvents); - - _udtFieldToUdtDeclarationMap = encapsulationCandidateFields - .Where(v => v.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.UserDefinedType) ?? false) - .Select(uv => CreateUDTTuple(uv)) - .ToDictionary(key => key.UDTVariable, element => (element.UserDefinedType, element.UDTMembers)); - - foreach (var field in encapsulationCandidateFields.Except(UdtFields)) - { - var efd = EncapsulateDeclaration(field); - _candidates.Add(efd.TargetID, efd); - } - - AddUDTEncapsulationFields(_udtFieldToUdtDeclarationMap); - - this[target].EncapsulationAttributes.EncapsulateFlag = true; + _useNewStructure = File.Exists("C:\\Users\\Brian\\Documents\\UseNewUDTStructure.txt"); //Maybe this should be passed in - EncapsulationStrategy = new EncapsulateWithBackingFields(_targetQMN, _indenter); + EncapsulationStrategy = new EncapsulateWithBackingFields(_targetQMN, _indenter, _declarationFinderProvider, _validator); + _candidates = EncapsulationStrategy.FlattenedTargetIDToCandidateMapping; + this[target].EncapsulateFlag = true; + } - public IEnumerable FlaggedEncapsulationFields + public IEnumerable FlaggedEncapsulationFields => _candidates.Values.Where(v => v.EncapsulationAttributes.EncapsulateFlag); public IEnumerable EncapsulationFields => _candidates.Values; - public IEncapsulateFieldCandidate this[string encapsulatedFieldIdentifier] + public IEncapsulateFieldCandidate this[string encapsulatedFieldIdentifier] => _candidates[encapsulatedFieldIdentifier]; - public IEncapsulateFieldCandidate this[Declaration fieldDeclaration] + public IEncapsulateFieldCandidate this[Declaration fieldDeclaration] => _candidates.Values.Where(efd => efd.Declaration.Equals(fieldDeclaration)).Select(encapsulatedField => encapsulatedField).Single(); public IEncapsulateFieldStrategy EncapsulationStrategy { set; get; } @@ -77,11 +64,12 @@ public bool EncapsulateWithUDT { set { + if (EncapsulationStrategy is EncapsulateWithBackingUserDefinedType ebd) { return; } + EncapsulationStrategy = value - ? new EncapsulateWithBackingUserDefinedType(_targetQMN, _indenter) as IEncapsulateFieldStrategy - : new EncapsulateWithBackingFields(_targetQMN, _indenter) as IEncapsulateFieldStrategy; + ? new EncapsulateWithBackingUserDefinedType(_targetQMN, _indenter, _declarationFinderProvider, _validator) as IEncapsulateFieldStrategy + : new EncapsulateWithBackingFields(_targetQMN, _indenter, _declarationFinderProvider, _validator) as IEncapsulateFieldStrategy; //This probably should go - or be in the ctor - EncapsulationStrategy.UdtMemberTargetIDToParentMap = _udtMemberTargetIDToParentMap; } get => EncapsulationStrategy is EncapsulateWithBackingUserDefinedType; @@ -97,57 +85,19 @@ public string PreviewRefactoring() return _previewFunc(this); } - private Dictionary _udtMemberTargetIDToParentMap { get; } = new Dictionary(); - private void AddUDTEncapsulationFields(IDictionary)> udtFieldToTypeMap) + public int? CodeSectionStartIndex { - foreach (var udtField in udtFieldToTypeMap.Keys) + get { - var udtEncapsulation = EncapsulateDeclaration(udtField); - _candidates.Add(udtEncapsulation.TargetID, udtEncapsulation); + var moduleMembers = _declarationFinderProvider.DeclarationFinder + .Members(_targetQMN).Where(m => m.IsMember()); + int? codeSectionStartIndex + = moduleMembers.OrderBy(c => c.Selection) + .FirstOrDefault()?.Context.Start.TokenIndex ?? null; - foreach (var udtMember in UdtFieldMembers(udtField)) - { - var encapsulatedUdtMember = EncapsulateDeclaration(udtMember); - encapsulatedUdtMember = DecorateUDTMember(encapsulatedUdtMember, udtEncapsulation as IEncapsulateFieldCandidate); - _candidates.Add(encapsulatedUdtMember.TargetID, encapsulatedUdtMember); - _udtMemberTargetIDToParentMap.Add(encapsulatedUdtMember.TargetID, udtEncapsulation); - } + return codeSectionStartIndex; } } - - private IEncapsulateFieldCandidate EncapsulateDeclaration(Declaration target) - => EncapsulateFieldDeclarationFactory.EncapsulateDeclaration(target, _validator); - - private IEncapsulateFieldCandidate DecorateUDTMember(IEncapsulateFieldCandidate udtMember, IEncapsulateFieldCandidate udtVariable) - { - var targetIDPair = new KeyValuePair(udtMember.Declaration,$"{udtVariable.Declaration.IdentifierName}.{udtMember.Declaration.IdentifierName}"); - return new EncapsulatedUserDefinedTypeMember(udtMember, udtVariable, HasMultipleInstantiationsOfSameType(udtVariable.Declaration, targetIDPair)); - } - - private bool HasMultipleInstantiationsOfSameType(Declaration udtVariable, KeyValuePair targetIDPair) - { - var udt = _udtFieldToUdtDeclarationMap[udtVariable].Item1; - var otherVariableOfTheSameType = _udtFieldToUdtDeclarationMap.Keys.Where(k => k != udtVariable && _udtFieldToUdtDeclarationMap[k].Item1 == udt); - return otherVariableOfTheSameType.Any(); - } - - private (Declaration UDTVariable, Declaration UserDefinedType, IEnumerable UDTMembers) CreateUDTTuple(Declaration udtVariable) - { - var userDefinedTypeDeclaration = _declarationFinderProvider.DeclarationFinder - .UserDeclarations(DeclarationType.UserDefinedType) - .Where(ut => ut.IdentifierName.Equals(udtVariable.AsTypeName) - && (ut.Accessibility.Equals(Accessibility.Private) - && ut.QualifiedModuleName == udtVariable.QualifiedModuleName) - || (ut.Accessibility != Accessibility.Private)) - .SingleOrDefault(); - - var udtMembers = _declarationFinderProvider.DeclarationFinder - .UserDeclarations(DeclarationType.UserDefinedTypeMember) - .Where(utm => userDefinedTypeDeclaration.IdentifierName == utm.ParentDeclaration.IdentifierName - && utm.QualifiedModuleName == userDefinedTypeDeclaration.QualifiedModuleName); - - return (udtVariable, userDefinedTypeDeclaration, udtMembers); - } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 858c4c142e..8ac114bb3a 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -34,7 +34,7 @@ public EncapsulateFieldRefactoring( _declarationFinderProvider = declarationFinderProvider; _selectedDeclarationProvider = selectedDeclarationProvider; _indenter = indenter; - _validator = new EncapsulateFieldNamesValidator(_declarationFinderProvider, FlaggedFields); + _validator = new EncapsulateFieldNamesValidator(_declarationFinderProvider, CandidateFields); } protected override Declaration FindTargetDeclaration(QualifiedSelection targetSelection) @@ -75,15 +75,13 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) } //Get rid of Model property after improving the validator ctor - private IEnumerable FlaggedFields() => Model?.FlaggedEncapsulationFields ?? Enumerable.Empty(); + private IEnumerable CandidateFields() => Model?.EncapsulationFields ?? Enumerable.Empty(); protected override void RefactorImpl(EncapsulateFieldModel model) { - //Model = model; var strategy = model.EncapsulationStrategy; var rewriteSession = strategy.RefactorRewrite(model, RewritingManager.CheckOutCodePaneSession()); - strategy.InsertNewContent(CodeSectionStartIndex, model, rewriteSession); if (!rewriteSession.TryRewrite()) { @@ -94,35 +92,12 @@ protected override void RefactorImpl(EncapsulateFieldModel model) private string PreviewRewrite(EncapsulateFieldModel model) { var strategy = model.EncapsulationStrategy; - var scratchPadRewriteSession = strategy.RefactorRewrite(model, RewritingManager.CheckOutCodePaneSession()); - strategy.InsertNewContent(CodeSectionStartIndex, model, scratchPadRewriteSession, true); + var scratchPadRewriteSession = strategy.GeneratePreview(model, RewritingManager.CheckOutCodePaneSession()); var previewRewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(scratchPadRewriteSession, _targetQMN); - var preview = previewRewriter.GetText(); - var counter = 0; - while ( counter++ < 10 && preview.Contains($"{Environment.NewLine}{Environment.NewLine}{Environment.NewLine}")) - { - preview = preview.Replace($"{Environment.NewLine}{Environment.NewLine}{Environment.NewLine}", $"{Environment.NewLine}{Environment.NewLine}"); - } - - return preview; - } - - private int? CodeSectionStartIndex - { - get - { - var moduleMembers = _declarationFinderProvider.DeclarationFinder - .Members(_targetQMN).Where(m => m.IsMember()); - - int? codeSectionStartIndex - = moduleMembers.OrderBy(c => c.Selection) - .FirstOrDefault()?.Context.Start.TokenIndex ?? null; - - return codeSectionStartIndex; - } + return previewRewriter.GetTextWithoutAbandonedLines(); } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs index ad7fa9427e..d60451e9b6 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs @@ -17,6 +17,8 @@ public interface IEncapsulateFieldRewriter : IModuleRewriter void Rename(Declaration element, string newName); void MakeImplicitDeclarationTypeExplicit(Declaration element); void InsertAtEndOfFile(string content); + string GetTextWithoutAbandonedLines(); + } public class EncapsulateFieldRewriter : IEncapsulateFieldRewriter @@ -85,6 +87,19 @@ public void MakeImplicitDeclarationTypeExplicit(Declaration element) } } + public string GetTextWithoutAbandonedLines() + { + var preview = GetText(); + + var counter = 0; + while (counter++ < 10 && preview.Contains($"{Environment.NewLine}{Environment.NewLine}{Environment.NewLine}")) + { + preview = preview.Replace($"{Environment.NewLine}{Environment.NewLine}{Environment.NewLine}", $"{Environment.NewLine}{Environment.NewLine}"); + } + return preview; + } + + public bool IsDirty => _rewriter.IsDirty; public Selection? Selection { get => _rewriter.Selection; set => _rewriter.Selection = value; } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs index bca50a8335..406e832954 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -72,22 +72,22 @@ namespace Rubberduck.Refactorings.EncapsulateField public interface IEncapsulateFieldNamesValidator { - bool HasValidEncapsulationAttributes(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, Predicate ignore); + bool HasValidEncapsulationAttributes(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, IEnumerable ignore); } public class EncapsulateFieldNamesValidator : IEncapsulateFieldNamesValidator { private readonly IDeclarationFinderProvider _declarationFinderProvider; - private Func> _selectedFieldsRetriever; + private Func> _candidateFieldsRetriever; public EncapsulateFieldNamesValidator(IDeclarationFinderProvider declarationFinderProvider, Func> selectedFieldsRetriever = null) { _declarationFinderProvider = declarationFinderProvider; - _selectedFieldsRetriever = selectedFieldsRetriever; + _candidateFieldsRetriever = selectedFieldsRetriever; } private DeclarationFinder DeclarationFinder => _declarationFinderProvider.DeclarationFinder; - public bool HasValidEncapsulationAttributes(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, Predicate ignore) + public bool HasValidEncapsulationAttributes(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, IEnumerable ignore) { var isSelfConsistent = HasValidIdentifiers(attributes) && !HasInternalNameConflicts(attributes); @@ -105,7 +105,7 @@ public bool HasValidEncapsulationAttributes(IFieldEncapsulationAttributes attrib return true; } - public int HasNewPropertyNameConflicts(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, Predicate ignoreThisDeclaration) + public int HasNewPropertyNameConflicts(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, IEnumerable declarationsToIgnore) { Predicate IsPrivateAccessiblityInOtherModule = (Declaration dec) => dec.QualifiedModuleName != qmn && dec.Accessibility.Equals(Accessibility.Private); Predicate IsInSearchScope = null; @@ -120,14 +120,14 @@ public int HasNewPropertyNameConflicts(IFieldEncapsulationAttributes attributes, var identifierMatches = DeclarationFinder.MatchName(attributes.PropertyName) .Where(match => IsInSearchScope(match) - && !ignoreThisDeclaration(match) + && !declarationsToIgnore.Contains(match) && !IsPrivateAccessiblityInOtherModule(match) && !IsEnumOrUDTMemberDeclaration(match) && !match.IsLocalVariable()).ToList(); var candidates = new List(); var candidateMatches = new List(); - var fields = _selectedFieldsRetriever is null ? Enumerable.Empty() : _selectedFieldsRetriever(); + var fields = _candidateFieldsRetriever is null ? Enumerable.Empty() : _candidateFieldsRetriever(); foreach (var efd in fields) { var matches = candidates.Where(c => c.PropertyName.EqualsVBAIdentifier(efd.PropertyName)); @@ -142,23 +142,25 @@ public int HasNewPropertyNameConflicts(IFieldEncapsulationAttributes attributes, } //FieldNames are always Private, so only look within the same module as the field to encapsulate - public int HasNewFieldNameConflicts(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, Predicate ignoreThisDeclaration) + public int HasNewFieldNameConflicts(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, IEnumerable declarationsToIgnore) { + var rawmatches = DeclarationFinder.MatchName(attributes.NewFieldName); var identifierMatches = DeclarationFinder.MatchName(attributes.NewFieldName) .Where(match => match.QualifiedModuleName == qmn - && !ignoreThisDeclaration(match) + && !declarationsToIgnore.Contains(match) && !IsEnumOrUDTMemberDeclaration(match) && !match.IsLocalVariable()).ToList(); var candidates = new List(); var candidateMatches = new List(); - var fields = _selectedFieldsRetriever is null + var fields = _candidateFieldsRetriever is null ? Enumerable.Empty() - : _selectedFieldsRetriever(); + : _candidateFieldsRetriever(); foreach (var efd in fields) { - var matches = candidates.Where(c => c.NewFieldName.EqualsVBAIdentifier(efd.NewFieldName)); + var matches = candidates.Where(c => c.EncapsulateFlag && c.NewFieldName.EqualsVBAIdentifier(efd.NewFieldName) + || c.IdentifierName.EqualsVBAIdentifier(efd.NewFieldName)); if (matches.Where(m => m.TargetID != efd.TargetID).Any()) { candidateMatches.Add(efd); diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs index 0762d04662..ea4646e14d 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs @@ -14,6 +14,7 @@ public interface IEncapsulateFieldCandidate Declaration Declaration { get; } DeclarationType DeclarationType { get; } string TargetID { get; } + string IdentifierName { get; } IFieldEncapsulationAttributes EncapsulationAttributes { set; get; } bool IsReadOnly { set; get; } bool CanBeReadWrite { set; get; } @@ -21,12 +22,30 @@ public interface IEncapsulateFieldCandidate bool EncapsulateFlag { set; get; } string NewFieldName { get; } string AsTypeName { get; } + string ParameterName { get; } + string FieldReferenceExpression { get; } bool IsUDTMember { set; get; } bool HasValidEncapsulationAttributes { get; } QualifiedModuleName QualifiedModuleName { get; } IEnumerable References { get; } + bool ImplementLetSetterType { get; set; } + bool ImplementSetSetterType { get; set; } + bool IsExistingDeclaration { get; } } + + ////string TargetName { get; } + ////string PropertyName { get; set; } + ////bool ReadOnly { get; set; } + ////bool EncapsulateFlag { get; set; } + ////string NewFieldName { set; get; } + //string FieldReferenceExpression { get; } + ////string AsTypeName { get; set; } + //string ParameterName { get; } + //bool ImplementLetSetterType { get; set; } + //bool ImplementSetSetterType { get; set; } + //bool FieldNameIsExemptFromValidation { get; } + public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate { protected Declaration _target; @@ -41,28 +60,43 @@ public EncapsulateFieldCandidate(Declaration declaration, IEncapsulateFieldNames //TargetID = declaration.IdentifierName; - var isValidAttributeSet = _validator.HasValidEncapsulationAttributes(_attributes, declaration.QualifiedModuleName, (Declaration dec) => dec.Equals(_target)); + var isValidAttributeSet = _validator.HasValidEncapsulationAttributes(_attributes, declaration.QualifiedModuleName, new Declaration[] { _target }); // (Declaration dec) => dec.Equals(_target)); for (var idx = 2; idx < 9 && !isValidAttributeSet; idx++) { _attributes.NewFieldName = $"{declaration.IdentifierName}{idx}"; - isValidAttributeSet = _validator.HasValidEncapsulationAttributes(_attributes, declaration.QualifiedModuleName, (Declaration dec) => dec.Equals(_target)); + isValidAttributeSet = _validator.HasValidEncapsulationAttributes(_attributes, declaration.QualifiedModuleName, new Declaration[] { _target }); //(Declaration dec) => dec.Equals(_target)); } } + public EncapsulateFieldCandidate(IFieldEncapsulationAttributes attributes, IEncapsulateFieldNamesValidator validator) + { + _target = null; + _attributes = attributes; // new FieldEncapsulationAttributes(identifier, asTypeName); + _validator = validator; + } + public Declaration Declaration => _target; - public DeclarationType DeclarationType => _target.DeclarationType; + public bool IsExistingDeclaration => _target != null; + + public DeclarationType DeclarationType => _target?.DeclarationType ?? DeclarationType.Variable; - public bool HasValidEncapsulationAttributes - => _validator.HasValidEncapsulationAttributes(EncapsulationAttributes, QualifiedModuleName, (Declaration dec) => dec.Equals(_target)); + public bool HasValidEncapsulationAttributes + { + get + { + var ignore = _target != null ? new Declaration[] { _target } : Enumerable.Empty(); + return _validator.HasValidEncapsulationAttributes(EncapsulationAttributes, QualifiedModuleName, ignore); //(Declaration dec) => dec.Equals(_target)); + } + } - public IFieldEncapsulationAttributes EncapsulationAttributes + public IFieldEncapsulationAttributes EncapsulationAttributes { set => _attributes = value; get => _attributes; } - public virtual string TargetID => _target.IdentifierName; + public virtual string TargetID => _target?.IdentifierName ?? _attributes.Identifier; public bool EncapsulateFlag { @@ -91,12 +125,22 @@ public string NewFieldName get => _attributes.NewFieldName; } - public string AsTypeName => _target.AsTypeName; + public string AsTypeName => _target?.AsTypeName ?? _attributes.AsTypeName; + //TODO: This needs to be readonly public bool IsUDTMember { set; get; } = false; - public QualifiedModuleName QualifiedModuleName => Declaration.QualifiedModuleName; + public QualifiedModuleName QualifiedModuleName => Declaration?.QualifiedModuleName ?? _attributes.QualifiedModuleName; + + public IEnumerable References => Declaration?.References ?? Enumerable.Empty(); + + public string IdentifierName => Declaration?.IdentifierName ?? _attributes.Identifier; + + public string ParameterName => _attributes.ParameterName;// throw new NotImplementedException(); + + public string FieldReferenceExpression => _attributes.FieldReferenceExpression; // throw new NotImplementedException(); - public IEnumerable References => Declaration.References; + public bool ImplementLetSetterType { get => _attributes.ImplementLetSetterType; /*throw new NotImplementedException();*/ set => _attributes.ImplementLetSetterType = value; } // throw new NotImplementedException(); } + public bool ImplementSetSetterType { get => _attributes.ImplementSetSetterType; /*throw new NotImplementedException();*/ set => _attributes.ImplementSetSetterType = value; } // throw new NotImplementedException(); } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationFieldGroup.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationFieldGroup.cs new file mode 100644 index 0000000000..223ed9b470 --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationFieldGroup.cs @@ -0,0 +1,19 @@ +using Rubberduck.Parsing.VBA; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + public class EncapsulationFieldGroup + { + private readonly IDeclarationFinderProvider _declarationFinderProvider; + + public EncapsulationFieldGroup(IDeclarationFinderProvider declarationFinderProvider) + { + _declarationFinderProvider = declarationFinderProvider; + } + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs index 5a4b70c8f8..0e8c708401 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs @@ -1,4 +1,5 @@ using Rubberduck.Parsing.Symbols; +using Rubberduck.VBEditor; using System; using System.Collections.Generic; @@ -6,7 +7,7 @@ namespace Rubberduck.Refactorings.EncapsulateField { public interface IFieldEncapsulationAttributes { - string TargetName { get; } + string Identifier { get; } string PropertyName { get; set; } bool ReadOnly { get; set; } bool EncapsulateFlag { get; set; } @@ -17,22 +18,96 @@ public interface IFieldEncapsulationAttributes bool ImplementLetSetterType { get; set; } bool ImplementSetSetterType { get; set; } bool FieldNameIsExemptFromValidation { get; } + QualifiedModuleName QualifiedModuleName { get; } + + //IEncapsulatedField + //Declaration Declaration { get; } + //DeclarationType DeclarationType { get; } + //dup //string TargetID { get; } + //IFieldEncapsulationAttributes EncapsulationAttributes { set; get; } + //dup //bool IsReadOnly { set; get; } + //bool CanBeReadWrite { set; get; } + //dup //string PropertyName { set; get; } + //dup //bool EncapsulateFlag { set; get; } + //dup //string NewFieldName { get; } + //dup //string AsTypeName { get; } + //bool IsUDTMember { set; get; } + //bool HasValidEncapsulationAttributes { get; } + //dup//QualifiedModuleName QualifiedModuleName { get; } + //IEnumerable References { get; } + } - public class FieldEncapsulationAttributes : IFieldEncapsulationAttributes + public class UnselectableField : IFieldEncapsulationAttributes { + private const string neverUsed = "x_x_x_x_x_x_x"; + private IEncapsulateFieldNamesValidator _validator; + private QualifiedModuleName _qmn; + + public UnselectableField(string identifier, string asTypeName, QualifiedModuleName qmn, IEncapsulateFieldNamesValidator validator) + { + //_fieldAndProperty = new EncapsulationIdentifiers(identifier); + _qmn = qmn; + _validator = validator; + Identifier = identifier; + NewFieldName = identifier; + AsTypeName = asTypeName; + FieldReferenceExpressionFunc = () => NewFieldName; + } + + public IFieldEncapsulationAttributes ApplyNewFieldName(string newFieldName) + { + NewFieldName = newFieldName; + return this; + } + + public string Identifier { private set; get; } + + public string NewFieldName { set; get; } + + string _tossString; + public string PropertyName { set => _tossString = value; get => $"{neverUsed}{Identifier}_{neverUsed}"; } + + public string FieldReferenceExpression => FieldReferenceExpressionFunc(); + public Func FieldReferenceExpressionFunc { set; get; } + + public string AsTypeName { get; set; } + public string ParameterName => neverUsed; + + private bool _toss; + public bool ReadOnly { get; set; } = false; + + public bool EncapsulateFlag { get => false; set => _toss = value; } + public bool ImplementLetSetterType { get => false; set => _toss = value; } + public bool ImplementSetSetterType { get => false; set => _toss = value; } + + public bool FieldNameIsExemptFromValidation => false; // NewFieldName.EqualsVBAIdentifier(Identifier); + public QualifiedModuleName QualifiedModuleName => _qmn; + } + + public class FieldEncapsulationAttributes : IFieldEncapsulationAttributes + { + private QualifiedModuleName _qmn; public FieldEncapsulationAttributes(Declaration target) { _fieldAndProperty = new EncapsulationIdentifiers(target); - TargetName = target.IdentifierName; + Identifier = target.IdentifierName; AsTypeName = target.AsTypeName; + _qmn = target.QualifiedModuleName; + FieldReferenceExpressionFunc = () => NewFieldName; + } + + public FieldEncapsulationAttributes(string identifier, string asTypeName) + { + _fieldAndProperty = new EncapsulationIdentifiers(identifier); + AsTypeName = asTypeName; FieldReferenceExpressionFunc = () => NewFieldName; } private EncapsulationIdentifiers _fieldAndProperty; - public string TargetName { private set; get; } + public string Identifier { private set; get; } public string NewFieldName { @@ -61,6 +136,7 @@ public string PropertyName private bool _implSet; public bool ImplementSetSetterType { get => !ReadOnly && _implSet; set => _implSet = value; } - public bool FieldNameIsExemptFromValidation => NewFieldName.EqualsVBAIdentifier(TargetName); + public bool FieldNameIsExemptFromValidation => NewFieldName.EqualsVBAIdentifier(Identifier); + public QualifiedModuleName QualifiedModuleName => _qmn; } } diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs index 6223caecbe..96cd4cc7ce 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs @@ -1,6 +1,7 @@ using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; using Rubberduck.SmartIndenter; using Rubberduck.VBEditor; using System; @@ -13,10 +14,9 @@ namespace Rubberduck.Refactorings.EncapsulateField.Strategies { public class EncapsulateWithBackingFields : EncapsulateFieldStrategiesBase { - public EncapsulateWithBackingFields(QualifiedModuleName qmn, IIndenter indenter) - : base(qmn, indenter) + public EncapsulateWithBackingFields(QualifiedModuleName qmn, IIndenter indenter, IDeclarationFinderProvider declarationFinderProvider, IEncapsulateFieldNamesValidator validator) + : base(qmn, indenter, declarationFinderProvider, validator) { - } protected override void ModifyEncapsulatedVariable(IEncapsulateFieldCandidate target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession) //, bool asUDT = false) //, EncapsulateFieldNewContent newContent) @@ -48,25 +48,6 @@ protected override EncapsulateFieldNewContent LoadNewDeclarationsContent(Encapsu var nonUdtMemberFields = FlaggedEncapsulationFields .Where(encFld => encFld.Declaration.IsVariable()); - //if (EncapsulateWithUDT) - //{ - // var udt = new UDTDeclarationGenerator(EncapsulateWithUDT_TypeIdentifier, _indenter); - // foreach (var nonUdtMemberField in nonUdtMemberFields) - // { - // udt.AddMember(nonUdtMemberField); - // } - // newContent.AddDeclarationBlock(udt.TypeDeclarationBlock); - // newContent.AddDeclarationBlock(udt.FieldDeclaration(EncapsulateWithUDT_FieldName)); - - // var udtMemberFields = FlaggedEncapsulationFields.Where(efd => efd.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)); - // foreach (var udtMember in udtMemberFields) - // { - // newContent.AddCodeBlock(EncapsulateInUDT_UDTMemberProperty(udtMember)); - // } - - // return newContent; - //} - foreach (var nonUdtMemberField in nonUdtMemberFields) { var attributes = nonUdtMemberField.EncapsulationAttributes; @@ -78,7 +59,7 @@ protected override EncapsulateFieldNewContent LoadNewDeclarationsContent(Encapsu if (nonUdtMemberField.Declaration.IsDeclaredInList()) { - var targetIdentifier = nonUdtMemberField.Declaration.Context.GetText().Replace(attributes.TargetName, attributes.NewFieldName); + var targetIdentifier = nonUdtMemberField.Declaration.Context.GetText().Replace(attributes.Identifier, attributes.NewFieldName); var newField = nonUdtMemberField.Declaration.IsTypeSpecified ? $"{Tokens.Private} {targetIdentifier}" : $"{Tokens.Private} {targetIdentifier} {Tokens.As} {nonUdtMemberField.Declaration.AsTypeName}"; newContent.AddDeclarationBlock(newField); @@ -89,19 +70,12 @@ protected override EncapsulateFieldNewContent LoadNewDeclarationsContent(Encapsu protected override IList PropertiesContent(IEnumerable flaggedEncapsulationFields) { - //get - //{ - var textBlocks = new List(); - foreach (var field in flaggedEncapsulationFields) - { - //if (/*EncapsulateWithUDT &&*/ field is EncapsulatedUserDefinedTypeMember) - //{ - // continue; - //} - textBlocks.Add(BuildPropertiesTextBlock(field.EncapsulationAttributes)); - } - return textBlocks; - //} + var textBlocks = new List(); + foreach (var field in flaggedEncapsulationFields) + { + textBlocks.Add(BuildPropertiesTextBlock(field.EncapsulationAttributes)); + } + return textBlocks; } private string BuildPropertiesTextBlock(IFieldEncapsulationAttributes attributes) @@ -110,9 +84,6 @@ private string BuildPropertiesTextBlock(IFieldEncapsulationAttributes attributes { PropertyName = attributes.PropertyName, AsTypeName = attributes.AsTypeName, - //BackingField = EncapsulateWithUDT - // ? $"{EncapsulateWithUDT_FieldName}.{attributes.PropertyName}" - // : attributes.FieldReferenceExpression, BackingField = attributes.FieldReferenceExpression, ParameterName = attributes.ParameterName, GenerateSetter = attributes.ImplementSetSetterType, diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs index 05201bc01b..33d1c11d2e 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs @@ -1,5 +1,6 @@ using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; using Rubberduck.SmartIndenter; using Rubberduck.VBEditor; using System; @@ -10,23 +11,35 @@ namespace Rubberduck.Refactorings.EncapsulateField.Strategies { - public class EncapsulateWithBackingUserDefinedType : EncapsulateFieldStrategiesBase + public interface IEncapsulateWithBackingUserDefinedType : IEncapsulateFieldStrategy { - public EncapsulateWithBackingUserDefinedType(QualifiedModuleName qmn, IIndenter indenter) - : base(qmn, indenter) { } + IEncapsulateFieldCandidate StateEncapsulationField { set; get; } + } + public class EncapsulateWithBackingUserDefinedType : EncapsulateFieldStrategiesBase, IEncapsulateWithBackingUserDefinedType + { private const string DEFAULT_TYPE_IDENTIFIER = "This_Type"; private const string DEFAULT_FIELD_IDENTIFIER = "this"; + + public EncapsulateWithBackingUserDefinedType(QualifiedModuleName qmn, IIndenter indenter, IDeclarationFinderProvider declarationFinderProvider, IEncapsulateFieldNamesValidator validator) + : base(qmn, indenter, declarationFinderProvider, validator) + { + StateEncapsulationField = _candidateFactory.CreateProposedField(DEFAULT_FIELD_IDENTIFIER, DEFAULT_TYPE_IDENTIFIER, qmn, validator); + } + + public IEncapsulateFieldCandidate StateEncapsulationField { set; get; } + public string TypeIdentifier { set; get; } = DEFAULT_TYPE_IDENTIFIER; public string FieldName { set; get; } = DEFAULT_FIELD_IDENTIFIER; - protected override void ModifyEncapsulatedVariable(IEncapsulateFieldCandidate target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession) //, bool asUDT = false) //, EncapsulateFieldNewContent newContent) + protected override void ModifyEncapsulatedVariable(IEncapsulateFieldCandidate target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession) { var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); RewriterRemoveWorkAround.Remove(target.Declaration, rewriter); + //rewriter.Remove(target.Declaration); return; } @@ -35,60 +48,39 @@ protected override EncapsulateFieldNewContent LoadNewDeclarationsContent(Encapsu var nonUdtMemberFields = FlaggedEncapsulationFields .Where(encFld => encFld.Declaration.IsVariable()); - //if (EncapsulateWithUDT) - //{ - var udt = new UDTDeclarationGenerator(TypeIdentifier); //, _indenter); - foreach (var nonUdtMemberField in nonUdtMemberFields) - { - udt.AddMember(nonUdtMemberField); - } - newContent.AddDeclarationBlock(udt.TypeDeclarationBlock(Indenter)); - newContent.AddDeclarationBlock(udt.FieldDeclaration(FieldName)); - - var udtMemberFields = FlaggedEncapsulationFields.Where(efd => efd.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)); - foreach (var udtMember in udtMemberFields) - { - newContent.AddCodeBlock(EncapsulateInUDT_UDTMemberProperty(udtMember)); - } - - return newContent; - //} - - //foreach (var nonUdtMemberField in nonUdtMemberFields) - //{ - // var attributes = nonUdtMemberField.EncapsulationAttributes; - - // if (nonUdtMemberField.Declaration.Accessibility == Accessibility.Private && attributes.NewFieldName.Equals(nonUdtMemberField.Declaration.IdentifierName)) - // { - // continue; - // } + var udt = new UDTDeclarationGenerator(TypeIdentifier); + foreach (var nonUdtMemberField in nonUdtMemberFields) + { + udt.AddMember(nonUdtMemberField); + } + newContent.AddDeclarationBlock(udt.TypeDeclarationBlock(Indenter)); + if (!StateEncapsulationField.HasValidEncapsulationAttributes) + { + ForceNonConflictFieldName(StateEncapsulationField); + } + newContent.AddDeclarationBlock(udt.FieldDeclaration(StateEncapsulationField.NewFieldName)); - // if (nonUdtMemberField.Declaration.IsDeclaredInList()) - // { - // var targetIdentifier = nonUdtMemberField.Declaration.Context.GetText().Replace(attributes.TargetName, attributes.NewFieldName); - // var newField = nonUdtMemberField.Declaration.IsTypeSpecified ? $"{Tokens.Private} {targetIdentifier}" : $"{Tokens.Private} {targetIdentifier} {Tokens.As} {nonUdtMemberField.Declaration.AsTypeName}"; + var udtMemberFields = FlaggedEncapsulationFields.Where(efd => efd.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)); + foreach (var udtMember in udtMemberFields) + { + newContent.AddCodeBlock(EncapsulateInUDT_UDTMemberProperty(udtMember)); + } - // newContent.AddDeclarationBlock(newField); - // } - //} - //return newContent; + return newContent; } protected override IList PropertiesContent(IEnumerable flaggedEncapsulationFields) { - //get - //{ var textBlocks = new List(); foreach (var field in flaggedEncapsulationFields) { - if (/*EncapsulateWithUDT &&*/ field is EncapsulatedUserDefinedTypeMember) + if (field is EncapsulatedUserDefinedTypeMember) { continue; } textBlocks.Add(BuildPropertiesTextBlock(field.EncapsulationAttributes)); } return textBlocks; - //} } protected string BuildPropertiesTextBlock(IFieldEncapsulationAttributes attributes) @@ -97,9 +89,7 @@ protected string BuildPropertiesTextBlock(IFieldEncapsulationAttributes attribut { PropertyName = attributes.PropertyName, AsTypeName = attributes.AsTypeName, - BackingField = //EncapsulateWithUDT - $"{FieldName}.{attributes.PropertyName}", - //: attributes.FieldReferenceExpression, + BackingField = $"{FieldName}.{attributes.PropertyName}", ParameterName = attributes.ParameterName, GenerateSetter = attributes.ImplementSetSetterType, GenerateLetter = attributes.ImplementLetSetterType @@ -116,8 +106,7 @@ private string EncapsulateInUDT_UDTMemberProperty(IEncapsulateFieldCandidate udt { PropertyName = udtMember.PropertyName, AsTypeName = udtMember.AsTypeName, - BackingField = $"{FieldName}.{parentField.PropertyName}.{udtMember.PropertyName}", - + BackingField = $"{StateEncapsulationField.NewFieldName}.{parentField.PropertyName}.{udtMember.PropertyName}", ParameterName = udtMember.EncapsulationAttributes.ParameterName, GenerateSetter = udtMember.EncapsulationAttributes.ImplementSetSetterType, GenerateLetter = udtMember.EncapsulationAttributes.ImplementLetSetterType diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs index 4e6fd423a6..6ab34bd46c 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs @@ -1,4 +1,6 @@ using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; using Rubberduck.SmartIndenter; using Rubberduck.VBEditor; using System; @@ -11,24 +13,92 @@ namespace Rubberduck.Refactorings.EncapsulateField.Strategies { public interface IEncapsulateFieldStrategy { + IExecutableRewriteSession GeneratePreview(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession); IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession); - void InsertNewContent(int? codeSectionStartIndex, EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool includePreviewMessage = false); Dictionary UdtMemberTargetIDToParentMap { get; set; } + Dictionary FlattenedTargetIDToCandidateMapping { get; } } public abstract class EncapsulateFieldStrategiesBase : IEncapsulateFieldStrategy { - public EncapsulateFieldStrategiesBase(QualifiedModuleName qmn, IIndenter indenter) + protected readonly IDeclarationFinderProvider _declarationFinderProvider; + protected EncapsulationCandidateFactory _candidateFactory; + private Dictionary _udtMemberTargetIDToParentMap { get; } = new Dictionary(); + private IEncapsulateFieldNamesValidator _validator; + + + public EncapsulateFieldStrategiesBase(QualifiedModuleName qmn, IIndenter indenter, IDeclarationFinderProvider declarationFinderProvider, IEncapsulateFieldNamesValidator validator) { TargetQMN = qmn; Indenter = indenter; + _declarationFinderProvider = declarationFinderProvider; + _validator = validator; + _candidateFactory = new EncapsulationCandidateFactory(declarationFinderProvider, _validator); + + EncapsulationCandidateFields = _declarationFinderProvider.DeclarationFinder + .Members(qmn) + .Where(v => v.IsMemberVariable() && !v.IsWithEvents); + + //if (_useNewStructure) + //{ + var candidates = _candidateFactory.CreateEncapsulationCandidates(EncapsulationCandidateFields); + foreach (var candidate in candidates) + { + HeirarchicalCandidates.Add(candidate.TargetID, candidate); + } + FlattenedTargetIDToCandidateMapping = Flatten(HeirarchicalCandidates); + foreach (var element in FlattenedTargetIDToCandidateMapping) + { + if (element.Value.IsUDTMember) + { + var udtMember = element.Value as EncapsulatedUserDefinedTypeMember; + UdtMemberTargetIDToParentMap.Add(element.Key, udtMember.Parent); + } + } + + //} } protected QualifiedModuleName TargetQMN {private set; get;} protected IIndenter Indenter { private set; get; } - public IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) + public IExecutableRewriteSession GeneratePreview(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) + { + return RefactorRewrite(model, rewriteSession, true); + } + + public IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) + { + return RefactorRewrite(model, rewriteSession, false); + } + + public Dictionary FlattenedTargetIDToCandidateMapping { get; } = new Dictionary(); + + protected virtual IEnumerable EncapsulationCandidateFields { set; get; } + + protected abstract void ModifyEncapsulatedVariable(IEncapsulateFieldCandidate target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession); //, EncapsulateFieldNewContent newContent) + + protected abstract EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNewContent newContent, IEnumerable FlaggedEncapsulationFields); + + protected abstract IList PropertiesContent(IEnumerable flaggedEncapsulationFields); + + protected Dictionary HeirarchicalCandidates { set; get; } = new Dictionary(); + + protected IEncapsulateFieldCandidate ForceNonConflictFieldName(IEncapsulateFieldCandidate candidate) + { + if (candidate.EncapsulationAttributes is UnselectableField concrete) + { + var attempt = 0; + while (attempt++ < 10 && !candidate.HasValidEncapsulationAttributes) + { + concrete.ApplyNewFieldName($"{concrete.NewFieldName}{attempt}"); + } + } + return candidate; + } + + private IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) { var nonUdtMemberFields = model.FlaggedEncapsulationFields .Where(encFld => encFld.Declaration.IsVariable()); @@ -36,46 +106,61 @@ public IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, I foreach (var nonUdtMemberField in nonUdtMemberFields) { var attributes = nonUdtMemberField.EncapsulationAttributes; - ModifyEncapsulatedVariable(nonUdtMemberField, attributes, rewriteSession); //, model.EncapsulateWithUDT); + ModifyEncapsulatedVariable(nonUdtMemberField, attributes, rewriteSession); RenameReferences(nonUdtMemberField, attributes.PropertyName ?? nonUdtMemberField.Declaration.IdentifierName, rewriteSession); } var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); RewriterRemoveWorkAround.RemoveDeclarationsFromVariableLists(rewriter); + InsertNewContent(model.CodeSectionStartIndex, model, rewriteSession, asPreview); + return rewriteSession; } - public Dictionary UdtMemberTargetIDToParentMap { get; set; } + public Dictionary UdtMemberTargetIDToParentMap { get; set; } = new Dictionary(); - public void InsertNewContent(int? codeSectionStartIndex, EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool includePreviewMessage = false) + private void InsertNewContent(int? codeSectionStartIndex, EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool includePreviewMessage = false) { var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); - //var newContent = model.NewContent(); - - var newContent1 = new EncapsulateFieldNewContent(); - newContent1 = LoadNewDeclarationsContent(newContent1, model.FlaggedEncapsulationFields); + var newContent = new EncapsulateFieldNewContent(); + newContent = LoadNewDeclarationsContent(newContent, model.FlaggedEncapsulationFields); if (includePreviewMessage) { var postScript = "'<===== No Changes below this line =====>"; - newContent1 = LoadNewPropertiesContent(newContent1, model.FlaggedEncapsulationFields, postScript); + newContent = LoadNewPropertiesContent(newContent, model.FlaggedEncapsulationFields, postScript); } else { - newContent1 = LoadNewPropertiesContent(newContent1, model.FlaggedEncapsulationFields); + newContent = LoadNewPropertiesContent(newContent, model.FlaggedEncapsulationFields); } - rewriter.InsertNewContent(codeSectionStartIndex, newContent1); + rewriter.InsertNewContent(codeSectionStartIndex, newContent); } - protected abstract void ModifyEncapsulatedVariable(IEncapsulateFieldCandidate target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession); //, EncapsulateFieldNewContent newContent) - - protected abstract EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNewContent newContent, IEnumerable FlaggedEncapsulationFields); - - protected abstract IList PropertiesContent(IEnumerable flaggedEncapsulationFields); + protected Dictionary Flatten(Dictionary heirarchicalCandidates) + { + var candidates = new Dictionary(); + foreach (var keyValue in heirarchicalCandidates) + { + candidates.Add(keyValue.Key, keyValue.Value); + if (keyValue.Value.Declaration.IsUserDefinedTypeField()) + { + if (keyValue.Value is EncapsulatedUserDefinedTypeField udt) + { + foreach (var member in udt.Members) + { + candidates.Add(member.TargetID, member); + _udtMemberTargetIDToParentMap.Add(member.TargetID, keyValue.Value); + } + } + } + } + return candidates; + } private EncapsulateFieldNewContent LoadNewPropertiesContent(EncapsulateFieldNewContent newContent, IEnumerable FlaggedEncapsulationFields, string postScript = null) { diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateAsUDTTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateAsUDTTests.cs index 1ceee9d2ec..b145b8cc42 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateAsUDTTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateAsUDTTests.cs @@ -47,7 +47,7 @@ End Type [TestCase("Private")] [Category("Refactorings")] [Category("Encapsulate Field")] - public void UserDefinedType_UserAcceptsDefaults_ToUDTInstances(string accessibility) + public void UserDefinedType_UserAcceptsDefaults_TwoUDTInstances(string accessibility) { string selectionModule = "ClassInput"; string inputCode = @@ -83,6 +83,31 @@ End Type StringAssert.DoesNotContain($"this1.First1 = value", actualCode[selectionModule]); } + [TestCase("Public")] + [TestCase("Private")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedType_UserAcceptsDefaults_ConflictWithEncapsulationUDT(string accessibility) + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +{accessibility} my|Bar As TBar + +Private this As Long"; + + + var presenterAction = Support.UserAcceptsDefaults(asUDT: true); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.Contains("Private this As Long", actualCode); + StringAssert.Contains("Private this1 As This_Type", actualCode); + //StringAssert.DoesNotContain($"Private this1 As This_Type", actualCode); + } + [TestCase("Public", true, true)] [TestCase("Private", true, true)] [TestCase("Public", false, false)] diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs index 4e3ed2d2f8..dece54e3f3 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs @@ -56,7 +56,7 @@ Public Property Get Test() As Integer mockBuzz }); - Assert.Less(0, validator.HasNewPropertyNameConflicts(mockFizz.EncapsulationAttributes, mockFizz.QualifiedModuleName, (Declaration dec) => false)); + Assert.Less(0, validator.HasNewPropertyNameConflicts(mockFizz.EncapsulationAttributes, mockFizz.QualifiedModuleName, Enumerable.Empty())); } } @@ -115,7 +115,7 @@ void ThisTest(IDeclarationFinderProvider declarationProviderProvider) }); - Assert.Less(0 ,validator.HasNewPropertyNameConflicts(thisField.EncapsulationAttributes, thisField.QualifiedModuleName, (Declaration dec) => false)); + Assert.Less(0 ,validator.HasNewPropertyNameConflicts(thisField.EncapsulationAttributes, thisField.QualifiedModuleName, Enumerable.Empty())); } } [Test] @@ -147,7 +147,7 @@ void ThisTest(IDeclarationFinderProvider declarationProviderProvider) fields.Add(new EncapsulateFieldCandidate(longValue, validator)); encapsulatedWholeNumber.EncapsulationAttributes.PropertyName = "LongValue"; - Assert.Less(0, validator.HasNewPropertyNameConflicts(encapsulatedWholeNumber.EncapsulationAttributes, encapsulatedWholeNumber.QualifiedModuleName, (Declaration dec) => dec.Equals(encapsulatedWholeNumber.Declaration))); + Assert.Less(0, validator.HasNewPropertyNameConflicts(encapsulatedWholeNumber.EncapsulationAttributes, encapsulatedWholeNumber.QualifiedModuleName, new Declaration[] {encapsulatedWholeNumber.Declaration})); } } @@ -181,7 +181,7 @@ private IFieldEncapsulationAttributes CreateAttributesMock(string targetID, stri { var identifiers = new EncapsulationIdentifiers(targetID); var mock = new Mock(); - mock.SetupGet(m => m.TargetName).Returns(identifiers.TargetFieldName); + mock.SetupGet(m => m.Identifier).Returns(identifiers.TargetFieldName); mock.SetupGet(m => m.NewFieldName).Returns(identifiers.Field); mock.SetupGet(m => m.PropertyName).Returns(modifiedPropertyName ?? identifiers.Property); mock.SetupGet(m => m.AsTypeName).Returns(asTypeName); diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index 902f5b6141..a944a9f077 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -370,7 +370,7 @@ End Property fields.Add(efd); efd.PropertyName = "Name"; - var hasConflict = !validator.HasValidEncapsulationAttributes(efd.EncapsulationAttributes, efd.QualifiedModuleName, (Declaration dec) => match.Equals(dec)); + var hasConflict = !validator.HasValidEncapsulationAttributes(efd.EncapsulationAttributes, efd.QualifiedModuleName, new Declaration[] { efd.Declaration }); //(Declaration dec) => match.Equals(dec)); Assert.IsTrue(hasConflict); } } From ac4728164ed8477858a96ac1ee7a3038a9191173 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Fri, 29 Nov 2019 16:08:33 -0800 Subject: [PATCH 037/461] GUI testing tweaks --- .../EncapsulateField/EncapsulateFieldModel.cs | 5 +++-- .../EncapsulateField/EncapsulateFieldRefactoring.cs | 2 +- .../EncapsulateField/EncapsulateFieldRewriter.cs | 13 +++++++------ .../EncapsulateWithBackingUserDefinedType.cs | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index 748c8b8156..59cb5c6c39 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -64,12 +64,13 @@ public bool EncapsulateWithUDT { set { - if (EncapsulationStrategy is EncapsulateWithBackingUserDefinedType ebd) { return; } + if (value && EncapsulationStrategy is EncapsulateWithBackingUserDefinedType ebd) { return; } + + if (!value && EncapsulationStrategy is EncapsulateWithBackingFields wbf) { return; } EncapsulationStrategy = value ? new EncapsulateWithBackingUserDefinedType(_targetQMN, _indenter, _declarationFinderProvider, _validator) as IEncapsulateFieldStrategy : new EncapsulateWithBackingFields(_targetQMN, _indenter, _declarationFinderProvider, _validator) as IEncapsulateFieldStrategy; - //This probably should go - or be in the ctor } get => EncapsulationStrategy is EncapsulateWithBackingUserDefinedType; diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 8ac114bb3a..38ba485e40 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -97,7 +97,7 @@ private string PreviewRewrite(EncapsulateFieldModel model) var previewRewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(scratchPadRewriteSession, _targetQMN); - return previewRewriter.GetTextWithoutAbandonedLines(); + return previewRewriter.GetText(maxConsecutiveNewLines: 3); } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs index d60451e9b6..373c4c31a9 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs @@ -7,6 +7,7 @@ using Rubberduck.Parsing.Symbols; using Rubberduck.VBEditor; using System; +using System.Linq; namespace Rubberduck.Refactorings.EncapsulateField { @@ -17,7 +18,7 @@ public interface IEncapsulateFieldRewriter : IModuleRewriter void Rename(Declaration element, string newName); void MakeImplicitDeclarationTypeExplicit(Declaration element); void InsertAtEndOfFile(string content); - string GetTextWithoutAbandonedLines(); + string GetText(int maxConsecutiveNewLines); } @@ -87,14 +88,14 @@ public void MakeImplicitDeclarationTypeExplicit(Declaration element) } } - public string GetTextWithoutAbandonedLines() + public string GetText(int maxConsecutiveNewLines) { var preview = GetText(); - - var counter = 0; - while (counter++ < 10 && preview.Contains($"{Environment.NewLine}{Environment.NewLine}{Environment.NewLine}")) + var target = string.Join(string.Empty, Enumerable.Repeat(Environment.NewLine, maxConsecutiveNewLines).ToList()); + var replacement = string.Join(string.Empty, Enumerable.Repeat(Environment.NewLine, maxConsecutiveNewLines - 1).ToList()); + for (var counter = 1; counter < 10 && preview.Contains(target); counter++) { - preview = preview.Replace($"{Environment.NewLine}{Environment.NewLine}{Environment.NewLine}", $"{Environment.NewLine}{Environment.NewLine}"); + preview = preview.Replace(target, replacement); } return preview; } diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs index 33d1c11d2e..746168aae6 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs @@ -89,7 +89,7 @@ protected string BuildPropertiesTextBlock(IFieldEncapsulationAttributes attribut { PropertyName = attributes.PropertyName, AsTypeName = attributes.AsTypeName, - BackingField = $"{FieldName}.{attributes.PropertyName}", + BackingField = $"{StateEncapsulationField.NewFieldName}.{attributes.PropertyName}", ParameterName = attributes.ParameterName, GenerateSetter = attributes.ImplementSetSetterType, GenerateLetter = attributes.ImplementLetSetterType From 905a2f17170b7ce6aca21db4f1e7304edcbb1a99 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Mon, 2 Dec 2019 05:00:44 -0800 Subject: [PATCH 038/461] Refactored from decoration to inheritance --- .../EncapsulateFieldViewModel.cs | 33 +++- .../EncapsulateFieldDeclarationFactory.cs | 114 +++++++------ .../EncapsulateFieldDecorators.cs | 131 --------------- .../EncapsulateFieldValidator.cs | 53 ++++++- .../EncapsulatedFieldDeclaration.cs | 150 ++++++++++++------ .../EncapsulationIdentifiers.cs | 31 +++- .../FieldEncapsulationAttributes.cs | 93 ++++++----- .../EncapsulateWithBackingFields.cs | 2 +- .../EncapsulateWithBackingUserDefinedType.cs | 13 +- .../Strategies/EncapsulationStrategiesBase.cs | 18 +-- .../EncapsulatedFieldTests.cs | 39 ++++- .../EncapsulateField/TestSupport.cs | 2 +- 12 files changed, 358 insertions(+), 321 deletions(-) delete mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs index 8ee8d1a9e8..d013f79224 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs @@ -3,6 +3,7 @@ using NLog; using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings.EncapsulateField; +using Rubberduck.Refactorings.EncapsulateField.Strategies; using Rubberduck.UI.Command; namespace Rubberduck.UI.Refactorings.EncapsulateField @@ -27,7 +28,7 @@ public ObservableCollection EncapsulationFields { get { - var flaggedFields = Model.FlaggedEncapsulationFields //.Where(efd => efd.EncapsulateFlag) + var flaggedFields = Model.FlaggedEncapsulationFields .OrderBy(efd => efd.Declaration.IdentifierName); var orderedFields = Model.EncapsulationFields.Except(flaggedFields) @@ -56,25 +57,47 @@ public bool EncapsulateAsUDT Model.EncapsulateWithUDT = value; UpdatePreview(); OnPropertyChanged(nameof(HideEncapsulateAsUDTFields)); + OnPropertyChanged(nameof(EncapsulateAsUDT_TypeIdentifier)); + OnPropertyChanged(nameof(EncapsulateAsUDT_FieldName)); } } public string EncapsulateAsUDT_TypeIdentifier { - get => Model.EncapsulateWithUDT_TypeIdentifier; + get + { + if (Model.EncapsulationStrategy is IEncapsulateWithBackingUserDefinedType udtStrategy) + { + return udtStrategy.StateEncapsulationField.AsTypeName; + } + return string.Empty; + } set { - Model.EncapsulateWithUDT_TypeIdentifier = value; + if (Model.EncapsulationStrategy is IEncapsulateWithBackingUserDefinedType udtStrategy) + { + udtStrategy.StateEncapsulationField.EncapsulationAttributes.AsTypeName = value; + } UpdatePreview(); } } public string EncapsulateAsUDT_FieldName { - get => Model.EncapsulateWithUDT_FieldName; + get + { + if (Model.EncapsulationStrategy is IEncapsulateWithBackingUserDefinedType udtStrategy) + { + return udtStrategy.StateEncapsulationField.NewFieldName; + } + return string.Empty; + } set { - Model.EncapsulateWithUDT_FieldName = value; + if (Model.EncapsulationStrategy is IEncapsulateWithBackingUserDefinedType udtStrategy) + { + udtStrategy.StateEncapsulationField.EncapsulationAttributes.NewFieldName = value; + } UpdatePreview(); } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs index 45ab4e8827..904e898036 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs @@ -16,10 +16,10 @@ public class EncapsulationCandidateFactory { private readonly IDeclarationFinderProvider _declarationFinderProvider; private IDictionary)> _udtFieldToUdtDeclarationMap = new Dictionary)>(); - private QualifiedModuleName _targetQMN; private readonly IEncapsulateFieldNamesValidator _validator; private IEnumerable _candidateFields; private bool _useNewStructure; + private List _encapsulatedFields = new List(); public EncapsulationCandidateFactory(IDeclarationFinderProvider declarationFinderProvider, IEncapsulateFieldNamesValidator validator) { @@ -30,9 +30,9 @@ public EncapsulationCandidateFactory(IDeclarationFinderProvider declarationFinde _useNewStructure = File.Exists("C:\\Users\\Brian\\Documents\\UseNewUDTStructure.txt"); } - public IEncapsulateFieldCandidate CreateProposedField(string identifier, string asTypeName, QualifiedModuleName qmn, IEncapsulateFieldNamesValidator validator) + public IEncapsulateFieldCandidate CreateInsertableField(string identifier, string asTypeName, QualifiedModuleName qmn, IEncapsulateFieldNamesValidator validator) { - var unselectableAttributes = new UnselectableField(identifier, asTypeName, qmn, validator); + var unselectableAttributes = new NeverEncapsulateAttributes(identifier, asTypeName, qmn, validator); return new EncapsulateFieldCandidate(unselectableAttributes, validator); } @@ -40,98 +40,94 @@ public IEnumerable CreateEncapsulationCandidates(IEn { _candidateFields = candidateFields; + var candidates = new List(); + foreach (var field in candidateFields) + { + _encapsulatedFields.Add(EncapsulateDeclaration(field, _validator)); + } + _udtFieldToUdtDeclarationMap = candidateFields .Where(v => v.IsUserDefinedTypeField()) .Select(uv => CreateUDTTuple(uv)) .ToDictionary(key => key.UDTVariable, element => (element.UserDefinedType, element.UDTMembers)); - var candidates = new List(); - foreach (var field in candidateFields) + foreach ( var udtField in _udtFieldToUdtDeclarationMap.Keys) { - candidates.Add(EncapsulateDeclaration(field, _validator)); + var encapsulatedUDTField = _encapsulatedFields.Where(ef => ef.Declaration == udtField).Single(); + + var moduleHasMultipleInstancesOfUDT = candidateFields.Any(fld => fld != encapsulatedUDTField.Declaration && encapsulatedUDTField.AsTypeName.Equals(fld.AsTypeName)); + var concreteParent = encapsulatedUDTField as EncapsulatedUserDefinedTypeField; + + foreach (var udtMember in _udtFieldToUdtDeclarationMap[udtField].Item2) + { + IEncapsulateFieldCandidate encapsulatedUDTMember = new EncapsulatedUserDefinedTypeMember(udtMember, encapsulatedUDTField, _validator, moduleHasMultipleInstancesOfUDT); + encapsulatedUDTMember = ApplySpecializationAttributes(encapsulatedUDTMember); + concreteParent.Members.Add(encapsulatedUDTMember); + } } - return candidates; + return _encapsulatedFields; } - public IEncapsulateFieldCandidate EncapsulateDeclaration(Declaration target, IEncapsulateFieldNamesValidator validator) + private IEncapsulateFieldCandidate EncapsulateDeclaration(Declaration target, IEncapsulateFieldNamesValidator validator) { - if (target.IsUserDefinedTypeField()) - { - var udtCandidate = new EncapsulatedUserDefinedTypeField(target, validator); - udtCandidate.EncapsulationAttributes.ImplementLetSetterType = true; - udtCandidate.EncapsulationAttributes.ImplementSetSetterType = false; + Debug.Assert(!target.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)); - if (_useNewStructure) - { - var udtMembers = new List(); + var candidate = target.IsUserDefinedTypeField() + ? new EncapsulatedUserDefinedTypeField(target, validator) + : new EncapsulateFieldCandidate(target, validator); - foreach (var member in _udtFieldToUdtDeclarationMap[target].Item2) - { - var udtMemberCandidate = EncapsulateDeclaration(member, validator); - var udtMember = new EncapsulatedUserDefinedTypeMember(udtMemberCandidate, udtCandidate, HasMultipleFieldsOfSameUserDefinedType(udtCandidate)); - udtMembers.Add(udtMember); - } + return ApplySpecializationAttributes(candidate); + } - udtCandidate.Members = udtMembers.Cast().ToList(); - } + private (Declaration UDTVariable, Declaration UserDefinedType, IEnumerable UDTMembers) CreateUDTTuple(Declaration udtVariable) + { + var userDefinedTypeDeclaration = _declarationFinderProvider.DeclarationFinder + .UserDeclarations(DeclarationType.UserDefinedType) + .Where(ut => ut.IdentifierName.Equals(udtVariable.AsTypeName) + && (ut.Accessibility.Equals(Accessibility.Private) + && ut.QualifiedModuleName == udtVariable.QualifiedModuleName) + || (ut.Accessibility != Accessibility.Private)) + .SingleOrDefault(); - return udtCandidate; - } + var udtMembers = _declarationFinderProvider.DeclarationFinder + .UserDeclarations(DeclarationType.UserDefinedTypeMember) + .Where(utm => userDefinedTypeDeclaration == utm.ParentDeclaration); - var candidate = new EncapsulateFieldCandidate(target, validator); + return (udtVariable, userDefinedTypeDeclaration, udtMembers); + } - if (target.IsArray) + private IEncapsulateFieldCandidate ApplySpecializationAttributes(IEncapsulateFieldCandidate candidate) + { + var target = candidate.Declaration; + if (target.IsUserDefinedTypeField()) + { + candidate.EncapsulationAttributes.ImplementLetSetterType = true; + candidate.EncapsulationAttributes.ImplementSetSetterType = false; + } + else if (target.IsArray) { candidate.EncapsulationAttributes.ImplementLetSetterType = false; candidate.EncapsulationAttributes.ImplementSetSetterType = false; candidate.EncapsulationAttributes.AsTypeName = Tokens.Variant; - candidate.CanBeReadWrite = false; - candidate.IsReadOnly = true; - return candidate; + candidate.EncapsulationAttributes.CanBeReadWrite = false; + candidate.EncapsulationAttributes.IsReadOnly = true; } else if (target.AsTypeName.Equals(Tokens.Variant)) { candidate.EncapsulationAttributes.ImplementLetSetterType = true; candidate.EncapsulationAttributes.ImplementSetSetterType = true; - return candidate; } else if (target.IsObject) { candidate.EncapsulationAttributes.ImplementLetSetterType = false; candidate.EncapsulationAttributes.ImplementSetSetterType = true; - return candidate; } - else if (target.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)) + else { - //TODO: This may need to pass back thru using it's AsTypeName candidate.EncapsulationAttributes.ImplementLetSetterType = true; candidate.EncapsulationAttributes.ImplementSetSetterType = false; - return candidate; } - - candidate.EncapsulationAttributes.ImplementLetSetterType = true; - candidate.EncapsulationAttributes.ImplementSetSetterType = false; return candidate; } - - private (Declaration UDTVariable, Declaration UserDefinedType, IEnumerable UDTMembers) CreateUDTTuple(Declaration udtVariable) - { - var userDefinedTypeDeclaration = _declarationFinderProvider.DeclarationFinder - .UserDeclarations(DeclarationType.UserDefinedType) - .Where(ut => ut.IdentifierName.Equals(udtVariable.AsTypeName) - && (ut.Accessibility.Equals(Accessibility.Private) - && ut.QualifiedModuleName == udtVariable.QualifiedModuleName) - || (ut.Accessibility != Accessibility.Private)) - .SingleOrDefault(); - - var udtMembers = _declarationFinderProvider.DeclarationFinder - .UserDeclarations(DeclarationType.UserDefinedTypeMember) - .Where(utm => userDefinedTypeDeclaration == utm.ParentDeclaration); - - return (udtVariable, userDefinedTypeDeclaration, udtMembers); - } - - private bool HasMultipleFieldsOfSameUserDefinedType(IEncapsulateFieldCandidate udtCandidate) - => _candidateFields.Any(fld => fld != udtCandidate.Declaration && udtCandidate.AsTypeName.Equals(fld.AsTypeName)); } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs deleted file mode 100644 index 24baece520..0000000000 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDecorators.cs +++ /dev/null @@ -1,131 +0,0 @@ -using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Symbols; -using Rubberduck.Refactorings.Common; -using Rubberduck.VBEditor; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Windows; - -namespace Rubberduck.Refactorings.EncapsulateField -{ - public class EncapsulatedUserDefinedTypeField : EncapsulateFieldCandidate - { - public List Members { set; get; } - public EncapsulatedUserDefinedTypeField(Declaration declaration, IEncapsulateFieldNamesValidator validator) - : base(declaration, validator) - { - } - } - - public class EncapsulatedUserDefinedTypeMember : IEncapsulateFieldCandidate //: EncapsulateFieldDecoratorBase - { - private IEncapsulateFieldCandidate _candidate; - public EncapsulatedUserDefinedTypeMember(IEncapsulateFieldCandidate candidate, IEncapsulateFieldCandidate udtVariable, bool propertyNameRequiresParentIdentiier) - { - _candidate = candidate; - Parent = udtVariable; - NameResolveProperty = propertyNameRequiresParentIdentiier; - - EncapsulationAttributes.PropertyName = NameResolveProperty - ? $"{Parent.IdentifierName.Capitalize()}_{IdentifierName}" - : IdentifierName; - - //var fea = EncapsulationAttributes as FieldEncapsulationAttributes; - (EncapsulationAttributes as FieldEncapsulationAttributes).FieldReferenceExpressionFunc = () => AsWithMemberExpression; - candidate.IsUDTMember = true; - } - - public string AsWithMemberExpression - { - get - { - var prefix = Parent.EncapsulateFlag - ? Parent.NewFieldName - : Parent.IdentifierName; - - return $"{prefix}.{NewFieldName}"; - } - } - - public IEncapsulateFieldCandidate Parent { private set; get; } - - public bool NameResolveProperty { set; get; } - - public bool IsExistingDeclaration => _candidate.IsExistingDeclaration; - - public Declaration Declaration => _candidate.Declaration; - - public DeclarationType DeclarationType => _candidate.DeclarationType; - - public IFieldEncapsulationAttributes EncapsulationAttributes - { - get => _candidate.EncapsulationAttributes; - set => _candidate.EncapsulationAttributes = value; - } - - public bool IsReadOnly - { - get => _candidate.EncapsulationAttributes.ReadOnly; - set => _candidate.EncapsulationAttributes.ReadOnly = value; - } - - public bool EncapsulateFlag - { - get => _candidate.EncapsulateFlag; - set => _candidate.EncapsulateFlag = value; - } - - public bool CanBeReadWrite - { - get => _candidate.CanBeReadWrite; - set => _candidate.CanBeReadWrite = value; - } - - public string PropertyName - { - get => _candidate.EncapsulationAttributes.PropertyName; - set => _candidate.EncapsulationAttributes.PropertyName = value; - } - - public string NewFieldName - { - get => _candidate.EncapsulationAttributes.NewFieldName; - } - - public string AsTypeName => _candidate.EncapsulationAttributes.AsTypeName; - - public bool IsUDTMember - { - get => _candidate.IsUDTMember; - set => _candidate.IsUDTMember = value; - } - - public bool HasValidEncapsulationAttributes - => _candidate.HasValidEncapsulationAttributes; - - public QualifiedModuleName QualifiedModuleName => _candidate.QualifiedModuleName; - - public IEnumerable References => _candidate.References; - - public string TargetID => $"{Parent.IdentifierName}.{IdentifierName}"; - - public string IdentifierName => _candidate.IdentifierName; - - public string ParameterName => _candidate.ParameterName;// throw new NotImplementedException(); - - public string FieldReferenceExpression => _candidate.FieldReferenceExpression; // throw new NotImplementedException(); - - public bool ImplementLetSetterType { get => _candidate.ImplementLetSetterType; /*throw new NotImplementedException();*/ set => _candidate.ImplementLetSetterType = value; } // throw new NotImplementedException(); } - public bool ImplementSetSetterType { get => _candidate.ImplementSetSetterType; /*throw new NotImplementedException();*/ set => _candidate.ImplementSetSetterType = value; } // throw new NotImplementedException(); } - - //private string BuildPropertyName() => NameResolveProperty ? $"{Parent.IdentifierName.Capitalize()}_{IdentifierName}" : IdentifierName; - //{ - // if (NameResolveProperty) - // { - // return $"{Parent.IdentifierName.Capitalize()}_{IdentifierName}"; - // } - // return IdentifierName; - //} - } -} diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs index 406e832954..e4a046ba3b 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -72,7 +72,9 @@ namespace Rubberduck.Refactorings.EncapsulateField public interface IEncapsulateFieldNamesValidator { - bool HasValidEncapsulationAttributes(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, IEnumerable ignore); + bool HasValidEncapsulationAttributes(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, IEnumerable ignore, DeclarationType declarationType); + void ForceNonConflictEncapsulationAttributes(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, Declaration target); + void ForceNonConflictPropertyName(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, Declaration target); } public class EncapsulateFieldNamesValidator : IEncapsulateFieldNamesValidator @@ -85,12 +87,49 @@ public EncapsulateFieldNamesValidator(IDeclarationFinderProvider declarationFind _candidateFieldsRetriever = selectedFieldsRetriever; } - private DeclarationFinder DeclarationFinder => _declarationFinderProvider.DeclarationFinder; + private DeclarationFinder DeclarationFinder => _declarationFinderProvider.DeclarationFinder; - public bool HasValidEncapsulationAttributes(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, IEnumerable ignore) + public void ForceNonConflictEncapsulationAttributes(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, Declaration target) { - var isSelfConsistent = HasValidIdentifiers(attributes) - && !HasInternalNameConflicts(attributes); + if (target?.DeclarationType.HasFlag(DeclarationType.UserDefinedTypeMember) ?? false) + { + ForceNonConflictPropertyName(attributes, qmn, target); + return; + } + ForceNonConflictNewName(attributes, qmn, target); + } + + public void ForceNonConflictNewName(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, Declaration target) + { + var identifier = attributes.NewFieldName; + var ignore = target is null ? Enumerable.Empty() : new Declaration[] { target }; + + var isValidAttributeSet = HasValidEncapsulationAttributes(attributes, qmn, ignore); + for (var idx = 1; idx < 9 && !isValidAttributeSet; idx++) + { + attributes.NewFieldName = $"{identifier}{idx}"; + isValidAttributeSet = HasValidEncapsulationAttributes(attributes, qmn, ignore); + } + } + + public void ForceNonConflictPropertyName(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, Declaration target) + { + var identifier = attributes.PropertyName; + var ignore = target is null ? Enumerable.Empty() : new Declaration[] { target }; + var isValidAttributeSet = HasValidEncapsulationAttributes(attributes, qmn, ignore); + for (var idx = 1; idx < 9 && !isValidAttributeSet; idx++) + { + attributes.PropertyName = $"{identifier}{idx}"; + isValidAttributeSet = HasValidEncapsulationAttributes(attributes, qmn, ignore); + } + } + + public bool HasValidEncapsulationAttributes(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, IEnumerable ignore, DeclarationType declaration = DeclarationType.Variable) + { + var hasValidIdentifiers = HasValidIdentifiers(attributes, declaration); + var hasInternalNameConflicts = HasInternalNameConflicts(attributes); + + var isSelfConsistent = hasValidIdentifiers || hasInternalNameConflicts; if (!isSelfConsistent) { return false; } @@ -183,9 +222,9 @@ private bool UsesScopeResolution(Antlr4.Runtime.RuleContext ruleContext) || (ruleContext is VBAParser.MemberAccessExprContext); } - private bool HasValidIdentifiers(IFieldEncapsulationAttributes attributes) + private bool HasValidIdentifiers(IFieldEncapsulationAttributes attributes, DeclarationType declarationType) { - return VBAIdentifierValidator.IsValidIdentifier(attributes.NewFieldName, DeclarationType.Variable) + return VBAIdentifierValidator.IsValidIdentifier(attributes.NewFieldName, declarationType) && VBAIdentifierValidator.IsValidIdentifier(attributes.PropertyName, DeclarationType.Property) && VBAIdentifierValidator.IsValidIdentifier(attributes.ParameterName, DeclarationType.Parameter); } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs index ea4646e14d..ca32bff162 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs @@ -1,4 +1,5 @@ -using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Symbols; using Rubberduck.Refactorings.Common; using Rubberduck.VBEditor; using System; @@ -15,70 +16,72 @@ public interface IEncapsulateFieldCandidate DeclarationType DeclarationType { get; } string TargetID { get; } string IdentifierName { get; } - IFieldEncapsulationAttributes EncapsulationAttributes { set; get; } + IFieldEncapsulationAttributes EncapsulationAttributes { get; } bool IsReadOnly { set; get; } - bool CanBeReadWrite { set; get; } + bool CanBeReadWrite { get; } string PropertyName { set; get; } bool EncapsulateFlag { set; get; } string NewFieldName { get; } string AsTypeName { get; } string ParameterName { get; } string FieldReferenceExpression { get; } - bool IsUDTMember { set; get; } + bool IsUDTMember { get; } bool HasValidEncapsulationAttributes { get; } QualifiedModuleName QualifiedModuleName { get; } IEnumerable References { get; } - bool ImplementLetSetterType { get; set; } - bool ImplementSetSetterType { get; set; } - bool IsExistingDeclaration { get; } + bool ImplementLetSetterType { get; } + bool ImplementSetSetterType { get; } } - - ////string TargetName { get; } - ////string PropertyName { get; set; } - ////bool ReadOnly { get; set; } - ////bool EncapsulateFlag { get; set; } - ////string NewFieldName { set; get; } - //string FieldReferenceExpression { get; } - ////string AsTypeName { get; set; } - //string ParameterName { get; } - //bool ImplementLetSetterType { get; set; } - //bool ImplementSetSetterType { get; set; } - //bool FieldNameIsExemptFromValidation { get; } - public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate { protected Declaration _target; - private IFieldEncapsulationAttributes _attributes; + protected IFieldEncapsulationAttributes _attributes; + protected FieldEncapsulationAttributes _concreteAttributes; private IEncapsulateFieldNamesValidator _validator; public EncapsulateFieldCandidate(Declaration declaration, IEncapsulateFieldNamesValidator validator) { _target = declaration; - _attributes = new FieldEncapsulationAttributes(_target); + _concreteAttributes = new FieldEncapsulationAttributes(_target); + _attributes = _concreteAttributes; _validator = validator; - //TargetID = declaration.IdentifierName; + _validator.ForceNonConflictEncapsulationAttributes(_attributes, _target.QualifiedModuleName, _target); + } + public EncapsulateFieldCandidate(IFieldEncapsulationAttributes attributes, IEncapsulateFieldNamesValidator validator) + { + _target = null; + _concreteAttributes = new FieldEncapsulationAttributes(attributes); + _attributes = _concreteAttributes; + _validator = validator; + _validator.ForceNonConflictEncapsulationAttributes(_attributes, _attributes.QualifiedModuleName, _target); + } - var isValidAttributeSet = _validator.HasValidEncapsulationAttributes(_attributes, declaration.QualifiedModuleName, new Declaration[] { _target }); // (Declaration dec) => dec.Equals(_target)); - for (var idx = 2; idx < 9 && !isValidAttributeSet; idx++) + //TODO: Defaulting to DeclarationType.Variable needs to be better + private static void ForceNonConflictNewName(string identifier, QualifiedModuleName qmn, IFieldEncapsulationAttributes attributes, IEncapsulateFieldNamesValidator validator, IEnumerable ignore) + { + var isValidAttributeSet = validator.HasValidEncapsulationAttributes(attributes, qmn, ignore, DeclarationType.Variable); + for (var idx = 1; idx < 9 && !isValidAttributeSet; idx++) { - _attributes.NewFieldName = $"{declaration.IdentifierName}{idx}"; - isValidAttributeSet = _validator.HasValidEncapsulationAttributes(_attributes, declaration.QualifiedModuleName, new Declaration[] { _target }); //(Declaration dec) => dec.Equals(_target)); + attributes.NewFieldName = $"{identifier}{idx}"; + isValidAttributeSet = validator.HasValidEncapsulationAttributes(attributes, qmn, ignore, DeclarationType.Variable); } } - public EncapsulateFieldCandidate(IFieldEncapsulationAttributes attributes, IEncapsulateFieldNamesValidator validator) + //TODO: Defaulting to DeclarationType.Variable needs to be better + private static void ForceNonConflictPropertyName(string identifier, QualifiedModuleName qmn, IFieldEncapsulationAttributes attributes, IEncapsulateFieldNamesValidator validator, IEnumerable ignore) { - _target = null; - _attributes = attributes; // new FieldEncapsulationAttributes(identifier, asTypeName); - _validator = validator; + var isValidAttributeSet = validator.HasValidEncapsulationAttributes(attributes, qmn, ignore, DeclarationType.Variable); + for (var idx = 1; idx < 9 && !isValidAttributeSet; idx++) + { + attributes.PropertyName = $"{identifier}{idx}"; + isValidAttributeSet = validator.HasValidEncapsulationAttributes(attributes, qmn, ignore, DeclarationType.Variable); + } } public Declaration Declaration => _target; - public bool IsExistingDeclaration => _target != null; - public DeclarationType DeclarationType => _target?.DeclarationType ?? DeclarationType.Variable; public bool HasValidEncapsulationAttributes @@ -86,13 +89,14 @@ public bool HasValidEncapsulationAttributes get { var ignore = _target != null ? new Declaration[] { _target } : Enumerable.Empty(); - return _validator.HasValidEncapsulationAttributes(EncapsulationAttributes, QualifiedModuleName, ignore); //(Declaration dec) => dec.Equals(_target)); + var declarationType = _target != null ? _target.DeclarationType : DeclarationType.Variable; + return _validator.HasValidEncapsulationAttributes(EncapsulationAttributes, QualifiedModuleName, ignore, declarationType); //(Declaration dec) => dec.Equals(_target)); } - } + } - public IFieldEncapsulationAttributes EncapsulationAttributes + public IFieldEncapsulationAttributes EncapsulationAttributes { - set => _attributes = value; + private set => _attributes = value; get => _attributes; } @@ -106,11 +110,15 @@ public bool EncapsulateFlag public bool IsReadOnly { - get => _attributes.ReadOnly; - set => _attributes.ReadOnly = value; + get => _attributes.IsReadOnly; + set => _attributes.IsReadOnly = value; } - public bool CanBeReadWrite { set; get; } = true; + public bool CanBeReadWrite + { + get => _attributes.CanBeReadWrite; + set => _attributes.CanBeReadWrite = value; + } public string PropertyName { @@ -127,8 +135,7 @@ public string NewFieldName public string AsTypeName => _target?.AsTypeName ?? _attributes.AsTypeName; - //TODO: This needs to be readonly - public bool IsUDTMember { set; get; } = false; + public virtual bool IsUDTMember { get; } = false; public QualifiedModuleName QualifiedModuleName => Declaration?.QualifiedModuleName ?? _attributes.QualifiedModuleName; @@ -136,11 +143,62 @@ public string NewFieldName public string IdentifierName => Declaration?.IdentifierName ?? _attributes.Identifier; - public string ParameterName => _attributes.ParameterName;// throw new NotImplementedException(); + public string ParameterName => _attributes.ParameterName; + + public string FieldReferenceExpression => _attributes.FieldAccessExpression; + + public bool ImplementLetSetterType { get => _attributes.ImplementLetSetterType; set => _attributes.ImplementLetSetterType = value; } + public bool ImplementSetSetterType { get => _attributes.ImplementSetSetterType; set => _attributes.ImplementSetSetterType = value; } + } + + public class EncapsulatedUserDefinedTypeField : EncapsulateFieldCandidate + { + public List Members { set; get; } = new List(); + public EncapsulatedUserDefinedTypeField(Declaration declaration, IEncapsulateFieldNamesValidator validator) + : base(declaration, validator) { } + } + + public interface IEncapsulatedUserDefinedTypeMember + { + Func FieldAccessExpressionFunc { set; get; } + } + + + public class EncapsulatedUserDefinedTypeMember : EncapsulateFieldCandidate, IEncapsulatedUserDefinedTypeMember + { + public EncapsulatedUserDefinedTypeMember(Declaration target, IEncapsulateFieldCandidate udtVariable, IEncapsulateFieldNamesValidator validator, bool propertyNameRequiresParentIdentifier) + : base(target, validator) + { + Parent = udtVariable; + NameResolveProperty = propertyNameRequiresParentIdentifier; + + EncapsulationAttributes.PropertyName = NameResolveProperty + ? $"{Parent.IdentifierName.Capitalize()}_{IdentifierName}" + : IdentifierName; + + FieldAccessExpressionFunc = + () => + { + var prefix = Parent.EncapsulateFlag + ? Parent.NewFieldName + : Parent.IdentifierName; + + return $"{prefix}.{NewFieldName}"; + }; + } + + public Func FieldAccessExpressionFunc + { + set => _concreteAttributes.FieldAccessExpressionFunc = value; + get => _concreteAttributes.FieldAccessExpressionFunc; + } + + public IEncapsulateFieldCandidate Parent { private set; get; } + + public bool NameResolveProperty { set; get; } - public string FieldReferenceExpression => _attributes.FieldReferenceExpression; // throw new NotImplementedException(); + public override string TargetID => $"{Parent.IdentifierName}.{IdentifierName}"; - public bool ImplementLetSetterType { get => _attributes.ImplementLetSetterType; /*throw new NotImplementedException();*/ set => _attributes.ImplementLetSetterType = value; } // throw new NotImplementedException(); } - public bool ImplementSetSetterType { get => _attributes.ImplementSetSetterType; /*throw new NotImplementedException();*/ set => _attributes.ImplementSetSetterType = value; } // throw new NotImplementedException(); } + public override bool IsUDTMember => true; } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationIdentifiers.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationIdentifiers.cs index 9eff1ce062..576ed527e7 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationIdentifiers.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationIdentifiers.cs @@ -1,15 +1,27 @@ using Rubberduck.Parsing.Symbols; using System; using System.Collections.Generic; +using System.IO; namespace Rubberduck.Refactorings.EncapsulateField { + public struct EncapsulationAttributeIdentifier + { + public EncapsulationAttributeIdentifier(string name, bool isImmutable = false) + { + Name = name; + IsImmutable = isImmutable; + } + public string Name; + public bool IsImmutable; + } + public class EncapsulationIdentifiers { private static string DEFAULT_WRITE_PARAMETER = "value"; private KeyValuePair _fieldAndProperty; - private string _targetIdentifier; + private EncapsulationAttributeIdentifier _targetIdentifier; private string _defaultPropertyName; private string _defaultFieldName; private string _setLetParameter; @@ -19,14 +31,23 @@ public EncapsulationIdentifiers(Declaration target) public EncapsulationIdentifiers(string field) { - _targetIdentifier = field; + _targetIdentifier = new EncapsulationAttributeIdentifier(field, true); _defaultPropertyName = field.Capitalize(); _defaultFieldName = $"{field.UnCapitalize()}1"; _fieldAndProperty = new KeyValuePair(_defaultFieldName, _defaultPropertyName); _setLetParameter = DEFAULT_WRITE_PARAMETER; } - public string TargetFieldName => _targetIdentifier; + public EncapsulationIdentifiers(string field, string fieldName, string propertyName) + { + _targetIdentifier = new EncapsulationAttributeIdentifier(field); + _defaultPropertyName = field.Capitalize(); + _defaultFieldName = $"{field.UnCapitalize()}1"; + _fieldAndProperty = new KeyValuePair(fieldName, propertyName); + _setLetParameter = DEFAULT_WRITE_PARAMETER; + } + + public string TargetFieldName => _targetIdentifier.Name; public string Field { @@ -44,8 +65,8 @@ public string Property set { var fieldIdentifier = Field.EqualsVBAIdentifier(value) - ? _defaultFieldName - : _targetIdentifier; + ? _defaultFieldName + : _targetIdentifier.Name; _fieldAndProperty = new KeyValuePair(fieldIdentifier, value); diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs index 0e8c708401..129571a520 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs @@ -9,50 +9,37 @@ public interface IFieldEncapsulationAttributes { string Identifier { get; } string PropertyName { get; set; } - bool ReadOnly { get; set; } + bool IsReadOnly { get; set; } bool EncapsulateFlag { get; set; } string NewFieldName { set; get; } - string FieldReferenceExpression { get; } + bool CanBeReadWrite { set; get; } + string FieldAccessExpression { get; } string AsTypeName { get; set; } string ParameterName { get;} bool ImplementLetSetterType { get; set; } bool ImplementSetSetterType { get; set; } bool FieldNameIsExemptFromValidation { get; } QualifiedModuleName QualifiedModuleName { get; } - - //IEncapsulatedField - //Declaration Declaration { get; } //DeclarationType DeclarationType { get; } - //dup //string TargetID { get; } - //IFieldEncapsulationAttributes EncapsulationAttributes { set; get; } - //dup //bool IsReadOnly { set; get; } - //bool CanBeReadWrite { set; get; } - //dup //string PropertyName { set; get; } - //dup //bool EncapsulateFlag { set; get; } - //dup //string NewFieldName { get; } - //dup //string AsTypeName { get; } - //bool IsUDTMember { set; get; } - //bool HasValidEncapsulationAttributes { get; } - //dup//QualifiedModuleName QualifiedModuleName { get; } - //IEnumerable References { get; } - } - public class UnselectableField : IFieldEncapsulationAttributes + + //Used for declarations that will be added to the code, but will never be encapsulated + //Satifies the IFieldEncapsulationAttributes interface but some properties return n + public class NeverEncapsulateAttributes : IFieldEncapsulationAttributes { - private const string neverUsed = "x_x_x_x_x_x_x"; + private const string neverUse = "x_x_x_x"; private IEncapsulateFieldNamesValidator _validator; private QualifiedModuleName _qmn; - public UnselectableField(string identifier, string asTypeName, QualifiedModuleName qmn, IEncapsulateFieldNamesValidator validator) + public NeverEncapsulateAttributes(string identifier, string asTypeName, QualifiedModuleName qmn, IEncapsulateFieldNamesValidator validator) { - //_fieldAndProperty = new EncapsulationIdentifiers(identifier); _qmn = qmn; _validator = validator; Identifier = identifier; NewFieldName = identifier; AsTypeName = asTypeName; - FieldReferenceExpressionFunc = () => NewFieldName; + FieldAccessExpressionFunc = () => NewFieldName; } public IFieldEncapsulationAttributes ApplyNewFieldName(string newFieldName) @@ -61,54 +48,80 @@ public IFieldEncapsulationAttributes ApplyNewFieldName(string newFieldName) return this; } + //public DeclarationType DeclarationType { get; } = DeclarationType.UserDefinedType; + public string Identifier { private set; get; } public string NewFieldName { set; get; } string _tossString; - public string PropertyName { set => _tossString = value; get => $"{neverUsed}{Identifier}_{neverUsed}"; } + public string PropertyName { set => _tossString = value; get => $"{neverUse}{Identifier}_{neverUse}"; } - public string FieldReferenceExpression => FieldReferenceExpressionFunc(); + public string FieldAccessExpression => FieldAccessExpressionFunc(); - public Func FieldReferenceExpressionFunc { set; get; } + public Func FieldAccessExpressionFunc { set; get; } public string AsTypeName { get; set; } - public string ParameterName => neverUsed; + public string ParameterName => neverUse; private bool _toss; - public bool ReadOnly { get; set; } = false; + public bool IsReadOnly { get; set; } = false; + public bool CanBeReadWrite { get => false; set => _toss = value; } + public bool EncapsulateFlag { get => false; set => _toss = value; } public bool ImplementLetSetterType { get => false; set => _toss = value; } public bool ImplementSetSetterType { get => false; set => _toss = value; } - public bool FieldNameIsExemptFromValidation => false; // NewFieldName.EqualsVBAIdentifier(Identifier); + public bool FieldNameIsExemptFromValidation => false; public QualifiedModuleName QualifiedModuleName => _qmn; } public class FieldEncapsulationAttributes : IFieldEncapsulationAttributes { private QualifiedModuleName _qmn; + private bool _fieldNameIsAlwaysValid; public FieldEncapsulationAttributes(Declaration target) { _fieldAndProperty = new EncapsulationIdentifiers(target); Identifier = target.IdentifierName; AsTypeName = target.AsTypeName; _qmn = target.QualifiedModuleName; - FieldReferenceExpressionFunc = () => NewFieldName; + FieldAccessExpressionFunc = () => NewFieldName; + _fieldNameIsAlwaysValid = target.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember); + //DeclarationType = target.DeclarationType; } public FieldEncapsulationAttributes(string identifier, string asTypeName) { _fieldAndProperty = new EncapsulationIdentifiers(identifier); AsTypeName = asTypeName; - FieldReferenceExpressionFunc = () => NewFieldName; + FieldAccessExpressionFunc = () => NewFieldName; + } + + public FieldEncapsulationAttributes(IFieldEncapsulationAttributes attributes) + { + _fieldAndProperty = new EncapsulationIdentifiers(attributes.Identifier, attributes.NewFieldName, attributes.PropertyName); + PropertyName = attributes.PropertyName; + IsReadOnly = attributes.IsReadOnly; + EncapsulateFlag = attributes.EncapsulateFlag; + NewFieldName = attributes.NewFieldName; + CanBeReadWrite = attributes.CanBeReadWrite; + AsTypeName = attributes.AsTypeName; + ImplementLetSetterType = attributes.ImplementLetSetterType; + ImplementSetSetterType = attributes.ImplementSetSetterType; + QualifiedModuleName = attributes.QualifiedModuleName; + FieldAccessExpressionFunc = () => NewFieldName; } private EncapsulationIdentifiers _fieldAndProperty; + //public DeclarationType DeclarationType { private set; get; } = DeclarationType.Variable; + public string Identifier { private set; get; } + public bool CanBeReadWrite { set; get; } = true; + public string NewFieldName { get => _fieldAndProperty.Field; @@ -121,22 +134,26 @@ public string PropertyName set => _fieldAndProperty.Property = value; } - public string FieldReferenceExpression => FieldReferenceExpressionFunc(); + public string FieldAccessExpression => FieldAccessExpressionFunc(); - public Func FieldReferenceExpressionFunc { set; get; } + public Func FieldAccessExpressionFunc { set; get; } public string AsTypeName { get; set; } public string ParameterName => _fieldAndProperty.SetLetParameter; - public bool ReadOnly { get; set; } + public bool IsReadOnly { get; set; } public bool EncapsulateFlag { get; set; } private bool _implLet; - public bool ImplementLetSetterType { get => !ReadOnly && _implLet; set => _implLet = value; } + public bool ImplementLetSetterType { get => !IsReadOnly && _implLet; set => _implLet = value; } private bool _implSet; - public bool ImplementSetSetterType { get => !ReadOnly && _implSet; set => _implSet = value; } + public bool ImplementSetSetterType { get => !IsReadOnly && _implSet; set => _implSet = value; } - public bool FieldNameIsExemptFromValidation => NewFieldName.EqualsVBAIdentifier(Identifier); - public QualifiedModuleName QualifiedModuleName => _qmn; + public bool FieldNameIsExemptFromValidation => _fieldNameIsAlwaysValid || NewFieldName.EqualsVBAIdentifier(Identifier); + public QualifiedModuleName QualifiedModuleName + { + get => _qmn; + set => _qmn = value; + } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs index 96cd4cc7ce..85db18b358 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs @@ -84,7 +84,7 @@ private string BuildPropertiesTextBlock(IFieldEncapsulationAttributes attributes { PropertyName = attributes.PropertyName, AsTypeName = attributes.AsTypeName, - BackingField = attributes.FieldReferenceExpression, + BackingField = attributes.FieldAccessExpression, ParameterName = attributes.ParameterName, GenerateSetter = attributes.ImplementSetSetterType, GenerateLetter = attributes.ImplementLetSetterType diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs index 746168aae6..1a0c5aef94 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs @@ -25,15 +25,11 @@ public class EncapsulateWithBackingUserDefinedType : EncapsulateFieldStrategiesB public EncapsulateWithBackingUserDefinedType(QualifiedModuleName qmn, IIndenter indenter, IDeclarationFinderProvider declarationFinderProvider, IEncapsulateFieldNamesValidator validator) : base(qmn, indenter, declarationFinderProvider, validator) { - StateEncapsulationField = _candidateFactory.CreateProposedField(DEFAULT_FIELD_IDENTIFIER, DEFAULT_TYPE_IDENTIFIER, qmn, validator); + StateEncapsulationField = _candidateFactory.CreateInsertableField(DEFAULT_FIELD_IDENTIFIER, DEFAULT_TYPE_IDENTIFIER, qmn, validator); } public IEncapsulateFieldCandidate StateEncapsulationField { set; get; } - public string TypeIdentifier { set; get; } = DEFAULT_TYPE_IDENTIFIER; - - public string FieldName { set; get; } = DEFAULT_FIELD_IDENTIFIER; - protected override void ModifyEncapsulatedVariable(IEncapsulateFieldCandidate target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession) { var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); @@ -48,16 +44,13 @@ protected override EncapsulateFieldNewContent LoadNewDeclarationsContent(Encapsu var nonUdtMemberFields = FlaggedEncapsulationFields .Where(encFld => encFld.Declaration.IsVariable()); - var udt = new UDTDeclarationGenerator(TypeIdentifier); + var udt = new UDTDeclarationGenerator(StateEncapsulationField.AsTypeName); foreach (var nonUdtMemberField in nonUdtMemberFields) { udt.AddMember(nonUdtMemberField); } newContent.AddDeclarationBlock(udt.TypeDeclarationBlock(Indenter)); - if (!StateEncapsulationField.HasValidEncapsulationAttributes) - { - ForceNonConflictFieldName(StateEncapsulationField); - } + newContent.AddDeclarationBlock(udt.FieldDeclaration(StateEncapsulationField.NewFieldName)); var udtMemberFields = FlaggedEncapsulationFields.Where(efd => efd.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)); diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs index 6ab34bd46c..825e9f28ee 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs @@ -39,13 +39,12 @@ public EncapsulateFieldStrategiesBase(QualifiedModuleName qmn, IIndenter indente .Members(qmn) .Where(v => v.IsMemberVariable() && !v.IsWithEvents); - //if (_useNewStructure) - //{ var candidates = _candidateFactory.CreateEncapsulationCandidates(EncapsulationCandidateFields); foreach (var candidate in candidates) { HeirarchicalCandidates.Add(candidate.TargetID, candidate); } + FlattenedTargetIDToCandidateMapping = Flatten(HeirarchicalCandidates); foreach (var element in FlattenedTargetIDToCandidateMapping) { @@ -55,8 +54,6 @@ public EncapsulateFieldStrategiesBase(QualifiedModuleName qmn, IIndenter indente UdtMemberTargetIDToParentMap.Add(element.Key, udtMember.Parent); } } - - //} } protected QualifiedModuleName TargetQMN {private set; get;} @@ -85,19 +82,6 @@ public IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IE protected Dictionary HeirarchicalCandidates { set; get; } = new Dictionary(); - protected IEncapsulateFieldCandidate ForceNonConflictFieldName(IEncapsulateFieldCandidate candidate) - { - if (candidate.EncapsulationAttributes is UnselectableField concrete) - { - var attempt = 0; - while (attempt++ < 10 && !candidate.HasValidEncapsulationAttributes) - { - concrete.ApplyNewFieldName($"{concrete.NewFieldName}{attempt}"); - } - } - return candidate; - } - private IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) { var nonUdtMemberFields = model.FlaggedEncapsulationFields diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs index a44fb1a502..eb62815718 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs @@ -5,6 +5,7 @@ using Rubberduck.SmartIndenter; using Rubberduck.VBEditor.SafeComWrappers.Abstract; using System.Linq; +using Rubberduck.Parsing.Symbols; namespace RubberduckTests.Refactoring.EncapsulateField { @@ -31,7 +32,7 @@ public void PropertyNameAttributeValidations_Internal(string originalFieldName, [Category("Refactorings")] [Category("Encapsulate Field")] public void FieldNameAttributeValidation_DefaultsToAvailableFieldName() - { + { string inputCode = $@"Public fizz As String @@ -50,6 +51,28 @@ End Property Assert.IsTrue(encapsulatedField.HasValidEncapsulationAttributes); } + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UDTMemberPropertyDefaultsToValidValue() + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +Public myBar As TBar + +Private Function First() As String + First = myBar.First +End Function"; + + var encapsulatedField = RetrieveEncapsulatedField(inputCode, "First", DeclarationType.UserDefinedTypeMember); + StringAssert.AreNotEqualIgnoringCase("First", encapsulatedField.PropertyName); + } + [Test] [Category("Refactorings")] [Category("Encapsulate Field")] @@ -145,6 +168,20 @@ private IEncapsulateFieldCandidate RetrieveEncapsulatedField(string inputCode, s } } + private IEncapsulateFieldCandidate RetrieveEncapsulatedField(string inputCode, string fieldName, DeclarationType declarationType) + { + var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; + + var selectedComponentName = vbe.SelectedVBComponent.Name; + + var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); + using (state) + { + var match = state.DeclarationFinder.MatchName(fieldName).Where(m => m.DeclarationType.Equals(declarationType)).Single(); + return new EncapsulateFieldCandidate(match, new EncapsulateFieldNamesValidator(state)) as IEncapsulateFieldCandidate; + } + } + private static IIndenter CreateIndenter(IVBE vbe = null) { return new Indenter(vbe, () => Settings.IndenterSettingsTests.GetMockIndenterSettings()); diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index bf6bac5927..09a9a6d044 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -69,7 +69,7 @@ public Func SetParameters(string o { var encapsulatedField = model[originalField]; encapsulatedField.EncapsulationAttributes.PropertyName = attrs.PropertyName; - encapsulatedField.EncapsulationAttributes.ReadOnly = attrs.IsReadOnly; + encapsulatedField.EncapsulationAttributes.IsReadOnly = attrs.IsReadOnly; encapsulatedField.EncapsulationAttributes.EncapsulateFlag = attrs.EncapsulateFlag; model.EncapsulateWithUDT = asUDT; From 82d073f072809d7f20fe232e28cea3e9ccb195c3 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Mon, 2 Dec 2019 06:15:37 -0800 Subject: [PATCH 039/461] Some cleanup --- .../EncapsulatedFieldDeclaration.cs | 4 +-- .../EncapsulationFieldGroup.cs | 19 -------------- .../EncapsulateWithBackingFields.cs | 2 +- .../EncapsulateWithBackingUserDefinedType.cs | 18 +++++++++---- .../Strategies/EncapsulationStrategiesBase.cs | 26 +++++++++---------- 5 files changed, 29 insertions(+), 40 deletions(-) delete mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulationFieldGroup.cs diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs index ca32bff162..b6db839b1d 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs @@ -135,7 +135,7 @@ public string NewFieldName public string AsTypeName => _target?.AsTypeName ?? _attributes.AsTypeName; - public virtual bool IsUDTMember { get; } = false; + public bool IsUDTMember => _target?.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember) ?? false; public QualifiedModuleName QualifiedModuleName => Declaration?.QualifiedModuleName ?? _attributes.QualifiedModuleName; @@ -199,6 +199,6 @@ public Func FieldAccessExpressionFunc public override string TargetID => $"{Parent.IdentifierName}.{IdentifierName}"; - public override bool IsUDTMember => true; + //public override bool IsUDTMember => true; } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationFieldGroup.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationFieldGroup.cs deleted file mode 100644 index 223ed9b470..0000000000 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationFieldGroup.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Rubberduck.Parsing.VBA; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Rubberduck.Refactorings.EncapsulateField -{ - public class EncapsulationFieldGroup - { - private readonly IDeclarationFinderProvider _declarationFinderProvider; - - public EncapsulationFieldGroup(IDeclarationFinderProvider declarationFinderProvider) - { - _declarationFinderProvider = declarationFinderProvider; - } - } -} diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs index 85db18b358..ee90fe6fe5 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs @@ -19,7 +19,7 @@ public EncapsulateWithBackingFields(QualifiedModuleName qmn, IIndenter indenter, { } - protected override void ModifyEncapsulatedVariable(IEncapsulateFieldCandidate target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession) //, bool asUDT = false) //, EncapsulateFieldNewContent newContent) + protected override void ModifyEncapsulatedVariable(IEncapsulateFieldCandidate target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession) { var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs index 1a0c5aef94..832de0c1e3 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs @@ -42,7 +42,7 @@ protected override void ModifyEncapsulatedVariable(IEncapsulateFieldCandidate ta protected override EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNewContent newContent, IEnumerable FlaggedEncapsulationFields) { var nonUdtMemberFields = FlaggedEncapsulationFields - .Where(encFld => encFld.Declaration.IsVariable()); + .Where(encFld => !encFld.IsUDTMember); var udt = new UDTDeclarationGenerator(StateEncapsulationField.AsTypeName); foreach (var nonUdtMemberField in nonUdtMemberFields) @@ -53,15 +53,23 @@ protected override EncapsulateFieldNewContent LoadNewDeclarationsContent(Encapsu newContent.AddDeclarationBlock(udt.FieldDeclaration(StateEncapsulationField.NewFieldName)); - var udtMemberFields = FlaggedEncapsulationFields.Where(efd => efd.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)); + return newContent; + } + + protected override EncapsulateFieldNewContent LoadNewPropertiesContent(EncapsulateFieldNewContent newContent, IEnumerable FlaggedEncapsulationFields, string postScript = null) + { + if (!FlaggedEncapsulationFields.Any()) { return newContent; } + + var udtMemberFields = FlaggedEncapsulationFields.Where(efd => efd.IsUDTMember); foreach (var udtMember in udtMemberFields) { - newContent.AddCodeBlock(EncapsulateInUDT_UDTMemberProperty(udtMember)); + newContent.AddCodeBlock(CreateUDTMemberProperty(udtMember)); } - return newContent; + return base.LoadNewPropertiesContent(newContent, FlaggedEncapsulationFields, postScript); } + protected override IList PropertiesContent(IEnumerable flaggedEncapsulationFields) { var textBlocks = new List(); @@ -92,7 +100,7 @@ protected string BuildPropertiesTextBlock(IFieldEncapsulationAttributes attribut return string.Join(Environment.NewLine, Indenter.Indent(propertyTextLines, true)); } - private string EncapsulateInUDT_UDTMemberProperty(IEncapsulateFieldCandidate udtMember) + private string CreateUDTMemberProperty(IEncapsulateFieldCandidate udtMember) { var parentField = UdtMemberTargetIDToParentMap[udtMember.TargetID]; var generator = new PropertyGenerator diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs index 825e9f28ee..338ee9c793 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs @@ -43,17 +43,17 @@ public EncapsulateFieldStrategiesBase(QualifiedModuleName qmn, IIndenter indente foreach (var candidate in candidates) { HeirarchicalCandidates.Add(candidate.TargetID, candidate); - } - - FlattenedTargetIDToCandidateMapping = Flatten(HeirarchicalCandidates); - foreach (var element in FlattenedTargetIDToCandidateMapping) - { - if (element.Value.IsUDTMember) + if (candidate is EncapsulatedUserDefinedTypeField udtField) { - var udtMember = element.Value as EncapsulatedUserDefinedTypeMember; - UdtMemberTargetIDToParentMap.Add(element.Key, udtMember.Parent); + foreach( var member in udtField.Members) + { + var concrete = member as EncapsulatedUserDefinedTypeMember; + UdtMemberTargetIDToParentMap.Add(member.TargetID, concrete.Parent); + } } } + + FlattenedTargetIDToCandidateMapping = Flatten(HeirarchicalCandidates); } protected QualifiedModuleName TargetQMN {private set; get;} @@ -74,7 +74,7 @@ public IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IE protected virtual IEnumerable EncapsulationCandidateFields { set; get; } - protected abstract void ModifyEncapsulatedVariable(IEncapsulateFieldCandidate target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession); //, EncapsulateFieldNewContent newContent) + protected abstract void ModifyEncapsulatedVariable(IEncapsulateFieldCandidate target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession); protected abstract EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNewContent newContent, IEnumerable FlaggedEncapsulationFields); @@ -85,7 +85,7 @@ public IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IE private IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) { var nonUdtMemberFields = model.FlaggedEncapsulationFields - .Where(encFld => encFld.Declaration.IsVariable()); + .Where(encFld => !encFld.IsUDTMember); foreach (var nonUdtMemberField in nonUdtMemberFields) { @@ -104,14 +104,14 @@ private IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, I public Dictionary UdtMemberTargetIDToParentMap { get; set; } = new Dictionary(); - private void InsertNewContent(int? codeSectionStartIndex, EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool includePreviewMessage = false) + private void InsertNewContent(int? codeSectionStartIndex, EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool postPendPreviewMessage = false) { var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); var newContent = new EncapsulateFieldNewContent(); newContent = LoadNewDeclarationsContent(newContent, model.FlaggedEncapsulationFields); - if (includePreviewMessage) + if (postPendPreviewMessage) { var postScript = "'<===== No Changes below this line =====>"; newContent = LoadNewPropertiesContent(newContent, model.FlaggedEncapsulationFields, postScript); @@ -146,7 +146,7 @@ protected Dictionary Flatten(Dictionary FlaggedEncapsulationFields, string postScript = null) + protected virtual EncapsulateFieldNewContent LoadNewPropertiesContent(EncapsulateFieldNewContent newContent, IEnumerable FlaggedEncapsulationFields, string postScript = null) { if (!FlaggedEncapsulationFields.Any()) { return newContent; } From e10e24647919db5ecf97947ab05c68b3b4bef6bd Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Tue, 3 Dec 2019 08:07:26 -0800 Subject: [PATCH 040/461] Added failing test(s) and refactoring --- .../EncapsulateFieldViewModel.cs | 8 +- .../EncapsulateFieldDeclarationFactory.cs | 43 +++--- .../EncapsulateField/EncapsulateFieldModel.cs | 65 +++++---- .../EncapsulatedFieldDeclaration.cs | 81 ++++------- .../FieldEncapsulationAttributes.cs | 24 +--- .../EncapsulateWithBackingFields.cs | 49 +++---- .../EncapsulateWithBackingUserDefinedType.cs | 134 ++++++++---------- .../Strategies/EncapsulationStrategiesBase.cs | 93 ++++-------- .../UDTDeclarationGenerator.cs | 45 ++---- .../EncapsulateField/EncapsulateAsUDTTests.cs | 35 +++++ .../EncapsulatedFieldTests.cs | 2 +- .../EncapsulateField/TestSupport.cs | 14 +- 12 files changed, 266 insertions(+), 327 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs index d013f79224..63430efe7e 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs @@ -68,7 +68,7 @@ public string EncapsulateAsUDT_TypeIdentifier { if (Model.EncapsulationStrategy is IEncapsulateWithBackingUserDefinedType udtStrategy) { - return udtStrategy.StateEncapsulationField.AsTypeName; + return udtStrategy.StateUDTField.AsTypeName; } return string.Empty; } @@ -76,7 +76,7 @@ public string EncapsulateAsUDT_TypeIdentifier { if (Model.EncapsulationStrategy is IEncapsulateWithBackingUserDefinedType udtStrategy) { - udtStrategy.StateEncapsulationField.EncapsulationAttributes.AsTypeName = value; + udtStrategy.StateUDTField.EncapsulationAttributes.AsTypeName = value; } UpdatePreview(); } @@ -88,7 +88,7 @@ public string EncapsulateAsUDT_FieldName { if (Model.EncapsulationStrategy is IEncapsulateWithBackingUserDefinedType udtStrategy) { - return udtStrategy.StateEncapsulationField.NewFieldName; + return udtStrategy.StateUDTField.NewFieldName; } return string.Empty; } @@ -96,7 +96,7 @@ public string EncapsulateAsUDT_FieldName { if (Model.EncapsulationStrategy is IEncapsulateWithBackingUserDefinedType udtStrategy) { - udtStrategy.StateEncapsulationField.EncapsulationAttributes.NewFieldName = value; + udtStrategy.StateUDTField.EncapsulationAttributes.NewFieldName = value; } UpdatePreview(); } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs index 904e898036..29a64e4664 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs @@ -14,55 +14,66 @@ namespace Rubberduck.Refactorings.EncapsulateField { public class EncapsulationCandidateFactory { + private const string DEFAULT_STATE_UDT_IDENTIFIER = "This_Type"; + private const string DEFAULT_STATE_UDT_FIELD_IDENTIFIER = "this"; + private readonly IDeclarationFinderProvider _declarationFinderProvider; - private IDictionary)> _udtFieldToUdtDeclarationMap = new Dictionary)>(); private readonly IEncapsulateFieldNamesValidator _validator; - private IEnumerable _candidateFields; - private bool _useNewStructure; private List _encapsulatedFields = new List(); + //TODO: This needs to go away + private bool _useNewStructure; + public EncapsulationCandidateFactory(IDeclarationFinderProvider declarationFinderProvider, IEncapsulateFieldNamesValidator validator) { _declarationFinderProvider = declarationFinderProvider; _validator = validator; + //TODO: This needs to go away _useNewStructure = File.Exists("C:\\Users\\Brian\\Documents\\UseNewUDTStructure.txt"); } - public IEncapsulateFieldCandidate CreateInsertableField(string identifier, string asTypeName, QualifiedModuleName qmn, IEncapsulateFieldNamesValidator validator) + public IEncapsulateFieldCandidate CreateStateUDTField(QualifiedModuleName qmn, string identifier = DEFAULT_STATE_UDT_FIELD_IDENTIFIER, string asTypeName = DEFAULT_STATE_UDT_IDENTIFIER) { - var unselectableAttributes = new NeverEncapsulateAttributes(identifier, asTypeName, qmn, validator); - return new EncapsulateFieldCandidate(unselectableAttributes, validator); + var unselectableAttributes = new NeverEncapsulateAttributes(identifier, asTypeName, qmn, _validator); + return new EncapsulateFieldCandidate(unselectableAttributes, _validator); } public IEnumerable CreateEncapsulationCandidates(IEnumerable candidateFields) { - _candidateFields = candidateFields; - var candidates = new List(); foreach (var field in candidateFields) { _encapsulatedFields.Add(EncapsulateDeclaration(field, _validator)); } - _udtFieldToUdtDeclarationMap = candidateFields + var udtFieldToUdtDeclarationMap = candidateFields .Where(v => v.IsUserDefinedTypeField()) .Select(uv => CreateUDTTuple(uv)) .ToDictionary(key => key.UDTVariable, element => (element.UserDefinedType, element.UDTMembers)); - foreach ( var udtField in _udtFieldToUdtDeclarationMap.Keys) + foreach ( var udtField in udtFieldToUdtDeclarationMap.Keys) { var encapsulatedUDTField = _encapsulatedFields.Where(ef => ef.Declaration == udtField).Single(); var moduleHasMultipleInstancesOfUDT = candidateFields.Any(fld => fld != encapsulatedUDTField.Declaration && encapsulatedUDTField.AsTypeName.Equals(fld.AsTypeName)); - var concreteParent = encapsulatedUDTField as EncapsulatedUserDefinedTypeField; + var parent = encapsulatedUDTField as IEncapsulatedUserDefinedTypeField; - foreach (var udtMember in _udtFieldToUdtDeclarationMap[udtField].Item2) + foreach (var udtMember in udtFieldToUdtDeclarationMap[udtField].Item2) { IEncapsulateFieldCandidate encapsulatedUDTMember = new EncapsulatedUserDefinedTypeMember(udtMember, encapsulatedUDTField, _validator, moduleHasMultipleInstancesOfUDT); - encapsulatedUDTMember = ApplySpecializationAttributes(encapsulatedUDTMember); - concreteParent.Members.Add(encapsulatedUDTMember); + encapsulatedUDTMember = ApplyTypeSpecificAttributes(encapsulatedUDTMember); + parent.Members.Add(encapsulatedUDTMember); + encapsulatedUDTMember.FieldAccessExpression = + () => + { + var prefix = encapsulatedUDTField.EncapsulateFlag + ? encapsulatedUDTField.NewFieldName + : encapsulatedUDTField.IdentifierName; + + return $"{prefix}.{encapsulatedUDTMember.NewFieldName}"; + }; } } return _encapsulatedFields; @@ -76,7 +87,7 @@ private IEncapsulateFieldCandidate EncapsulateDeclaration(Declaration target, IE ? new EncapsulatedUserDefinedTypeField(target, validator) : new EncapsulateFieldCandidate(target, validator); - return ApplySpecializationAttributes(candidate); + return ApplyTypeSpecificAttributes(candidate); } private (Declaration UDTVariable, Declaration UserDefinedType, IEnumerable UDTMembers) CreateUDTTuple(Declaration udtVariable) @@ -96,7 +107,7 @@ private IEncapsulateFieldCandidate EncapsulateDeclaration(Declaration target, IE return (udtVariable, userDefinedTypeDeclaration, udtMembers); } - private IEncapsulateFieldCandidate ApplySpecializationAttributes(IEncapsulateFieldCandidate candidate) + private IEncapsulateFieldCandidate ApplyTypeSpecificAttributes(IEncapsulateFieldCandidate candidate) { var target = candidate.Declaration; if (target.IsUserDefinedTypeField()) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index 59cb5c6c39..de257735b3 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -14,9 +14,6 @@ namespace Rubberduck.Refactorings.EncapsulateField { public class EncapsulateFieldModel : IRefactoringModel { - private const string DEFAULT_ENCAPSULATION_UDT_IDENTIFIER = "This_Type"; - private const string DEFAULT_ENCAPSULATION_UDT_FIELD_IDENTIFIER = "this"; - private readonly IIndenter _indenter; private readonly IDeclarationFinderProvider _declarationFinderProvider; private readonly IEncapsulateFieldNamesValidator _validator; @@ -27,8 +24,6 @@ public class EncapsulateFieldModel : IRefactoringModel private IDictionary)> _udtFieldToUdtDeclarationMap = new Dictionary)>(); - private Dictionary _candidates = new Dictionary(); - public EncapsulateFieldModel(Declaration target, IDeclarationFinderProvider declarationFinderProvider, /*IEnumerable allMemberFields, IDictionary)> udtFieldToUdtDeclarationMap,*/ IIndenter indenter, IEncapsulateFieldNamesValidator validator, Func previewFunc) { _declarationFinderProvider = declarationFinderProvider; @@ -39,24 +34,43 @@ public EncapsulateFieldModel(Declaration target, IDeclarationFinderProvider decl _useNewStructure = File.Exists("C:\\Users\\Brian\\Documents\\UseNewUDTStructure.txt"); - //Maybe this should be passed in - EncapsulationStrategy = new EncapsulateWithBackingFields(_targetQMN, _indenter, _declarationFinderProvider, _validator); - _candidates = EncapsulationStrategy.FlattenedTargetIDToCandidateMapping; + CandidateFactory = new EncapsulationCandidateFactory(declarationFinderProvider, _validator); + var encapsulationCandidateFields = _declarationFinderProvider.DeclarationFinder + .Members(_targetQMN) + .Where(v => v.IsMemberVariable() && !v.IsWithEvents); + + var candidates = CandidateFactory.CreateEncapsulationCandidates(encapsulationCandidateFields); + + FieldCandidates.AddRange(candidates); + + AllEncapsulationCandidates = Enumerable.Empty() + .Concat(FieldCandidates) + .Concat(UDTFieldCandidates.SelectMany(c => c.Members)).ToList(); + + EncapsulationStrategy = new EncapsulateWithBackingFields(_targetQMN, _indenter, _validator); this[target].EncapsulateFlag = true; } + public EncapsulationCandidateFactory CandidateFactory { private set; get; } + + public List FieldCandidates { set; get; } = new List(); + + public IEnumerable UDTFieldCandidates => FieldCandidates.Where(v => v is IEncapsulatedUserDefinedTypeField).Cast(); + + private List AllEncapsulationCandidates { get; } = new List(); + public IEnumerable FlaggedEncapsulationFields - => _candidates.Values.Where(v => v.EncapsulationAttributes.EncapsulateFlag); + => AllEncapsulationCandidates.Where(v => v.EncapsulationAttributes.EncapsulateFlag); public IEnumerable EncapsulationFields - => _candidates.Values; + => AllEncapsulationCandidates; public IEncapsulateFieldCandidate this[string encapsulatedFieldIdentifier] - => _candidates[encapsulatedFieldIdentifier]; + => AllEncapsulationCandidates.Where(c => c.TargetID.Equals(encapsulatedFieldIdentifier)).Single(); public IEncapsulateFieldCandidate this[Declaration fieldDeclaration] - => _candidates.Values.Where(efd => efd.Declaration.Equals(fieldDeclaration)).Select(encapsulatedField => encapsulatedField).Single(); + => AllEncapsulationCandidates.Where(c => c.Declaration == fieldDeclaration).Single(); public IEncapsulateFieldStrategy EncapsulationStrategy { set; get; } @@ -64,23 +78,26 @@ public bool EncapsulateWithUDT { set { - if (value && EncapsulationStrategy is EncapsulateWithBackingUserDefinedType ebd) { return; } - - if (!value && EncapsulationStrategy is EncapsulateWithBackingFields wbf) { return; } - - EncapsulationStrategy = value - ? new EncapsulateWithBackingUserDefinedType(_targetQMN, _indenter, _declarationFinderProvider, _validator) as IEncapsulateFieldStrategy - : new EncapsulateWithBackingFields(_targetQMN, _indenter, _declarationFinderProvider, _validator) as IEncapsulateFieldStrategy; + if (value && EncapsulationStrategy is EncapsulateWithBackingUserDefinedType) { return; } + + if (!value && EncapsulationStrategy is EncapsulateWithBackingFields) { return; } + + if (value) + { + EncapsulationStrategy = new EncapsulateWithBackingUserDefinedType(_targetQMN, _indenter, _validator) + { + StateUDTField = CandidateFactory.CreateStateUDTField(_targetQMN) + }; + } + else + { + EncapsulationStrategy = new EncapsulateWithBackingFields(_targetQMN, _indenter, _validator); + } } get => EncapsulationStrategy is EncapsulateWithBackingUserDefinedType; } - //What to do with these as far as IStrategy goes - only here to support the view model - public string EncapsulateWithUDT_TypeIdentifier { set; get; } = DEFAULT_ENCAPSULATION_UDT_IDENTIFIER; - - public string EncapsulateWithUDT_FieldName { set; get; } = DEFAULT_ENCAPSULATION_UDT_FIELD_IDENTIFIER; - public string PreviewRefactoring() { return _previewFunc(this); diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs index b6db839b1d..ed6090a039 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs @@ -24,27 +24,31 @@ public interface IEncapsulateFieldCandidate string NewFieldName { get; } string AsTypeName { get; } string ParameterName { get; } - string FieldReferenceExpression { get; } bool IsUDTMember { get; } bool HasValidEncapsulationAttributes { get; } QualifiedModuleName QualifiedModuleName { get; } IEnumerable References { get; } bool ImplementLetSetterType { get; } bool ImplementSetSetterType { get; } + Func FieldAccessExpression { set; get; } + } + + public interface IEncapsulatedUserDefinedTypeField : IEncapsulateFieldCandidate + { + IList Members { set; get; } + IEnumerable SelectedMembers { get; } } public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate { protected Declaration _target; protected IFieldEncapsulationAttributes _attributes; - protected FieldEncapsulationAttributes _concreteAttributes; private IEncapsulateFieldNamesValidator _validator; public EncapsulateFieldCandidate(Declaration declaration, IEncapsulateFieldNamesValidator validator) { _target = declaration; - _concreteAttributes = new FieldEncapsulationAttributes(_target); - _attributes = _concreteAttributes; + _attributes = new FieldEncapsulationAttributes(_target); _validator = validator; _validator.ForceNonConflictEncapsulationAttributes(_attributes, _target.QualifiedModuleName, _target); } @@ -52,34 +56,11 @@ public EncapsulateFieldCandidate(Declaration declaration, IEncapsulateFieldNames public EncapsulateFieldCandidate(IFieldEncapsulationAttributes attributes, IEncapsulateFieldNamesValidator validator) { _target = null; - _concreteAttributes = new FieldEncapsulationAttributes(attributes); - _attributes = _concreteAttributes; + _attributes = new FieldEncapsulationAttributes(attributes); _validator = validator; _validator.ForceNonConflictEncapsulationAttributes(_attributes, _attributes.QualifiedModuleName, _target); } - //TODO: Defaulting to DeclarationType.Variable needs to be better - private static void ForceNonConflictNewName(string identifier, QualifiedModuleName qmn, IFieldEncapsulationAttributes attributes, IEncapsulateFieldNamesValidator validator, IEnumerable ignore) - { - var isValidAttributeSet = validator.HasValidEncapsulationAttributes(attributes, qmn, ignore, DeclarationType.Variable); - for (var idx = 1; idx < 9 && !isValidAttributeSet; idx++) - { - attributes.NewFieldName = $"{identifier}{idx}"; - isValidAttributeSet = validator.HasValidEncapsulationAttributes(attributes, qmn, ignore, DeclarationType.Variable); - } - } - - //TODO: Defaulting to DeclarationType.Variable needs to be better - private static void ForceNonConflictPropertyName(string identifier, QualifiedModuleName qmn, IFieldEncapsulationAttributes attributes, IEncapsulateFieldNamesValidator validator, IEnumerable ignore) - { - var isValidAttributeSet = validator.HasValidEncapsulationAttributes(attributes, qmn, ignore, DeclarationType.Variable); - for (var idx = 1; idx < 9 && !isValidAttributeSet; idx++) - { - attributes.PropertyName = $"{identifier}{idx}"; - isValidAttributeSet = validator.HasValidEncapsulationAttributes(attributes, qmn, ignore, DeclarationType.Variable); - } - } - public Declaration Declaration => _target; public DeclarationType DeclarationType => _target?.DeclarationType ?? DeclarationType.Variable; @@ -145,26 +126,30 @@ public string NewFieldName public string ParameterName => _attributes.ParameterName; - public string FieldReferenceExpression => _attributes.FieldAccessExpression; - public bool ImplementLetSetterType { get => _attributes.ImplementLetSetterType; set => _attributes.ImplementLetSetterType = value; } public bool ImplementSetSetterType { get => _attributes.ImplementSetSetterType; set => _attributes.ImplementSetSetterType = value; } + + public Func FieldAccessExpression + { + set => _attributes.FieldAccessExpression = value; + get => _attributes.FieldAccessExpression; + } + } - public class EncapsulatedUserDefinedTypeField : EncapsulateFieldCandidate + public class EncapsulatedUserDefinedTypeField : EncapsulateFieldCandidate, IEncapsulatedUserDefinedTypeField { - public List Members { set; get; } = new List(); public EncapsulatedUserDefinedTypeField(Declaration declaration, IEncapsulateFieldNamesValidator validator) - : base(declaration, validator) { } - } + : base(declaration, validator) + { + FieldAccessExpression = () => EncapsulateFlag ? NewFieldName : IdentifierName; + } - public interface IEncapsulatedUserDefinedTypeMember - { - Func FieldAccessExpressionFunc { set; get; } + public IList Members { set; get; } = new List(); + public IEnumerable SelectedMembers => Members.Where(m => m.EncapsulateFlag); } - - public class EncapsulatedUserDefinedTypeMember : EncapsulateFieldCandidate, IEncapsulatedUserDefinedTypeMember + public class EncapsulatedUserDefinedTypeMember : EncapsulateFieldCandidate { public EncapsulatedUserDefinedTypeMember(Declaration target, IEncapsulateFieldCandidate udtVariable, IEncapsulateFieldNamesValidator validator, bool propertyNameRequiresParentIdentifier) : base(target, validator) @@ -175,22 +160,6 @@ public EncapsulatedUserDefinedTypeMember(Declaration target, IEncapsulateFieldCa EncapsulationAttributes.PropertyName = NameResolveProperty ? $"{Parent.IdentifierName.Capitalize()}_{IdentifierName}" : IdentifierName; - - FieldAccessExpressionFunc = - () => - { - var prefix = Parent.EncapsulateFlag - ? Parent.NewFieldName - : Parent.IdentifierName; - - return $"{prefix}.{NewFieldName}"; - }; - } - - public Func FieldAccessExpressionFunc - { - set => _concreteAttributes.FieldAccessExpressionFunc = value; - get => _concreteAttributes.FieldAccessExpressionFunc; } public IEncapsulateFieldCandidate Parent { private set; get; } @@ -198,7 +167,5 @@ public Func FieldAccessExpressionFunc public bool NameResolveProperty { set; get; } public override string TargetID => $"{Parent.IdentifierName}.{IdentifierName}"; - - //public override bool IsUDTMember => true; } } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs index 129571a520..dc40c170b3 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs @@ -13,14 +13,13 @@ public interface IFieldEncapsulationAttributes bool EncapsulateFlag { get; set; } string NewFieldName { set; get; } bool CanBeReadWrite { set; get; } - string FieldAccessExpression { get; } string AsTypeName { get; set; } string ParameterName { get;} bool ImplementLetSetterType { get; set; } bool ImplementSetSetterType { get; set; } bool FieldNameIsExemptFromValidation { get; } QualifiedModuleName QualifiedModuleName { get; } - //DeclarationType DeclarationType { get; } + Func FieldAccessExpression { set; get; } } @@ -39,7 +38,7 @@ public NeverEncapsulateAttributes(string identifier, string asTypeName, Qualifie Identifier = identifier; NewFieldName = identifier; AsTypeName = asTypeName; - FieldAccessExpressionFunc = () => NewFieldName; + FieldAccessExpression = () => NewFieldName; } public IFieldEncapsulationAttributes ApplyNewFieldName(string newFieldName) @@ -48,8 +47,6 @@ public IFieldEncapsulationAttributes ApplyNewFieldName(string newFieldName) return this; } - //public DeclarationType DeclarationType { get; } = DeclarationType.UserDefinedType; - public string Identifier { private set; get; } public string NewFieldName { set; get; } @@ -57,9 +54,7 @@ public IFieldEncapsulationAttributes ApplyNewFieldName(string newFieldName) string _tossString; public string PropertyName { set => _tossString = value; get => $"{neverUse}{Identifier}_{neverUse}"; } - public string FieldAccessExpression => FieldAccessExpressionFunc(); - - public Func FieldAccessExpressionFunc { set; get; } + public Func FieldAccessExpression { set; get; } public string AsTypeName { get; set; } public string ParameterName => neverUse; @@ -87,16 +82,15 @@ public FieldEncapsulationAttributes(Declaration target) Identifier = target.IdentifierName; AsTypeName = target.AsTypeName; _qmn = target.QualifiedModuleName; - FieldAccessExpressionFunc = () => NewFieldName; + FieldAccessExpression = () => NewFieldName; _fieldNameIsAlwaysValid = target.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember); - //DeclarationType = target.DeclarationType; } public FieldEncapsulationAttributes(string identifier, string asTypeName) { _fieldAndProperty = new EncapsulationIdentifiers(identifier); AsTypeName = asTypeName; - FieldAccessExpressionFunc = () => NewFieldName; + FieldAccessExpression = () => NewFieldName; } public FieldEncapsulationAttributes(IFieldEncapsulationAttributes attributes) @@ -111,13 +105,11 @@ public FieldEncapsulationAttributes(IFieldEncapsulationAttributes attributes) ImplementLetSetterType = attributes.ImplementLetSetterType; ImplementSetSetterType = attributes.ImplementSetSetterType; QualifiedModuleName = attributes.QualifiedModuleName; - FieldAccessExpressionFunc = () => NewFieldName; + FieldAccessExpression = () => NewFieldName; } private EncapsulationIdentifiers _fieldAndProperty; - //public DeclarationType DeclarationType { private set; get; } = DeclarationType.Variable; - public string Identifier { private set; get; } public bool CanBeReadWrite { set; get; } = true; @@ -134,9 +126,7 @@ public string PropertyName set => _fieldAndProperty.Property = value; } - public string FieldAccessExpression => FieldAccessExpressionFunc(); - - public Func FieldAccessExpressionFunc { set; get; } + public Func FieldAccessExpression { set; get; } public string AsTypeName { get; set; } public string ParameterName => _fieldAndProperty.SetLetParameter; diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs index ee90fe6fe5..f1d6789664 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs @@ -14,8 +14,8 @@ namespace Rubberduck.Refactorings.EncapsulateField.Strategies { public class EncapsulateWithBackingFields : EncapsulateFieldStrategiesBase { - public EncapsulateWithBackingFields(QualifiedModuleName qmn, IIndenter indenter, IDeclarationFinderProvider declarationFinderProvider, IEncapsulateFieldNamesValidator validator) - : base(qmn, indenter, declarationFinderProvider, validator) + public EncapsulateWithBackingFields(QualifiedModuleName qmn, IIndenter indenter, IEncapsulateFieldNamesValidator validator) + : base(qmn, indenter, validator) { } @@ -43,10 +43,23 @@ protected override void ModifyEncapsulatedVariable(IEncapsulateFieldCandidate ta return; } - protected override EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNewContent newContent, IEnumerable FlaggedEncapsulationFields) + protected override IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) { - var nonUdtMemberFields = FlaggedEncapsulationFields - .Where(encFld => encFld.Declaration.IsVariable()); + foreach (var field in model.UDTFieldCandidates) + { + foreach (var member in field.Members) + { + member.FieldAccessExpression = () => $"{field.FieldAccessExpression()}.{member.IdentifierName}"; + } + } + + return base.RefactorRewrite(model, rewriteSession, asPreview); + } + + protected override EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNewContent newContent, IEnumerable encapsulationCandates) + { + var nonUdtMemberFields = encapsulationCandates + .Where(encFld => !encFld.IsUDTMember && encFld.EncapsulateFlag); foreach (var nonUdtMemberField in nonUdtMemberFields) { @@ -67,31 +80,5 @@ protected override EncapsulateFieldNewContent LoadNewDeclarationsContent(Encapsu } return newContent; } - - protected override IList PropertiesContent(IEnumerable flaggedEncapsulationFields) - { - var textBlocks = new List(); - foreach (var field in flaggedEncapsulationFields) - { - textBlocks.Add(BuildPropertiesTextBlock(field.EncapsulationAttributes)); - } - return textBlocks; - } - - private string BuildPropertiesTextBlock(IFieldEncapsulationAttributes attributes) - { - var generator = new PropertyGenerator - { - PropertyName = attributes.PropertyName, - AsTypeName = attributes.AsTypeName, - BackingField = attributes.FieldAccessExpression, - ParameterName = attributes.ParameterName, - GenerateSetter = attributes.ImplementSetSetterType, - GenerateLetter = attributes.ImplementLetSetterType - }; - - var propertyTextLines = generator.AllPropertyCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None); - return string.Join(Environment.NewLine, Indenter.Indent(propertyTextLines, true)); - } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs index 832de0c1e3..31e1cedbb1 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs @@ -13,22 +13,60 @@ namespace Rubberduck.Refactorings.EncapsulateField.Strategies { public interface IEncapsulateWithBackingUserDefinedType : IEncapsulateFieldStrategy { - IEncapsulateFieldCandidate StateEncapsulationField { set; get; } + IEncapsulateFieldCandidate StateUDTField { set; get; } } public class EncapsulateWithBackingUserDefinedType : EncapsulateFieldStrategiesBase, IEncapsulateWithBackingUserDefinedType { - private const string DEFAULT_TYPE_IDENTIFIER = "This_Type"; - private const string DEFAULT_FIELD_IDENTIFIER = "this"; + public EncapsulateWithBackingUserDefinedType(QualifiedModuleName qmn, IIndenter indenter, IEncapsulateFieldNamesValidator validator) + : base(qmn, indenter, validator) { } - - public EncapsulateWithBackingUserDefinedType(QualifiedModuleName qmn, IIndenter indenter, IDeclarationFinderProvider declarationFinderProvider, IEncapsulateFieldNamesValidator validator) - : base(qmn, indenter, declarationFinderProvider, validator) + protected override IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) { - StateEncapsulationField = _candidateFactory.CreateInsertableField(DEFAULT_FIELD_IDENTIFIER, DEFAULT_TYPE_IDENTIFIER, qmn, validator); + var stateUDTField_UDTMembers = model.UDTFieldCandidates + .Where(c => c.EncapsulateFlag || c.SelectedMembers.Any()); + + foreach (var field in model.FieldCandidates) + { + if (field is IEncapsulatedUserDefinedTypeField udt) + { + udt.FieldAccessExpression = + () => { + var accessor = udt.EncapsulateFlag || stateUDTField_UDTMembers.Contains(udt) ? udt.PropertyName : udt.NewFieldName; + return $"{StateUDTField.FieldAccessExpression()}.{accessor}"; + }; + + foreach (var member in udt.Members) + { + member.FieldAccessExpression = () => $"{udt.FieldAccessExpression()}.{member.PropertyName}"; + } + } + else + { + var efd = field; + efd.FieldAccessExpression = () => $"{StateUDTField.FieldAccessExpression()}.{efd.PropertyName}"; + } + } + + var fieldsToModify = model.EncapsulationFields + .Where(encFld => !encFld.IsUDTMember && encFld.EncapsulateFlag).Union(stateUDTField_UDTMembers); + + foreach (var field in fieldsToModify) + { + var attributes = field.EncapsulationAttributes; + ModifyEncapsulatedVariable(field, attributes, rewriteSession); + RenameReferences(field, attributes.PropertyName ?? field.Declaration.IdentifierName, rewriteSession); + } + + var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); + RewriterRemoveWorkAround.RemoveDeclarationsFromVariableLists(rewriter); + + InsertNewContent(model.CodeSectionStartIndex, model, rewriteSession, asPreview); + + return rewriteSession; } - public IEncapsulateFieldCandidate StateEncapsulationField { set; get; } + public IEncapsulateFieldCandidate StateUDTField { set; get; } protected override void ModifyEncapsulatedVariable(IEncapsulateFieldCandidate target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession) { @@ -39,82 +77,22 @@ protected override void ModifyEncapsulatedVariable(IEncapsulateFieldCandidate ta return; } - protected override EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNewContent newContent, IEnumerable FlaggedEncapsulationFields) + protected override EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNewContent newContent, IEnumerable encapsulationCandidates) { - var nonUdtMemberFields = FlaggedEncapsulationFields - .Where(encFld => !encFld.IsUDTMember); + var udt = new UDTDeclarationGenerator(StateUDTField.AsTypeName); - var udt = new UDTDeclarationGenerator(StateEncapsulationField.AsTypeName); - foreach (var nonUdtMemberField in nonUdtMemberFields) - { - udt.AddMember(nonUdtMemberField); - } - newContent.AddDeclarationBlock(udt.TypeDeclarationBlock(Indenter)); - - newContent.AddDeclarationBlock(udt.FieldDeclaration(StateEncapsulationField.NewFieldName)); + var stateUDTMembers = encapsulationCandidates + .Where(encFld => !encFld.IsUDTMember + && (encFld.EncapsulateFlag + || encFld is IEncapsulatedUserDefinedTypeField udtFld && udtFld.Members.Any(m => m.EncapsulateFlag))); - return newContent; - } + udt.AddMembers(stateUDTMembers); - protected override EncapsulateFieldNewContent LoadNewPropertiesContent(EncapsulateFieldNewContent newContent, IEnumerable FlaggedEncapsulationFields, string postScript = null) - { - if (!FlaggedEncapsulationFields.Any()) { return newContent; } - - var udtMemberFields = FlaggedEncapsulationFields.Where(efd => efd.IsUDTMember); - foreach (var udtMember in udtMemberFields) - { - newContent.AddCodeBlock(CreateUDTMemberProperty(udtMember)); - } - - return base.LoadNewPropertiesContent(newContent, FlaggedEncapsulationFields, postScript); - } - - - protected override IList PropertiesContent(IEnumerable flaggedEncapsulationFields) - { - var textBlocks = new List(); - foreach (var field in flaggedEncapsulationFields) - { - if (field is EncapsulatedUserDefinedTypeMember) - { - continue; - } - textBlocks.Add(BuildPropertiesTextBlock(field.EncapsulationAttributes)); - } - return textBlocks; - } + newContent.AddDeclarationBlock(udt.TypeDeclarationBlock(Indenter)); - protected string BuildPropertiesTextBlock(IFieldEncapsulationAttributes attributes) - { - var generator = new PropertyGenerator - { - PropertyName = attributes.PropertyName, - AsTypeName = attributes.AsTypeName, - BackingField = $"{StateEncapsulationField.NewFieldName}.{attributes.PropertyName}", - ParameterName = attributes.ParameterName, - GenerateSetter = attributes.ImplementSetSetterType, - GenerateLetter = attributes.ImplementLetSetterType - }; - - var propertyTextLines = generator.AllPropertyCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None); - return string.Join(Environment.NewLine, Indenter.Indent(propertyTextLines, true)); - } + newContent.AddDeclarationBlock(udt.FieldDeclaration(StateUDTField.NewFieldName)); - private string CreateUDTMemberProperty(IEncapsulateFieldCandidate udtMember) - { - var parentField = UdtMemberTargetIDToParentMap[udtMember.TargetID]; - var generator = new PropertyGenerator - { - PropertyName = udtMember.PropertyName, - AsTypeName = udtMember.AsTypeName, - BackingField = $"{StateEncapsulationField.NewFieldName}.{parentField.PropertyName}.{udtMember.PropertyName}", - ParameterName = udtMember.EncapsulationAttributes.ParameterName, - GenerateSetter = udtMember.EncapsulationAttributes.ImplementSetSetterType, - GenerateLetter = udtMember.EncapsulationAttributes.ImplementLetSetterType - }; - - var propertyTextLines = generator.AllPropertyCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None); - return string.Join(Environment.NewLine, Indenter.Indent(propertyTextLines, true)); + return newContent; } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs index 338ee9c793..99e3c5aa4b 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs @@ -15,45 +15,17 @@ public interface IEncapsulateFieldStrategy { IExecutableRewriteSession GeneratePreview(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession); IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession); - Dictionary UdtMemberTargetIDToParentMap { get; set; } - Dictionary FlattenedTargetIDToCandidateMapping { get; } - } + } public abstract class EncapsulateFieldStrategiesBase : IEncapsulateFieldStrategy { - protected readonly IDeclarationFinderProvider _declarationFinderProvider; - protected EncapsulationCandidateFactory _candidateFactory; - private Dictionary _udtMemberTargetIDToParentMap { get; } = new Dictionary(); private IEncapsulateFieldNamesValidator _validator; - - public EncapsulateFieldStrategiesBase(QualifiedModuleName qmn, IIndenter indenter, IDeclarationFinderProvider declarationFinderProvider, IEncapsulateFieldNamesValidator validator) + public EncapsulateFieldStrategiesBase(QualifiedModuleName qmn, IIndenter indenter, IEncapsulateFieldNamesValidator validator) { TargetQMN = qmn; Indenter = indenter; - _declarationFinderProvider = declarationFinderProvider; _validator = validator; - _candidateFactory = new EncapsulationCandidateFactory(declarationFinderProvider, _validator); - - EncapsulationCandidateFields = _declarationFinderProvider.DeclarationFinder - .Members(qmn) - .Where(v => v.IsMemberVariable() && !v.IsWithEvents); - - var candidates = _candidateFactory.CreateEncapsulationCandidates(EncapsulationCandidateFields); - foreach (var candidate in candidates) - { - HeirarchicalCandidates.Add(candidate.TargetID, candidate); - if (candidate is EncapsulatedUserDefinedTypeField udtField) - { - foreach( var member in udtField.Members) - { - var concrete = member as EncapsulatedUserDefinedTypeMember; - UdtMemberTargetIDToParentMap.Add(member.TargetID, concrete.Parent); - } - } - } - - FlattenedTargetIDToCandidateMapping = Flatten(HeirarchicalCandidates); } protected QualifiedModuleName TargetQMN {private set; get;} @@ -70,19 +42,11 @@ public IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IE return RefactorRewrite(model, rewriteSession, false); } - public Dictionary FlattenedTargetIDToCandidateMapping { get; } = new Dictionary(); - - protected virtual IEnumerable EncapsulationCandidateFields { set; get; } - protected abstract void ModifyEncapsulatedVariable(IEncapsulateFieldCandidate target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession); - protected abstract EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNewContent newContent, IEnumerable FlaggedEncapsulationFields); - - protected abstract IList PropertiesContent(IEnumerable flaggedEncapsulationFields); + protected abstract EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNewContent newContent, IEnumerable encapsulationCandidates); - protected Dictionary HeirarchicalCandidates { set; get; } = new Dictionary(); - - private IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) + protected virtual IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) { var nonUdtMemberFields = model.FlaggedEncapsulationFields .Where(encFld => !encFld.IsUDTMember); @@ -102,14 +66,11 @@ private IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, I return rewriteSession; } - public Dictionary UdtMemberTargetIDToParentMap { get; set; } = new Dictionary(); - - private void InsertNewContent(int? codeSectionStartIndex, EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool postPendPreviewMessage = false) + protected void InsertNewContent(int? codeSectionStartIndex, EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool postPendPreviewMessage = false) { var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); - var newContent = new EncapsulateFieldNewContent(); - newContent = LoadNewDeclarationsContent(newContent, model.FlaggedEncapsulationFields); + var newContent = LoadNewDeclarationsContent(new EncapsulateFieldNewContent(), model.EncapsulationFields); if (postPendPreviewMessage) { @@ -125,28 +86,34 @@ private void InsertNewContent(int? codeSectionStartIndex, EncapsulateFieldModel } - protected Dictionary Flatten(Dictionary heirarchicalCandidates) + protected virtual IList PropertiesContent(IEnumerable flaggedEncapsulationFields) { - var candidates = new Dictionary(); - foreach (var keyValue in heirarchicalCandidates) + var textBlocks = new List(); + foreach (var field in flaggedEncapsulationFields) { - candidates.Add(keyValue.Key, keyValue.Value); - if (keyValue.Value.Declaration.IsUserDefinedTypeField()) - { - if (keyValue.Value is EncapsulatedUserDefinedTypeField udt) - { - foreach (var member in udt.Members) - { - candidates.Add(member.TargetID, member); - _udtMemberTargetIDToParentMap.Add(member.TargetID, keyValue.Value); - } - } - } + textBlocks.Add(BuildPropertiesTextBlock(field)); } - return candidates; + return textBlocks; + } + + private string BuildPropertiesTextBlock(IEncapsulateFieldCandidate field) + { + var attributes = field.EncapsulationAttributes; + var generator = new PropertyGenerator + { + PropertyName = attributes.PropertyName, + AsTypeName = attributes.AsTypeName, + BackingField = attributes.FieldAccessExpression(), + ParameterName = attributes.ParameterName, + GenerateSetter = attributes.ImplementSetSetterType, + GenerateLetter = attributes.ImplementLetSetterType + }; + + var propertyTextLines = generator.AllPropertyCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None); + return string.Join(Environment.NewLine, Indenter.Indent(propertyTextLines, true)); } - protected virtual EncapsulateFieldNewContent LoadNewPropertiesContent(EncapsulateFieldNewContent newContent, IEnumerable FlaggedEncapsulationFields, string postScript = null) + private EncapsulateFieldNewContent LoadNewPropertiesContent(EncapsulateFieldNewContent newContent, IEnumerable FlaggedEncapsulationFields, string postScript = null) { if (!FlaggedEncapsulationFields.Any()) { return newContent; } @@ -159,7 +126,7 @@ protected virtual EncapsulateFieldNewContent LoadNewPropertiesContent(Encapsulat return newContent; } - private void RenameReferences(IEncapsulateFieldCandidate efd, string propertyName, IRewriteSession rewriteSession) + protected void RenameReferences(IEncapsulateFieldCandidate efd, string propertyName, IRewriteSession rewriteSession) { foreach (var reference in efd.Declaration.References) { diff --git a/Rubberduck.Refactorings/EncapsulateField/UDTDeclarationGenerator.cs b/Rubberduck.Refactorings/EncapsulateField/UDTDeclarationGenerator.cs index cf46db7652..cb8b13708a 100644 --- a/Rubberduck.Refactorings/EncapsulateField/UDTDeclarationGenerator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/UDTDeclarationGenerator.cs @@ -11,51 +11,34 @@ namespace Rubberduck.Refactorings.EncapsulateField { public class UDTDeclarationGenerator { - private readonly string _typeIdentifier = "This_Type"; - private readonly IIndenter _indenter; + private readonly string _typeIdentifierName; private List _members; - public UDTDeclarationGenerator(string typeIdentifier) //, IIndenter indenter) - : this() - //:this(indenter) + public UDTDeclarationGenerator(string typeIdentifierName) { - _typeIdentifier = typeIdentifier; - } - - public UDTDeclarationGenerator() //IIndenter indenter) - { - //_indenter = indenter; + _typeIdentifierName = typeIdentifierName; _members = new List(); } - public string AsTypeName => _typeIdentifier; + public void AddMember(IEncapsulateFieldCandidate field) => _members.Add(field); - public void AddMember(IEncapsulateFieldCandidate field) - { - _members.Add(field); - } + public void AddMembers(IEnumerable fields) => _members.AddRange(fields); - public string FieldDeclaration(string identifier, Accessibility accessibility = Accessibility.Private) - => $"{accessibility} {identifier} {Tokens.As} {_typeIdentifier}"; + public string FieldDeclaration(string identifierName, Accessibility accessibility = Accessibility.Private) + => $"{accessibility} {identifierName} {Tokens.As} {_typeIdentifierName}"; - public string TypeDeclarationBlock(IIndenter indenter) + public string TypeDeclarationBlock(IIndenter indenter, Accessibility accessibility = Accessibility.Private) { - //get - //{ - var members = new List(); - members.Add($"{Tokens.Private} {Tokens.Type} {_typeIdentifier}"); + var blockLines = new List(); + + blockLines.Add($"{accessibility.TokenString()} {Tokens.Type} {_typeIdentifierName}"); - foreach (var member in _members) - { - var declaration = $"{member.PropertyName} As {member.AsTypeName}"; - members.Add(declaration); - } + _members.ForEach(m => blockLines.Add($"{m.PropertyName} As {m.AsTypeName}")); - members.Add("End Type"); + blockLines.Add("End Type"); - return string.Join(Environment.NewLine, indenter.Indent(members, true)); - //} + return string.Join(Environment.NewLine, indenter.Indent(blockLines, true)); } } } diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateAsUDTTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateAsUDTTests.cs index b145b8cc42..923c79eaa6 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateAsUDTTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateAsUDTTests.cs @@ -235,6 +235,38 @@ End Type StringAssert.Contains($"Second = this.Second", actualCode); } + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedTypeMembers_OnlyEncapsulateUDTMembersUsingUDT() + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +Private my|Bar As TBar"; + + + var userInput = new UserInputDataObject("myBar"); + userInput["myBar"].EncapsulateFlag = false; + userInput.AddUDTMemberNameFlagPairs(("myBar", "First", true)); + userInput.AddUDTMemberNameFlagPairs(("myBar", "Second", true)); + userInput.EncapsulateAsUDT = true; + + var presenterAction = Support.SetParameters(userInput); + + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.Contains("this.MyBar.First = value", actualCode); + StringAssert.Contains($"First = this.MyBar.First", actualCode); + StringAssert.Contains("this.MyBar.Second = value", actualCode); + StringAssert.Contains($"Second = this.MyBar.Second", actualCode); + StringAssert.Contains($"MyBar As TBar", actualCode); + StringAssert.DoesNotContain($"myBar As TBar", actualCode); + } + [TestCase("Public")] [TestCase("Private")] [Category("Refactorings")] @@ -581,6 +613,9 @@ Public myBar As TBar StringAssert.Contains("First = this.MyBar.First", actualCode); StringAssert.Contains("this.MyBar.Second = value", actualCode); StringAssert.Contains("Second = this.MyBar.Second", actualCode); + var index = actualCode.IndexOf("Get Second", StringComparison.InvariantCultureIgnoreCase); + var indexLast = actualCode.LastIndexOf("Get Second", StringComparison.InvariantCultureIgnoreCase); + Assert.AreEqual(index, indexLast); } protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs index eb62815718..619df05794 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs @@ -145,7 +145,7 @@ public void CreateUDT() mock.SetupGet(m => m.AsTypeName).Returns("String"); mock.SetupGet(m => m.PropertyName).Returns("Fizz"); - var newUserDefinedType = new UDTDeclarationGenerator(); + var newUserDefinedType = new UDTDeclarationGenerator("This_Type"); newUserDefinedType.AddMember(mock.Object); var result = newUserDefinedType.TypeDeclarationBlock(CreateIndenter()); diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index 09a9a6d044..443eaf6b4b 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -28,7 +28,11 @@ private TestEncapsulationAttributes UserModifiedEncapsulationAttributes(string f public Func UserAcceptsDefaults(bool asUDT = false) { - return model => { model.EncapsulateWithUDT = asUDT; return model; }; + return model => + { + model.EncapsulateWithUDT = asUDT; + return model; + }; } public Func SetParametersForSingleTarget(string field, string property = null, bool? isReadonly = null, bool encapsulateFlag = true, bool asUDT = false) @@ -54,10 +58,10 @@ public Func SetParameters(UserInpu currentAttributes.PropertyName = attrsInitializedByTheRefactoring.PropertyName; currentAttributes.EncapsulateFlag = attrsInitializedByTheRefactoring.EncapsulateFlag; - foreach ((string instanceVariable, string memberName, bool flag) in userModifications.UDTMemberNameFlagPairs) - { - model[$"{instanceVariable}.{memberName}"].EncapsulateFlag = flag; - } + } + foreach ((string instanceVariable, string memberName, bool flag) in userModifications.UDTMemberNameFlagPairs) + { + model[$"{instanceVariable}.{memberName}"].EncapsulateFlag = flag; } return model; }; From fec3f017d7a8e698b765f150785765944add9967 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Thu, 5 Dec 2019 06:04:40 -0800 Subject: [PATCH 041/461] Applies UDT/UDTMember encapsulation rule If the UDT Type Declaraiton is Public, then encapsulate the UDT Field. If the UDT Type Declaration is Private, then encapsulate all the UDTMembers. --- .../EncapsulateFieldDeclarationFactory.cs | 3 +- .../EncapsulateField/EncapsulateFieldModel.cs | 3 + .../EncapsulatedFieldDeclaration.cs | 58 ++- .../FieldEncapsulationAttributes.cs | 21 +- .../EncapsulateWithBackingFields.cs | 16 +- .../EncapsulateWithBackingUserDefinedType.cs | 28 +- .../Strategies/EncapsulationStrategiesBase.cs | 115 ++++- .../EncapsulateUsingStateUDTTests.cs | 173 +++++++ ...eAsUDTTests.cs => EncapsulatedUDTField.cs} | 431 +++++++++--------- .../Refactoring/EncapsulateFieldTests.cs | 79 +++- 10 files changed, 680 insertions(+), 247 deletions(-) create mode 100644 RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs rename RubberduckTests/Refactoring/EncapsulateField/{EncapsulateAsUDTTests.cs => EncapsulatedUDTField.cs} (59%) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs index 29a64e4664..787154b488 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs @@ -59,13 +59,14 @@ public IEnumerable CreateEncapsulationCandidates(IEn var moduleHasMultipleInstancesOfUDT = candidateFields.Any(fld => fld != encapsulatedUDTField.Declaration && encapsulatedUDTField.AsTypeName.Equals(fld.AsTypeName)); var parent = encapsulatedUDTField as IEncapsulatedUserDefinedTypeField; + parent.TypeDeclarationIsPrivate = udtFieldToUdtDeclarationMap[udtField].UserDefinedType.Accessibility.Equals(Accessibility.Private); foreach (var udtMember in udtFieldToUdtDeclarationMap[udtField].Item2) { IEncapsulateFieldCandidate encapsulatedUDTMember = new EncapsulatedUserDefinedTypeMember(udtMember, encapsulatedUDTField, _validator, moduleHasMultipleInstancesOfUDT); encapsulatedUDTMember = ApplyTypeSpecificAttributes(encapsulatedUDTMember); parent.Members.Add(encapsulatedUDTMember); - encapsulatedUDTMember.FieldAccessExpression = + encapsulatedUDTMember.PropertyAccessExpression = () => { var prefix = encapsulatedUDTField.EncapsulateFlag diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index de257735b3..a30cec590d 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -56,6 +56,9 @@ public EncapsulateFieldModel(Declaration target, IDeclarationFinderProvider decl public List FieldCandidates { set; get; } = new List(); + public IEnumerable FlaggedFieldCandidates + => FieldCandidates.Where(v => v.EncapsulationAttributes.EncapsulateFlag); + public IEnumerable UDTFieldCandidates => FieldCandidates.Where(v => v is IEncapsulatedUserDefinedTypeField).Cast(); private List AllEncapsulationCandidates { get; } = new List(); diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs index ed6090a039..c6a3d3bdb0 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs @@ -13,7 +13,7 @@ namespace Rubberduck.Refactorings.EncapsulateField public interface IEncapsulateFieldCandidate { Declaration Declaration { get; } - DeclarationType DeclarationType { get; } + //DeclarationType DeclarationType { get; } string TargetID { get; } string IdentifierName { get; } IFieldEncapsulationAttributes EncapsulationAttributes { get; } @@ -30,13 +30,17 @@ public interface IEncapsulateFieldCandidate IEnumerable References { get; } bool ImplementLetSetterType { get; } bool ImplementSetSetterType { get; } - Func FieldAccessExpression { set; get; } + Func PropertyAccessExpression { set; get; } + Func ReferenceExpression { set; get; } + string this[IdentifierReference idRef] { set; get; } + bool TryGetReferenceExpression(IdentifierReference idRef, out string expression); } public interface IEncapsulatedUserDefinedTypeField : IEncapsulateFieldCandidate { IList Members { set; get; } IEnumerable SelectedMembers { get; } + bool TypeDeclarationIsPrivate { set; get; } } public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate @@ -44,6 +48,7 @@ public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate protected Declaration _target; protected IFieldEncapsulationAttributes _attributes; private IEncapsulateFieldNamesValidator _validator; + private Dictionary _idRefRenames { set; get; } = new Dictionary(); public EncapsulateFieldCandidate(Declaration declaration, IEncapsulateFieldNamesValidator validator) { @@ -63,7 +68,7 @@ public EncapsulateFieldCandidate(IFieldEncapsulationAttributes attributes, IEnca public Declaration Declaration => _target; - public DeclarationType DeclarationType => _target?.DeclarationType ?? DeclarationType.Variable; + //public DeclarationType DeclarationType => _target?.DeclarationType ?? DeclarationType.Variable; public bool HasValidEncapsulationAttributes { @@ -75,6 +80,33 @@ public bool HasValidEncapsulationAttributes } } + public bool TryGetReferenceExpression(IdentifierReference idRef, out string expression) + { + expression = string.Empty; + if (_idRefRenames.ContainsKey(idRef)) + { + expression = _idRefRenames[idRef]; + } + return expression.Length > 0; + } + + public string this[IdentifierReference idRef] + { + get => _idRefRenames[idRef]; + set + { + if (!_idRefRenames.ContainsKey(idRef)) + { + _idRefRenames.Add(idRef, value); + } + else + { + _idRefRenames[idRef] = value; + } + } + } + + public IFieldEncapsulationAttributes EncapsulationAttributes { private set => _attributes = value; @@ -129,12 +161,17 @@ public string NewFieldName public bool ImplementLetSetterType { get => _attributes.ImplementLetSetterType; set => _attributes.ImplementLetSetterType = value; } public bool ImplementSetSetterType { get => _attributes.ImplementSetSetterType; set => _attributes.ImplementSetSetterType = value; } - public Func FieldAccessExpression + public Func PropertyAccessExpression { - set => _attributes.FieldAccessExpression = value; - get => _attributes.FieldAccessExpression; + set => _attributes.PropertyAccessExpression = value; + get => _attributes.PropertyAccessExpression; } + public Func ReferenceExpression + { + set => _attributes.ReferenceExpression = value; + get => _attributes.ReferenceExpression; + } } public class EncapsulatedUserDefinedTypeField : EncapsulateFieldCandidate, IEncapsulatedUserDefinedTypeField @@ -142,11 +179,12 @@ public class EncapsulatedUserDefinedTypeField : EncapsulateFieldCandidate, IEnca public EncapsulatedUserDefinedTypeField(Declaration declaration, IEncapsulateFieldNamesValidator validator) : base(declaration, validator) { - FieldAccessExpression = () => EncapsulateFlag ? NewFieldName : IdentifierName; + PropertyAccessExpression = () => EncapsulateFlag ? NewFieldName : IdentifierName; } public IList Members { set; get; } = new List(); public IEnumerable SelectedMembers => Members.Where(m => m.EncapsulateFlag); + public bool TypeDeclarationIsPrivate { set; get; } } public class EncapsulatedUserDefinedTypeMember : EncapsulateFieldCandidate @@ -155,16 +193,16 @@ public EncapsulatedUserDefinedTypeMember(Declaration target, IEncapsulateFieldCa : base(target, validator) { Parent = udtVariable; - NameResolveProperty = propertyNameRequiresParentIdentifier; + FieldNameQualifyProperty = propertyNameRequiresParentIdentifier; - EncapsulationAttributes.PropertyName = NameResolveProperty + EncapsulationAttributes.PropertyName = FieldNameQualifyProperty ? $"{Parent.IdentifierName.Capitalize()}_{IdentifierName}" : IdentifierName; } public IEncapsulateFieldCandidate Parent { private set; get; } - public bool NameResolveProperty { set; get; } + public bool FieldNameQualifyProperty { set; get; } public override string TargetID => $"{Parent.IdentifierName}.{IdentifierName}"; } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs index dc40c170b3..bd05fadff1 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs @@ -19,7 +19,8 @@ public interface IFieldEncapsulationAttributes bool ImplementSetSetterType { get; set; } bool FieldNameIsExemptFromValidation { get; } QualifiedModuleName QualifiedModuleName { get; } - Func FieldAccessExpression { set; get; } + Func PropertyAccessExpression { set; get; } + Func ReferenceExpression { set; get; } } @@ -38,7 +39,8 @@ public NeverEncapsulateAttributes(string identifier, string asTypeName, Qualifie Identifier = identifier; NewFieldName = identifier; AsTypeName = asTypeName; - FieldAccessExpression = () => NewFieldName; + PropertyAccessExpression = () => NewFieldName; + ReferenceExpression = () => NewFieldName; } public IFieldEncapsulationAttributes ApplyNewFieldName(string newFieldName) @@ -54,7 +56,9 @@ public IFieldEncapsulationAttributes ApplyNewFieldName(string newFieldName) string _tossString; public string PropertyName { set => _tossString = value; get => $"{neverUse}{Identifier}_{neverUse}"; } - public Func FieldAccessExpression { set; get; } + public Func PropertyAccessExpression { set; get; } + + public Func ReferenceExpression { set; get; } public string AsTypeName { get; set; } public string ParameterName => neverUse; @@ -82,7 +86,8 @@ public FieldEncapsulationAttributes(Declaration target) Identifier = target.IdentifierName; AsTypeName = target.AsTypeName; _qmn = target.QualifiedModuleName; - FieldAccessExpression = () => NewFieldName; + PropertyAccessExpression = () => NewFieldName; + ReferenceExpression = () => NewFieldName; _fieldNameIsAlwaysValid = target.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember); } @@ -90,7 +95,7 @@ public FieldEncapsulationAttributes(string identifier, string asTypeName) { _fieldAndProperty = new EncapsulationIdentifiers(identifier); AsTypeName = asTypeName; - FieldAccessExpression = () => NewFieldName; + PropertyAccessExpression = () => NewFieldName; } public FieldEncapsulationAttributes(IFieldEncapsulationAttributes attributes) @@ -105,7 +110,7 @@ public FieldEncapsulationAttributes(IFieldEncapsulationAttributes attributes) ImplementLetSetterType = attributes.ImplementLetSetterType; ImplementSetSetterType = attributes.ImplementSetSetterType; QualifiedModuleName = attributes.QualifiedModuleName; - FieldAccessExpression = () => NewFieldName; + PropertyAccessExpression = () => NewFieldName; } private EncapsulationIdentifiers _fieldAndProperty; @@ -126,7 +131,9 @@ public string PropertyName set => _fieldAndProperty.Property = value; } - public Func FieldAccessExpression { set; get; } + public Func PropertyAccessExpression { set; get; } + + public Func ReferenceExpression { set; get; } public string AsTypeName { get; set; } public string ParameterName => _fieldAndProperty.SetLetParameter; diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs index f1d6789664..a4075e748e 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs @@ -47,10 +47,22 @@ protected override IExecutableRewriteSession RefactorRewrite(EncapsulateFieldMod { foreach (var field in model.UDTFieldCandidates) { - foreach (var member in field.Members) + if (!field.TypeDeclarationIsPrivate) { - member.FieldAccessExpression = () => $"{field.FieldAccessExpression()}.{member.IdentifierName}"; + field.ReferenceExpression = () => field.PropertyName; } + else + { + foreach (var member in field.Members) + { + member.PropertyAccessExpression = () => $"{field.PropertyAccessExpression()}.{member.IdentifierName}"; + } + } + } + + foreach (var field in model.FieldCandidates.Except(model.UDTFieldCandidates).Where(fld => fld.EncapsulateFlag)) + { + field.ReferenceExpression = () => field.PropertyName; } return base.RefactorRewrite(model, rewriteSession, asPreview); diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs index 31e1cedbb1..08a28b12f5 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs @@ -30,24 +30,35 @@ protected override IExecutableRewriteSession RefactorRewrite(EncapsulateFieldMod { if (field is IEncapsulatedUserDefinedTypeField udt) { - udt.FieldAccessExpression = + udt.PropertyAccessExpression = () => { var accessor = udt.EncapsulateFlag || stateUDTField_UDTMembers.Contains(udt) ? udt.PropertyName : udt.NewFieldName; - return $"{StateUDTField.FieldAccessExpression()}.{accessor}"; + return $"{StateUDTField.PropertyAccessExpression()}.{accessor}"; }; + udt.ReferenceExpression = udt.PropertyAccessExpression; + foreach (var member in udt.Members) { - member.FieldAccessExpression = () => $"{udt.FieldAccessExpression()}.{member.PropertyName}"; + member.PropertyAccessExpression = () => $"{udt.PropertyAccessExpression()}.{member.PropertyName}"; + member.ReferenceExpression = () => + { + return member.EncapsulateFlag + ? member.PropertyName + : $"{udt.PropertyAccessExpression()}.{member.PropertyName}"; + }; } } else { var efd = field; - efd.FieldAccessExpression = () => $"{StateUDTField.FieldAccessExpression()}.{efd.PropertyName}"; + efd.PropertyAccessExpression = () => $"{StateUDTField.PropertyAccessExpression()}.{efd.PropertyName}"; + efd.ReferenceExpression = efd.PropertyAccessExpression; } } + SetupReferenceModifications(model); + var fieldsToModify = model.EncapsulationFields .Where(encFld => !encFld.IsUDTMember && encFld.EncapsulateFlag).Union(stateUDTField_UDTMembers); @@ -55,7 +66,14 @@ protected override IExecutableRewriteSession RefactorRewrite(EncapsulateFieldMod { var attributes = field.EncapsulationAttributes; ModifyEncapsulatedVariable(field, attributes, rewriteSession); - RenameReferences(field, attributes.PropertyName ?? field.Declaration.IdentifierName, rewriteSession); + RenameReferences(field, rewriteSession); + if (field is IEncapsulatedUserDefinedTypeField udtField) + { + foreach (var member in udtField.Members) + { + RenameReferences(member, rewriteSession); + } + } } var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs index 99e3c5aa4b..45dcf30bea 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs @@ -1,8 +1,10 @@ -using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.SmartIndenter; using Rubberduck.VBEditor; +using Rubberduck.VBEditor.SafeComWrappers; using System; using System.Collections.Generic; using System.Linq; @@ -48,6 +50,8 @@ public IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IE protected virtual IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) { + SetupReferenceModifications(model); + var nonUdtMemberFields = model.FlaggedEncapsulationFields .Where(encFld => !encFld.IsUDTMember); @@ -55,7 +59,7 @@ protected virtual IExecutableRewriteSession RefactorRewrite(EncapsulateFieldMode { var attributes = nonUdtMemberField.EncapsulationAttributes; ModifyEncapsulatedVariable(nonUdtMemberField, attributes, rewriteSession); - RenameReferences(nonUdtMemberField, attributes.PropertyName ?? nonUdtMemberField.Declaration.IdentifierName, rewriteSession); + RenameReferences(nonUdtMemberField, rewriteSession); } var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); @@ -66,6 +70,90 @@ protected virtual IExecutableRewriteSession RefactorRewrite(EncapsulateFieldMode return rewriteSession; } + protected void SetupReferenceModifications(EncapsulateFieldModel model) + { + foreach (var field in model.FieldCandidates.Except(model.UDTFieldCandidates)) + { + foreach (var rf in field.References) + { + LoadFieldReferenceData(field, rf); + } + } + + foreach( var udtField in model.UDTFieldCandidates) + { + if (!udtField.TypeDeclarationIsPrivate) + { + foreach (var rf in udtField.References) + { + LoadUDTFieldReferenceData(udtField, rf); + } + } + else + { + foreach (var member in udtField.Members) + { + foreach (var rf in member.References) + { + if (rf.QualifiedModuleName == udtField.QualifiedModuleName || udtField.QualifiedModuleName.ComponentType == ComponentType.ClassModule) + { + member[rf] = udtField.EncapsulateFlag + ? $"{member.PropertyName}" + : $"{member.ReferenceExpression()}"; + } + else + { + member[rf] = udtField.EncapsulateFlag + ? $"{udtField.QualifiedModuleName.ComponentName}.{member.PropertyName}" + : $"{member.ReferenceExpression()}"; + } + } + } + } + } + } + + private void LoadFieldReferenceData(IEncapsulateFieldCandidate field, IdentifierReference idRef) + { + if (idRef.QualifiedModuleName == field.QualifiedModuleName || field.QualifiedModuleName.ComponentType == ComponentType.ClassModule) + { + field[idRef] = field.ReferenceExpression(); + } + else + { + if (idRef.Context.Parent is VBAParser.MemberAccessExprContext maec + || idRef.Context.Parent is VBAParser.WithMemberAccessExprContext wmaec) + { + field[idRef] = field.ReferenceExpression(); + } + else + { + field[idRef] = $"{field.QualifiedModuleName.ComponentName}.{field.ReferenceExpression()}"; + } + } + } + + private void LoadUDTFieldReferenceData(IEncapsulateFieldCandidate field, IdentifierReference idRef) + { + if (idRef.QualifiedModuleName == field.QualifiedModuleName || field.QualifiedModuleName.ComponentType == ComponentType.ClassModule) + { + field[idRef] = field.ReferenceExpression(); + } + else + { + if ((idRef.Context.Parent is VBAParser.MemberAccessExprContext maec + || idRef.Context.Parent is VBAParser.WithMemberAccessExprContext wmaec) + && !(idRef.Context is VBAParser.SimpleNameExprContext)) + { + field[idRef] = field.ReferenceExpression(); + } + else + { + field[idRef] = $"{field.QualifiedModuleName.ComponentName}.{field.ReferenceExpression()}"; + } + } + } + protected void InsertNewContent(int? codeSectionStartIndex, EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool postPendPreviewMessage = false) { var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); @@ -91,6 +179,14 @@ protected virtual IList PropertiesContent(IEnumerable(); foreach (var field in flaggedEncapsulationFields) { + if (field is IEncapsulatedUserDefinedTypeField udtField && udtField.TypeDeclarationIsPrivate) + { + foreach (var member in udtField.Members) + { + textBlocks.Add(BuildPropertiesTextBlock(member)); + } + continue; + } textBlocks.Add(BuildPropertiesTextBlock(field)); } return textBlocks; @@ -103,7 +199,7 @@ private string BuildPropertiesTextBlock(IEncapsulateFieldCandidate field) { PropertyName = attributes.PropertyName, AsTypeName = attributes.AsTypeName, - BackingField = attributes.FieldAccessExpression(), + BackingField = attributes.PropertyAccessExpression(), ParameterName = attributes.ParameterName, GenerateSetter = attributes.ImplementSetSetterType, GenerateLetter = attributes.ImplementLetSetterType @@ -126,12 +222,19 @@ private EncapsulateFieldNewContent LoadNewPropertiesContent(EncapsulateFieldNewC return newContent; } - protected void RenameReferences(IEncapsulateFieldCandidate efd, string propertyName, IRewriteSession rewriteSession) + protected virtual void RenameReferences(IEncapsulateFieldCandidate efd, IRewriteSession rewriteSession) { foreach (var reference in efd.Declaration.References) { - var rewriter = rewriteSession.CheckOutModuleRewriter(reference.QualifiedModuleName); - rewriter.Replace(reference.Context, propertyName ?? efd.Declaration.IdentifierName); + if (efd.TryGetReferenceExpression(reference, out var expression)) + { + var replacementContext = efd.IsUDTMember + ? reference.Context.Parent + : reference.Context; + + var rewriter = rewriteSession.CheckOutModuleRewriter(reference.QualifiedModuleName); + rewriter.Replace(replacementContext, expression); + } } } } diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs new file mode 100644 index 0000000000..6356a05703 --- /dev/null +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs @@ -0,0 +1,173 @@ +using NUnit.Framework; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.VBA; +using Rubberduck.Refactorings; +using Rubberduck.Refactorings.EncapsulateField; +using Rubberduck.VBEditor.SafeComWrappers; +using Rubberduck.VBEditor.Utility; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RubberduckTests.Refactoring.EncapsulateField +{ + [TestFixture] + public class EncapsulateUsingStateUDTTests : InteractiveRefactoringTestBase + { + private EncapsulateFieldTestSupport Support { get; } = new EncapsulateFieldTestSupport(); + + [TestCase("Public")] + [TestCase("Private")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedType_UserAcceptsDefaults_ConflictWithStateUDT(string accessibility) + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +{accessibility} my|Bar As TBar + +Private this As Long"; + + + var presenterAction = Support.UserAcceptsDefaults(asUDT: true); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.Contains("Private this As Long", actualCode); + StringAssert.Contains("Private this1 As This_Type", actualCode); + } + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedTypeMembers_OnlyEncapsulateUDTMembers() + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +Private my|Bar As TBar"; + + + var userInput = new UserInputDataObject("myBar"); + userInput["myBar"].EncapsulateFlag = false; + userInput.AddUDTMemberNameFlagPairs(("myBar", "First", true)); + userInput.AddUDTMemberNameFlagPairs(("myBar", "Second", true)); + userInput.EncapsulateAsUDT = true; + + var presenterAction = Support.SetParameters(userInput); + + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.Contains("this.MyBar.First = value", actualCode); + StringAssert.Contains($"First = this.MyBar.First", actualCode); + StringAssert.Contains("this.MyBar.Second = value", actualCode); + StringAssert.Contains($"Second = this.MyBar.Second", actualCode); + StringAssert.Contains($"MyBar As TBar", actualCode); + StringAssert.DoesNotContain($"myBar As TBar", actualCode); + } + + [TestCase(false, "this.MyBar.First = newValue")] + [TestCase(true, " First = newValue")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedTypeMembers_UDTFieldReferences(bool encapsulateFirst, string expected) + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +Private my|Bar As TBar + +Public Sub Foo(newValue As String) + myBar.First = newValue +End Sub"; + + + var userInput = new UserInputDataObject("myBar"); + userInput["myBar"].EncapsulateFlag = false; + userInput.AddUDTMemberNameFlagPairs(("myBar", "First", encapsulateFirst)); + userInput.AddUDTMemberNameFlagPairs(("myBar", "Second", true)); + userInput.EncapsulateAsUDT = true; + + var presenterAction = Support.SetParameters(userInput); + + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.Contains(expected, actualCode); + } + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void MultipleFields() + { + string inputCode = +$@" +Public fo|o As Long +Public bar As String +Public foobar As Byte +"; + + var userInput = new UserInputDataObject("foo", encapsulationFlag: true); + userInput.AddAttributeSet("bar", encapsulationFlag: true); + userInput.AddAttributeSet("foobar", encapsulationFlag: true); + userInput.EncapsulateAsUDT = true; + + var presenterAction = Support.SetParameters(userInput); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.Contains("Private this As This_Type", actualCode); + StringAssert.Contains("Private Type This_Type", actualCode); + StringAssert.Contains("Foo As Long", actualCode); + StringAssert.Contains("Bar As String", actualCode); + StringAssert.Contains("Foobar As Byte", actualCode); + } + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedType_MultipleFieldsWithUDT() + { + string inputCode = +$@" + +Private Type TBar + First As Long + Second As String +End Type + +Public fo|o As Long +Public myBar As TBar +"; + + var userInput = new UserInputDataObject("foo", encapsulationFlag: true); + userInput.AddAttributeSet("myBar", encapsulationFlag: true); + //userInput.AddUDTMemberNameFlagPairs(("myBar", "First", true), ("myBar", "Second", true)); + userInput.EncapsulateAsUDT = true; + + var presenterAction = Support.SetParameters(userInput); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.Contains("this.MyBar.First = value", actualCode); + StringAssert.Contains("First = this.MyBar.First", actualCode); + StringAssert.Contains("this.MyBar.Second = value", actualCode); + StringAssert.Contains("Second = this.MyBar.Second", actualCode); + var index = actualCode.IndexOf("Get Second", StringComparison.InvariantCultureIgnoreCase); + var indexLast = actualCode.LastIndexOf("Get Second", StringComparison.InvariantCultureIgnoreCase); + Assert.AreEqual(index, indexLast); + } + + protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) + { + return Support.SupportTestRefactoring(rewritingManager, state, factory, selectionService); + } + } +} diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateAsUDTTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTField.cs similarity index 59% rename from RubberduckTests/Refactoring/EncapsulateField/EncapsulateAsUDTTests.cs rename to RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTField.cs index 923c79eaa6..bd1dd6f9f0 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateAsUDTTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTField.cs @@ -7,14 +7,12 @@ using Rubberduck.VBEditor.Utility; using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; namespace RubberduckTests.Refactoring.EncapsulateField { [TestFixture] - public class EncapsulateAsUDTTests : InteractiveRefactoringTestBase + public class EncapsulatedUDTField : InteractiveRefactoringTestBase { private EncapsulateFieldTestSupport Support { get; } = new EncapsulateFieldTestSupport(); @@ -37,9 +35,14 @@ End Type var presenterAction = Support.UserAcceptsDefaults(); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.Contains("Private this1 As TBar", actualCode); - StringAssert.Contains("this1 = value", actualCode); - StringAssert.Contains($"This = this1", actualCode); - StringAssert.DoesNotContain($"this1.First1 = value", actualCode); + StringAssert.DoesNotContain("this1 = value", actualCode); + StringAssert.DoesNotContain($"This = this1", actualCode); + StringAssert.Contains($"Public Property Get First", actualCode); + StringAssert.Contains($"Public Property Get Second", actualCode); + StringAssert.Contains($"this1.First = value", actualCode); + StringAssert.Contains($"First = this1.First", actualCode); + StringAssert.Contains($"this1.Second = value", actualCode); + StringAssert.Contains($"Second = this1.Second", actualCode); } @@ -78,35 +81,17 @@ End Type var codeString = inputCode.ToCodeString(); var actualCode = RefactoredCode(selectionModule, codeString.CaretPosition.ToOneBased(), presenterAdjustment, null, false, (selectionModule, codeString.Code, ComponentType.ClassModule), (otherModule, moduleCode, ComponentType.StandardModule)); StringAssert.Contains("Private this1 As TBar", actualCode[selectionModule]); - StringAssert.Contains("this1 = value", actualCode[selectionModule]); - StringAssert.Contains($"This = this1", actualCode[selectionModule]); - StringAssert.DoesNotContain($"this1.First1 = value", actualCode[selectionModule]); + StringAssert.DoesNotContain("this1 = value", actualCode[selectionModule]); + StringAssert.DoesNotContain($"This = this1", actualCode[selectionModule]); + StringAssert.DoesNotContain($"Public Property Get This(", actualCode[selectionModule]); + StringAssert.Contains($"Public Property Get This_First", actualCode[selectionModule]); + StringAssert.Contains($"Public Property Get This_Second", actualCode[selectionModule]); + StringAssert.Contains($"this1.First = value", actualCode[selectionModule]); + StringAssert.Contains($"This_First = this1.First", actualCode[selectionModule]); + StringAssert.Contains($"this1.Second = value", actualCode[selectionModule]); + StringAssert.Contains($"This_Second = this1.Second", actualCode[selectionModule]); } - [TestCase("Public")] - [TestCase("Private")] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void UserDefinedType_UserAcceptsDefaults_ConflictWithEncapsulationUDT(string accessibility) - { - string inputCode = -$@" -Private Type TBar - First As String - Second As Long -End Type - -{accessibility} my|Bar As TBar - -Private this As Long"; - - - var presenterAction = Support.UserAcceptsDefaults(asUDT: true); - var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - StringAssert.Contains("Private this As Long", actualCode); - StringAssert.Contains("Private this1 As This_Type", actualCode); - //StringAssert.DoesNotContain($"Private this1 As This_Type", actualCode); - } [TestCase("Public", true, true)] [TestCase("Private", true, true)] @@ -132,10 +117,6 @@ End Type var userInput = new UserInputDataObject("this", "MyType", encapsulateThis); userInput.AddAttributeSet("that", "MyOtherType", encapsulateThat); - userInput.AddUDTMemberNameFlagPairs(("this", "First", true)); - userInput.AddUDTMemberNameFlagPairs(("this", "Second", true)); - userInput.AddUDTMemberNameFlagPairs(("that", "First", true)); - userInput.AddUDTMemberNameFlagPairs(("that", "Second", true)); var expectedThis = new EncapsulationIdentifiers("this") { Property = "MyType" }; var expectedThat = new EncapsulationIdentifiers("that") { Property = "MyOtherType" }; @@ -145,65 +126,32 @@ End Type if (encapsulateThis) { StringAssert.Contains($"Private {expectedThis.Field} As TBar", actualCode); - StringAssert.Contains($"MyType = {expectedThis.Field}", actualCode); - StringAssert.Contains($"{expectedThis.Field} = value", actualCode); - StringAssert.Contains($"{expectedThis.Field}.First = value", actualCode); + StringAssert.Contains($"This_First = {expectedThis.Field}.First", actualCode); + StringAssert.Contains($"This_Second = {expectedThis.Field}.Second", actualCode); StringAssert.Contains($"{expectedThis.Field}.First = value", actualCode); StringAssert.Contains($"{expectedThis.Field}.Second = value", actualCode); + StringAssert.Contains($"Property Get This_First", actualCode); + StringAssert.Contains($"Property Get This_Second", actualCode); } else { StringAssert.Contains($"{accessibility} this As TBar", actualCode); - StringAssert.Contains($"this.First = value", actualCode); - StringAssert.Contains($"this.Second = value", actualCode); } if (encapsulateThat) { StringAssert.Contains($"Private {expectedThat.Field} As TBar", actualCode); - StringAssert.Contains($"MyOtherType = {expectedThat.Field}", actualCode); - StringAssert.Contains($"{expectedThat.Field} = value", actualCode); + StringAssert.Contains($"That_First = {expectedThat.Field}.First", actualCode); + StringAssert.Contains($"That_Second = {expectedThat.Field}.Second", actualCode); StringAssert.Contains($"{expectedThat.Field}.First = value", actualCode); StringAssert.Contains($"{expectedThat.Field}.Second = value", actualCode); + StringAssert.Contains($"Property Get That_First", actualCode); + StringAssert.Contains($"Property Get That_Second", actualCode); } else { StringAssert.Contains($"{accessibility} that As TBar", actualCode); - StringAssert.Contains($"that.First = value", actualCode); - StringAssert.Contains($"that.Second = value", actualCode); } - - StringAssert.Contains($"Property Get This_First", actualCode); - StringAssert.Contains($"Property Get That_First", actualCode); - StringAssert.Contains($"Property Get This_Second", actualCode); - StringAssert.Contains($"Property Get That_Second", actualCode); - } - - - [TestCase("First")] - [TestCase("Second")] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void UserDefinedTypeMembers_Subset(string memberToEncapsulate) - { - string inputCode = -$@" -Private Type TBar - First As String - Second As Long -End Type - -Private th|is As TBar"; - - - var userInput = new UserInputDataObject("this", "MyType", true); - userInput.AddUDTMemberNameFlagPairs(("this", memberToEncapsulate, true)); - - var presenterAction = Support.SetParameters(userInput); - - var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - StringAssert.Contains($"this.{memberToEncapsulate} = value", actualCode); - StringAssert.Contains($"{memberToEncapsulate} = this.{memberToEncapsulate}", actualCode); } [Test] @@ -222,49 +170,14 @@ End Type var userInput = new UserInputDataObject("this"); - userInput["this"].EncapsulateFlag = false; - userInput.AddUDTMemberNameFlagPairs(("this", "First", true)); - userInput.AddUDTMemberNameFlagPairs(("this", "Second", true)); - - var presenterAction = Support.SetParameters(userInput); - - var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - StringAssert.Contains("this.First = value", actualCode); - StringAssert.Contains($"First = this.First", actualCode); - StringAssert.Contains("this.Second = value", actualCode); - StringAssert.Contains($"Second = this.Second", actualCode); - } - - [Test] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void UserDefinedTypeMembers_OnlyEncapsulateUDTMembersUsingUDT() - { - string inputCode = -$@" -Private Type TBar - First As String - Second As Long -End Type - -Private my|Bar As TBar"; - - - var userInput = new UserInputDataObject("myBar"); - userInput["myBar"].EncapsulateFlag = false; - userInput.AddUDTMemberNameFlagPairs(("myBar", "First", true)); - userInput.AddUDTMemberNameFlagPairs(("myBar", "Second", true)); - userInput.EncapsulateAsUDT = true; var presenterAction = Support.SetParameters(userInput); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - StringAssert.Contains("this.MyBar.First = value", actualCode); - StringAssert.Contains($"First = this.MyBar.First", actualCode); - StringAssert.Contains("this.MyBar.Second = value", actualCode); - StringAssert.Contains($"Second = this.MyBar.Second", actualCode); - StringAssert.Contains($"MyBar As TBar", actualCode); - StringAssert.DoesNotContain($"myBar As TBar", actualCode); + StringAssert.Contains("this1.First = value", actualCode); + StringAssert.Contains($"First = this1.First", actualCode); + StringAssert.Contains("this1.Second = value", actualCode); + StringAssert.Contains($"Second = this1.Second", actualCode); } [TestCase("Public")] @@ -288,7 +201,6 @@ Private mFizz var userInput = new UserInputDataObject("this", "MyType", true); - userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true)); userInput.AddAttributeSet("mFoo", "Foo", true); userInput.AddAttributeSet("mBar", "Bar", true); userInput.AddAttributeSet("mFizz", "Fizz", true); @@ -298,9 +210,8 @@ Private mFizz var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.Contains("Private this As TBar", actualCode); - StringAssert.Contains("this = value", actualCode); - StringAssert.Contains("MyType = this", actualCode); - Assert.AreEqual(actualCode.IndexOf("MyType = this"), actualCode.LastIndexOf("MyType = this")); + StringAssert.DoesNotContain("this = value", actualCode); + StringAssert.DoesNotContain("MyType = this", actualCode); StringAssert.Contains($"this.First = value", actualCode); StringAssert.Contains($"First = this.First", actualCode); StringAssert.Contains($"this.Second = value", actualCode); @@ -341,8 +252,6 @@ End Sub var userInput = new UserInputDataObject("this", "MyType", true); - userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true)); - var presenterAction = Support.SetParameters(userInput); var codeString = inputCode.ToCodeString(); @@ -358,8 +267,8 @@ End Sub var actualCode = actualModuleCode["Module1"]; StringAssert.Contains("Private this As TBar", actualCode); - StringAssert.Contains("this = value", actualCode); - StringAssert.Contains("MyType = this", actualCode); + StringAssert.DoesNotContain("this = value", actualCode); + StringAssert.DoesNotContain("MyType = this", actualCode); StringAssert.Contains("Property Set First(ByVal value As Class1)", actualCode); StringAssert.Contains("Property Get First() As Class1", actualCode); StringAssert.Contains($"Set this.First = value", actualCode); @@ -367,6 +276,7 @@ End Sub StringAssert.Contains($"this.Second = value", actualCode); StringAssert.Contains($"Second = this.Second", actualCode); StringAssert.DoesNotContain($"Second = Second", actualCode); + Assert.AreEqual(actualCode.IndexOf("this.First = value"), actualCode.LastIndexOf("this.First = value")); } [TestCase("Public")] @@ -384,16 +294,14 @@ End Type {accessibility} th|is As TBar"; - var userInput = new UserInputDataObject("this", "MyType", true); - userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true)); + var userInput = new UserInputDataObject("this", "MyType"); var presenterAction = Support.SetParameters(userInput); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.Contains("Private this As TBar", actualCode); - StringAssert.Contains("this = value", actualCode); - StringAssert.Contains("MyType = this", actualCode); - Assert.AreEqual(actualCode.IndexOf("MyType = this"), actualCode.LastIndexOf("MyType = this")); + StringAssert.DoesNotContain("this = value", actualCode); + StringAssert.DoesNotContain("MyType = this", actualCode); StringAssert.Contains($"this.First = value", actualCode); StringAssert.Contains($"First = this.First", actualCode); StringAssert.Contains($"IsObject", actualCode); @@ -418,13 +326,12 @@ End Type {accessibility} t|his As TBar"; - var userInput = new UserInputDataObject("this", "MyType", false); - userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true), ("this", "Third", true)); + var userInput = new UserInputDataObject("this", "MyType"); var presenterAction = Support.SetParameters(userInput); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - StringAssert.Contains($"{accessibility} this As TBar", actualCode); + StringAssert.Contains($"Private this As TBar", actualCode); StringAssert.DoesNotContain("this = value", actualCode); StringAssert.DoesNotContain($"this.First = value", actualCode); StringAssert.Contains($"Property Get First() As Variant", actualCode); @@ -436,37 +343,6 @@ End Type StringAssert.Contains($"Property Get Third() As Variant", actualCode); } - [TestCase("Public", "Public")] - [TestCase("Private", "Private")] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void UserDefinedTypeMembersOnly(string accessibility, string expectedAccessibility) - { - string inputCode = -$@" -Private Type TBar - First As String - Second As Long -End Type - -{accessibility} th|is As TBar"; - - var userInput = new UserInputDataObject("this", "MyType", false); - userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true)); - - var presenterAction = Support.SetParameters(userInput); - - var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - StringAssert.Contains($"{expectedAccessibility} this As TBar", actualCode); - StringAssert.DoesNotContain("this = value", actualCode); - StringAssert.DoesNotContain("MyType = this", actualCode); - StringAssert.Contains($"this.First = value", actualCode); - StringAssert.Contains($"First = this.First", actualCode); - StringAssert.Contains($"this.Second = value", actualCode); - StringAssert.Contains($"Second = this.Second", actualCode); - StringAssert.DoesNotContain($"Second = Second", actualCode); - } - [TestCase("Public")] [TestCase("Private")] [Category("Refactorings")] @@ -488,7 +364,6 @@ End Type "; var userInput = new UserInputDataObject("this", "MyType", true); - userInput.AddUDTMemberNameFlagPairs(("this", "First", true), ("this", "Second", true)); var presenterAction = Support.SetParameters(userInput); @@ -507,14 +382,16 @@ End Type var actualCode = actualModuleCode["Class1"]; StringAssert.Contains("Private this As TBar", actualCode); - StringAssert.Contains("this = value", actualCode); - StringAssert.Contains("MyType = this", actualCode); - Assert.AreEqual(actualCode.IndexOf("MyType = this"), actualCode.LastIndexOf("MyType = this")); - StringAssert.Contains($"this.First = value", actualCode); - StringAssert.Contains($"First = this.First", actualCode); - StringAssert.Contains($"this.Second = value", actualCode); - StringAssert.Contains($"Second = this.Second", actualCode); - StringAssert.DoesNotContain($"Second = Second", actualCode); + { + StringAssert.Contains("this = value", actualCode); + StringAssert.Contains("MyType = this", actualCode); + StringAssert.Contains($"Public Property Get MyType", actualCode); + StringAssert.Contains($"Private this As TBar", actualCode); + Assert.AreEqual(actualCode.IndexOf("MyType = this"), actualCode.LastIndexOf("MyType = this")); + StringAssert.DoesNotContain($"this.First = value", actualCode); + StringAssert.DoesNotContain($"this.Second = value", actualCode); + StringAssert.DoesNotContain($"Second = Second", actualCode); + } } [TestCase("Public")] @@ -559,65 +436,203 @@ End Sub StringAssert.Contains($"Public Property Set {defaults.Property}", actualCode); } - [Test] + [TestCase(false)] + [TestCase(true)] [Category("Refactorings")] [Category("Encapsulate Field")] - public void UserDefinedType_MultipleFields_ToNewUDT() + public void StandardModuleSource_UDTFieldSelection_ExternalReferences(bool moduleQualifyReference) { - string inputCode = + var userInput = new UserInputDataObject("this", "MyType"); + var sourceModuleName = "SourceModule"; + + var actualModuleCode = StdModuleSource_TwoReferencingModulesScenario(moduleQualifyReference, sourceModuleName, userInput); + + var referencingModuleCode = actualModuleCode["StdModule"]; + StringAssert.Contains($"{sourceModuleName}.MyType.First = ", referencingModuleCode); + StringAssert.Contains($"{sourceModuleName}.MyType.Second = ", referencingModuleCode); + StringAssert.Contains($" .MyType.Second = ", referencingModuleCode); + + var referencingClassCode = actualModuleCode["ClassModule"]; + StringAssert.Contains($"{sourceModuleName}.MyType.First = ", referencingClassCode); + StringAssert.Contains($"{sourceModuleName}.MyType.Second = ", referencingClassCode); + StringAssert.Contains($" .MyType.Second = ", referencingClassCode); + } + + private IDictionary StdModuleSource_TwoReferencingModulesScenario(bool moduleResolve, string sourceModuleName, UserInputDataObject userInput) + { + var referenceExpression = moduleResolve ? $"{sourceModuleName}.this" : "this"; + var sourceModuleCode = $@" -Public fo|o As Long -Public bar As String -Public foobar As Byte +Public Type TBar + First As String + Second As Long +End Type + +Public th|is As TBar"; + + var procedureModuleReferencingCode = +$@"Option Explicit + +Private Const foo As String = ""Foo"" + +Private Const bar As Long = 7 + +Public Sub Foo() + {referenceExpression}.First = foo +End Sub + +Public Sub Bar() + {referenceExpression}.Second = bar +End Sub + +Public Sub FooBar() + With {sourceModuleName} + .this.First = foo + .this.Second = bar + End With +End Sub "; - var userInput = new UserInputDataObject("foo", encapsulationFlag: true); - userInput.AddAttributeSet("bar", encapsulationFlag: true); - userInput.AddAttributeSet("foobar", encapsulationFlag: true); - userInput.EncapsulateAsUDT = true; + string classModuleReferencingCode = +$@"Option Explicit + +Private Const foo As String = ""Foo"" + +Private Const bar As Long = 7 + +Public Sub Foo() + {referenceExpression}.First = foo +End Sub + +Public Sub Bar() + {referenceExpression}.Second = bar +End Sub + +Public Sub FooBar() + With {sourceModuleName} + .this.First = foo + .this.Second = bar + End With +End Sub +"; var presenterAction = Support.SetParameters(userInput); - var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - StringAssert.Contains("Private this As This_Type", actualCode); - StringAssert.Contains("Private Type This_Type", actualCode); - StringAssert.Contains("Foo As Long", actualCode); - StringAssert.Contains("Bar As String", actualCode); - StringAssert.Contains("Foobar As Byte", actualCode); + + var sourceCodeString = sourceModuleCode.ToCodeString(); + var actualModuleCode = RefactoredCode( + sourceModuleName, + sourceCodeString.CaretPosition.ToOneBased(), + presenterAction, + null, + false, + ("StdModule", procedureModuleReferencingCode, ComponentType.StandardModule), + ("ClassModule", classModuleReferencingCode, ComponentType.ClassModule), + (sourceModuleName, sourceCodeString.Code, ComponentType.StandardModule)); + + return actualModuleCode; } [Test] [Category("Refactorings")] [Category("Encapsulate Field")] - public void UserDefinedType_MultipleFieldsWithUDT_ToNewUDT() + public void ClassModuleSource_UDTFieldSelection_ExternalReferences() { - string inputCode = + var sourceModuleName = "SourceModule"; + var sourceClassName = "theClass"; + var sourceModuleCode = $@" -Private Type TBar - First As Long - Second As String +Public th|is As TBar"; + + var procedureModuleReferencingCode = +$@"Option Explicit + +Public Type TBar + First As String + Second As Long End Type -Public fo|o As Long -Public myBar As TBar +Private {sourceClassName} As {sourceModuleName} +Private Const foo As String = ""Foo"" +Private Const bar As Long = 7 + +Public Sub Initialize() + Set {sourceClassName} = New {sourceModuleName} +End Sub + +Public Sub Foo() + {sourceClassName}.this.First = foo +End Sub + +Public Sub Bar() + {sourceClassName}.this.Second = bar +End Sub + +Public Sub FooBar() + With {sourceClassName} + .this.First = foo + .this.Second = bar + End With +End Sub +"; + + string classModuleReferencingCode = +$@"Option Explicit + +Private {sourceClassName} As {sourceModuleName} +Private Const foo As String = ""Foo"" +Private Const bar As Long = 7 + +Private Sub Class_Initialize() + Set {sourceClassName} = New {sourceModuleName} +End Sub + +Public Sub Foo() + {sourceClassName}.this.First = foo +End Sub + +Public Sub Bar() + {sourceClassName}.this.Second = bar +End Sub + +Public Sub FooBar() + With {sourceClassName} + .this.First = foo + .this.Second = bar + End With +End Sub "; - var userInput = new UserInputDataObject("foo", encapsulationFlag: true); - userInput.AddAttributeSet("myBar", encapsulationFlag: true); - userInput.AddUDTMemberNameFlagPairs(("myBar", "First", true), ("myBar", "Second", true)); - userInput.EncapsulateAsUDT = true; + var userInput = new UserInputDataObject("this", "MyType"); var presenterAction = Support.SetParameters(userInput); - var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - StringAssert.Contains("this.MyBar.First = value", actualCode); - StringAssert.Contains("First = this.MyBar.First", actualCode); - StringAssert.Contains("this.MyBar.Second = value", actualCode); - StringAssert.Contains("Second = this.MyBar.Second", actualCode); - var index = actualCode.IndexOf("Get Second", StringComparison.InvariantCultureIgnoreCase); - var indexLast = actualCode.LastIndexOf("Get Second", StringComparison.InvariantCultureIgnoreCase); - Assert.AreEqual(index, indexLast); + + var sourceCodeString = sourceModuleCode.ToCodeString(); + + var actualModuleCode = RefactoredCode( + sourceModuleName, + sourceCodeString.CaretPosition.ToOneBased(), + presenterAction, + null, + false, + ("StdModule", procedureModuleReferencingCode, ComponentType.StandardModule), + ("ClassModule", classModuleReferencingCode, ComponentType.ClassModule), + (sourceModuleName, sourceCodeString.Code, ComponentType.ClassModule)); + + var referencingModuleCode = actualModuleCode["StdModule"]; + StringAssert.Contains($"{sourceClassName}.MyType.First = ", referencingModuleCode); + StringAssert.Contains($"{sourceClassName}.MyType.Second = ", referencingModuleCode); + StringAssert.Contains($" .MyType.Second = ", referencingModuleCode); + + var referencingClassCode = actualModuleCode["ClassModule"]; + StringAssert.Contains($"{sourceClassName}.MyType.First = ", referencingClassCode); + StringAssert.Contains($"{sourceClassName}.MyType.Second = ", referencingClassCode); + StringAssert.Contains($" .MyType.Second = ", referencingClassCode); } + + + protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) { return Support.SupportTestRefactoring(rewritingManager, state, factory, selectionService); diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index a944a9f077..c688823e27 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -693,17 +693,80 @@ End Property Assert.AreEqual(expectedCode, actualCode); } + [TestCase(false)] + [TestCase(true)] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void StandardModuleSource_ExternalReferences(bool moduleResolve) + { + var sourceModuleName = "SourceModule"; + var referenceExpression = moduleResolve ? $"{sourceModuleName}." : string.Empty; + var sourceModuleCode = +$@" + +Public th|is As Long"; + + var procedureModuleReferencingCode = +$@"Option Explicit + +Private Const bar As Long = 7 + +Public Sub Bar() + {referenceExpression}this = bar +End Sub + +Public Sub Foo() + With {sourceModuleName} + .this = bar + End With +End Sub +"; + + string classModuleReferencingCode = +$@"Option Explicit + +Private Const bar As Long = 7 + +Public Sub Bar() + {referenceExpression}this = bar +End Sub + +Public Sub Foo() + With {sourceModuleName} + .this = bar + End With +End Sub +"; + + var userInput = new UserInputDataObject("this", "MyProperty", true); + + var presenterAction = Support.SetParameters(userInput); + + var sourceCodeString = sourceModuleCode.ToCodeString(); + var actualModuleCode = RefactoredCode( + sourceModuleName, + sourceCodeString.CaretPosition.ToOneBased(), + presenterAction, + null, + false, + ("StdModule", procedureModuleReferencingCode, ComponentType.StandardModule), + ("ClassModule", classModuleReferencingCode, ComponentType.ClassModule), + (sourceModuleName, sourceCodeString.Code, ComponentType.StandardModule)); + + var referencingModuleCode = actualModuleCode["StdModule"]; + StringAssert.Contains($"{sourceModuleName}.MyProperty = ", referencingModuleCode); + StringAssert.DoesNotContain($"{sourceModuleName}.{sourceModuleName}.MyProperty = ", referencingModuleCode); + StringAssert.Contains($" .MyProperty = bar", referencingModuleCode); + + var referencingClassCode = actualModuleCode["ClassModule"]; + StringAssert.Contains($"{sourceModuleName}.MyProperty = ", referencingClassCode); + StringAssert.DoesNotContain($"{sourceModuleName}.{sourceModuleName}.MyProperty = ", referencingClassCode); + StringAssert.Contains($" .MyProperty = bar", referencingClassCode); + } + protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) { return Support.SupportTestRefactoring(rewritingManager, state, factory, selectionService); - //var indenter = CreateIndenter(); //The refactoring only uses method independent of the VBE instance. - //var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); - //return new EncapsulateFieldRefactoring(state, indenter, factory, rewritingManager, selectionService, selectedDeclarationProvider); } - - //private static IIndenter CreateIndenter(IVBE vbe = null) - //{ - // return new Indenter(vbe, () => Settings.IndenterSettingsTests.GetMockIndenterSettings()); - //} } } From ab2a2cbed47fd490cee63042d442f6a5e2491d1e Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Thu, 5 Dec 2019 06:33:17 -0800 Subject: [PATCH 042/461] Cleanup after merge conflict resolutions --- .../EncapsulateFieldRefactoring.cs | 5 ----- .../Refactoring/EncapsulateField/TestSupport.cs | 10 ++++++++-- .../Refactoring/EncapsulateFieldTests.cs | 16 ++-------------- 3 files changed, 10 insertions(+), 21 deletions(-) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 837088feca..b62547ffa3 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -29,14 +29,9 @@ public EncapsulateFieldRefactoring( IRefactoringPresenterFactory factory, IRewritingManager rewritingManager, ISelectionProvider selectionProvider, -<<<<<<< HEAD - ISelectedDeclarationProvider selectedDeclarationProvider) - : base(rewritingManager, selectionProvider, factory) -======= ISelectedDeclarationProvider selectedDeclarationProvider, IUiDispatcher uiDispatcher) :base(rewritingManager, selectionProvider, factory, uiDispatcher) ->>>>>>> rubberduck-vba/next { _declarationFinderProvider = declarationFinderProvider; _selectedDeclarationProvider = selectedDeclarationProvider; diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index 443eaf6b4b..1e3128adb5 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -1,4 +1,6 @@ -using Rubberduck.Parsing.Rewriter; +using Moq; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.UIContext; using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings; using Rubberduck.Refactorings.EncapsulateField; @@ -88,7 +90,11 @@ public IRefactoring SupportTestRefactoring(IRewritingManager rewritingManager, R { var indenter = CreateIndenter(); //The refactoring only uses method independent of the VBE instance. var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); - return new EncapsulateFieldRefactoring(state, indenter, factory, rewritingManager, selectionService, selectedDeclarationProvider); + var uiDispatcherMock = new Mock(); + uiDispatcherMock + .Setup(m => m.Invoke(It.IsAny())) + .Callback((Action action) => action.Invoke()); + return new EncapsulateFieldRefactoring(state, indenter, factory, rewritingManager, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); } private static IIndenter CreateIndenter(IVBE vbe = null) diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index fac5612299..fbdeea5b2e 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -765,19 +765,7 @@ End Sub StringAssert.Contains($" .MyProperty = bar", referencingClassCode); } - protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) - { -//<<<<<<< HEAD - return Support.SupportTestRefactoring(rewritingManager, state, factory, selectionService); -//======= -// var indenter = CreateIndenter(); //The refactoring only uses method independent of the VBE instance. -// var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); -// var uiDispatcherMock = new Mock(); -// uiDispatcherMock -// .Setup(m => m.Invoke(It.IsAny())) -// .Callback((Action action) => action.Invoke()); -// return new EncapsulateFieldRefactoring(state, indenter, factory, rewritingManager, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); -//>>>>>>> rubberduck-vba/next - } + protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) + => Support.SupportTestRefactoring(rewritingManager, state, factory, selectionService); } } From 17a1b079f7321cc2c576c159879440da9bdf8701 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Fri, 6 Dec 2019 12:10:49 -0800 Subject: [PATCH 043/461] Integrated simplified UDT encapsulation rules --- .../EncapsulateFieldViewModel.cs | 4 +- .../EncapsulateFieldDeclarationFactory.cs | 14 +- .../EncapsulateField/EncapsulateFieldModel.cs | 27 +- .../EncapsulateFieldRefactoring.cs | 2 +- .../EncapsulateFieldValidator.cs | 90 +--- .../EncapsulatedFieldDeclaration.cs | 123 ++++-- .../FieldEncapsulationAttributes.cs | 52 ++- .../RewriterRemoveWorkaround.cs | 2 +- .../EncapsulateWithBackingFields.cs | 44 +- .../EncapsulateWithBackingUserDefinedType.cs | 37 +- .../Strategies/EncapsulationStrategiesBase.cs | 212 +++++++--- .../EncapsulateFieldValidatorTests.cs | 2 +- .../EncapsulateUsingStateUDTTests.cs | 37 +- ...TField.cs => EncapsulatedUDTFieldTests.cs} | 393 +++++++++++++----- .../EncapsulateField/TestSupport.cs | 34 +- .../Refactoring/EncapsulateFieldTests.cs | 2 +- 16 files changed, 664 insertions(+), 411 deletions(-) rename RubberduckTests/Refactoring/EncapsulateField/{EncapsulatedUDTField.cs => EncapsulatedUDTFieldTests.cs} (63%) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs index 63430efe7e..ddbe290877 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs @@ -31,7 +31,7 @@ public ObservableCollection EncapsulationFields var flaggedFields = Model.FlaggedEncapsulationFields .OrderBy(efd => efd.Declaration.IdentifierName); - var orderedFields = Model.EncapsulationFields.Except(flaggedFields) + var orderedFields = Model.FieldCandidates.Except(flaggedFields) .OrderBy(efd => efd.Declaration.IdentifierName); var viewableFields = new ObservableCollection(); @@ -103,7 +103,7 @@ public string EncapsulateAsUDT_FieldName } public bool TargetsHaveValidEncapsulationSettings - => Model.EncapsulationFields.Where(efd => efd.EncapsulateFlag) + => Model.FieldCandidates.Where(efd => efd.EncapsulateFlag) .Any(ff => !ff.HasValidEncapsulationAttributes); public IEncapsulateFieldNamesValidator RefactoringValidator { set; get; } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs index 787154b488..0d298fd20b 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs @@ -21,17 +21,11 @@ public class EncapsulationCandidateFactory private readonly IEncapsulateFieldNamesValidator _validator; private List _encapsulatedFields = new List(); - //TODO: This needs to go away - private bool _useNewStructure; - public EncapsulationCandidateFactory(IDeclarationFinderProvider declarationFinderProvider, IEncapsulateFieldNamesValidator validator) { _declarationFinderProvider = declarationFinderProvider; _validator = validator; - - //TODO: This needs to go away - _useNewStructure = File.Exists("C:\\Users\\Brian\\Documents\\UseNewUDTStructure.txt"); } public IEncapsulateFieldCandidate CreateStateUDTField(QualifiedModuleName qmn, string identifier = DEFAULT_STATE_UDT_FIELD_IDENTIFIER, string asTypeName = DEFAULT_STATE_UDT_IDENTIFIER) @@ -57,13 +51,12 @@ public IEnumerable CreateEncapsulationCandidates(IEn { var encapsulatedUDTField = _encapsulatedFields.Where(ef => ef.Declaration == udtField).Single(); - var moduleHasMultipleInstancesOfUDT = candidateFields.Any(fld => fld != encapsulatedUDTField.Declaration && encapsulatedUDTField.AsTypeName.Equals(fld.AsTypeName)); var parent = encapsulatedUDTField as IEncapsulatedUserDefinedTypeField; parent.TypeDeclarationIsPrivate = udtFieldToUdtDeclarationMap[udtField].UserDefinedType.Accessibility.Equals(Accessibility.Private); foreach (var udtMember in udtFieldToUdtDeclarationMap[udtField].Item2) { - IEncapsulateFieldCandidate encapsulatedUDTMember = new EncapsulatedUserDefinedTypeMember(udtMember, encapsulatedUDTField, _validator, moduleHasMultipleInstancesOfUDT); + var encapsulatedUDTMember = new EncapsulatedUserDefinedTypeMember(udtMember, encapsulatedUDTField, _validator) as IEncapsulatedUserDefinedTypeMember; encapsulatedUDTMember = ApplyTypeSpecificAttributes(encapsulatedUDTMember); parent.Members.Add(encapsulatedUDTMember); encapsulatedUDTMember.PropertyAccessExpression = @@ -72,8 +65,7 @@ public IEnumerable CreateEncapsulationCandidates(IEn var prefix = encapsulatedUDTField.EncapsulateFlag ? encapsulatedUDTField.NewFieldName : encapsulatedUDTField.IdentifierName; - - return $"{prefix}.{encapsulatedUDTMember.NewFieldName}"; + return $"{prefix}.{encapsulatedUDTMember.IdentifierName}"; }; } } @@ -108,7 +100,7 @@ private IEncapsulateFieldCandidate EncapsulateDeclaration(Declaration target, IE return (udtVariable, userDefinedTypeDeclaration, udtMembers); } - private IEncapsulateFieldCandidate ApplyTypeSpecificAttributes(IEncapsulateFieldCandidate candidate) + private T ApplyTypeSpecificAttributes(T candidate) where T: IEncapsulateFieldCandidate { var target = candidate.Declaration; if (target.IsUserDefinedTypeField()) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index a30cec590d..64a2d1b46d 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -24,7 +24,7 @@ public class EncapsulateFieldModel : IRefactoringModel private IDictionary)> _udtFieldToUdtDeclarationMap = new Dictionary)>(); - public EncapsulateFieldModel(Declaration target, IDeclarationFinderProvider declarationFinderProvider, /*IEnumerable allMemberFields, IDictionary)> udtFieldToUdtDeclarationMap,*/ IIndenter indenter, IEncapsulateFieldNamesValidator validator, Func previewFunc) + public EncapsulateFieldModel(Declaration target, IDeclarationFinderProvider declarationFinderProvider, IIndenter indenter, IEncapsulateFieldNamesValidator validator, Func previewFunc) { _declarationFinderProvider = declarationFinderProvider; _indenter = indenter; @@ -43,10 +43,6 @@ public EncapsulateFieldModel(Declaration target, IDeclarationFinderProvider decl FieldCandidates.AddRange(candidates); - AllEncapsulationCandidates = Enumerable.Empty() - .Concat(FieldCandidates) - .Concat(UDTFieldCandidates.SelectMany(c => c.Members)).ToList(); - EncapsulationStrategy = new EncapsulateWithBackingFields(_targetQMN, _indenter, _validator); this[target].EncapsulateFlag = true; @@ -57,23 +53,26 @@ public EncapsulateFieldModel(Declaration target, IDeclarationFinderProvider decl public List FieldCandidates { set; get; } = new List(); public IEnumerable FlaggedFieldCandidates - => FieldCandidates.Where(v => v.EncapsulationAttributes.EncapsulateFlag); + => FieldCandidates.Where(v => v.EncapsulateFlag); - public IEnumerable UDTFieldCandidates => FieldCandidates.Where(v => v is IEncapsulatedUserDefinedTypeField).Cast(); + public IEnumerable UDTFieldCandidates + => FieldCandidates + .Where(v => v is IEncapsulatedUserDefinedTypeField) + .Cast(); - private List AllEncapsulationCandidates { get; } = new List(); + public IEnumerable FlaggedUDTFieldCandidates + => FlaggedFieldCandidates + .Where(v => v is IEncapsulatedUserDefinedTypeField) + .Cast(); public IEnumerable FlaggedEncapsulationFields - => AllEncapsulationCandidates.Where(v => v.EncapsulationAttributes.EncapsulateFlag); - - public IEnumerable EncapsulationFields - => AllEncapsulationCandidates; + => FlaggedFieldCandidates; public IEncapsulateFieldCandidate this[string encapsulatedFieldIdentifier] - => AllEncapsulationCandidates.Where(c => c.TargetID.Equals(encapsulatedFieldIdentifier)).Single(); + => FieldCandidates.Where(c => c.TargetID.Equals(encapsulatedFieldIdentifier)).Single(); public IEncapsulateFieldCandidate this[Declaration fieldDeclaration] - => AllEncapsulationCandidates.Where(c => c.Declaration == fieldDeclaration).Single(); + => FieldCandidates.Where(c => c.Declaration == fieldDeclaration).Single(); public IEncapsulateFieldStrategy EncapsulationStrategy { set; get; } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index b62547ffa3..894b5b4478 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -77,7 +77,7 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) } //Get rid of Model property after improving the validator ctor - private IEnumerable CandidateFields() => Model?.EncapsulationFields ?? Enumerable.Empty(); + private IEnumerable CandidateFields() => Model?.FieldCandidates ?? Enumerable.Empty(); protected override void RefactorImpl(EncapsulateFieldModel model) { diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs index e4a046ba3b..58c10f5823 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -13,68 +13,11 @@ namespace Rubberduck.Refactorings.EncapsulateField { - //public interface IDeclarationFacade - //{ - // DeclarationType DeclarationType { get; } - // string IdentifierName { get;} - // string AsTypeName { get; } - // Accessibility Accessibility { get; } - // QualifiedModuleName QualifiedModuleName { get; } - // IEnumerable References { get; } - //} - - //public struct WrappedDeclaration : IDeclarationFacade - //{ - // public WrappedDeclaration(Declaration declaration) - // { - // DeclarationType = declaration.DeclarationType; - // IdentifierName = declaration.IdentifierName; - // Accessibility = declaration.Accessibility; - // References = declaration.References; - // AsTypeName = declaration.AsTypeName; - // QualifiedModuleName = declaration.QualifiedModuleName; - // } - - // public DeclarationType DeclarationType { set; get; } - // public string IdentifierName { set; get; } - // public string AsTypeName { set; get; } - // public Accessibility Accessibility { set; get; } - // public QualifiedModuleName QualifiedModuleName { set; get; } - // public IEnumerable References { set; get; } - //} - - //public struct ProposedDeclaration : IDeclarationFacade - //{ - - // public ProposedDeclaration(IEncapsulatedFieldDeclaration efd, DeclarationType declarationType) - // { - // DeclarationType = declarationType; - // IdentifierName = efd.PropertyName; - // Accessibility = Accessibility.Public; - // References = efd.References; - // if (declarationType.Equals(DeclarationType.Variable)) - // { - // IdentifierName = efd.NewFieldName; - // Accessibility = Accessibility.Private; - // References = Enumerable.Empty(); - // } - // AsTypeName = efd.AsTypeName; - // QualifiedModuleName = efd.QualifiedModuleName; - // } - - // public DeclarationType DeclarationType { set; get; } - // public string IdentifierName { set; get; } - // public string AsTypeName { set; get; } - // public Accessibility Accessibility { set; get; } - // public QualifiedModuleName QualifiedModuleName { set; get; } - // public IEnumerable References { set; get; } - //} - public interface IEncapsulateFieldNamesValidator { - bool HasValidEncapsulationAttributes(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, IEnumerable ignore, DeclarationType declarationType); - void ForceNonConflictEncapsulationAttributes(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, Declaration target); - void ForceNonConflictPropertyName(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, Declaration target); + bool HasValidEncapsulationAttributes(IEncapsulateFieldCandidate attributes, QualifiedModuleName qmn, IEnumerable ignore, DeclarationType declarationType); + void ForceNonConflictEncapsulationAttributes(IEncapsulateFieldCandidate attributes, QualifiedModuleName qmn, Declaration target); + void ForceNonConflictPropertyName(IEncapsulateFieldCandidate attributes, QualifiedModuleName qmn, Declaration target); } public class EncapsulateFieldNamesValidator : IEncapsulateFieldNamesValidator @@ -89,43 +32,46 @@ public EncapsulateFieldNamesValidator(IDeclarationFinderProvider declarationFind private DeclarationFinder DeclarationFinder => _declarationFinderProvider.DeclarationFinder; - public void ForceNonConflictEncapsulationAttributes(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, Declaration target) + public void ForceNonConflictEncapsulationAttributes(IEncapsulateFieldCandidate candidate, QualifiedModuleName qmn, Declaration target) { if (target?.DeclarationType.HasFlag(DeclarationType.UserDefinedTypeMember) ?? false) { - ForceNonConflictPropertyName(attributes, qmn, target); + ForceNonConflictPropertyName(candidate, qmn, target); return; } - ForceNonConflictNewName(attributes, qmn, target); + ForceNonConflictNewName(candidate, qmn, target); } - public void ForceNonConflictNewName(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, Declaration target) + public void ForceNonConflictNewName(IEncapsulateFieldCandidate candidate, QualifiedModuleName qmn, Declaration target) { - var identifier = attributes.NewFieldName; + var attributes = candidate.EncapsulationAttributes; + var identifier = candidate.NewFieldName; var ignore = target is null ? Enumerable.Empty() : new Declaration[] { target }; - var isValidAttributeSet = HasValidEncapsulationAttributes(attributes, qmn, ignore); + var isValidAttributeSet = HasValidEncapsulationAttributes(candidate, qmn, ignore); for (var idx = 1; idx < 9 && !isValidAttributeSet; idx++) { attributes.NewFieldName = $"{identifier}{idx}"; - isValidAttributeSet = HasValidEncapsulationAttributes(attributes, qmn, ignore); + isValidAttributeSet = HasValidEncapsulationAttributes(candidate, qmn, ignore); } } - public void ForceNonConflictPropertyName(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, Declaration target) + public void ForceNonConflictPropertyName(IEncapsulateFieldCandidate candidate, QualifiedModuleName qmn, Declaration target) { + var attributes = candidate.EncapsulationAttributes; var identifier = attributes.PropertyName; var ignore = target is null ? Enumerable.Empty() : new Declaration[] { target }; - var isValidAttributeSet = HasValidEncapsulationAttributes(attributes, qmn, ignore); + var isValidAttributeSet = HasValidEncapsulationAttributes(candidate, qmn, ignore); for (var idx = 1; idx < 9 && !isValidAttributeSet; idx++) { attributes.PropertyName = $"{identifier}{idx}"; - isValidAttributeSet = HasValidEncapsulationAttributes(attributes, qmn, ignore); + isValidAttributeSet = HasValidEncapsulationAttributes(candidate, qmn, ignore); } } - public bool HasValidEncapsulationAttributes(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, IEnumerable ignore, DeclarationType declaration = DeclarationType.Variable) + public bool HasValidEncapsulationAttributes(IEncapsulateFieldCandidate candidate, QualifiedModuleName qmn, IEnumerable ignore, DeclarationType declaration = DeclarationType.Variable) { + var attributes = candidate.EncapsulationAttributes; var hasValidIdentifiers = HasValidIdentifiers(attributes, declaration); var hasInternalNameConflicts = HasInternalNameConflicts(attributes); @@ -134,7 +80,7 @@ public bool HasValidEncapsulationAttributes(IFieldEncapsulationAttributes attrib if (!isSelfConsistent) { return false; } - if (!attributes.FieldNameIsExemptFromValidation) + if (!candidate.FieldNameIsExemptFromValidation) { if (HasNewFieldNameConflicts(attributes, qmn, ignore) > 0) { return false; } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs index c6a3d3bdb0..0f96d3ea46 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs @@ -10,36 +10,35 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface IEncapsulateFieldCandidate + public interface IEncapsulateFieldCandidate : IFieldEncapsulationAttributes { Declaration Declaration { get; } - //DeclarationType DeclarationType { get; } string TargetID { get; } - string IdentifierName { get; } + //string IdentifierName { get; } IFieldEncapsulationAttributes EncapsulationAttributes { get; } - bool IsReadOnly { set; get; } - bool CanBeReadWrite { get; } - string PropertyName { set; get; } - bool EncapsulateFlag { set; get; } - string NewFieldName { get; } - string AsTypeName { get; } - string ParameterName { get; } + //bool IsReadOnly { set; get; } + //bool CanBeReadWrite { get; } + //string PropertyName { set; get; } + //bool EncapsulateFlag { set; get; } + //string NewFieldName { get; } + //string AsTypeName { get; } + //string ParameterName { get; } bool IsUDTMember { get; } bool HasValidEncapsulationAttributes { get; } - QualifiedModuleName QualifiedModuleName { get; } + //QualifiedModuleName QualifiedModuleName { get; } IEnumerable References { get; } - bool ImplementLetSetterType { get; } - bool ImplementSetSetterType { get; } - Func PropertyAccessExpression { set; get; } - Func ReferenceExpression { set; get; } + //bool ImplementLetSetterType { get; } + //bool ImplementSetSetterType { get; } + //Func PropertyAccessExpression { set; get; } + //Func ReferenceExpression { set; get; } string this[IdentifierReference idRef] { set; get; } bool TryGetReferenceExpression(IdentifierReference idRef, out string expression); + bool FieldNameIsExemptFromValidation { get; } } public interface IEncapsulatedUserDefinedTypeField : IEncapsulateFieldCandidate { - IList Members { set; get; } - IEnumerable SelectedMembers { get; } + IList Members { set; get; } bool TypeDeclarationIsPrivate { set; get; } } @@ -53,9 +52,10 @@ public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate public EncapsulateFieldCandidate(Declaration declaration, IEncapsulateFieldNamesValidator validator) { _target = declaration; + AsTypeName = _target.AsTypeName; _attributes = new FieldEncapsulationAttributes(_target); _validator = validator; - _validator.ForceNonConflictEncapsulationAttributes(_attributes, _target.QualifiedModuleName, _target); + _validator.ForceNonConflictEncapsulationAttributes(this, _target.QualifiedModuleName, _target); } public EncapsulateFieldCandidate(IFieldEncapsulationAttributes attributes, IEncapsulateFieldNamesValidator validator) @@ -63,20 +63,18 @@ public EncapsulateFieldCandidate(IFieldEncapsulationAttributes attributes, IEnca _target = null; _attributes = new FieldEncapsulationAttributes(attributes); _validator = validator; - _validator.ForceNonConflictEncapsulationAttributes(_attributes, _attributes.QualifiedModuleName, _target); + _validator.ForceNonConflictEncapsulationAttributes(this, _attributes.QualifiedModuleName, _target); } public Declaration Declaration => _target; - //public DeclarationType DeclarationType => _target?.DeclarationType ?? DeclarationType.Variable; - public bool HasValidEncapsulationAttributes { get { var ignore = _target != null ? new Declaration[] { _target } : Enumerable.Empty(); var declarationType = _target != null ? _target.DeclarationType : DeclarationType.Variable; - return _validator.HasValidEncapsulationAttributes(EncapsulationAttributes, QualifiedModuleName, ignore, declarationType); //(Declaration dec) => dec.Equals(_target)); + return _validator.HasValidEncapsulationAttributes(this, QualifiedModuleName, ignore, declarationType); //(Declaration dec) => dec.Equals(_target)); } } @@ -110,10 +108,10 @@ public string this[IdentifierReference idRef] public IFieldEncapsulationAttributes EncapsulationAttributes { private set => _attributes = value; - get => _attributes; + get => this as IFieldEncapsulationAttributes; // _attributes; } - public virtual string TargetID => _target?.IdentifierName ?? _attributes.Identifier; + public virtual string TargetID => _target?.IdentifierName ?? _attributes.IdentifierName; public bool EncapsulateFlag { @@ -144,9 +142,29 @@ public string PropertyName public string NewFieldName { get => _attributes.NewFieldName; + set => _attributes.NewFieldName = value; } - public string AsTypeName => _target?.AsTypeName ?? _attributes.AsTypeName; + private string _asTypeName; + public string AsTypeName + { + set + { + _asTypeName = value; + if (_attributes != null) { _attributes.AsTypeName = value; } + } + get + { + return _attributes?.AsTypeName ?? _asTypeName; + } + } //=> _target?.AsTypeName ?? _attributes.AsTypeName; + //{ + // get => /*_target?.AsTypeName ??*/ _attributes.AsTypeName; + // set => _attributes.AsTypeName = value; + // //{ + // // if (_target is null) { _attributes.AsTypeName = value; } + // //} + //} public bool IsUDTMember => _target?.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember) ?? false; @@ -154,7 +172,10 @@ public string NewFieldName public IEnumerable References => Declaration?.References ?? Enumerable.Empty(); - public string IdentifierName => Declaration?.IdentifierName ?? _attributes.Identifier; + public string IdentifierName + { + get => Declaration?.IdentifierName ?? _attributes.IdentifierName; + } public string ParameterName => _attributes.ParameterName; @@ -163,15 +184,27 @@ public string NewFieldName public Func PropertyAccessExpression { - set => _attributes.PropertyAccessExpression = value; + //set => _attributes.PropertyAccessExpression = value; get => _attributes.PropertyAccessExpression; + set + { + _attributes.PropertyAccessExpression = value; + var test = value(); + } } public Func ReferenceExpression { - set => _attributes.ReferenceExpression = value; get => _attributes.ReferenceExpression; + set + { + _attributes.ReferenceExpression = value; + var test = value(); + } } + + public bool FieldNameIsExemptFromValidation + => Declaration?.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember) ?? false || NewFieldName.EqualsVBAIdentifier(IdentifierName); } public class EncapsulatedUserDefinedTypeField : EncapsulateFieldCandidate, IEncapsulatedUserDefinedTypeField @@ -182,28 +215,42 @@ public EncapsulatedUserDefinedTypeField(Declaration declaration, IEncapsulateFie PropertyAccessExpression = () => EncapsulateFlag ? NewFieldName : IdentifierName; } - public IList Members { set; get; } = new List(); - public IEnumerable SelectedMembers => Members.Where(m => m.EncapsulateFlag); + public IList Members { set; get; } = new List(); public bool TypeDeclarationIsPrivate { set; get; } } - public class EncapsulatedUserDefinedTypeMember : EncapsulateFieldCandidate + public interface IEncapsulatedUserDefinedTypeMember : IEncapsulateFieldCandidate + { + IEncapsulateFieldCandidate Parent { get; } + bool FieldQualifyProperty { set; get; } + } + + public class EncapsulatedUserDefinedTypeMember : EncapsulateFieldCandidate, IEncapsulatedUserDefinedTypeMember { - public EncapsulatedUserDefinedTypeMember(Declaration target, IEncapsulateFieldCandidate udtVariable, IEncapsulateFieldNamesValidator validator, bool propertyNameRequiresParentIdentifier) + public EncapsulatedUserDefinedTypeMember(Declaration target, IEncapsulateFieldCandidate udtVariable, IEncapsulateFieldNamesValidator validator) : base(target, validator) { Parent = udtVariable; - FieldNameQualifyProperty = propertyNameRequiresParentIdentifier; - EncapsulationAttributes.PropertyName = FieldNameQualifyProperty - ? $"{Parent.IdentifierName.Capitalize()}_{IdentifierName}" - : IdentifierName; + PropertyName = IdentifierName; + PropertyAccessExpression = () => $"{Parent.PropertyAccessExpression()}.{PropertyName}"; + ReferenceExpression = () => $"{Parent.PropertyAccessExpression()}.{PropertyName}"; } public IEncapsulateFieldCandidate Parent { private set; get; } - public bool FieldNameQualifyProperty { set; get; } - + private bool _fieldNameQualifyProperty; + public bool FieldQualifyProperty + { + get => _fieldNameQualifyProperty; + set + { + _fieldNameQualifyProperty = value; + PropertyName = _fieldNameQualifyProperty + ? $"{Parent.IdentifierName.Capitalize()}_{IdentifierName}" + : IdentifierName; + } + } public override string TargetID => $"{Parent.IdentifierName}.{IdentifierName}"; } } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs index bd05fadff1..a3142ea198 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs @@ -7,7 +7,7 @@ namespace Rubberduck.Refactorings.EncapsulateField { public interface IFieldEncapsulationAttributes { - string Identifier { get; } + string IdentifierName { get; } string PropertyName { get; set; } bool IsReadOnly { get; set; } bool EncapsulateFlag { get; set; } @@ -17,7 +17,7 @@ public interface IFieldEncapsulationAttributes string ParameterName { get;} bool ImplementLetSetterType { get; set; } bool ImplementSetSetterType { get; set; } - bool FieldNameIsExemptFromValidation { get; } + //bool FieldNameIsExemptFromValidation { get; } QualifiedModuleName QualifiedModuleName { get; } Func PropertyAccessExpression { set; get; } Func ReferenceExpression { set; get; } @@ -36,7 +36,7 @@ public NeverEncapsulateAttributes(string identifier, string asTypeName, Qualifie { _qmn = qmn; _validator = validator; - Identifier = identifier; + IdentifierName = identifier; NewFieldName = identifier; AsTypeName = asTypeName; PropertyAccessExpression = () => NewFieldName; @@ -49,12 +49,12 @@ public IFieldEncapsulationAttributes ApplyNewFieldName(string newFieldName) return this; } - public string Identifier { private set; get; } + public string IdentifierName { private set; get; } public string NewFieldName { set; get; } string _tossString; - public string PropertyName { set => _tossString = value; get => $"{neverUse}{Identifier}_{neverUse}"; } + public string PropertyName { set => _tossString = value; get => $"{neverUse}{IdentifierName}_{neverUse}"; } public Func PropertyAccessExpression { set; get; } @@ -72,7 +72,7 @@ public IFieldEncapsulationAttributes ApplyNewFieldName(string newFieldName) public bool ImplementLetSetterType { get => false; set => _toss = value; } public bool ImplementSetSetterType { get => false; set => _toss = value; } - public bool FieldNameIsExemptFromValidation => false; + //public bool FieldNameIsExemptFromValidation => false; public QualifiedModuleName QualifiedModuleName => _qmn; } @@ -83,24 +83,26 @@ public class FieldEncapsulationAttributes : IFieldEncapsulationAttributes public FieldEncapsulationAttributes(Declaration target) { _fieldAndProperty = new EncapsulationIdentifiers(target); - Identifier = target.IdentifierName; + IdentifierName = target.IdentifierName; AsTypeName = target.AsTypeName; _qmn = target.QualifiedModuleName; PropertyAccessExpression = () => NewFieldName; - ReferenceExpression = () => NewFieldName; + //ReferenceExpression = () => NewFieldName; + ReferenceExpression = () => PropertyName; _fieldNameIsAlwaysValid = target.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember); } - public FieldEncapsulationAttributes(string identifier, string asTypeName) - { - _fieldAndProperty = new EncapsulationIdentifiers(identifier); - AsTypeName = asTypeName; - PropertyAccessExpression = () => NewFieldName; - } + //public FieldEncapsulationAttributes(string identifier, string asTypeName) + //{ + // _fieldAndProperty = new EncapsulationIdentifiers(identifier); + // AsTypeName = asTypeName; + // PropertyAccessExpression = () => NewFieldName; + // ReferenceExpression = () => PropertyName; + //} public FieldEncapsulationAttributes(IFieldEncapsulationAttributes attributes) { - _fieldAndProperty = new EncapsulationIdentifiers(attributes.Identifier, attributes.NewFieldName, attributes.PropertyName); + _fieldAndProperty = new EncapsulationIdentifiers(attributes.IdentifierName, attributes.NewFieldName, attributes.PropertyName); PropertyName = attributes.PropertyName; IsReadOnly = attributes.IsReadOnly; EncapsulateFlag = attributes.EncapsulateFlag; @@ -111,11 +113,12 @@ public FieldEncapsulationAttributes(IFieldEncapsulationAttributes attributes) ImplementSetSetterType = attributes.ImplementSetSetterType; QualifiedModuleName = attributes.QualifiedModuleName; PropertyAccessExpression = () => NewFieldName; + ReferenceExpression = () => PropertyName; } private EncapsulationIdentifiers _fieldAndProperty; - public string Identifier { private set; get; } + public string IdentifierName { private set; get; } public bool CanBeReadWrite { set; get; } = true; @@ -131,7 +134,20 @@ public string PropertyName set => _fieldAndProperty.Property = value; } - public Func PropertyAccessExpression { set; get; } + private Func _propertyAccessExpression; + public Func PropertyAccessExpression + { + get + { + var test = _propertyAccessExpression(); + return _propertyAccessExpression; + } + set + { + _propertyAccessExpression = value; + var test = value(); + } + } public Func ReferenceExpression { set; get; } @@ -146,7 +162,7 @@ public string PropertyName private bool _implSet; public bool ImplementSetSetterType { get => !IsReadOnly && _implSet; set => _implSet = value; } - public bool FieldNameIsExemptFromValidation => _fieldNameIsAlwaysValid || NewFieldName.EqualsVBAIdentifier(Identifier); + public bool FieldNameIsExemptFromValidation => _fieldNameIsAlwaysValid || NewFieldName.EqualsVBAIdentifier(IdentifierName); public QualifiedModuleName QualifiedModuleName { get => _qmn; diff --git a/Rubberduck.Refactorings/EncapsulateField/RewriterRemoveWorkaround.cs b/Rubberduck.Refactorings/EncapsulateField/RewriterRemoveWorkaround.cs index e5e4b7e8df..75254055a9 100644 --- a/Rubberduck.Refactorings/EncapsulateField/RewriterRemoveWorkaround.cs +++ b/Rubberduck.Refactorings/EncapsulateField/RewriterRemoveWorkaround.cs @@ -31,7 +31,7 @@ public static void Remove(Declaration target, IEncapsulateFieldRewriter rewriter RemovedVariables[varList].Add(target); } - public static void RemoveDeclarationsFromVariableLists(IEncapsulateFieldRewriter rewriter) + public static void RemoveFieldsDeclaredInLists(IEncapsulateFieldRewriter rewriter) { foreach (var key in RemovedVariables.Keys) { diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs index a4075e748e..f5974e511f 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs @@ -19,55 +19,31 @@ public EncapsulateWithBackingFields(QualifiedModuleName qmn, IIndenter indenter, { } - protected override void ModifyEncapsulatedVariable(IEncapsulateFieldCandidate target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession) + protected override void ModifyEncapsulatedField(IEncapsulateFieldCandidate field, IRewriteSession rewriteSession) { + var attributes = field.EncapsulationAttributes; var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); - if (target.Declaration.Accessibility == Accessibility.Private && attributes.NewFieldName.Equals(target.Declaration.IdentifierName)) + if (field.Declaration.Accessibility == Accessibility.Private && attributes.NewFieldName.Equals(field.Declaration.IdentifierName)) { - rewriter.MakeImplicitDeclarationTypeExplicit(target.Declaration); + rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); return; } - if (target.Declaration.IsDeclaredInList()) + if (field.Declaration.IsDeclaredInList()) { - RewriterRemoveWorkAround.Remove(target.Declaration, rewriter); + RewriterRemoveWorkAround.Remove(field.Declaration, rewriter); //rewriter.Remove(target.Declaration); } else { - rewriter.Rename(target.Declaration, attributes.NewFieldName); - rewriter.SetVariableVisiblity(target.Declaration, Accessibility.Private.TokenString()); - rewriter.MakeImplicitDeclarationTypeExplicit(target.Declaration); + rewriter.Rename(field.Declaration, attributes.NewFieldName); + rewriter.SetVariableVisiblity(field.Declaration, Accessibility.Private.TokenString()); + rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); } return; } - protected override IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) - { - foreach (var field in model.UDTFieldCandidates) - { - if (!field.TypeDeclarationIsPrivate) - { - field.ReferenceExpression = () => field.PropertyName; - } - else - { - foreach (var member in field.Members) - { - member.PropertyAccessExpression = () => $"{field.PropertyAccessExpression()}.{member.IdentifierName}"; - } - } - } - - foreach (var field in model.FieldCandidates.Except(model.UDTFieldCandidates).Where(fld => fld.EncapsulateFlag)) - { - field.ReferenceExpression = () => field.PropertyName; - } - - return base.RefactorRewrite(model, rewriteSession, asPreview); - } - protected override EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNewContent newContent, IEnumerable encapsulationCandates) { var nonUdtMemberFields = encapsulationCandates @@ -84,7 +60,7 @@ protected override EncapsulateFieldNewContent LoadNewDeclarationsContent(Encapsu if (nonUdtMemberField.Declaration.IsDeclaredInList()) { - var targetIdentifier = nonUdtMemberField.Declaration.Context.GetText().Replace(attributes.Identifier, attributes.NewFieldName); + var targetIdentifier = nonUdtMemberField.Declaration.Context.GetText().Replace(attributes.IdentifierName, attributes.NewFieldName); var newField = nonUdtMemberField.Declaration.IsTypeSpecified ? $"{Tokens.Private} {targetIdentifier}" : $"{Tokens.Private} {targetIdentifier} {Tokens.As} {nonUdtMemberField.Declaration.AsTypeName}"; newContent.AddDeclarationBlock(newField); diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs index 08a28b12f5..15b7002bcc 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs @@ -23,30 +23,23 @@ public EncapsulateWithBackingUserDefinedType(QualifiedModuleName qmn, IIndenter protected override IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) { - var stateUDTField_UDTMembers = model.UDTFieldCandidates - .Where(c => c.EncapsulateFlag || c.SelectedMembers.Any()); - foreach (var field in model.FieldCandidates) { if (field is IEncapsulatedUserDefinedTypeField udt) { udt.PropertyAccessExpression = - () => { - var accessor = udt.EncapsulateFlag || stateUDTField_UDTMembers.Contains(udt) ? udt.PropertyName : udt.NewFieldName; - return $"{StateUDTField.PropertyAccessExpression()}.{accessor}"; - }; + () => + { + var accessor = udt.EncapsulateFlag ? udt.PropertyName : udt.NewFieldName; + return $"{StateUDTField.PropertyAccessExpression()}.{accessor}"; + }; udt.ReferenceExpression = udt.PropertyAccessExpression; foreach (var member in udt.Members) { member.PropertyAccessExpression = () => $"{udt.PropertyAccessExpression()}.{member.PropertyName}"; - member.ReferenceExpression = () => - { - return member.EncapsulateFlag - ? member.PropertyName - : $"{udt.PropertyAccessExpression()}.{member.PropertyName}"; - }; + member.ReferenceExpression = () => $"{udt.PropertyAccessExpression()}.{member.PropertyName}"; } } else @@ -57,15 +50,15 @@ protected override IExecutableRewriteSession RefactorRewrite(EncapsulateFieldMod } } - SetupReferenceModifications(model); - - var fieldsToModify = model.EncapsulationFields - .Where(encFld => !encFld.IsUDTMember && encFld.EncapsulateFlag).Union(stateUDTField_UDTMembers); - - foreach (var field in fieldsToModify) + foreach (var field in model.FlaggedFieldCandidates) { var attributes = field.EncapsulationAttributes; - ModifyEncapsulatedVariable(field, attributes, rewriteSession); + ModifyEncapsulatedField(field, /*attributes,*/ rewriteSession); + } + + SetupReferenceModifications(model); + foreach (var field in model.FlaggedFieldCandidates) + { RenameReferences(field, rewriteSession); if (field is IEncapsulatedUserDefinedTypeField udtField) { @@ -77,7 +70,7 @@ protected override IExecutableRewriteSession RefactorRewrite(EncapsulateFieldMod } var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); - RewriterRemoveWorkAround.RemoveDeclarationsFromVariableLists(rewriter); + RewriterRemoveWorkAround.RemoveFieldsDeclaredInLists(rewriter); InsertNewContent(model.CodeSectionStartIndex, model, rewriteSession, asPreview); @@ -86,7 +79,7 @@ protected override IExecutableRewriteSession RefactorRewrite(EncapsulateFieldMod public IEncapsulateFieldCandidate StateUDTField { set; get; } - protected override void ModifyEncapsulatedVariable(IEncapsulateFieldCandidate target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession) + protected override void ModifyEncapsulatedField(IEncapsulateFieldCandidate target, /*IFieldEncapsulationAttributes attributes,*/ IRewriteSession rewriteSession) { var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs index 45dcf30bea..ff6db9f977 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs @@ -1,4 +1,5 @@ -using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing; +using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; @@ -44,121 +45,202 @@ public IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IE return RefactorRewrite(model, rewriteSession, false); } - protected abstract void ModifyEncapsulatedVariable(IEncapsulateFieldCandidate target, IFieldEncapsulationAttributes attributes, IRewriteSession rewriteSession); + protected abstract void ModifyEncapsulatedField(IEncapsulateFieldCandidate target, /*IFieldEncapsulationAttributes attributes, */IRewriteSession rewriteSession); protected abstract EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNewContent newContent, IEnumerable encapsulationCandidates); protected virtual IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) { - SetupReferenceModifications(model); + var udtFieldsByTypeName = model.FlaggedUDTFieldCandidates.GroupBy((udtCandidate) => udtCandidate.AsTypeName); + foreach (var udtField in model.FlaggedUDTFieldCandidates) + { + var hasMultipleUDTFieldsOfSameType = udtFieldsByTypeName + .Where(group => group.Key == udtField.AsTypeName).Single().Count() > 1; - var nonUdtMemberFields = model.FlaggedEncapsulationFields - .Where(encFld => !encFld.IsUDTMember); + foreach (var member in udtField.Members) + { + member.FieldQualifyProperty = hasMultipleUDTFieldsOfSameType; + } + } - foreach (var nonUdtMemberField in nonUdtMemberFields) + foreach (var field in model.FlaggedEncapsulationFields) { - var attributes = nonUdtMemberField.EncapsulationAttributes; - ModifyEncapsulatedVariable(nonUdtMemberField, attributes, rewriteSession); - RenameReferences(nonUdtMemberField, rewriteSession); + ModifyEncapsulatedField(field, rewriteSession); } + ModifyReferences(model, rewriteSession); + var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); - RewriterRemoveWorkAround.RemoveDeclarationsFromVariableLists(rewriter); + RewriterRemoveWorkAround.RemoveFieldsDeclaredInLists(rewriter); InsertNewContent(model.CodeSectionStartIndex, model, rewriteSession, asPreview); return rewriteSession; } - protected void SetupReferenceModifications(EncapsulateFieldModel model) + private void ModifyReferences(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) { - foreach (var field in model.FieldCandidates.Except(model.UDTFieldCandidates)) - { - foreach (var rf in field.References) - { - LoadFieldReferenceData(field, rf); - } - } - - foreach( var udtField in model.UDTFieldCandidates) + SetupReferenceModifications(model); + foreach (var field in model.FlaggedEncapsulationFields) { - if (!udtField.TypeDeclarationIsPrivate) - { - foreach (var rf in udtField.References) - { - LoadUDTFieldReferenceData(udtField, rf); - } - } - else + RenameReferences(field, rewriteSession); + if (field is IEncapsulatedUserDefinedTypeField udtField) { foreach (var member in udtField.Members) { - foreach (var rf in member.References) - { - if (rf.QualifiedModuleName == udtField.QualifiedModuleName || udtField.QualifiedModuleName.ComponentType == ComponentType.ClassModule) - { - member[rf] = udtField.EncapsulateFlag - ? $"{member.PropertyName}" - : $"{member.ReferenceExpression()}"; - } - else - { - member[rf] = udtField.EncapsulateFlag - ? $"{udtField.QualifiedModuleName.ComponentName}.{member.PropertyName}" - : $"{member.ReferenceExpression()}"; - } - } + RenameReferences(member, rewriteSession); } } } } - private void LoadFieldReferenceData(IEncapsulateFieldCandidate field, IdentifierReference idRef) + protected void SetupReferenceModifications(EncapsulateFieldModel model) + { + var flaggedPrivateUDTFields = model.FlaggedUDTFieldCandidates.Where(udt => udt.TypeDeclarationIsPrivate).ToList(); + + foreach (var field in model.FlaggedFieldCandidates.Except(flaggedPrivateUDTFields)) + { + LoadFieldReferenceExpressions(field); + } + + foreach( var udtField in flaggedPrivateUDTFields) + { + LoadPrivateUDTFieldReferenceExpressions(udtField); + LoadUDTMemberReferenceExpressions(udtField); + } + } + + private void LoadFieldReferenceExpressions(IEncapsulateFieldCandidate field) { - if (idRef.QualifiedModuleName == field.QualifiedModuleName || field.QualifiedModuleName.ComponentType == ComponentType.ClassModule) + foreach (var idRef in field.References) { - field[idRef] = field.ReferenceExpression(); + //if (idRef.QualifiedModuleName == field.QualifiedModuleName + // && idRef.Context.Parent is VBAParser.WithStmtContext wsc) + //{ + // field[idRef] = field.NewFieldName; + // continue; + //} + + field[idRef] = RequiresAccessQualification(idRef) + ? $"{field.QualifiedModuleName.ComponentName}.{field.ReferenceExpression()}" + : field.ReferenceExpression(); } - else + } + + private void LoadPrivateUDTFieldReferenceExpressions(IEncapsulateFieldCandidate field) + { + foreach (var idRef in field.References) { - if (idRef.Context.Parent is VBAParser.MemberAccessExprContext maec - || idRef.Context.Parent is VBAParser.WithMemberAccessExprContext wmaec) - { - field[idRef] = field.ReferenceExpression(); - } - else + if (idRef.QualifiedModuleName == field.QualifiedModuleName + && idRef.Context.Parent.Parent is VBAParser.WithStmtContext wsc) { - field[idRef] = $"{field.QualifiedModuleName.ComponentName}.{field.ReferenceExpression()}"; + field[idRef] = field.NewFieldName; } } } - private void LoadUDTFieldReferenceData(IEncapsulateFieldCandidate field, IdentifierReference idRef) + private void LoadUDTMemberReferenceExpressions(IEncapsulatedUserDefinedTypeField udtField) { - if (idRef.QualifiedModuleName == field.QualifiedModuleName || field.QualifiedModuleName.ComponentType == ComponentType.ClassModule) + foreach (var member in udtField.Members) { - field[idRef] = field.ReferenceExpression(); + var references = GetUDTMemberReferencesForField(member, udtField); + foreach (var rf in references) + { + var test = member.ReferenceExpression(); + if (rf.QualifiedModuleName == udtField.QualifiedModuleName) + { + //If rf is a WithMemberAccess expression, modify the LExpr. e.g. "With this" => "With this1" + if (rf.Context.TryGetAncestor(out var wmac)) + { + var wm = wmac.GetAncestor(); + var Lexpr = wm.GetChild(); + continue; + } + member[rf] = $"{member.PropertyName}"; + } + else + { + //If rf is a WithMemberAccess expression, modify the LExpr. e.g. "With this" => "With " + var moduleQualifier = rf.Context.TryGetAncestor(out _) + || rf.QualifiedModuleName == udtField.QualifiedModuleName + ? string.Empty + : $"{udtField.QualifiedModuleName.ComponentName}"; + + member[rf] = $"{moduleQualifier}.{member.PropertyName}"; + } + test = member[rf]; + } } - else + } + + private IEnumerable GetUDTMemberReferencesForField(IEncapsulateFieldCandidate udtMember, IEncapsulatedUserDefinedTypeField field) + { + //var fieldMAECs = field.References.Where(rf => rf.Context.Parent is VBAParser.MemberAccessExprContext).Select(r => r.Context.Parent); + //var refMAECs = field.Members.SelectMany(m => m.References).Where(rf => rf.Context.Parent is VBAParser.MemberAccessExprContext).Select(r => r.Context.Parent); + //var matches = refMAECs.Intersect(fieldMAECs); + var refs = new List(); + foreach (var idRef in udtMember.References) { - if ((idRef.Context.Parent is VBAParser.MemberAccessExprContext maec - || idRef.Context.Parent is VBAParser.WithMemberAccessExprContext wmaec) - && !(idRef.Context is VBAParser.SimpleNameExprContext)) + if (idRef.Context.TryGetAncestor(out var mac)) { - field[idRef] = field.ReferenceExpression(); + //var match = field.References.Select(rf => rf.Context.Parent).Contains(mac); + var LHS = mac.children.First(); + //if (LHS.GetText().Equals(field.IdentifierName)) + //{ + // refs.Add(idRef); + //} + + switch(LHS) + { + case VBAParser.SimpleNameExprContext snec: + if (snec.GetText().Equals(field.IdentifierName)) + { + refs.Add(idRef); + } + break; + case VBAParser.MemberAccessExprContext submac: + if (submac.children.Last() is VBAParser.UnrestrictedIdentifierContext ur && ur.GetText().Equals(field.IdentifierName)) + { + refs.Add(idRef); + } + break; + case VBAParser.WithMemberAccessExprContext wmac: + if (wmac.children.Last().GetText().Equals(field.IdentifierName)) + { + refs.Add(idRef); + } + break; + } } - else + else if (idRef.Context.TryGetAncestor(out var wmac)) { - field[idRef] = $"{field.QualifiedModuleName.ComponentName}.{field.ReferenceExpression()}"; + var wm = wmac.GetAncestor(); + var Lexpr = wm.GetChild(); + if (Lexpr.GetText().Equals(field.IdentifierName)) + { + refs.Add(idRef); + } } } + return refs; + } + + private bool RequiresAccessQualification(IdentifierReference idRef) + { + var isLHSOfMemberAccess = + (idRef.Context.Parent is VBAParser.MemberAccessExprContext + || idRef.Context.Parent is VBAParser.WithMemberAccessExprContext) + && !(idRef.Context == idRef.Context.Parent.GetChild(0));// is VBAParser.SimpleNameExprContext)) + + return idRef.QualifiedModuleName != idRef.Declaration.QualifiedModuleName + && !isLHSOfMemberAccess; } protected void InsertNewContent(int? codeSectionStartIndex, EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool postPendPreviewMessage = false) { var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); - var newContent = LoadNewDeclarationsContent(new EncapsulateFieldNewContent(), model.EncapsulationFields); + var newContent = LoadNewDeclarationsContent(new EncapsulateFieldNewContent(), model.FieldCandidates); if (postPendPreviewMessage) { diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs index dece54e3f3..7850f04b0c 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs @@ -181,7 +181,7 @@ private IFieldEncapsulationAttributes CreateAttributesMock(string targetID, stri { var identifiers = new EncapsulationIdentifiers(targetID); var mock = new Mock(); - mock.SetupGet(m => m.Identifier).Returns(identifiers.TargetFieldName); + mock.SetupGet(m => m.IdentifierName).Returns(identifiers.TargetFieldName); mock.SetupGet(m => m.NewFieldName).Returns(identifiers.Field); mock.SetupGet(m => m.PropertyName).Returns(modifiedPropertyName ?? identifiers.Property); mock.SetupGet(m => m.AsTypeName).Returns(asTypeName); diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs index 6356a05703..b913356498 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs @@ -57,10 +57,9 @@ End Type Private my|Bar As TBar"; - var userInput = new UserInputDataObject("myBar"); - userInput["myBar"].EncapsulateFlag = false; - userInput.AddUDTMemberNameFlagPairs(("myBar", "First", true)); - userInput.AddUDTMemberNameFlagPairs(("myBar", "Second", true)); + var userInput = new UserInputDataObject() + .AddAttributeSet("myBar"); + userInput.EncapsulateAsUDT = true; var presenterAction = Support.SetParameters(userInput); @@ -71,14 +70,13 @@ End Type StringAssert.Contains("this.MyBar.Second = value", actualCode); StringAssert.Contains($"Second = this.MyBar.Second", actualCode); StringAssert.Contains($"MyBar As TBar", actualCode); - StringAssert.DoesNotContain($"myBar As TBar", actualCode); + StringAssert.Contains($"MyBar As TBar", actualCode); } - [TestCase(false, "this.MyBar.First = newValue")] - [TestCase(true, " First = newValue")] + [Test] [Category("Refactorings")] [Category("Encapsulate Field")] - public void UserDefinedTypeMembers_UDTFieldReferences(bool encapsulateFirst, string expected) + public void UserDefinedTypeMembers_UDTFieldReferences() { string inputCode = $@" @@ -94,16 +92,15 @@ Public Sub Foo(newValue As String) End Sub"; - var userInput = new UserInputDataObject("myBar"); - userInput["myBar"].EncapsulateFlag = false; - userInput.AddUDTMemberNameFlagPairs(("myBar", "First", encapsulateFirst)); - userInput.AddUDTMemberNameFlagPairs(("myBar", "Second", true)); + var userInput = new UserInputDataObject() + .AddAttributeSet("myBar"); + userInput.EncapsulateAsUDT = true; var presenterAction = Support.SetParameters(userInput); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - StringAssert.Contains(expected, actualCode); + StringAssert.Contains(" First = newValue", actualCode); } [Test] @@ -118,9 +115,11 @@ Public bar As String Public foobar As Byte "; - var userInput = new UserInputDataObject("foo", encapsulationFlag: true); - userInput.AddAttributeSet("bar", encapsulationFlag: true); - userInput.AddAttributeSet("foobar", encapsulationFlag: true); + var userInput = new UserInputDataObject() + .AddAttributeSet("foo") + .AddAttributeSet("bar") + .AddAttributeSet("foobar"); + userInput.EncapsulateAsUDT = true; var presenterAction = Support.SetParameters(userInput); @@ -149,9 +148,9 @@ Public fo|o As Long Public myBar As TBar "; - var userInput = new UserInputDataObject("foo", encapsulationFlag: true); - userInput.AddAttributeSet("myBar", encapsulationFlag: true); - //userInput.AddUDTMemberNameFlagPairs(("myBar", "First", true), ("myBar", "Second", true)); + var userInput = new UserInputDataObject() + .AddAttributeSet("myBar"); + userInput.EncapsulateAsUDT = true; var presenterAction = Support.SetParameters(userInput); diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTField.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs similarity index 63% rename from RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTField.cs rename to RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs index bd1dd6f9f0..743d757ebb 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTField.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs @@ -12,7 +12,7 @@ namespace RubberduckTests.Refactoring.EncapsulateField { [TestFixture] - public class EncapsulatedUDTField : InteractiveRefactoringTestBase + public class EncapsulatedUDTFieldTests : InteractiveRefactoringTestBase { private EncapsulateFieldTestSupport Support { get; } = new EncapsulateFieldTestSupport(); @@ -45,14 +45,14 @@ End Type StringAssert.Contains($"Second = this1.Second", actualCode); } - - [TestCase("Public")] - [TestCase("Private")] + [TestCase(true, true)] + [TestCase(false, false)] + [TestCase(true, false)] + [TestCase(false, true)] [Category("Refactorings")] [Category("Encapsulate Field")] - public void UserDefinedType_UserAcceptsDefaults_TwoUDTInstances(string accessibility) + public void UserDefinedType_TwoFields(bool encapsulateThis, bool encapsulateThat) { - string selectionModule = "ClassInput"; string inputCode = $@" Private Type TBar @@ -60,70 +60,18 @@ First As String Second As Long End Type -{accessibility} th|is As TBar - -Private that As TBar"; - - string otherModule = "OtherModule"; - string moduleCode = -$@" -Private Type TBar - First As String - Second As Long -End Type - -{accessibility} this As TBar +Public th|is As TBar +Public that As TBar"; -Private that As TBar"; - - - var presenterAdjustment = Support.UserAcceptsDefaults(); - var codeString = inputCode.ToCodeString(); - var actualCode = RefactoredCode(selectionModule, codeString.CaretPosition.ToOneBased(), presenterAdjustment, null, false, (selectionModule, codeString.Code, ComponentType.ClassModule), (otherModule, moduleCode, ComponentType.StandardModule)); - StringAssert.Contains("Private this1 As TBar", actualCode[selectionModule]); - StringAssert.DoesNotContain("this1 = value", actualCode[selectionModule]); - StringAssert.DoesNotContain($"This = this1", actualCode[selectionModule]); - StringAssert.DoesNotContain($"Public Property Get This(", actualCode[selectionModule]); - StringAssert.Contains($"Public Property Get This_First", actualCode[selectionModule]); - StringAssert.Contains($"Public Property Get This_Second", actualCode[selectionModule]); - StringAssert.Contains($"this1.First = value", actualCode[selectionModule]); - StringAssert.Contains($"This_First = this1.First", actualCode[selectionModule]); - StringAssert.Contains($"this1.Second = value", actualCode[selectionModule]); - StringAssert.Contains($"This_Second = this1.Second", actualCode[selectionModule]); - } - - - [TestCase("Public", true, true)] - [TestCase("Private", true, true)] - [TestCase("Public", false, false)] - [TestCase("Private", false, false)] - [TestCase("Public", true, false)] - [TestCase("Private", true, false)] - [TestCase("Public", false, true)] - [TestCase("Private", false, true)] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void UserDefinedType_TwoInstanceVariables(string accessibility, bool encapsulateThis, bool encapsulateThat) - { - string inputCode = -$@" -Private Type TBar - First As String - Second As Long -End Type - -{accessibility} th|is As TBar -{accessibility} that As TBar"; - - var userInput = new UserInputDataObject("this", "MyType", encapsulateThis); - userInput.AddAttributeSet("that", "MyOtherType", encapsulateThat); + var userInput = new UserInputDataObject("this", "MyType", encapsulateThis) + .AddAttributeSet("that", "MyOtherType", encapsulateThat); var expectedThis = new EncapsulationIdentifiers("this") { Property = "MyType" }; var expectedThat = new EncapsulationIdentifiers("that") { Property = "MyOtherType" }; var presenterAction = Support.SetParameters(userInput); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - if (encapsulateThis) + if (encapsulateThis && encapsulateThat) { StringAssert.Contains($"Private {expectedThis.Field} As TBar", actualCode); StringAssert.Contains($"This_First = {expectedThis.Field}.First", actualCode); @@ -132,14 +80,7 @@ End Type StringAssert.Contains($"{expectedThis.Field}.Second = value", actualCode); StringAssert.Contains($"Property Get This_First", actualCode); StringAssert.Contains($"Property Get This_Second", actualCode); - } - else - { - StringAssert.Contains($"{accessibility} this As TBar", actualCode); - } - if (encapsulateThat) - { StringAssert.Contains($"Private {expectedThat.Field} As TBar", actualCode); StringAssert.Contains($"That_First = {expectedThat.Field}.First", actualCode); StringAssert.Contains($"That_Second = {expectedThat.Field}.Second", actualCode); @@ -148,16 +89,41 @@ End Type StringAssert.Contains($"Property Get That_First", actualCode); StringAssert.Contains($"Property Get That_Second", actualCode); } + else if (encapsulateThis && !encapsulateThat) + { + StringAssert.Contains($"Private {expectedThis.Field} As TBar", actualCode); + StringAssert.Contains($"First = {expectedThis.Field}.First", actualCode); + StringAssert.Contains($"Second = {expectedThis.Field}.Second", actualCode); + StringAssert.Contains($"{expectedThis.Field}.First = value", actualCode); + StringAssert.Contains($"{expectedThis.Field}.Second = value", actualCode); + StringAssert.Contains($"Property Get First", actualCode); + StringAssert.Contains($"Property Get Second", actualCode); + + StringAssert.Contains($"Public that As TBar", actualCode); + } + else if (!encapsulateThis && encapsulateThat) + { + StringAssert.Contains($"Private {expectedThat.Field} As TBar", actualCode); + StringAssert.Contains($"First = {expectedThat.Field}.First", actualCode); + StringAssert.Contains($"Second = {expectedThat.Field}.Second", actualCode); + StringAssert.Contains($"{expectedThat.Field}.First = value", actualCode); + StringAssert.Contains($"{expectedThat.Field}.Second = value", actualCode); + StringAssert.Contains($"Property Get First", actualCode); + StringAssert.Contains($"Property Get Second", actualCode); + + StringAssert.Contains($"Public this As TBar", actualCode); + } else { - StringAssert.Contains($"{accessibility} that As TBar", actualCode); + StringAssert.Contains($"Public this As TBar", actualCode); + StringAssert.Contains($"Public that As TBar", actualCode); } } [Test] [Category("Refactorings")] [Category("Encapsulate Field")] - public void UserDefinedTypeMembers_OnlyEncapsulateUDTMembers() + public void ModifiesCorrectUDTMemberReference_MemberAccess() { string inputCode = $@" @@ -166,18 +132,133 @@ First As String Second As Long End Type -Private th|is As TBar"; +Private th|is As TBar +Private that As TBar - var userInput = new UserInputDataObject("this"); +Public Sub Foo(arg1 As String, arg2 As Long) + this.First = arg1 + that.First = arg1 + this.Second = arg2 + that.Second = arg2 +End Sub +"; - var presenterAction = Support.SetParameters(userInput); + + //var userInput = new UserInputDataObject("this"); + var presenterAction = Support.UserAcceptsDefaults(); + + //var presenterAction = Support.SetParameters(userInput); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.Contains("this1.First = value", actualCode); StringAssert.Contains($"First = this1.First", actualCode); StringAssert.Contains("this1.Second = value", actualCode); StringAssert.Contains($"Second = this1.Second", actualCode); + StringAssert.Contains($"First = arg1", actualCode); + StringAssert.Contains($"Second = arg2", actualCode); + StringAssert.Contains($"that.First = arg1", actualCode); + StringAssert.Contains($"that.Second = arg2", actualCode); + } + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void ModifiesCorrectUDTMemberReference_WithMemberAccess() + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +Private th|is As TBar + +Private that As TBar + +Public Sub Foo(arg1 As String, arg2 As Long) + With this + .First = arg1 + .Second = arg2 + End With + + With that + .First = arg1 + .Second = arg2 + End With +End Sub +"; + //var userInput = new UserInputDataObject("this"); + var presenterAction = Support.UserAcceptsDefaults(); + + //var presenterAction = Support.SetParameters(userInput); + + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.DoesNotContain($" First = arg1", actualCode); + StringAssert.DoesNotContain($" Second = arg2", actualCode); + StringAssert.Contains($" .First = arg1", actualCode); + StringAssert.Contains($" .Second = arg2", actualCode); + StringAssert.Contains("With this1", actualCode); + } + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void ModifiesCorrectUDTMemberReference_WithMemberAccessExternal() + { + string sourceModuleName = "SourceModule"; + string inputCode = +$@" +Public Type TBar + First As String + Second As Long +End Type + +Public th|is As TBar + +Private that As TBar +"; + string module2 = +$@" +Public Sub Foo(arg1 As String, arg2 As Long) + With {sourceModuleName}.this + .First = arg1 + .Second = arg2 + End With + + With that + .First = arg1 + .Second = arg2 + End With +End Sub +"; + + //var userInput = new UserInputDataObject("this"); + + //var presenterAction = Support.SetParameters(userInput); + var presenterAction = Support.UserAcceptsDefaults(); + + var codeString = inputCode.ToCodeString(); + + var actualModuleCode = RefactoredCode( + sourceModuleName, + codeString.CaretPosition.ToOneBased(), + presenterAction, + null, + false, + ("Module2", module2, ComponentType.StandardModule), + (sourceModuleName, codeString.Code, ComponentType.StandardModule)); + + var actualCode = actualModuleCode["Module2"]; + var sourceCode = actualModuleCode[sourceModuleName]; + + //var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.DoesNotContain($" First = arg1", actualCode); + StringAssert.DoesNotContain($" Second = arg2", actualCode); + StringAssert.Contains($" .First = arg1", actualCode); + StringAssert.Contains($" .Second = arg2", actualCode); + StringAssert.Contains($"With {sourceModuleName}.This", actualCode); } [TestCase("Public")] @@ -436,34 +517,136 @@ End Sub StringAssert.Contains($"Public Property Set {defaults.Property}", actualCode); } - [TestCase(false)] - [TestCase(true)] + [TestCase("SourceModule", "this", "Public")] + [TestCase("SourceModule", "SourceModule.this", "Private")] [Category("Refactorings")] [Category("Encapsulate Field")] - public void StandardModuleSource_UDTFieldSelection_ExternalReferences(bool moduleQualifyReference) + public void StdModuleSource_UDTField_StdModuleReferences(string sourceModuleName, string referenceQualifier, string typeDeclarationAccessibility) { + //var sourceModuleName = "SourceModule"; + + //var actualModuleCode = Scenario_StdModuleSource_StandardAndClassReferencingModules(referenceQualifier, typeDeclarationAccessibility, sourceModuleName, userInput); + + var sourceModuleCode = +$@" +{typeDeclarationAccessibility} Type TBar + First As String + Second As Long +End Type + +Public th|is As TBar"; + + var moduleReferencingCode = +$@"Option Explicit + +'StdModule referencing the UDT + +Private Const fooConst As String = ""Foo"" + +Private Const barConst As Long = 7 + +Public Sub Foo() + {referenceQualifier}.First = fooConst +End Sub + +Public Sub Bar() + {referenceQualifier}.Second = barConst +End Sub + +Public Sub FooBar() + With {sourceModuleName} + .this.First = fooConst + .this.Second = barConst + End With +End Sub +"; + + // string classModuleReferencingCode = + //$@"Option Explicit + + //'ClassModule referencing the UDT + + //Private Const foo As String = ""Foo"" + + //Private Const bar As Long = 7 + + //Public Sub Foo() + // {referenceQualifier}.First = foo + //End Sub + + //Public Sub Bar() + // {referenceQualifier}.Second = bar + //End Sub + + //Public Sub FooBar() + // With {sourceModuleName} + // .this.First = foo + // .this.Second = bar + // End With + //End Sub + //"; + var userInput = new UserInputDataObject("this", "MyType"); - var sourceModuleName = "SourceModule"; + var presenterAction = Support.SetParameters(userInput); - var actualModuleCode = StdModuleSource_TwoReferencingModulesScenario(moduleQualifyReference, sourceModuleName, userInput); + var sourceCodeString = sourceModuleCode.ToCodeString(); - var referencingModuleCode = actualModuleCode["StdModule"]; - StringAssert.Contains($"{sourceModuleName}.MyType.First = ", referencingModuleCode); - StringAssert.Contains($"{sourceModuleName}.MyType.Second = ", referencingModuleCode); - StringAssert.Contains($" .MyType.Second = ", referencingModuleCode); + var actualModuleCode = RefactoredCode( + sourceModuleName, + sourceCodeString.CaretPosition.ToOneBased(), + presenterAction, + null, + false, + ("StdModule", moduleReferencingCode, ComponentType.StandardModule), + (sourceModuleName, sourceCodeString.Code, ComponentType.StandardModule)); - var referencingClassCode = actualModuleCode["ClassModule"]; - StringAssert.Contains($"{sourceModuleName}.MyType.First = ", referencingClassCode); - StringAssert.Contains($"{sourceModuleName}.MyType.Second = ", referencingClassCode); - StringAssert.Contains($" .MyType.Second = ", referencingClassCode); + //Only Public Types are accessible to ClassModules + //if (typeDeclarationAccessibility.Equals("Public")) + //{ + // actualModuleCode = RefactoredCode( + // sourceModuleName, + // sourceCodeString.CaretPosition.ToOneBased(), + // presenterAction, + // null, + // false, + // ("StdModule", procedureModuleReferencingCode, ComponentType.StandardModule), + // ("ClassModule", classModuleReferencingCode, ComponentType.ClassModule), + // (sourceModuleName, sourceCodeString.Code, ComponentType.StandardModule)); + //} + + //return actualModuleCode; + + + + if (typeDeclarationAccessibility.Equals("Public")) + { + var referencingModuleCode = actualModuleCode["StdModule"]; + StringAssert.Contains($"{sourceModuleName}.MyType.First = ", referencingModuleCode); + StringAssert.Contains($"{sourceModuleName}.MyType.Second = ", referencingModuleCode); + StringAssert.Contains($" .MyType.Second = ", referencingModuleCode); + + //var referencingClassCode = actualModuleCode["ClassModule"]; + //StringAssert.Contains($"{sourceModuleName}.MyType.First = ", referencingClassCode); + //StringAssert.Contains($"{sourceModuleName}.MyType.Second = ", referencingClassCode); + //StringAssert.Contains($" .MyType.Second = ", referencingClassCode); + } + + if (typeDeclarationAccessibility.Equals("Private")) + { + var referencingModuleCode = actualModuleCode["StdModule"]; + StringAssert.Contains($"{sourceModuleName}.First = ", referencingModuleCode); + StringAssert.Contains($"{sourceModuleName}.Second = ", referencingModuleCode); + StringAssert.Contains($" .First = ", referencingModuleCode); + StringAssert.Contains($" .Second = ", referencingModuleCode); + } } - private IDictionary StdModuleSource_TwoReferencingModulesScenario(bool moduleResolve, string sourceModuleName, UserInputDataObject userInput) + private IDictionary Scenario_StdModuleSource_StandardAndClassReferencingModules(string referenceQualifier, string typeDeclarationAccessibility, string sourceModuleName, UserInputDataObject userInput) { - var referenceExpression = moduleResolve ? $"{sourceModuleName}.this" : "this"; + //var referenceQualifier = moduleQualifyReferences ? $"{sourceModuleName}.this" : "this"; var sourceModuleCode = $@" -Public Type TBar +{typeDeclarationAccessibility} Type TBar First As String Second As Long End Type @@ -473,16 +656,18 @@ End Type var procedureModuleReferencingCode = $@"Option Explicit +'StdModule referencing the UDT + Private Const foo As String = ""Foo"" Private Const bar As Long = 7 Public Sub Foo() - {referenceExpression}.First = foo + {referenceQualifier}.First = foo End Sub Public Sub Bar() - {referenceExpression}.Second = bar + {referenceQualifier}.Second = bar End Sub Public Sub FooBar() @@ -496,16 +681,18 @@ End Sub string classModuleReferencingCode = $@"Option Explicit +'ClassModule referencing the UDT + Private Const foo As String = ""Foo"" Private Const bar As Long = 7 Public Sub Foo() - {referenceExpression}.First = foo + {referenceQualifier}.First = foo End Sub Public Sub Bar() - {referenceExpression}.Second = bar + {referenceQualifier}.Second = bar End Sub Public Sub FooBar() @@ -519,6 +706,20 @@ End Sub var presenterAction = Support.SetParameters(userInput); var sourceCodeString = sourceModuleCode.ToCodeString(); + + //Only Public Types are accessible to ClassModules + if (typeDeclarationAccessibility.Equals("Public")) + { + return RefactoredCode( + sourceModuleName, + sourceCodeString.CaretPosition.ToOneBased(), + presenterAction, + null, + false, + ("StdModule", procedureModuleReferencingCode, ComponentType.StandardModule), + ("ClassModule", classModuleReferencingCode, ComponentType.ClassModule), + (sourceModuleName, sourceCodeString.Code, ComponentType.StandardModule)); + } var actualModuleCode = RefactoredCode( sourceModuleName, sourceCodeString.CaretPosition.ToOneBased(), @@ -526,7 +727,7 @@ End Sub null, false, ("StdModule", procedureModuleReferencingCode, ComponentType.StandardModule), - ("ClassModule", classModuleReferencingCode, ComponentType.ClassModule), + //("ClassModule", classModuleReferencingCode, ComponentType.ClassModule), (sourceModuleName, sourceCodeString.Code, ComponentType.StandardModule)); return actualModuleCode; diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index 1e3128adb5..078382bf7d 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -44,27 +44,23 @@ public Func SetParametersForSingle return SetParameters(field, clientAttrs, asUDT); } - public Func SetParameters(UserInputDataObject userModifications) + public Func SetParameters(UserInputDataObject userInput) { return model => { - model.EncapsulateWithUDT = userModifications.EncapsulateAsUDT; - foreach (var testModifiedAttribute in userModifications.EncapsulateFieldAttributes) + model.EncapsulateWithUDT = userInput.EncapsulateAsUDT; + foreach (var testModifiedAttribute in userInput.EncapsulateFieldAttributes) { - var attrsInitializedByTheRefactoring = model[testModifiedAttribute.TargetFieldName].EncapsulationAttributes; + var attrsInitializedByTheRefactoring = model[testModifiedAttribute.TargetFieldName]; //.EncapsulationAttributes; attrsInitializedByTheRefactoring.PropertyName = testModifiedAttribute.PropertyName; attrsInitializedByTheRefactoring.EncapsulateFlag = testModifiedAttribute.EncapsulateFlag; - var currentAttributes = model[testModifiedAttribute.TargetFieldName].EncapsulationAttributes; - currentAttributes.PropertyName = attrsInitializedByTheRefactoring.PropertyName; - currentAttributes.EncapsulateFlag = attrsInitializedByTheRefactoring.EncapsulateFlag; + //var currentAttributes = model[testModifiedAttribute.TargetFieldName].EncapsulationAttributes; + //currentAttributes.PropertyName = attrsInitializedByTheRefactoring.PropertyName; + //currentAttributes.EncapsulateFlag = attrsInitializedByTheRefactoring.EncapsulateFlag; } - foreach ((string instanceVariable, string memberName, bool flag) in userModifications.UDTMemberNameFlagPairs) - { - model[$"{instanceVariable}.{memberName}"].EncapsulateFlag = flag; - } return model; }; } @@ -139,15 +135,21 @@ public class UserInputDataObject private List _userInput = new List(); private List<(string, string, bool)> _udtNameFlagPairs = new List<(string, string, bool)>(); + public UserInputDataObject() { } + public UserInputDataObject(string fieldName, string propertyName = null, bool encapsulationFlag = true, bool isReadOnly = false) - => AddAttributeSet(fieldName, propertyName, encapsulationFlag, isReadOnly); + : this() + { + AddAttributeSet(fieldName, propertyName, encapsulationFlag, isReadOnly); + } - public void AddAttributeSet(string fieldName, string propertyName = null, bool encapsulationFlag = true, bool isReadOnly = false) + public UserInputDataObject AddAttributeSet(string fieldName, string propertyName = null, bool encapsulationFlag = true, bool isReadOnly = false) { var attrs = new TestEncapsulationAttributes(fieldName, encapsulationFlag, isReadOnly); attrs.PropertyName = propertyName ?? attrs.PropertyName; _userInput.Add(attrs); + return this; } public bool EncapsulateAsUDT { set; get; } @@ -158,9 +160,9 @@ public TestEncapsulationAttributes this[string fieldName] public IEnumerable EncapsulateFieldAttributes => _userInput; - public void AddUDTMemberNameFlagPairs(params (string, string, bool)[] nameFlagPairs) - => _udtNameFlagPairs.AddRange(nameFlagPairs); + //public void AddUDTMemberNameFlagPairs(params (string, string, bool)[] nameFlagPairs) + // => _udtNameFlagPairs.AddRange(nameFlagPairs); - public IEnumerable<(string, string, bool)> UDTMemberNameFlagPairs => _udtNameFlagPairs; + //public IEnumerable<(string, string, bool)> UDTMemberNameFlagPairs => _udtNameFlagPairs; } } diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index fbdeea5b2e..910c4f1160 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -371,7 +371,7 @@ End Property fields.Add(efd); efd.PropertyName = "Name"; - var hasConflict = !validator.HasValidEncapsulationAttributes(efd.EncapsulationAttributes, efd.QualifiedModuleName, new Declaration[] { efd.Declaration }); //(Declaration dec) => match.Equals(dec)); + var hasConflict = !validator.HasValidEncapsulationAttributes(efd, efd.QualifiedModuleName, new Declaration[] { efd.Declaration }); Assert.IsTrue(hasConflict); } } From 5f23764de32345974a7a57cbcf5ee12d1a86a0e5 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Fri, 6 Dec 2019 14:16:24 -0800 Subject: [PATCH 044/461] Removed FieldEncapsulation class and interface --- .../EncapsulateFieldViewModel.cs | 4 +- .../EncapsulateFieldDeclarationFactory.cs | 30 +- .../EncapsulateFieldValidator.cs | 28 +- .../EncapsulatedFieldDeclaration.cs | 156 +++----- .../EncapsulationIdentifiers.cs | 43 ++- .../FieldEncapsulationAttributes.cs | 337 +++++++++--------- .../EncapsulateField/PropertyGenerator.cs | 10 + .../EncapsulateWithBackingFields.cs | 10 +- .../EncapsulateWithBackingUserDefinedType.cs | 14 +- .../Strategies/EncapsulationStrategiesBase.cs | 33 +- .../EncapsulateFieldValidatorTests.cs | 18 +- .../EncapsulatedFieldTests.cs | 4 +- .../EncapsulateField/TestSupport.cs | 6 +- 13 files changed, 340 insertions(+), 353 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs index ddbe290877..4645c6c126 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs @@ -76,7 +76,7 @@ public string EncapsulateAsUDT_TypeIdentifier { if (Model.EncapsulationStrategy is IEncapsulateWithBackingUserDefinedType udtStrategy) { - udtStrategy.StateUDTField.EncapsulationAttributes.AsTypeName = value; + udtStrategy.StateUDTField.AsTypeName = value; } UpdatePreview(); } @@ -96,7 +96,7 @@ public string EncapsulateAsUDT_FieldName { if (Model.EncapsulationStrategy is IEncapsulateWithBackingUserDefinedType udtStrategy) { - udtStrategy.StateUDTField.EncapsulationAttributes.NewFieldName = value; + udtStrategy.StateUDTField.NewFieldName = value; } UpdatePreview(); } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs index 0d298fd20b..c4c6c90ca3 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs @@ -30,8 +30,8 @@ public EncapsulationCandidateFactory(IDeclarationFinderProvider declarationFinde public IEncapsulateFieldCandidate CreateStateUDTField(QualifiedModuleName qmn, string identifier = DEFAULT_STATE_UDT_FIELD_IDENTIFIER, string asTypeName = DEFAULT_STATE_UDT_IDENTIFIER) { - var unselectableAttributes = new NeverEncapsulateAttributes(identifier, asTypeName, qmn, _validator); - return new EncapsulateFieldCandidate(unselectableAttributes, _validator); + //var unselectableAttributes = new NeverEncapsulateAttributes(identifier, asTypeName, qmn, _validator); + return new EncapsulateFieldCandidate(identifier, asTypeName, qmn, _validator, true); } public IEnumerable CreateEncapsulationCandidates(IEnumerable candidateFields) @@ -105,31 +105,31 @@ private T ApplyTypeSpecificAttributes(T candidate) where T: IEncapsulateField var target = candidate.Declaration; if (target.IsUserDefinedTypeField()) { - candidate.EncapsulationAttributes.ImplementLetSetterType = true; - candidate.EncapsulationAttributes.ImplementSetSetterType = false; + candidate.ImplementLetSetterType = true; + candidate.ImplementSetSetterType = false; } else if (target.IsArray) { - candidate.EncapsulationAttributes.ImplementLetSetterType = false; - candidate.EncapsulationAttributes.ImplementSetSetterType = false; - candidate.EncapsulationAttributes.AsTypeName = Tokens.Variant; - candidate.EncapsulationAttributes.CanBeReadWrite = false; - candidate.EncapsulationAttributes.IsReadOnly = true; + candidate.ImplementLetSetterType = false; + candidate.ImplementSetSetterType = false; + candidate.AsTypeName = Tokens.Variant; + candidate.CanBeReadWrite = false; + candidate.IsReadOnly = true; } else if (target.AsTypeName.Equals(Tokens.Variant)) { - candidate.EncapsulationAttributes.ImplementLetSetterType = true; - candidate.EncapsulationAttributes.ImplementSetSetterType = true; + candidate.ImplementLetSetterType = true; + candidate.ImplementSetSetterType = true; } else if (target.IsObject) { - candidate.EncapsulationAttributes.ImplementLetSetterType = false; - candidate.EncapsulationAttributes.ImplementSetSetterType = true; + candidate.ImplementLetSetterType = false; + candidate.ImplementSetSetterType = true; } else { - candidate.EncapsulationAttributes.ImplementLetSetterType = true; - candidate.EncapsulationAttributes.ImplementSetSetterType = false; + candidate.ImplementLetSetterType = true; + candidate.ImplementSetSetterType = false; } return candidate; } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs index 58c10f5823..1159187823 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -44,36 +44,36 @@ public void ForceNonConflictEncapsulationAttributes(IEncapsulateFieldCandidate c public void ForceNonConflictNewName(IEncapsulateFieldCandidate candidate, QualifiedModuleName qmn, Declaration target) { - var attributes = candidate.EncapsulationAttributes; + //var attributes = candidate.EncapsulationAttributes; var identifier = candidate.NewFieldName; var ignore = target is null ? Enumerable.Empty() : new Declaration[] { target }; var isValidAttributeSet = HasValidEncapsulationAttributes(candidate, qmn, ignore); for (var idx = 1; idx < 9 && !isValidAttributeSet; idx++) { - attributes.NewFieldName = $"{identifier}{idx}"; + candidate.NewFieldName = $"{identifier}{idx}"; isValidAttributeSet = HasValidEncapsulationAttributes(candidate, qmn, ignore); } } public void ForceNonConflictPropertyName(IEncapsulateFieldCandidate candidate, QualifiedModuleName qmn, Declaration target) { - var attributes = candidate.EncapsulationAttributes; - var identifier = attributes.PropertyName; + //var attributes = candidate.EncapsulationAttributes; + var identifier = candidate.PropertyName; var ignore = target is null ? Enumerable.Empty() : new Declaration[] { target }; var isValidAttributeSet = HasValidEncapsulationAttributes(candidate, qmn, ignore); for (var idx = 1; idx < 9 && !isValidAttributeSet; idx++) { - attributes.PropertyName = $"{identifier}{idx}"; + candidate.PropertyName = $"{identifier}{idx}"; isValidAttributeSet = HasValidEncapsulationAttributes(candidate, qmn, ignore); } } public bool HasValidEncapsulationAttributes(IEncapsulateFieldCandidate candidate, QualifiedModuleName qmn, IEnumerable ignore, DeclarationType declaration = DeclarationType.Variable) { - var attributes = candidate.EncapsulationAttributes; - var hasValidIdentifiers = HasValidIdentifiers(attributes, declaration); - var hasInternalNameConflicts = HasInternalNameConflicts(attributes); + //var attributes = candidate.EncapsulationAttributes; + var hasValidIdentifiers = HasValidIdentifiers(candidate, declaration); + var hasInternalNameConflicts = HasInternalNameConflicts(candidate); var isSelfConsistent = hasValidIdentifiers || hasInternalNameConflicts; @@ -82,15 +82,15 @@ public bool HasValidEncapsulationAttributes(IEncapsulateFieldCandidate candidate if (!candidate.FieldNameIsExemptFromValidation) { - if (HasNewFieldNameConflicts(attributes, qmn, ignore) > 0) { return false; } + if (HasNewFieldNameConflicts(candidate, qmn, ignore) > 0) { return false; } } - if (HasNewPropertyNameConflicts(attributes, qmn, ignore) > 0) { return false; } + if (HasNewPropertyNameConflicts(candidate, qmn, ignore) > 0) { return false; } return true; } - public int HasNewPropertyNameConflicts(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, IEnumerable declarationsToIgnore) + public int HasNewPropertyNameConflicts(IEncapsulateFieldCandidate attributes, QualifiedModuleName qmn, IEnumerable declarationsToIgnore) { Predicate IsPrivateAccessiblityInOtherModule = (Declaration dec) => dec.QualifiedModuleName != qmn && dec.Accessibility.Equals(Accessibility.Private); Predicate IsInSearchScope = null; @@ -127,7 +127,7 @@ public int HasNewPropertyNameConflicts(IFieldEncapsulationAttributes attributes, } //FieldNames are always Private, so only look within the same module as the field to encapsulate - public int HasNewFieldNameConflicts(IFieldEncapsulationAttributes attributes, QualifiedModuleName qmn, IEnumerable declarationsToIgnore) + public int HasNewFieldNameConflicts(IEncapsulateFieldCandidate attributes, QualifiedModuleName qmn, IEnumerable declarationsToIgnore) { var rawmatches = DeclarationFinder.MatchName(attributes.NewFieldName); var identifierMatches = DeclarationFinder.MatchName(attributes.NewFieldName) @@ -168,14 +168,14 @@ private bool UsesScopeResolution(Antlr4.Runtime.RuleContext ruleContext) || (ruleContext is VBAParser.MemberAccessExprContext); } - private bool HasValidIdentifiers(IFieldEncapsulationAttributes attributes, DeclarationType declarationType) + private bool HasValidIdentifiers(IEncapsulateFieldCandidate attributes, DeclarationType declarationType) { return VBAIdentifierValidator.IsValidIdentifier(attributes.NewFieldName, declarationType) && VBAIdentifierValidator.IsValidIdentifier(attributes.PropertyName, DeclarationType.Property) && VBAIdentifierValidator.IsValidIdentifier(attributes.ParameterName, DeclarationType.Parameter); } - private bool HasInternalNameConflicts(IFieldEncapsulationAttributes attributes) + private bool HasInternalNameConflicts(IEncapsulateFieldCandidate attributes) { return attributes.PropertyName.EqualsVBAIdentifier(attributes.NewFieldName) || attributes.PropertyName.EqualsVBAIdentifier(attributes.ParameterName) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs index 0f96d3ea46..ac11125e0f 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs @@ -10,60 +10,74 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface IEncapsulateFieldCandidate : IFieldEncapsulationAttributes + public interface IEncapsulateFieldCandidate { Declaration Declaration { get; } + string IdentifierName { get; } string TargetID { get; } - //string IdentifierName { get; } - IFieldEncapsulationAttributes EncapsulationAttributes { get; } - //bool IsReadOnly { set; get; } - //bool CanBeReadWrite { get; } - //string PropertyName { set; get; } - //bool EncapsulateFlag { set; get; } - //string NewFieldName { get; } - //string AsTypeName { get; } - //string ParameterName { get; } + bool IsReadOnly { get; set; } + bool EncapsulateFlag { get; set; } + string NewFieldName { set; get; } + bool CanBeReadWrite { set; get; } bool IsUDTMember { get; } bool HasValidEncapsulationAttributes { get; } - //QualifiedModuleName QualifiedModuleName { get; } + QualifiedModuleName QualifiedModuleName { get; } IEnumerable References { get; } - //bool ImplementLetSetterType { get; } - //bool ImplementSetSetterType { get; } - //Func PropertyAccessExpression { set; get; } - //Func ReferenceExpression { set; get; } string this[IdentifierReference idRef] { set; get; } bool TryGetReferenceExpression(IdentifierReference idRef, out string expression); bool FieldNameIsExemptFromValidation { get; } + Func ReferenceExpression { set; get; } + string PropertyName { get; set; } + string AsTypeName { get; set; } + string ParameterName { get; } + bool ImplementLetSetterType { get; set; } + bool ImplementSetSetterType { get; set; } + Func PropertyAccessExpression { set; get; } } - public interface IEncapsulatedUserDefinedTypeField : IEncapsulateFieldCandidate + public interface IEncapsulatedUserDefinedTypeField : IEncapsulateFieldCandidate, ISupportPropertyGenerator { IList Members { set; get; } bool TypeDeclarationIsPrivate { set; get; } } - public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate + public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate, ISupportPropertyGenerator { protected Declaration _target; - protected IFieldEncapsulationAttributes _attributes; + protected QualifiedModuleName _qmn; private IEncapsulateFieldNamesValidator _validator; private Dictionary _idRefRenames { set; get; } = new Dictionary(); + private EncapsulationIdentifiers _fieldAndProperty; public EncapsulateFieldCandidate(Declaration declaration, IEncapsulateFieldNamesValidator validator) { _target = declaration; AsTypeName = _target.AsTypeName; - _attributes = new FieldEncapsulationAttributes(_target); + + _fieldAndProperty = new EncapsulationIdentifiers(_target); + IdentifierName = _target.IdentifierName; + AsTypeName = _target.AsTypeName; + _qmn = _target.QualifiedModuleName; + PropertyAccessExpression = () => NewFieldName; + ReferenceExpression = () => PropertyName; + _validator = validator; _validator.ForceNonConflictEncapsulationAttributes(this, _target.QualifiedModuleName, _target); } - public EncapsulateFieldCandidate(IFieldEncapsulationAttributes attributes, IEncapsulateFieldNamesValidator validator) + public EncapsulateFieldCandidate(string identifier, string asTypeName, QualifiedModuleName qmn,/*IFieldEncapsulationAttributes attributes,*/ IEncapsulateFieldNamesValidator validator, bool neverEncapsulate = false) { _target = null; - _attributes = new FieldEncapsulationAttributes(attributes); + + _fieldAndProperty = new EncapsulationIdentifiers(identifier, neverEncapsulate); + IdentifierName = identifier; + AsTypeName = asTypeName; + _qmn = qmn; + PropertyAccessExpression = () => NewFieldName; + ReferenceExpression = () => PropertyName; + _validator = validator; - _validator.ForceNonConflictEncapsulationAttributes(this, _attributes.QualifiedModuleName, _target); + _validator.ForceNonConflictEncapsulationAttributes(this, qmn, _target); } public Declaration Declaration => _target; @@ -74,7 +88,7 @@ public bool HasValidEncapsulationAttributes { var ignore = _target != null ? new Declaration[] { _target } : Enumerable.Empty(); var declarationType = _target != null ? _target.DeclarationType : DeclarationType.Variable; - return _validator.HasValidEncapsulationAttributes(this, QualifiedModuleName, ignore, declarationType); //(Declaration dec) => dec.Equals(_target)); + return _validator.HasValidEncapsulationAttributes(this, QualifiedModuleName, ignore, declarationType); } } @@ -104,107 +118,55 @@ public string this[IdentifierReference idRef] } } + public virtual string TargetID => _target?.IdentifierName ?? IdentifierName; - public IFieldEncapsulationAttributes EncapsulationAttributes - { - private set => _attributes = value; - get => this as IFieldEncapsulationAttributes; // _attributes; - } - - public virtual string TargetID => _target?.IdentifierName ?? _attributes.IdentifierName; - - public bool EncapsulateFlag - { - get => _attributes.EncapsulateFlag; - set => _attributes.EncapsulateFlag = value; - } - - public bool IsReadOnly - { - get => _attributes.IsReadOnly; - set => _attributes.IsReadOnly = value; - } - - public bool CanBeReadWrite - { - get => _attributes.CanBeReadWrite; - set => _attributes.CanBeReadWrite = value; - } + public bool EncapsulateFlag { set; get; } + public bool IsReadOnly { set; get; } + public bool CanBeReadWrite { set; get; } public string PropertyName { - get => _attributes.PropertyName; - set => _attributes.PropertyName = value; + get => _fieldAndProperty.Property; + set => _fieldAndProperty.Property = value; } public bool IsEditableReadWriteFieldIdentifier { set; get; } = true; public string NewFieldName { - get => _attributes.NewFieldName; - set => _attributes.NewFieldName = value; + get => _fieldAndProperty.Field; + set => _fieldAndProperty.Field = value; } - private string _asTypeName; - public string AsTypeName - { - set - { - _asTypeName = value; - if (_attributes != null) { _attributes.AsTypeName = value; } - } - get - { - return _attributes?.AsTypeName ?? _asTypeName; - } - } //=> _target?.AsTypeName ?? _attributes.AsTypeName; - //{ - // get => /*_target?.AsTypeName ??*/ _attributes.AsTypeName; - // set => _attributes.AsTypeName = value; - // //{ - // // if (_target is null) { _attributes.AsTypeName = value; } - // //} - //} + public string AsTypeName { set; get; } public bool IsUDTMember => _target?.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember) ?? false; - public QualifiedModuleName QualifiedModuleName => Declaration?.QualifiedModuleName ?? _attributes.QualifiedModuleName; + public QualifiedModuleName QualifiedModuleName => _qmn; public IEnumerable References => Declaration?.References ?? Enumerable.Empty(); + private string _identifierName; public string IdentifierName { - get => Declaration?.IdentifierName ?? _attributes.IdentifierName; + get => Declaration?.IdentifierName ?? _identifierName; + set => _identifierName = value; } - public string ParameterName => _attributes.ParameterName; + public string ParameterName => _fieldAndProperty.SetLetParameter; - public bool ImplementLetSetterType { get => _attributes.ImplementLetSetterType; set => _attributes.ImplementLetSetterType = value; } - public bool ImplementSetSetterType { get => _attributes.ImplementSetSetterType; set => _attributes.ImplementSetSetterType = value; } + private bool _implLet; + public bool ImplementLetSetterType { get => !IsReadOnly && _implLet; set => _implLet = value; } - public Func PropertyAccessExpression - { - //set => _attributes.PropertyAccessExpression = value; - get => _attributes.PropertyAccessExpression; - set - { - _attributes.PropertyAccessExpression = value; - var test = value(); - } - } + private bool _implSet; + public bool ImplementSetSetterType { get => !IsReadOnly && _implSet; set => _implSet = value; } - public Func ReferenceExpression - { - get => _attributes.ReferenceExpression; - set - { - _attributes.ReferenceExpression = value; - var test = value(); - } - } + public Func PropertyAccessExpression { set; get; } + + public Func ReferenceExpression { set; get; } public bool FieldNameIsExemptFromValidation - => Declaration?.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember) ?? false || NewFieldName.EqualsVBAIdentifier(IdentifierName); + => Declaration?.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember) ?? false; } public class EncapsulatedUserDefinedTypeField : EncapsulateFieldCandidate, IEncapsulatedUserDefinedTypeField diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationIdentifiers.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationIdentifiers.cs index 576ed527e7..a7a57172ff 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationIdentifiers.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationIdentifiers.cs @@ -5,49 +5,54 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public struct EncapsulationAttributeIdentifier - { - public EncapsulationAttributeIdentifier(string name, bool isImmutable = false) - { - Name = name; - IsImmutable = isImmutable; - } - public string Name; - public bool IsImmutable; - } + //public struct EncapsulationAttributeIdentifier + //{ + // public EncapsulationAttributeIdentifier(string name, bool isImmutable = false) + // { + // Name = name; + // IsImmutable = isImmutable; + // } + // public string Name; + // public bool IsImmutable; + //} public class EncapsulationIdentifiers { private static string DEFAULT_WRITE_PARAMETER = "value"; private KeyValuePair _fieldAndProperty; - private EncapsulationAttributeIdentifier _targetIdentifier; + //private EncapsulationAttributeIdentifier _targetIdentifier; + private string _targetIdentifier; private string _defaultPropertyName; private string _defaultFieldName; private string _setLetParameter; + private bool _cannotEncapsulate; public EncapsulationIdentifiers(Declaration target) : this(target.IdentifierName) { } - public EncapsulationIdentifiers(string field) + public EncapsulationIdentifiers(string field, bool cannotBeEncapsulated = false) { - _targetIdentifier = new EncapsulationAttributeIdentifier(field, true); - _defaultPropertyName = field.Capitalize(); - _defaultFieldName = $"{field.UnCapitalize()}1"; + //_targetIdentifier = new EncapsulationAttributeIdentifier(field, true); + _targetIdentifier = field; + _defaultPropertyName = cannotBeEncapsulated ? $"{field}99" : field.Capitalize(); + _defaultFieldName = cannotBeEncapsulated ? field : $"{field.UnCapitalize()}1"; _fieldAndProperty = new KeyValuePair(_defaultFieldName, _defaultPropertyName); _setLetParameter = DEFAULT_WRITE_PARAMETER; + _cannotEncapsulate = cannotBeEncapsulated; } public EncapsulationIdentifiers(string field, string fieldName, string propertyName) { - _targetIdentifier = new EncapsulationAttributeIdentifier(field); + //_targetIdentifier = new EncapsulationAttributeIdentifier(field); + _targetIdentifier = field; _defaultPropertyName = field.Capitalize(); _defaultFieldName = $"{field.UnCapitalize()}1"; _fieldAndProperty = new KeyValuePair(fieldName, propertyName); _setLetParameter = DEFAULT_WRITE_PARAMETER; } - public string TargetFieldName => _targetIdentifier.Name; + public string TargetFieldName => _targetIdentifier; public string Field { @@ -55,7 +60,7 @@ public string Field set { _fieldAndProperty = new KeyValuePair(value, _fieldAndProperty.Value); - GenerateNonConflictParamIdentifier(); + GenerateNonConflictParamIdentifier(); } } @@ -66,7 +71,7 @@ public string Property { var fieldIdentifier = Field.EqualsVBAIdentifier(value) ? _defaultFieldName - : _targetIdentifier.Name; + : _targetIdentifier; _fieldAndProperty = new KeyValuePair(fieldIdentifier, value); diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs index a3142ea198..1873964727 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs @@ -5,168 +5,185 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface IFieldEncapsulationAttributes - { - string IdentifierName { get; } - string PropertyName { get; set; } - bool IsReadOnly { get; set; } - bool EncapsulateFlag { get; set; } - string NewFieldName { set; get; } - bool CanBeReadWrite { set; get; } - string AsTypeName { get; set; } - string ParameterName { get;} - bool ImplementLetSetterType { get; set; } - bool ImplementSetSetterType { get; set; } - //bool FieldNameIsExemptFromValidation { get; } - QualifiedModuleName QualifiedModuleName { get; } - Func PropertyAccessExpression { set; get; } - Func ReferenceExpression { set; get; } - } + // PropertyName = field.PropertyName, + //AsTypeName = field.AsTypeName, + //BackingField = field.PropertyAccessExpression(), + //ParameterName = field.ParameterName, + //GenerateSetter = field.ImplementSetSetterType, + //GenerateLetter = field.ImplementLetSetterType + + //public interface IFieldEncapsulationAttributesX //: ISupportPropertyGenerator + //{ + // ////string IdentifierName { get; } + // ////string PropertyName { get; set; } //req'd + // ////bool IsReadOnly { get; set; } + // ////bool EncapsulateFlag { get; set; } + // ////string NewFieldName { set; get; } + // ////bool CanBeReadWrite { set; get; } + // ////string AsTypeName { get; set; } //req'd + // ////string ParameterName { get; } //req'd + // ////bool ImplementLetSetterType { get; set; }//req'd + // ////bool ImplementSetSetterType { get; set; }//req'd + // ////bool FieldNameIsExemptFromValidation { get; } + // //QualifiedModuleName QualifiedModuleName { get; } + // ////Func PropertyAccessExpression { set; get; } //req'd + // //Func ReferenceExpression { set; get; } + //} + + //public interface ISupportPropertyGenerator + //{ + // string PropertyName { get; set; } //req'd + // string AsTypeName { get; set; } //req'd + // string ParameterName { get; } //req'd + // bool ImplementLetSetterType { get; set; }//req'd + // bool ImplementSetSetterType { get; set; }//req'd + // Func PropertyAccessExpression { set; get; } //req'd + //} //Used for declarations that will be added to the code, but will never be encapsulated //Satifies the IFieldEncapsulationAttributes interface but some properties return n - public class NeverEncapsulateAttributes : IFieldEncapsulationAttributes - { - private const string neverUse = "x_x_x_x"; - private IEncapsulateFieldNamesValidator _validator; - private QualifiedModuleName _qmn; - - public NeverEncapsulateAttributes(string identifier, string asTypeName, QualifiedModuleName qmn, IEncapsulateFieldNamesValidator validator) - { - _qmn = qmn; - _validator = validator; - IdentifierName = identifier; - NewFieldName = identifier; - AsTypeName = asTypeName; - PropertyAccessExpression = () => NewFieldName; - ReferenceExpression = () => NewFieldName; - } - - public IFieldEncapsulationAttributes ApplyNewFieldName(string newFieldName) - { - NewFieldName = newFieldName; - return this; - } - - public string IdentifierName { private set; get; } - - public string NewFieldName { set; get; } - - string _tossString; - public string PropertyName { set => _tossString = value; get => $"{neverUse}{IdentifierName}_{neverUse}"; } - - public Func PropertyAccessExpression { set; get; } - - public Func ReferenceExpression { set; get; } - - public string AsTypeName { get; set; } - public string ParameterName => neverUse; - - private bool _toss; - public bool IsReadOnly { get; set; } = false; - public bool CanBeReadWrite { get => false; set => _toss = value; } - - - public bool EncapsulateFlag { get => false; set => _toss = value; } - public bool ImplementLetSetterType { get => false; set => _toss = value; } - public bool ImplementSetSetterType { get => false; set => _toss = value; } - - //public bool FieldNameIsExemptFromValidation => false; - public QualifiedModuleName QualifiedModuleName => _qmn; - } - - public class FieldEncapsulationAttributes : IFieldEncapsulationAttributes - { - private QualifiedModuleName _qmn; - private bool _fieldNameIsAlwaysValid; - public FieldEncapsulationAttributes(Declaration target) - { - _fieldAndProperty = new EncapsulationIdentifiers(target); - IdentifierName = target.IdentifierName; - AsTypeName = target.AsTypeName; - _qmn = target.QualifiedModuleName; - PropertyAccessExpression = () => NewFieldName; - //ReferenceExpression = () => NewFieldName; - ReferenceExpression = () => PropertyName; - _fieldNameIsAlwaysValid = target.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember); - } - - //public FieldEncapsulationAttributes(string identifier, string asTypeName) - //{ - // _fieldAndProperty = new EncapsulationIdentifiers(identifier); - // AsTypeName = asTypeName; - // PropertyAccessExpression = () => NewFieldName; - // ReferenceExpression = () => PropertyName; - //} - - public FieldEncapsulationAttributes(IFieldEncapsulationAttributes attributes) - { - _fieldAndProperty = new EncapsulationIdentifiers(attributes.IdentifierName, attributes.NewFieldName, attributes.PropertyName); - PropertyName = attributes.PropertyName; - IsReadOnly = attributes.IsReadOnly; - EncapsulateFlag = attributes.EncapsulateFlag; - NewFieldName = attributes.NewFieldName; - CanBeReadWrite = attributes.CanBeReadWrite; - AsTypeName = attributes.AsTypeName; - ImplementLetSetterType = attributes.ImplementLetSetterType; - ImplementSetSetterType = attributes.ImplementSetSetterType; - QualifiedModuleName = attributes.QualifiedModuleName; - PropertyAccessExpression = () => NewFieldName; - ReferenceExpression = () => PropertyName; - } - - private EncapsulationIdentifiers _fieldAndProperty; - - public string IdentifierName { private set; get; } - - public bool CanBeReadWrite { set; get; } = true; - - public string NewFieldName - { - get => _fieldAndProperty.Field; - set => _fieldAndProperty.Field = value; - } - - public string PropertyName - { - get => _fieldAndProperty.Property; - set => _fieldAndProperty.Property = value; - } - - private Func _propertyAccessExpression; - public Func PropertyAccessExpression - { - get - { - var test = _propertyAccessExpression(); - return _propertyAccessExpression; - } - set - { - _propertyAccessExpression = value; - var test = value(); - } - } - - public Func ReferenceExpression { set; get; } - - public string AsTypeName { get; set; } - public string ParameterName => _fieldAndProperty.SetLetParameter; - public bool IsReadOnly { get; set; } - public bool EncapsulateFlag { get; set; } - - private bool _implLet; - public bool ImplementLetSetterType { get => !IsReadOnly && _implLet; set => _implLet = value; } - - private bool _implSet; - public bool ImplementSetSetterType { get => !IsReadOnly && _implSet; set => _implSet = value; } - - public bool FieldNameIsExemptFromValidation => _fieldNameIsAlwaysValid || NewFieldName.EqualsVBAIdentifier(IdentifierName); - public QualifiedModuleName QualifiedModuleName - { - get => _qmn; - set => _qmn = value; - } - } + //public class NeverEncapsulateAttributes //: IFieldEncapsulationAttributes + //{ + // private const string neverUse = "x_x_x_x"; + // private IEncapsulateFieldNamesValidator _validator; + // private QualifiedModuleName _qmn; + + // public NeverEncapsulateAttributes(string identifier, string asTypeName, QualifiedModuleName qmn, IEncapsulateFieldNamesValidator validator) + // { + // _qmn = qmn; + // _validator = validator; + // IdentifierName = identifier; + // NewFieldName = identifier; + // AsTypeName = asTypeName; + // PropertyAccessExpression = () => NewFieldName; + // ReferenceExpression = () => NewFieldName; + // } + + // //public IFieldEncapsulationAttributes ApplyNewFieldName(string newFieldName) + // //{ + // // NewFieldName = newFieldName; + // // return this; + // //} + + // public string IdentifierName { private set; get; } + + // public string NewFieldName { set; get; } + + // string _tossString; + // public string PropertyName { set => _tossString = value; get => $"{neverUse}{IdentifierName}_{neverUse}"; } + + // public Func PropertyAccessExpression { set; get; } + + // public Func ReferenceExpression { set; get; } + + // public string AsTypeName { get; set; } + // public string ParameterName => neverUse; + + // private bool _toss; + // public bool IsReadOnly { get; set; } = false; + // public bool CanBeReadWrite { get => false; set => _toss = value; } + + + // public bool EncapsulateFlag { get => false; set => _toss = value; } + // public bool ImplementLetSetterType { get => false; set => _toss = value; } + // public bool ImplementSetSetterType { get => false; set => _toss = value; } + + // //public bool FieldNameIsExemptFromValidation => false; + // public QualifiedModuleName QualifiedModuleName => _qmn; + //} + + //public class FieldEncapsulationAttributes //: IFieldEncapsulationAttributes + //{ + // private QualifiedModuleName _qmn; + // private bool _fieldNameIsAlwaysValid; + // public FieldEncapsulationAttributes(Declaration target) + // { + // _fieldAndProperty = new EncapsulationIdentifiers(target); + // IdentifierName = target.IdentifierName; + // AsTypeName = target.AsTypeName; + // _qmn = target.QualifiedModuleName; + // PropertyAccessExpression = () => NewFieldName; + // //ReferenceExpression = () => NewFieldName; + // ReferenceExpression = () => PropertyName; + // _fieldNameIsAlwaysValid = target.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember); + // } + + // //public FieldEncapsulationAttributes(string identifier, string asTypeName) + // //{ + // // _fieldAndProperty = new EncapsulationIdentifiers(identifier); + // // AsTypeName = asTypeName; + // // PropertyAccessExpression = () => NewFieldName; + // // ReferenceExpression = () => PropertyName; + // //} + + // //public FieldEncapsulationAttributes(IFieldEncapsulationAttributes attributes) + // //{ + // //_fieldAndProperty = new EncapsulationIdentifiers(attributes.IdentifierName, attributes.NewFieldName, attributes.PropertyName); + // //PropertyName = attributes.PropertyName; + // //IsReadOnly = attributes.IsReadOnly; + // //EncapsulateFlag = attributes.EncapsulateFlag; + // //NewFieldName = attributes.NewFieldName; + // //CanBeReadWrite = attributes.CanBeReadWrite; + // //AsTypeName = attributes.AsTypeName; + // //ImplementLetSetterType = attributes.ImplementLetSetterType; + // //ImplementSetSetterType = attributes.ImplementSetSetterType; + // //QualifiedModuleName = attributes.QualifiedModuleName; + // //PropertyAccessExpression = () => NewFieldName; + // //ReferenceExpression = () => PropertyName; + // //} + + // private EncapsulationIdentifiers _fieldAndProperty; + + // public string IdentifierName { private set; get; } + + // public bool CanBeReadWrite { set; get; } = true; + + // public string NewFieldName + // { + // get => _fieldAndProperty.Field; + // set => _fieldAndProperty.Field = value; + // } + + // public string PropertyName + // { + // get => _fieldAndProperty.Property; + // set => _fieldAndProperty.Property = value; + // } + + // private Func _propertyAccessExpression; + // public Func PropertyAccessExpression + // { + // get + // { + // var test = _propertyAccessExpression(); + // return _propertyAccessExpression; + // } + // set + // { + // _propertyAccessExpression = value; + // var test = value(); + // } + // } + + // public Func ReferenceExpression { set; get; } + + // public string AsTypeName { get; set; } + // public string ParameterName => _fieldAndProperty.SetLetParameter; + // public bool IsReadOnly { get; set; } + // public bool EncapsulateFlag { get; set; } + + // private bool _implLet; + // public bool ImplementLetSetterType { get => !IsReadOnly && _implLet; set => _implLet = value; } + + // private bool _implSet; + // public bool ImplementSetSetterType { get => !IsReadOnly && _implSet; set => _implSet = value; } + + // public bool FieldNameIsExemptFromValidation => _fieldNameIsAlwaysValid || NewFieldName.EqualsVBAIdentifier(IdentifierName); + // public QualifiedModuleName QualifiedModuleName + // { + // get => _qmn; + // set => _qmn = value; + // } + //} } diff --git a/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs b/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs index f0e9426ff5..8d7c136fad 100644 --- a/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs @@ -2,6 +2,16 @@ namespace Rubberduck.Refactorings.EncapsulateField { + public interface ISupportPropertyGenerator + { + string PropertyName { get; set; } //req'd + string AsTypeName { get; set; } //req'd + string ParameterName { get; } //req'd + bool ImplementLetSetterType { get; set; }//req'd + bool ImplementSetSetterType { get; set; }//req'd + Func PropertyAccessExpression { set; get; } //req'd + } + public class PropertyGenerator { public string PropertyName { get; set; } diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs index f5974e511f..39a29622fe 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs @@ -21,10 +21,9 @@ public EncapsulateWithBackingFields(QualifiedModuleName qmn, IIndenter indenter, protected override void ModifyEncapsulatedField(IEncapsulateFieldCandidate field, IRewriteSession rewriteSession) { - var attributes = field.EncapsulationAttributes; var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); - if (field.Declaration.Accessibility == Accessibility.Private && attributes.NewFieldName.Equals(field.Declaration.IdentifierName)) + if (field.Declaration.Accessibility == Accessibility.Private && field.NewFieldName.Equals(field.Declaration.IdentifierName)) { rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); return; @@ -37,7 +36,7 @@ protected override void ModifyEncapsulatedField(IEncapsulateFieldCandidate field } else { - rewriter.Rename(field.Declaration, attributes.NewFieldName); + rewriter.Rename(field.Declaration, field.NewFieldName); rewriter.SetVariableVisiblity(field.Declaration, Accessibility.Private.TokenString()); rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); } @@ -51,16 +50,15 @@ protected override EncapsulateFieldNewContent LoadNewDeclarationsContent(Encapsu foreach (var nonUdtMemberField in nonUdtMemberFields) { - var attributes = nonUdtMemberField.EncapsulationAttributes; - if (nonUdtMemberField.Declaration.Accessibility == Accessibility.Private && attributes.NewFieldName.Equals(nonUdtMemberField.Declaration.IdentifierName)) + if (nonUdtMemberField.Declaration.Accessibility == Accessibility.Private && nonUdtMemberField.NewFieldName.Equals(nonUdtMemberField.Declaration.IdentifierName)) { continue; } if (nonUdtMemberField.Declaration.IsDeclaredInList()) { - var targetIdentifier = nonUdtMemberField.Declaration.Context.GetText().Replace(attributes.IdentifierName, attributes.NewFieldName); + var targetIdentifier = nonUdtMemberField.Declaration.Context.GetText().Replace(nonUdtMemberField.IdentifierName, nonUdtMemberField.NewFieldName); var newField = nonUdtMemberField.Declaration.IsTypeSpecified ? $"{Tokens.Private} {targetIdentifier}" : $"{Tokens.Private} {targetIdentifier} {Tokens.As} {nonUdtMemberField.Declaration.AsTypeName}"; newContent.AddDeclarationBlock(newField); diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs index 15b7002bcc..5f2cc544c1 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs @@ -27,19 +27,20 @@ protected override IExecutableRewriteSession RefactorRewrite(EncapsulateFieldMod { if (field is IEncapsulatedUserDefinedTypeField udt) { - udt.PropertyAccessExpression = + var fd = udt as IEncapsulateFieldCandidate; + fd.PropertyAccessExpression = () => { - var accessor = udt.EncapsulateFlag ? udt.PropertyName : udt.NewFieldName; + var accessor = udt.EncapsulateFlag ? fd.PropertyName : udt.NewFieldName; return $"{StateUDTField.PropertyAccessExpression()}.{accessor}"; }; - udt.ReferenceExpression = udt.PropertyAccessExpression; + udt.ReferenceExpression = fd.PropertyAccessExpression; foreach (var member in udt.Members) { - member.PropertyAccessExpression = () => $"{udt.PropertyAccessExpression()}.{member.PropertyName}"; - member.ReferenceExpression = () => $"{udt.PropertyAccessExpression()}.{member.PropertyName}"; + member.PropertyAccessExpression = () => $"{fd.PropertyAccessExpression()}.{member.PropertyName}"; + member.ReferenceExpression = () => $"{fd.PropertyAccessExpression()}.{member.PropertyName}"; } } else @@ -52,8 +53,7 @@ protected override IExecutableRewriteSession RefactorRewrite(EncapsulateFieldMod foreach (var field in model.FlaggedFieldCandidates) { - var attributes = field.EncapsulationAttributes; - ModifyEncapsulatedField(field, /*attributes,*/ rewriteSession); + ModifyEncapsulatedField(field, rewriteSession); } SetupReferenceModifications(model); diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs index ff6db9f977..41cb13f912 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs @@ -51,11 +51,12 @@ public IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IE protected virtual IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) { - var udtFieldsByTypeName = model.FlaggedUDTFieldCandidates.GroupBy((udtCandidate) => udtCandidate.AsTypeName); + var udtFieldsByTypeName = model.FlaggedUDTFieldCandidates.GroupBy((udtCandidate) => (udtCandidate as IEncapsulateFieldCandidate).AsTypeName); foreach (var udtField in model.FlaggedUDTFieldCandidates) { + var fd = udtField as IEncapsulateFieldCandidate; var hasMultipleUDTFieldsOfSameType = udtFieldsByTypeName - .Where(group => group.Key == udtField.AsTypeName).Single().Count() > 1; + .Where(group => group.Key == fd.AsTypeName).Single().Count() > 1; foreach (var member in udtField.Members) { @@ -175,21 +176,12 @@ private void LoadUDTMemberReferenceExpressions(IEncapsulatedUserDefinedTypeField private IEnumerable GetUDTMemberReferencesForField(IEncapsulateFieldCandidate udtMember, IEncapsulatedUserDefinedTypeField field) { - //var fieldMAECs = field.References.Where(rf => rf.Context.Parent is VBAParser.MemberAccessExprContext).Select(r => r.Context.Parent); - //var refMAECs = field.Members.SelectMany(m => m.References).Where(rf => rf.Context.Parent is VBAParser.MemberAccessExprContext).Select(r => r.Context.Parent); - //var matches = refMAECs.Intersect(fieldMAECs); var refs = new List(); foreach (var idRef in udtMember.References) { if (idRef.Context.TryGetAncestor(out var mac)) { - //var match = field.References.Select(rf => rf.Context.Parent).Contains(mac); var LHS = mac.children.First(); - //if (LHS.GetText().Equals(field.IdentifierName)) - //{ - // refs.Add(idRef); - //} - switch(LHS) { case VBAParser.SimpleNameExprContext snec: @@ -265,26 +257,25 @@ protected virtual IList PropertiesContent(IEnumerable())); + //Assert.Less(0, validator.HasNewPropertyNameConflicts(mockFizz.EncapsulationAttributes, mockFizz.QualifiedModuleName, Enumerable.Empty())); + Assert.Less(0, validator.HasNewPropertyNameConflicts(mockFizz, mockFizz.QualifiedModuleName, Enumerable.Empty())); } } @@ -115,7 +116,8 @@ void ThisTest(IDeclarationFinderProvider declarationProviderProvider) }); - Assert.Less(0 ,validator.HasNewPropertyNameConflicts(thisField.EncapsulationAttributes, thisField.QualifiedModuleName, Enumerable.Empty())); + //Assert.Less(0, validator.HasNewPropertyNameConflicts(thisField.EncapsulationAttributes, thisField.QualifiedModuleName, Enumerable.Empty())); + Assert.Less(0, validator.HasNewPropertyNameConflicts(thisField, thisField.QualifiedModuleName, Enumerable.Empty())); } } [Test] @@ -146,8 +148,10 @@ void ThisTest(IDeclarationFinderProvider declarationProviderProvider) fields.Add(new EncapsulateFieldCandidate(wholeNumber, validator)); fields.Add(new EncapsulateFieldCandidate(longValue, validator)); - encapsulatedWholeNumber.EncapsulationAttributes.PropertyName = "LongValue"; - Assert.Less(0, validator.HasNewPropertyNameConflicts(encapsulatedWholeNumber.EncapsulationAttributes, encapsulatedWholeNumber.QualifiedModuleName, new Declaration[] {encapsulatedWholeNumber.Declaration})); + //encapsulatedWholeNumber.EncapsulationAttributes.PropertyName = "LongValue"; + encapsulatedWholeNumber.PropertyName = "LongValue"; + //Assert.Less(0, validator.HasNewPropertyNameConflicts(encapsulatedWholeNumber.EncapsulationAttributes, encapsulatedWholeNumber.QualifiedModuleName, new Declaration[] { encapsulatedWholeNumber.Declaration })); + Assert.Less(0, validator.HasNewPropertyNameConflicts(encapsulatedWholeNumber, encapsulatedWholeNumber.QualifiedModuleName, new Declaration[] { encapsulatedWholeNumber.Declaration })); } } @@ -172,15 +176,15 @@ private IEncapsulateFieldCandidate CreateEncapsulatedFieldMock(string targetID, mock.SetupGet(m => m.PropertyName).Returns(modifiedPropertyName ?? identifiers.Property); mock.SetupGet(m => m.AsTypeName).Returns(asTypeName); mock.SetupGet(m => m.EncapsulateFlag).Returns(encapsulateFlag); - mock.SetupGet(m => m.EncapsulationAttributes).Returns(attributesMock); + //mock.SetupGet(m => m.EncapsulationAttributes).Returns(attributesMock); mock.SetupGet(m => m.QualifiedModuleName).Returns(new QualifiedModuleName(component)); return mock.Object; } - private IFieldEncapsulationAttributes CreateAttributesMock(string targetID, string asTypeName, string modifiedPropertyName = null, bool encapsulateFlag = true) + private IEncapsulateFieldCandidate CreateAttributesMock(string targetID, string asTypeName, string modifiedPropertyName = null, bool encapsulateFlag = true) { var identifiers = new EncapsulationIdentifiers(targetID); - var mock = new Mock(); + var mock = new Mock(); mock.SetupGet(m => m.IdentifierName).Returns(identifiers.TargetFieldName); mock.SetupGet(m => m.NewFieldName).Returns(identifiers.Field); mock.SetupGet(m => m.PropertyName).Returns(modifiedPropertyName ?? identifiers.Property); diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs index 619df05794..f5d8e14423 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs @@ -129,10 +129,10 @@ public void PropertyNameChange_UniqueParamName() var encapsulatedField = RetrieveEncapsulatedField(inputCode, "value"); encapsulatedField.PropertyName = "Test"; - StringAssert.AreEqualIgnoringCase("value_value", encapsulatedField.EncapsulationAttributes.ParameterName); + StringAssert.AreEqualIgnoringCase("value_value", encapsulatedField.ParameterName); encapsulatedField.PropertyName = "Value"; - StringAssert.AreEqualIgnoringCase("Value_value1_value", encapsulatedField.EncapsulationAttributes.ParameterName); + StringAssert.AreEqualIgnoringCase("Value_value1_value", encapsulatedField.ParameterName); } [Test] diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index 078382bf7d..601e337d59 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -70,9 +70,9 @@ public Func SetParameters(string o return model => { var encapsulatedField = model[originalField]; - encapsulatedField.EncapsulationAttributes.PropertyName = attrs.PropertyName; - encapsulatedField.EncapsulationAttributes.IsReadOnly = attrs.IsReadOnly; - encapsulatedField.EncapsulationAttributes.EncapsulateFlag = attrs.EncapsulateFlag; + encapsulatedField.PropertyName = attrs.PropertyName; + encapsulatedField.IsReadOnly = attrs.IsReadOnly; + encapsulatedField.EncapsulateFlag = attrs.EncapsulateFlag; model.EncapsulateWithUDT = asUDT; return model; From 2df72f73863e8bd04bf059f8de8358e50d33157a Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Fri, 6 Dec 2019 15:00:17 -0800 Subject: [PATCH 045/461] Property Generator updates --- .../EncapsulatedFieldDeclaration.cs | 29 +++++++++++---- .../EncapsulateField/PropertyGenerator.cs | 35 +++++++++++++++---- .../Strategies/EncapsulationStrategiesBase.cs | 17 +++------ 3 files changed, 55 insertions(+), 26 deletions(-) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs index ac11125e0f..0d5a699a78 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs @@ -25,23 +25,24 @@ public interface IEncapsulateFieldCandidate IEnumerable References { get; } string this[IdentifierReference idRef] { set; get; } bool TryGetReferenceExpression(IdentifierReference idRef, out string expression); - bool FieldNameIsExemptFromValidation { get; } - Func ReferenceExpression { set; get; } string PropertyName { get; set; } - string AsTypeName { get; set; } - string ParameterName { get; } + string AsTypeName { get; set; } + string ParameterName { get; } bool ImplementLetSetterType { get; set; } bool ImplementSetSetterType { get; set; } Func PropertyAccessExpression { set; get; } + bool FieldNameIsExemptFromValidation { get; } + Func ReferenceExpression { set; get; } + IPropertyGeneratorSpecification AsPropertyGeneratorSpec { get; } } - public interface IEncapsulatedUserDefinedTypeField : IEncapsulateFieldCandidate, ISupportPropertyGenerator + public interface IEncapsulatedUserDefinedTypeField : IEncapsulateFieldCandidate { IList Members { set; get; } bool TypeDeclarationIsPrivate { set; get; } } - public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate, ISupportPropertyGenerator + public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate { protected Declaration _target; protected QualifiedModuleName _qmn; @@ -161,8 +162,24 @@ public string IdentifierName private bool _implSet; public bool ImplementSetSetterType { get => !IsReadOnly && _implSet; set => _implSet = value; } + public Func PropertyAccessExpression { set; get; } + public IPropertyGeneratorSpecification AsPropertyGeneratorSpec + { + get + { + return new PropertyGeneratorDataObject() + { + PropertyName = PropertyName, + BackingField = PropertyAccessExpression(), + AsTypeName = AsTypeName, + ParameterName = ParameterName, + GenerateLetter = ImplementLetSetterType, + GenerateSetter = ImplementSetSetterType + }; + } + } public Func ReferenceExpression { set; get; } public bool FieldNameIsExemptFromValidation diff --git a/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs b/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs index 8d7c136fad..5de54506a8 100644 --- a/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs @@ -2,18 +2,39 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface ISupportPropertyGenerator + public interface IPropertyGeneratorSpecification { - string PropertyName { get; set; } //req'd - string AsTypeName { get; set; } //req'd - string ParameterName { get; } //req'd - bool ImplementLetSetterType { get; set; }//req'd - bool ImplementSetSetterType { get; set; }//req'd - Func PropertyAccessExpression { set; get; } //req'd + string PropertyName { get; } + string BackingField { get; } + string AsTypeName { get; } + string ParameterName { get; } + bool GenerateLetter { get; } + bool GenerateSetter { get; } + } + + public struct PropertyGeneratorDataObject : IPropertyGeneratorSpecification + { + public string PropertyName { get; set; } + public string BackingField { get; set; } + public string AsTypeName { get; set; } + public string ParameterName { get; set; } + public bool GenerateLetter { get; set; } + public bool GenerateSetter { get; set; } } public class PropertyGenerator { + public PropertyGenerator() { } + + public PropertyGenerator(IPropertyGeneratorSpecification spec) + { + PropertyName = spec.PropertyName; + BackingField = spec.BackingField; + AsTypeName = spec.AsTypeName; + ParameterName = spec.ParameterName; + GenerateLetter = spec.GenerateLetter; + GenerateSetter = spec.GenerateSetter; + } public string PropertyName { get; set; } public string BackingField { get; set; } public string AsTypeName { get; set; } diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs index 41cb13f912..2a64b4082a 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs @@ -257,27 +257,18 @@ protected virtual IList PropertiesContent(IEnumerable Date: Sat, 7 Dec 2019 12:07:20 -0800 Subject: [PATCH 046/461] Refactored to reduce exposure of UDTMember Most manipulations moved to owning Field object. Fixed PropertyGenerator bug. --- .../EncapsulateFieldDeclarationFactory.cs | 8 +- .../EncapsulateField/EncapsulateFieldModel.cs | 20 +- .../EncapsulateFieldNewContent.cs | 54 +++- .../EncapsulateFieldRewriter.cs | 17 +- .../EncapsulatedFieldDeclaration.cs | 145 +++++----- .../EncapsulatedUserDefinedTypeField.cs | 140 ++++++++++ .../EncapsulatedUserDefinedTypeMember.cs | 134 +++++++++ .../EncapsulateField/PropertyGenerator.cs | 26 +- .../RewriterRemoveWorkaround.cs | 26 +- .../EncapsulateWithBackingFields.cs | 22 +- .../EncapsulateWithBackingUserDefinedType.cs | 61 +---- .../Strategies/EncapsulationStrategiesBase.cs | 256 +++--------------- .../EncapsulateField/TestSupport.cs | 6 +- .../Refactoring/EncapsulateFieldTests.cs | 20 ++ 14 files changed, 553 insertions(+), 382 deletions(-) create mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeField.cs create mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeMember.cs diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs index c4c6c90ca3..5791926b61 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs @@ -49,16 +49,16 @@ public IEnumerable CreateEncapsulationCandidates(IEn foreach ( var udtField in udtFieldToUdtDeclarationMap.Keys) { - var encapsulatedUDTField = _encapsulatedFields.Where(ef => ef.Declaration == udtField).Single(); + var encapsulatedUDTField = _encapsulatedFields.Where(ef => ef.Declaration == udtField).Single() as IEncapsulatedUserDefinedTypeField; - var parent = encapsulatedUDTField as IEncapsulatedUserDefinedTypeField; - parent.TypeDeclarationIsPrivate = udtFieldToUdtDeclarationMap[udtField].UserDefinedType.Accessibility.Equals(Accessibility.Private); + //var parent = encapsulatedUDTField as IEncapsulatedUserDefinedTypeField; + encapsulatedUDTField.TypeDeclarationIsPrivate = udtFieldToUdtDeclarationMap[udtField].UserDefinedType.Accessibility.Equals(Accessibility.Private); foreach (var udtMember in udtFieldToUdtDeclarationMap[udtField].Item2) { var encapsulatedUDTMember = new EncapsulatedUserDefinedTypeMember(udtMember, encapsulatedUDTField, _validator) as IEncapsulatedUserDefinedTypeMember; encapsulatedUDTMember = ApplyTypeSpecificAttributes(encapsulatedUDTMember); - parent.Members.Add(encapsulatedUDTMember); + encapsulatedUDTField.AddMember(encapsulatedUDTMember); encapsulatedUDTMember.PropertyAccessExpression = () => { diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index 64a2d1b46d..d64a2f6f01 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -17,19 +17,19 @@ public class EncapsulateFieldModel : IRefactoringModel private readonly IIndenter _indenter; private readonly IDeclarationFinderProvider _declarationFinderProvider; private readonly IEncapsulateFieldNamesValidator _validator; - private readonly Func _previewFunc; + private readonly Func _previewDelegate; private QualifiedModuleName _targetQMN; private bool _useNewStructure; private IDictionary)> _udtFieldToUdtDeclarationMap = new Dictionary)>(); - public EncapsulateFieldModel(Declaration target, IDeclarationFinderProvider declarationFinderProvider, IIndenter indenter, IEncapsulateFieldNamesValidator validator, Func previewFunc) + public EncapsulateFieldModel(Declaration target, IDeclarationFinderProvider declarationFinderProvider, IIndenter indenter, IEncapsulateFieldNamesValidator validator, Func previewDelegate) { _declarationFinderProvider = declarationFinderProvider; _indenter = indenter; _validator = validator; - _previewFunc = previewFunc; + _previewDelegate = previewDelegate; _targetQMN = target.QualifiedModuleName; _useNewStructure = File.Exists("C:\\Users\\Brian\\Documents\\UseNewUDTStructure.txt"); @@ -68,8 +68,8 @@ public IEnumerable FlaggedUDTFieldCandidates public IEnumerable FlaggedEncapsulationFields => FlaggedFieldCandidates; - public IEncapsulateFieldCandidate this[string encapsulatedFieldIdentifier] - => FieldCandidates.Where(c => c.TargetID.Equals(encapsulatedFieldIdentifier)).Single(); + public IEncapsulateFieldCandidate this[string encapsulatedFieldTargetID] + => FieldCandidates.Where(c => c.TargetID.Equals(encapsulatedFieldTargetID)).Single(); public IEncapsulateFieldCandidate this[Declaration fieldDeclaration] => FieldCandidates.Where(c => c.Declaration == fieldDeclaration).Single(); @@ -80,9 +80,8 @@ public bool EncapsulateWithUDT { set { - if (value && EncapsulationStrategy is EncapsulateWithBackingUserDefinedType) { return; } - - if (!value && EncapsulationStrategy is EncapsulateWithBackingFields) { return; } + if ((value && EncapsulationStrategy is EncapsulateWithBackingUserDefinedType) + || (!value && EncapsulationStrategy is EncapsulateWithBackingFields)) { return; } if (value) { @@ -100,10 +99,7 @@ public bool EncapsulateWithUDT get => EncapsulationStrategy is EncapsulateWithBackingUserDefinedType; } - public string PreviewRefactoring() - { - return _previewFunc(this); - } + public string PreviewRefactoring() => _previewDelegate(this); public int? CodeSectionStartIndex { diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldNewContent.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldNewContent.cs index 5c5a69f2b2..bcefd7177b 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldNewContent.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldNewContent.cs @@ -24,8 +24,19 @@ public interface IEncapsulateFieldNewContentProvider public class EncapsulateFieldNewContent : IEncapsulateFieldNewContentProvider { + protected static string DoubleSpace => $"{Environment.NewLine}{Environment.NewLine}"; + protected static string SingleSpace => $"{Environment.NewLine}"; + private IEnumerable SourceModuleElements { get; } + public void AddTypeDeclarationBlock(string declarationBlock) + { + if (declarationBlock.Length > 0) + { + TypeDeclarations.Add(declarationBlock); + } + } + public void AddDeclarationBlock(string declarationBlock) { if (declarationBlock.Length > 0) @@ -42,6 +53,21 @@ public void AddCodeBlock(string codeBlock) } } + private string _postPendComment; + public string PostPendComment + { + get => _postPendComment; + set + { + if (value.Length > 0) + { + _postPendComment = value.StartsWith("'") ? value : $"'{value}"; + } + } + } + + public List TypeDeclarations { get; } = new List(); + public List Declarations { get; } = new List(); public List CodeBlocks { get; } = new List(); @@ -50,10 +76,11 @@ public string PreCodeSectionContent { get { - var preCodeSectionContent = new List(Declarations); + var allDeclarations = Enumerable.Empty().Concat(TypeDeclarations).Concat(Declarations); + var preCodeSectionContent = new List(allDeclarations); if (preCodeSectionContent.Any()) { - var preCodeSection = string.Join(Environment.NewLine, preCodeSectionContent); + var preCodeSection = string.Join(SingleSpace, preCodeSectionContent); return preCodeSection; } return string.Empty; @@ -62,7 +89,7 @@ public string PreCodeSectionContent public bool HasNewContent => Declarations.Any() || CodeBlocks.Any(); - public string CodeSectionContent => CodeBlocks.Any() ? string.Join($"{Environment.NewLine}{Environment.NewLine}", CodeBlocks) : string.Empty; + public string CodeSectionContent => CodeBlocks.Any() ? string.Join($"{DoubleSpace}", CodeBlocks) : string.Empty; public string AsSingleTextBlock { @@ -70,19 +97,28 @@ public string AsSingleTextBlock { if (!HasNewContent) { return string.Empty; } + var content = string.Empty; if (PreCodeSectionContent.Length > 0) { - return CodeSectionContent.Length > 0 - ? $"{PreCodeSectionContent}{Environment.NewLine}{Environment.NewLine}{CodeSectionContent}" + content = CodeSectionContent.Length > 0 + ? $"{PreCodeSectionContent}{DoubleSpace}{CodeSectionContent}" : $"{PreCodeSectionContent}"; } + else + { + content = CodeSectionContent.Length > 0 + ? $"{SingleSpace}{CodeSectionContent}" + : string.Empty; + } - return CodeSectionContent.Length > 0 - ? $"{Environment.NewLine}{CodeSectionContent}" - : string.Empty; + if (PostPendComment != null && PostPendComment.Length > 0) + { + content = $"{content}{SingleSpace}{PostPendComment}{SingleSpace}"; + } + return content; } } - public int CountOfProcLines => CodeSectionContent.Split(new string[] { Environment.NewLine }, StringSplitOptions.None).Count(); + public int CountOfProcLines => CodeSectionContent.Split(new string[] {SingleSpace}, StringSplitOptions.None).Count(); } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs index 373c4c31a9..7a8490df9f 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs @@ -11,6 +11,17 @@ namespace Rubberduck.Refactorings.EncapsulateField { + public struct RewriteReplacePair + { + public RewriteReplacePair(string text, ParserRuleContext context) + { + Text = text; + Context = context; + } + public string Text { private set; get; } + public ParserRuleContext Context { private set; get; } + } + public interface IEncapsulateFieldRewriter : IModuleRewriter { void InsertNewContent(int? codeSectionStartIndex, IEncapsulateFieldNewContentProvider newContent); @@ -19,7 +30,7 @@ public interface IEncapsulateFieldRewriter : IModuleRewriter void MakeImplicitDeclarationTypeExplicit(Declaration element); void InsertAtEndOfFile(string content); string GetText(int maxConsecutiveNewLines); - + void Replace(RewriteReplacePair pair); } public class EncapsulateFieldRewriter : IEncapsulateFieldRewriter @@ -42,7 +53,7 @@ public void InsertNewContent(int? codeSectionStartIndex, IEncapsulateFieldNewCon var allContent = newContent.AsSingleTextBlock; if (codeSectionStartIndex.HasValue && newContent.HasNewContent) { - _rewriter.InsertBefore(codeSectionStartIndex.Value, $"{Environment.NewLine}{allContent}"); + _rewriter.InsertBefore(codeSectionStartIndex.Value, $"{Environment.NewLine}{allContent}{Environment.NewLine}"); } else { @@ -131,6 +142,8 @@ public string GetText(int maxConsecutiveNewLines) public void Replace(Declaration target, string content) => _rewriter.Replace(target, content); + public void Replace(RewriteReplacePair pair) => _rewriter.Replace(pair.Context, pair.Text); + public void Replace(ParserRuleContext target, string content) => _rewriter.Replace(target, content); public void Replace(IToken token, string content) => _rewriter.Replace(token, content); diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs index 0d5a699a78..8a6d5e5fea 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs @@ -1,4 +1,6 @@ -using Rubberduck.Parsing.Grammar; +using Antlr4.Runtime; +using Rubberduck.Parsing; +using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.Refactorings.Common; using Rubberduck.VBEditor; @@ -23,8 +25,6 @@ public interface IEncapsulateFieldCandidate bool HasValidEncapsulationAttributes { get; } QualifiedModuleName QualifiedModuleName { get; } IEnumerable References { get; } - string this[IdentifierReference idRef] { set; get; } - bool TryGetReferenceExpression(IdentifierReference idRef, out string expression); string PropertyName { get; set; } string AsTypeName { get; set; } string ParameterName { get; } @@ -33,19 +33,20 @@ public interface IEncapsulateFieldCandidate Func PropertyAccessExpression { set; get; } bool FieldNameIsExemptFromValidation { get; } Func ReferenceExpression { set; get; } - IPropertyGeneratorSpecification AsPropertyGeneratorSpec { get; } - } - - public interface IEncapsulatedUserDefinedTypeField : IEncapsulateFieldCandidate - { - IList Members { set; get; } - bool TypeDeclarationIsPrivate { set; get; } + //IPropertyGeneratorSpecification AsPropertyGeneratorSpec { get; } + IEnumerable PropertyGenerationSpecs { get; } + IEnumerable> ReferenceReplacements { get; } + void LoadReferenceExpressionChanges(); + void AddReferenceReplacement(IdentifierReference idRef, string replacementText); + RewriteReplacePair ReferenceReplacement(IdentifierReference idRef); + RewriteReplacePair? FindRewriteReplacePair(IdentifierReference idRef); } public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate { protected Declaration _target; protected QualifiedModuleName _qmn; + private string _identifierName; private IEncapsulateFieldNamesValidator _validator; private Dictionary _idRefRenames { set; get; } = new Dictionary(); private EncapsulationIdentifiers _fieldAndProperty; @@ -57,7 +58,6 @@ public EncapsulateFieldCandidate(Declaration declaration, IEncapsulateFieldNames _fieldAndProperty = new EncapsulationIdentifiers(_target); IdentifierName = _target.IdentifierName; - AsTypeName = _target.AsTypeName; _qmn = _target.QualifiedModuleName; PropertyAccessExpression = () => NewFieldName; ReferenceExpression = () => PropertyName; @@ -81,42 +81,53 @@ public EncapsulateFieldCandidate(string identifier, string asTypeName, Qualified _validator.ForceNonConflictEncapsulationAttributes(this, qmn, _target); } + protected Dictionary IdentifierReplacements { get; } = new Dictionary(); + public Declaration Declaration => _target; public bool HasValidEncapsulationAttributes { get { - var ignore = _target != null ? new Declaration[] { _target } : Enumerable.Empty(); + var declarationsToIgnore = _target != null ? new Declaration[] { _target } : Enumerable.Empty(); var declarationType = _target != null ? _target.DeclarationType : DeclarationType.Variable; - return _validator.HasValidEncapsulationAttributes(this, QualifiedModuleName, ignore, declarationType); + return _validator.HasValidEncapsulationAttributes(this, QualifiedModuleName, declarationsToIgnore, declarationType); } } - public bool TryGetReferenceExpression(IdentifierReference idRef, out string expression) + public virtual IEnumerable> ReferenceReplacements { - expression = string.Empty; - if (_idRefRenames.ContainsKey(idRef)) + get { - expression = _idRefRenames[idRef]; + var results = new List>(); + foreach (var replacement in IdentifierReplacements) + { + var kv = new KeyValuePair + (replacement.Key, replacement.Value); + results.Add(kv); + } + return results; } - return expression.Length > 0; } - public string this[IdentifierReference idRef] + + public RewriteReplacePair? FindRewriteReplacePair(IdentifierReference idRef) { - get => _idRefRenames[idRef]; - set + if (IdentifierReplacements.ContainsKey(idRef)) { - if (!_idRefRenames.ContainsKey(idRef)) - { - _idRefRenames.Add(idRef, value); - } - else - { - _idRefRenames[idRef] = value; - } + return IdentifierReplacements[idRef]; } + return null; + } + + public virtual void AddReferenceReplacement(IdentifierReference idRef, string replacementText) + { + IdentifierReplacements.Add(idRef, new RewriteReplacePair(replacementText, idRef.Context)); + } + + public RewriteReplacePair ReferenceReplacement(IdentifierReference idRef) //, ParserRuleContextExtensions context)] + { + return IdentifierReplacements.Single(r => r.Key == idRef).Value; } public virtual string TargetID => _target?.IdentifierName ?? IdentifierName; @@ -145,9 +156,8 @@ public string NewFieldName public QualifiedModuleName QualifiedModuleName => _qmn; - public IEnumerable References => Declaration?.References ?? Enumerable.Empty(); + public virtual IEnumerable References => Declaration?.References ?? Enumerable.Empty(); - private string _identifierName; public string IdentifierName { get => Declaration?.IdentifierName ?? _identifierName; @@ -165,71 +175,58 @@ public string IdentifierName public Func PropertyAccessExpression { set; get; } - public IPropertyGeneratorSpecification AsPropertyGeneratorSpec + public virtual IEnumerable PropertyGenerationSpecs + => new List() { AsPropertyGeneratorSpec }; + + protected virtual IPropertyGeneratorSpecification AsPropertyGeneratorSpec { get { - return new PropertyGeneratorDataObject() + return new PropertyGeneratorSpecification() { PropertyName = PropertyName, BackingField = PropertyAccessExpression(), AsTypeName = AsTypeName, ParameterName = ParameterName, GenerateLetter = ImplementLetSetterType, - GenerateSetter = ImplementSetSetterType + GenerateSetter = ImplementSetSetterType, + UsesSetAssignment = Declaration.IsObject }; } } - public Func ReferenceExpression { set; get; } - - public bool FieldNameIsExemptFromValidation - => Declaration?.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember) ?? false; - } - public class EncapsulatedUserDefinedTypeField : EncapsulateFieldCandidate, IEncapsulatedUserDefinedTypeField - { - public EncapsulatedUserDefinedTypeField(Declaration declaration, IEncapsulateFieldNamesValidator validator) - : base(declaration, validator) + public virtual void LoadReferenceExpressionChanges() { - PropertyAccessExpression = () => EncapsulateFlag ? NewFieldName : IdentifierName; + LoadFieldReferenceExpressions(); } - public IList Members { set; get; } = new List(); - public bool TypeDeclarationIsPrivate { set; get; } - } + protected virtual void LoadFieldReferenceExpressions() + { + var field = this; + foreach (var idRef in field.References) + { + var replacementText = RequiresAccessQualification(idRef) + ? $"{field.QualifiedModuleName.ComponentName}.{field.ReferenceExpression()}" + : field.ReferenceExpression(); - public interface IEncapsulatedUserDefinedTypeMember : IEncapsulateFieldCandidate - { - IEncapsulateFieldCandidate Parent { get; } - bool FieldQualifyProperty { set; get; } - } + field.AddReferenceReplacement(idRef, replacementText); + } + } - public class EncapsulatedUserDefinedTypeMember : EncapsulateFieldCandidate, IEncapsulatedUserDefinedTypeMember - { - public EncapsulatedUserDefinedTypeMember(Declaration target, IEncapsulateFieldCandidate udtVariable, IEncapsulateFieldNamesValidator validator) - : base(target, validator) + protected bool RequiresAccessQualification(IdentifierReference idRef) { - Parent = udtVariable; + var isLHSOfMemberAccess = + (idRef.Context.Parent is VBAParser.MemberAccessExprContext + || idRef.Context.Parent is VBAParser.WithMemberAccessExprContext) + && !(idRef.Context == idRef.Context.Parent.GetChild(0));// is VBAParser.SimpleNameExprContext)) - PropertyName = IdentifierName; - PropertyAccessExpression = () => $"{Parent.PropertyAccessExpression()}.{PropertyName}"; - ReferenceExpression = () => $"{Parent.PropertyAccessExpression()}.{PropertyName}"; + return idRef.QualifiedModuleName != idRef.Declaration.QualifiedModuleName + && !isLHSOfMemberAccess; } - public IEncapsulateFieldCandidate Parent { private set; get; } + public Func ReferenceExpression { set; get; } - private bool _fieldNameQualifyProperty; - public bool FieldQualifyProperty - { - get => _fieldNameQualifyProperty; - set - { - _fieldNameQualifyProperty = value; - PropertyName = _fieldNameQualifyProperty - ? $"{Parent.IdentifierName.Capitalize()}_{IdentifierName}" - : IdentifierName; - } - } - public override string TargetID => $"{Parent.IdentifierName}.{IdentifierName}"; + public bool FieldNameIsExemptFromValidation + => Declaration?.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember) ?? false; } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeField.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeField.cs new file mode 100644 index 0000000000..a3be39719d --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeField.cs @@ -0,0 +1,140 @@ +using Rubberduck.Parsing; +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.EncapsulateField +{ + public interface IEncapsulatedUserDefinedTypeField : IEncapsulateFieldCandidate + { + IEnumerable Members { get; } + void AddMember(IEncapsulatedUserDefinedTypeMember member); + bool FieldQualifyMemberPropertyNames { set; get; } + bool TypeDeclarationIsPrivate { set; get; } + } + + public class EncapsulatedUserDefinedTypeField : EncapsulateFieldCandidate, IEncapsulatedUserDefinedTypeField + { + public EncapsulatedUserDefinedTypeField(Declaration declaration, IEncapsulateFieldNamesValidator validator) + : base(declaration, validator) + { + PropertyAccessExpression = () => EncapsulateFlag ? NewFieldName : IdentifierName; + } + + public void AddMember(IEncapsulatedUserDefinedTypeMember member) + { + _udtMembers.Add(member); + } + + private List _udtMembers = new List(); + public IEnumerable Members => _udtMembers; + + public bool TypeDeclarationIsPrivate { set; get; } + + public bool FieldQualifyMemberPropertyNames + { + set + { + foreach (var member in Members) + { + member.FieldQualifyPropertyName = value; + } + } + + get => Members.All(m => m.FieldQualifyPropertyName); + } + + public override void LoadReferenceExpressionChanges() + { + if (TypeDeclarationIsPrivate) + { + LoadPrivateUDTFieldReferenceExpressions(); + LoadUDTMemberReferenceExpressions(); + return; + } + LoadFieldReferenceExpressions(); + } + + public override IEnumerable PropertyGenerationSpecs + { + get + { + if (TypeDeclarationIsPrivate) + { + var specs = new List(); + foreach (var member in Members) + { + specs.Add(member.AsPropertyGeneratorSpec); + } + return specs; + } + return new List() { AsPropertyGeneratorSpec }; + } + } + + public override IEnumerable> ReferenceReplacements + { + get + { + var results = new List>(); + foreach (var replacement in IdentifierReplacements) + { + var kv = new KeyValuePair + (replacement.Key, replacement.Value); + results.Add(kv); + } + foreach (var member in Members) + { + foreach (var replacement in member.IdentifierReplacements) + { + var kv = new KeyValuePair + (replacement.Key, replacement.Value); + results.Add(kv); + } + } + return results; + } + } + + private void LoadPrivateUDTFieldReferenceExpressions() + { + foreach (var idRef in References) + { + if (idRef.QualifiedModuleName == QualifiedModuleName + && idRef.Context.Parent.Parent is VBAParser.WithStmtContext wsc) + { + AddReferenceReplacement(idRef, NewFieldName); + } + } + } + + private void LoadUDTMemberReferenceExpressions() + { + foreach (var member in Members) + { + foreach (var rf in member.References) + { + if (rf.QualifiedModuleName == QualifiedModuleName + && !rf.Context.TryGetAncestor(out _)) + { + member.AddReferenceReplacement(rf, member.PropertyName); + } + else + { + //If rf is a WithMemberAccess expression, modify the LExpr. e.g. "With this" => "With " + var moduleQualifier = rf.Context.TryGetAncestor(out _) + || rf.QualifiedModuleName == QualifiedModuleName + ? string.Empty + : $"{QualifiedModuleName.ComponentName}"; + + member.AddReferenceReplacement(rf, $"{moduleQualifier}.{member.PropertyName}"); + } + } + } + } + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeMember.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeMember.cs new file mode 100644 index 0000000000..35844a83c2 --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeMember.cs @@ -0,0 +1,134 @@ +using Antlr4.Runtime; +using Rubberduck.Parsing; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Symbols; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + public interface IEncapsulatedUserDefinedTypeMember : IEncapsulateFieldCandidate + { + IEncapsulatedUserDefinedTypeField Parent { get; } + bool FieldQualifyPropertyName { set; get; } + IPropertyGeneratorSpecification AsPropertyGeneratorSpec { get; } + Dictionary IdentifierReplacements { get; } + } + + public class EncapsulatedUserDefinedTypeMember : EncapsulateFieldCandidate, IEncapsulatedUserDefinedTypeMember + { + public EncapsulatedUserDefinedTypeMember(Declaration target, IEncapsulatedUserDefinedTypeField udtVariable, IEncapsulateFieldNamesValidator validator) + : base(target, validator) + { + Parent = udtVariable; + + PropertyName = IdentifierName; + PropertyAccessExpression = () => $"{Parent.PropertyAccessExpression()}.{PropertyName}"; + ReferenceExpression = () => $"{Parent.PropertyAccessExpression()}.{PropertyName}"; + } + + public IEncapsulatedUserDefinedTypeField Parent { private set; get; } + + private bool _fieldNameQualifyProperty; + public bool FieldQualifyPropertyName + { + get => _fieldNameQualifyProperty; + set + { + _fieldNameQualifyProperty = value; + PropertyName = _fieldNameQualifyProperty + ? $"{Parent.IdentifierName.Capitalize()}_{IdentifierName}" + : IdentifierName; + } + } + + public override string TargetID => $"{Parent.IdentifierName}.{IdentifierName}"; + + public override IEnumerable References + { + get + { + //var references = new List(); + //foreach (var member in Members) + //{ + //references.AddRange(GetUDTMemberReferencesForField(this, Parent)); + //} + return GetUDTMemberReferencesForField(this, Parent); + } + } + + public override void AddReferenceReplacement(IdentifierReference idRef, string replacementText) + { + Debug.Assert(idRef.Context.Parent is ParserRuleContext, "idRef.Context.Parent is not convertable to ParserRuleContext"); + //if (idRef.Context.Parent is ParserRuleContext prContext) + //{ + IdentifierReplacements.Add(idRef, new RewriteReplacePair(replacementText, idRef.Context.Parent as ParserRuleContext)); + return; + //} + } + + public new IPropertyGeneratorSpecification AsPropertyGeneratorSpec + => base.AsPropertyGeneratorSpec; + + public new Dictionary IdentifierReplacements { get; } = new Dictionary(); + + + private IEnumerable GetUDTMemberReferencesForField(IEncapsulateFieldCandidate udtMember, IEncapsulatedUserDefinedTypeField field) + { + var refs = new List(); + foreach (var idRef in udtMember.Declaration.References) + { + if (idRef.Context.TryGetAncestor(out var mac)) + { + var LHS = mac.children.First(); + switch (LHS) + { + case VBAParser.SimpleNameExprContext snec: + if (snec.GetText().Equals(field.IdentifierName)) + { + refs.Add(idRef); + } + break; + case VBAParser.MemberAccessExprContext submac: + if (submac.children.Last() is VBAParser.UnrestrictedIdentifierContext ur && ur.GetText().Equals(field.IdentifierName)) + { + refs.Add(idRef); + } + break; + case VBAParser.WithMemberAccessExprContext wmac: + if (wmac.children.Last().GetText().Equals(field.IdentifierName)) + { + refs.Add(idRef); + } + break; + } + } + else if (idRef.Context.TryGetAncestor(out var wmac)) + { + var wm = wmac.GetAncestor(); + var Lexpr = wm.GetChild(); + if (Lexpr.GetText().Equals(field.IdentifierName)) + { + refs.Add(idRef); + } + } + } + return refs; + } + + //private bool RequiresAccessQualification(IdentifierReference idRef) + //{ + // var isLHSOfMemberAccess = + // (idRef.Context.Parent is VBAParser.MemberAccessExprContext + // || idRef.Context.Parent is VBAParser.WithMemberAccessExprContext) + // && !(idRef.Context == idRef.Context.Parent.GetChild(0));// is VBAParser.SimpleNameExprContext)) + + // return idRef.QualifiedModuleName != idRef.Declaration.QualifiedModuleName + // && !isLHSOfMemberAccess; + //} + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs b/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs index 5de54506a8..1a5156afa1 100644 --- a/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs @@ -1,4 +1,6 @@ -using System; +using Rubberduck.SmartIndenter; +using System; +using System.Collections.Generic; namespace Rubberduck.Refactorings.EncapsulateField { @@ -10,9 +12,10 @@ public interface IPropertyGeneratorSpecification string ParameterName { get; } bool GenerateLetter { get; } bool GenerateSetter { get; } + bool UsesSetAssignment { get; } } - public struct PropertyGeneratorDataObject : IPropertyGeneratorSpecification + public struct PropertyGeneratorSpecification : IPropertyGeneratorSpecification { public string PropertyName { get; set; } public string BackingField { get; set; } @@ -20,6 +23,7 @@ public struct PropertyGeneratorDataObject : IPropertyGeneratorSpecification public string ParameterName { get; set; } public bool GenerateLetter { get; set; } public bool GenerateSetter { get; set; } + public bool UsesSetAssignment { get; set; } } public class PropertyGenerator @@ -34,18 +38,28 @@ public PropertyGenerator(IPropertyGeneratorSpecification spec) ParameterName = spec.ParameterName; GenerateLetter = spec.GenerateLetter; GenerateSetter = spec.GenerateSetter; + UsesSetAssignment = spec.UsesSetAssignment; } + public string PropertyName { get; set; } public string BackingField { get; set; } public string AsTypeName { get; set; } public string ParameterName { get; set; } public bool GenerateLetter { get; set; } public bool GenerateSetter { get; set; } + public bool UsesSetAssignment { get; set; } public string AllPropertyCode => $"{GetterCode}{(GenerateLetter ? LetterCode : string.Empty)}{(GenerateSetter ? SetterCode : string.Empty)}"; - public string GetterCode + public IEnumerable AsEnumerableLines => AllPropertyCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None); + + public string AsPropertyBlock(IIndenter indenter) + { + return string.Join(Environment.NewLine, indenter.Indent(AsEnumerableLines, true)); + } + + private string GetterCode { get { @@ -64,13 +78,13 @@ public string GetterCode return string.Join(Environment.NewLine, $"Public Property Get {PropertyName}() As {AsTypeName}", - $" {(GenerateSetter ? "Set " : string.Empty)}{PropertyName} = {BackingField}", + $" {(UsesSetAssignment ? "Set " : string.Empty)}{PropertyName} = {BackingField}", "End Property", Environment.NewLine); } } - public string SetterCode + private string SetterCode { get { @@ -86,7 +100,7 @@ public string SetterCode } } - public string LetterCode + private string LetterCode { get { diff --git a/Rubberduck.Refactorings/EncapsulateField/RewriterRemoveWorkaround.cs b/Rubberduck.Refactorings/EncapsulateField/RewriterRemoveWorkaround.cs index 75254055a9..5bce43dde7 100644 --- a/Rubberduck.Refactorings/EncapsulateField/RewriterRemoveWorkaround.cs +++ b/Rubberduck.Refactorings/EncapsulateField/RewriterRemoveWorkaround.cs @@ -1,6 +1,8 @@ using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; +using Rubberduck.VBEditor; using System; using System.Collections.Generic; using System.Linq; @@ -31,8 +33,30 @@ public static void Remove(Declaration target, IEncapsulateFieldRewriter rewriter RemovedVariables[varList].Add(target); } - public static void RemoveFieldsDeclaredInLists(IEncapsulateFieldRewriter rewriter) + //public static void RemoveFieldsDeclaredInLists(IEncapsulateFieldRewriter rewriter) + //{ + // foreach (var key in RemovedVariables.Keys) + // { + // var variables = key.children.Where(ch => ch is VBAParser.VariableSubStmtContext); + // if (variables.Count() == RemovedVariables[key].Count) + // { + // rewriter.Remove(key.Parent); + // } + // else + // { + // foreach (var dec in RemovedVariables[key]) + // { + // rewriter.Remove(dec); + // } + // } + // } + // RemovedVariables = new Dictionary>(); + //} + + public static void RemoveFieldsDeclaredInLists(IExecutableRewriteSession rewriteSession, QualifiedModuleName qmn) { + var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, qmn); + foreach (var key in RemovedVariables.Keys) { var variables = key.children.Where(ch => ch is VBAParser.VariableSubStmtContext); diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs index 39a29622fe..bb60f02dca 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs @@ -19,7 +19,7 @@ public EncapsulateWithBackingFields(QualifiedModuleName qmn, IIndenter indenter, { } - protected override void ModifyEncapsulatedField(IEncapsulateFieldCandidate field, IRewriteSession rewriteSession) + protected override void ModifyField(IEncapsulateFieldCandidate field, IRewriteSession rewriteSession) { var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); @@ -43,23 +43,25 @@ protected override void ModifyEncapsulatedField(IEncapsulateFieldCandidate field return; } - protected override EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNewContent newContent, IEnumerable encapsulationCandates) + protected override EncapsulateFieldNewContent LoadNewDeclarationBlocks(EncapsulateFieldNewContent newContent, EncapsulateFieldModel model) { - var nonUdtMemberFields = encapsulationCandates - .Where(encFld => !encFld.IsUDTMember && encFld.EncapsulateFlag); - - foreach (var nonUdtMemberField in nonUdtMemberFields) + foreach (var field in model.FlaggedFieldCandidates) { - if (nonUdtMemberField.Declaration.Accessibility == Accessibility.Private && nonUdtMemberField.NewFieldName.Equals(nonUdtMemberField.Declaration.IdentifierName)) + if (field.Declaration.Accessibility == Accessibility.Private && field.NewFieldName.Equals(field.Declaration.IdentifierName)) { continue; } - if (nonUdtMemberField.Declaration.IsDeclaredInList()) + //Fields within a list (where Accessibility is 'Public' + //are removed from the list (within ModifyField(...)) and + //inserted as a new Declaration + if (field.Declaration.IsDeclaredInList()) { - var targetIdentifier = nonUdtMemberField.Declaration.Context.GetText().Replace(nonUdtMemberField.IdentifierName, nonUdtMemberField.NewFieldName); - var newField = nonUdtMemberField.Declaration.IsTypeSpecified ? $"{Tokens.Private} {targetIdentifier}" : $"{Tokens.Private} {targetIdentifier} {Tokens.As} {nonUdtMemberField.Declaration.AsTypeName}"; + var targetIdentifier = field.Declaration.Context.GetText().Replace(field.IdentifierName, field.NewFieldName); + var newField = field.Declaration.IsTypeSpecified + ? $"{Tokens.Private} {targetIdentifier}" + : $"{Tokens.Private} {targetIdentifier} {Tokens.As} {field.Declaration.AsTypeName}"; newContent.AddDeclarationBlock(newField); } diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs index 5f2cc544c1..8af0f064fb 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs @@ -23,83 +23,48 @@ public EncapsulateWithBackingUserDefinedType(QualifiedModuleName qmn, IIndenter protected override IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) { - foreach (var field in model.FieldCandidates) + foreach (var field in model.FlaggedFieldCandidates) { if (field is IEncapsulatedUserDefinedTypeField udt) { - var fd = udt as IEncapsulateFieldCandidate; - fd.PropertyAccessExpression = - () => - { - var accessor = udt.EncapsulateFlag ? fd.PropertyName : udt.NewFieldName; - return $"{StateUDTField.PropertyAccessExpression()}.{accessor}"; - }; + udt.PropertyAccessExpression = () => $"{StateUDTField.PropertyAccessExpression()}.{udt.PropertyName}"; - udt.ReferenceExpression = fd.PropertyAccessExpression; + udt.ReferenceExpression = udt.PropertyAccessExpression; foreach (var member in udt.Members) { - member.PropertyAccessExpression = () => $"{fd.PropertyAccessExpression()}.{member.PropertyName}"; - member.ReferenceExpression = () => $"{fd.PropertyAccessExpression()}.{member.PropertyName}"; + member.PropertyAccessExpression = () => $"{udt.PropertyAccessExpression()}.{member.PropertyName}"; + member.ReferenceExpression = () => $"{udt.PropertyAccessExpression()}.{member.PropertyName}"; } } else { - var efd = field; - efd.PropertyAccessExpression = () => $"{StateUDTField.PropertyAccessExpression()}.{efd.PropertyName}"; - efd.ReferenceExpression = efd.PropertyAccessExpression; + field.PropertyAccessExpression = () => $"{StateUDTField.PropertyAccessExpression()}.{field.PropertyName}"; + field.ReferenceExpression = field.PropertyAccessExpression; } } - foreach (var field in model.FlaggedFieldCandidates) - { - ModifyEncapsulatedField(field, rewriteSession); - } - - SetupReferenceModifications(model); - foreach (var field in model.FlaggedFieldCandidates) - { - RenameReferences(field, rewriteSession); - if (field is IEncapsulatedUserDefinedTypeField udtField) - { - foreach (var member in udtField.Members) - { - RenameReferences(member, rewriteSession); - } - } - } - - var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); - RewriterRemoveWorkAround.RemoveFieldsDeclaredInLists(rewriter); - - InsertNewContent(model.CodeSectionStartIndex, model, rewriteSession, asPreview); - - return rewriteSession; + return base.RefactorRewrite(model, rewriteSession, asPreview); } public IEncapsulateFieldCandidate StateUDTField { set; get; } - protected override void ModifyEncapsulatedField(IEncapsulateFieldCandidate target, /*IFieldEncapsulationAttributes attributes,*/ IRewriteSession rewriteSession) + protected override void ModifyField(IEncapsulateFieldCandidate field, IRewriteSession rewriteSession) { var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); - RewriterRemoveWorkAround.Remove(target.Declaration, rewriter); + RewriterRemoveWorkAround.Remove(field.Declaration, rewriter); //rewriter.Remove(target.Declaration); return; } - protected override EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNewContent newContent, IEnumerable encapsulationCandidates) + protected override EncapsulateFieldNewContent LoadNewDeclarationBlocks(EncapsulateFieldNewContent newContent, EncapsulateFieldModel model) { var udt = new UDTDeclarationGenerator(StateUDTField.AsTypeName); - var stateUDTMembers = encapsulationCandidates - .Where(encFld => !encFld.IsUDTMember - && (encFld.EncapsulateFlag - || encFld is IEncapsulatedUserDefinedTypeField udtFld && udtFld.Members.Any(m => m.EncapsulateFlag))); - - udt.AddMembers(stateUDTMembers); + udt.AddMembers(model.FlaggedFieldCandidates); - newContent.AddDeclarationBlock(udt.TypeDeclarationBlock(Indenter)); + newContent.AddTypeDeclarationBlock(udt.TypeDeclarationBlock(Indenter)); newContent.AddDeclarationBlock(udt.FieldDeclaration(StateUDTField.NewFieldName)); diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs index 2a64b4082a..d81855ba1c 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs @@ -2,15 +2,12 @@ using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; -using Rubberduck.Parsing.VBA; using Rubberduck.SmartIndenter; using Rubberduck.VBEditor; -using Rubberduck.VBEditor.SafeComWrappers; using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Rubberduck.Refactorings.EncapsulateField.Strategies { @@ -23,6 +20,7 @@ public interface IEncapsulateFieldStrategy public abstract class EncapsulateFieldStrategiesBase : IEncapsulateFieldStrategy { private IEncapsulateFieldNamesValidator _validator; + protected static string DoubleSpace => $"{Environment.NewLine}{Environment.NewLine}"; public EncapsulateFieldStrategiesBase(QualifiedModuleName qmn, IIndenter indenter, IEncapsulateFieldNamesValidator validator) { @@ -37,269 +35,101 @@ public EncapsulateFieldStrategiesBase(QualifiedModuleName qmn, IIndenter indente public IExecutableRewriteSession GeneratePreview(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) { - return RefactorRewrite(model, rewriteSession, true); + if (!model.FlaggedEncapsulationFields.Any()) { return rewriteSession; } + + return RefactorRewrite(model, rewriteSession, asPreview: true); } public IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) { - return RefactorRewrite(model, rewriteSession, false); + if (!model.FlaggedEncapsulationFields.Any()) { return rewriteSession; } + + return RefactorRewrite(model, rewriteSession, asPreview: false); } - protected abstract void ModifyEncapsulatedField(IEncapsulateFieldCandidate target, /*IFieldEncapsulationAttributes attributes, */IRewriteSession rewriteSession); + protected abstract void ModifyField(IEncapsulateFieldCandidate target, IRewriteSession rewriteSession); - protected abstract EncapsulateFieldNewContent LoadNewDeclarationsContent(EncapsulateFieldNewContent newContent, IEnumerable encapsulationCandidates); + protected abstract EncapsulateFieldNewContent LoadNewDeclarationBlocks(EncapsulateFieldNewContent newContent, EncapsulateFieldModel model); protected virtual IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) { - var udtFieldsByTypeName = model.FlaggedUDTFieldCandidates.GroupBy((udtCandidate) => (udtCandidate as IEncapsulateFieldCandidate).AsTypeName); - foreach (var udtField in model.FlaggedUDTFieldCandidates) - { - var fd = udtField as IEncapsulateFieldCandidate; - var hasMultipleUDTFieldsOfSameType = udtFieldsByTypeName - .Where(group => group.Key == fd.AsTypeName).Single().Count() > 1; + ConfigureSelectedEncapsulationObjects(model); - foreach (var member in udtField.Members) - { - member.FieldQualifyProperty = hasMultipleUDTFieldsOfSameType; - } - } - - foreach (var field in model.FlaggedEncapsulationFields) - { - ModifyEncapsulatedField(field, rewriteSession); - } + ModifyFields(model, rewriteSession); ModifyReferences(model, rewriteSession); - var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); - RewriterRemoveWorkAround.RemoveFieldsDeclaredInLists(rewriter); + RewriterRemoveWorkAround.RemoveFieldsDeclaredInLists(rewriteSession, TargetQMN); - InsertNewContent(model.CodeSectionStartIndex, model, rewriteSession, asPreview); + InsertNewContent(model, rewriteSession, asPreview); return rewriteSession; } - private void ModifyReferences(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) + protected void ConfigureSelectedEncapsulationObjects(EncapsulateFieldModel model) { - SetupReferenceModifications(model); - foreach (var field in model.FlaggedEncapsulationFields) - { - RenameReferences(field, rewriteSession); - if (field is IEncapsulatedUserDefinedTypeField udtField) - { - foreach (var member in udtField.Members) - { - RenameReferences(member, rewriteSession); - } - } - } - } - - protected void SetupReferenceModifications(EncapsulateFieldModel model) - { - var flaggedPrivateUDTFields = model.FlaggedUDTFieldCandidates.Where(udt => udt.TypeDeclarationIsPrivate).ToList(); - - foreach (var field in model.FlaggedFieldCandidates.Except(flaggedPrivateUDTFields)) - { - LoadFieldReferenceExpressions(field); - } - - foreach( var udtField in flaggedPrivateUDTFields) + foreach (var udtField in model.FlaggedUDTFieldCandidates) { - LoadPrivateUDTFieldReferenceExpressions(udtField); - LoadUDTMemberReferenceExpressions(udtField); + udtField.FieldQualifyMemberPropertyNames = model.FlaggedUDTFieldCandidates.Where(f => f.AsTypeName.Equals(udtField.AsTypeName)).Count() > 1; } - } - - private void LoadFieldReferenceExpressions(IEncapsulateFieldCandidate field) - { - foreach (var idRef in field.References) - { - //if (idRef.QualifiedModuleName == field.QualifiedModuleName - // && idRef.Context.Parent is VBAParser.WithStmtContext wsc) - //{ - // field[idRef] = field.NewFieldName; - // continue; - //} - field[idRef] = RequiresAccessQualification(idRef) - ? $"{field.QualifiedModuleName.ComponentName}.{field.ReferenceExpression()}" - : field.ReferenceExpression(); - } + StageReferenceReplacementExpressions(model); } - private void LoadPrivateUDTFieldReferenceExpressions(IEncapsulateFieldCandidate field) + protected void ModifyFields(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) { - foreach (var idRef in field.References) + foreach (var field in model.FlaggedEncapsulationFields) { - if (idRef.QualifiedModuleName == field.QualifiedModuleName - && idRef.Context.Parent.Parent is VBAParser.WithStmtContext wsc) - { - field[idRef] = field.NewFieldName; - } + ModifyField(field, rewriteSession); } } - private void LoadUDTMemberReferenceExpressions(IEncapsulatedUserDefinedTypeField udtField) + protected void ModifyReferences(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) { - foreach (var member in udtField.Members) + foreach (var rewriteReplacement in model.FlaggedEncapsulationFields.SelectMany(fld => fld.ReferenceReplacements)) { - var references = GetUDTMemberReferencesForField(member, udtField); - foreach (var rf in references) - { - var test = member.ReferenceExpression(); - if (rf.QualifiedModuleName == udtField.QualifiedModuleName) - { - //If rf is a WithMemberAccess expression, modify the LExpr. e.g. "With this" => "With this1" - if (rf.Context.TryGetAncestor(out var wmac)) - { - var wm = wmac.GetAncestor(); - var Lexpr = wm.GetChild(); - continue; - } - member[rf] = $"{member.PropertyName}"; - } - else - { - //If rf is a WithMemberAccess expression, modify the LExpr. e.g. "With this" => "With " - var moduleQualifier = rf.Context.TryGetAncestor(out _) - || rf.QualifiedModuleName == udtField.QualifiedModuleName - ? string.Empty - : $"{udtField.QualifiedModuleName.ComponentName}"; - - member[rf] = $"{moduleQualifier}.{member.PropertyName}"; - } - test = member[rf]; - } + var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, rewriteReplacement.Key.QualifiedModuleName); + rewriter.Replace(rewriteReplacement.Value); } } - private IEnumerable GetUDTMemberReferencesForField(IEncapsulateFieldCandidate udtMember, IEncapsulatedUserDefinedTypeField field) - { - var refs = new List(); - foreach (var idRef in udtMember.References) + protected void StageReferenceReplacementExpressions(EncapsulateFieldModel model) + { + foreach (var field in model.FlaggedEncapsulationFields) { - if (idRef.Context.TryGetAncestor(out var mac)) - { - var LHS = mac.children.First(); - switch(LHS) - { - case VBAParser.SimpleNameExprContext snec: - if (snec.GetText().Equals(field.IdentifierName)) - { - refs.Add(idRef); - } - break; - case VBAParser.MemberAccessExprContext submac: - if (submac.children.Last() is VBAParser.UnrestrictedIdentifierContext ur && ur.GetText().Equals(field.IdentifierName)) - { - refs.Add(idRef); - } - break; - case VBAParser.WithMemberAccessExprContext wmac: - if (wmac.children.Last().GetText().Equals(field.IdentifierName)) - { - refs.Add(idRef); - } - break; - } - } - else if (idRef.Context.TryGetAncestor(out var wmac)) - { - var wm = wmac.GetAncestor(); - var Lexpr = wm.GetChild(); - if (Lexpr.GetText().Equals(field.IdentifierName)) - { - refs.Add(idRef); - } - } + field.LoadReferenceExpressionChanges(); } - return refs; - } - - private bool RequiresAccessQualification(IdentifierReference idRef) - { - var isLHSOfMemberAccess = - (idRef.Context.Parent is VBAParser.MemberAccessExprContext - || idRef.Context.Parent is VBAParser.WithMemberAccessExprContext) - && !(idRef.Context == idRef.Context.Parent.GetChild(0));// is VBAParser.SimpleNameExprContext)) - - return idRef.QualifiedModuleName != idRef.Declaration.QualifiedModuleName - && !isLHSOfMemberAccess; } - protected void InsertNewContent(int? codeSectionStartIndex, EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool postPendPreviewMessage = false) + protected void InsertNewContent(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool postPendPreviewMessage = false) { var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); - var newContent = LoadNewDeclarationsContent(new EncapsulateFieldNewContent(), model.FieldCandidates); - - if (postPendPreviewMessage) + var newContent = new EncapsulateFieldNewContent() { - var postScript = "'<===== No Changes below this line =====>"; - newContent = LoadNewPropertiesContent(newContent, model.FlaggedEncapsulationFields, postScript); - } - else - { - newContent = LoadNewPropertiesContent(newContent, model.FlaggedEncapsulationFields); - } + PostPendComment = postPendPreviewMessage ? "'<===== All Changes above this line =====>" : string.Empty, + }; - rewriter.InsertNewContent(codeSectionStartIndex, newContent); + newContent = LoadNewDeclarationBlocks(newContent, model); - } + newContent = LoadNewPropertyBlocks(newContent, model); - protected virtual IList PropertiesContent(IEnumerable flaggedEncapsulationFields) - { - var textBlocks = new List(); - foreach (var field in flaggedEncapsulationFields) - { - if (field is IEncapsulatedUserDefinedTypeField udtField && udtField.TypeDeclarationIsPrivate) - { - foreach (var member in udtField.Members) - { - textBlocks.Add(BuildPropertiesTextBlock(member.AsPropertyGeneratorSpec)); - } - continue; - } - textBlocks.Add(BuildPropertiesTextBlock(field.AsPropertyGeneratorSpec)); - } - return textBlocks; + rewriter.InsertNewContent(model.CodeSectionStartIndex, newContent); } - private string BuildPropertiesTextBlock(IPropertyGeneratorSpecification field) + private EncapsulateFieldNewContent LoadNewPropertyBlocks(EncapsulateFieldNewContent newContent, EncapsulateFieldModel model) //, string postScript = null) { - var generator = new PropertyGenerator(field); - var propertyTextLines = generator.AllPropertyCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None); - return string.Join(Environment.NewLine, Indenter.Indent(propertyTextLines, true)); - } + if (!model.FlaggedEncapsulationFields.Any()) { return newContent; } - private EncapsulateFieldNewContent LoadNewPropertiesContent(EncapsulateFieldNewContent newContent, IEnumerable FlaggedEncapsulationFields, string postScript = null) - { - if (!FlaggedEncapsulationFields.Any()) { return newContent; } + var propertyBlocks = new List(); + var propertyGenerationSpecs = model.FlaggedEncapsulationFields + .SelectMany(f => f.PropertyGenerationSpecs); - var theContent = string.Join($"{Environment.NewLine}{Environment.NewLine}", PropertiesContent(FlaggedEncapsulationFields)); - newContent.AddCodeBlock(theContent); - if (postScript?.Length > 0) + foreach (var spec in propertyGenerationSpecs) { - newContent.AddCodeBlock($"{postScript}{Environment.NewLine}{Environment.NewLine}"); + newContent.AddCodeBlock(new PropertyGenerator(spec).AsPropertyBlock(Indenter)); } return newContent; } - - protected virtual void RenameReferences(IEncapsulateFieldCandidate efd, IRewriteSession rewriteSession) - { - foreach (var reference in efd.Declaration.References) - { - if (efd.TryGetReferenceExpression(reference, out var expression)) - { - var replacementContext = efd.IsUDTMember - ? reference.Context.Parent - : reference.Context; - - var rewriter = rewriteSession.CheckOutModuleRewriter(reference.QualifiedModuleName); - rewriter.Replace(replacementContext, expression); - } - } - } } } diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index 601e337d59..5c8cfdddeb 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -18,9 +18,9 @@ namespace RubberduckTests.Refactoring.EncapsulateField { public class EncapsulateFieldTestSupport : InteractiveRefactoringTestBase { - private TestEncapsulationAttributes UserModifiedEncapsulationAttributes(string field, string property = null, bool? isReadonly = null, bool encapsulateFlag = true) + private TestEncapsulationAttributes UserModifiedEncapsulationAttributes(string field, string property = null, bool isReadonly = false, bool encapsulateFlag = true) { - var testAttrs = new TestEncapsulationAttributes(field, encapsulateFlag, isReadonly ?? false); + var testAttrs = new TestEncapsulationAttributes(field, encapsulateFlag, isReadonly); if (property != null) { testAttrs.PropertyName = property; @@ -37,7 +37,7 @@ public Func UserAcceptsDefaults(bo }; } - public Func SetParametersForSingleTarget(string field, string property = null, bool? isReadonly = null, bool encapsulateFlag = true, bool asUDT = false) + public Func SetParametersForSingleTarget(string field, string property = null, bool isReadonly = false, bool encapsulateFlag = true, bool asUDT = false) { var clientAttrs = UserModifiedEncapsulationAttributes(field, property, isReadonly, encapsulateFlag); diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index 910c4f1160..c4b9b780f8 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -339,6 +339,26 @@ End Property Assert.AreEqual(expectedCode, actualCode); } + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulatePrivateField_ReadOnlyRequiresSet() + { + const string inputCode = + @"|Private fizz As Collection"; + + const string expectedCode = + @"Private fizz As Collection + +Public Property Get Name() As Collection + Set Name = fizz +End Property +"; + var presenterAction = Support.SetParametersForSingleTarget("fizz", "Name", isReadonly: true); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + Assert.AreEqual(expectedCode, actualCode); + } + [Test] [Category("Refactorings")] [Category("Encapsulate Field")] From 6e06f4570044e45374f1ff8e8f4c29b2ee43715c Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Sat, 7 Dec 2019 13:23:26 -0800 Subject: [PATCH 047/461] Allow overwrite of IdentifierReference replacement --- .../EncapsulateField/EncapsulateFieldModel.cs | 24 ++++-------- .../EncapsulatedFieldDeclaration.cs | 22 +++++------ .../EncapsulatedUserDefinedTypeField.cs | 6 +-- .../EncapsulatedUserDefinedTypeMember.cs | 37 +++++-------------- 4 files changed, 29 insertions(+), 60 deletions(-) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index d64a2f6f01..a7951b8d74 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -43,7 +43,7 @@ public EncapsulateFieldModel(Declaration target, IDeclarationFinderProvider decl FieldCandidates.AddRange(candidates); - EncapsulationStrategy = new EncapsulateWithBackingFields(_targetQMN, _indenter, _validator); + //EncapsulationStrategy = new EncapsulateWithBackingFields(_targetQMN, _indenter, _validator); this[target].EncapsulateFlag = true; } @@ -74,31 +74,23 @@ public IEncapsulateFieldCandidate this[string encapsulatedFieldTargetID] public IEncapsulateFieldCandidate this[Declaration fieldDeclaration] => FieldCandidates.Where(c => c.Declaration == fieldDeclaration).Single(); - public IEncapsulateFieldStrategy EncapsulationStrategy { set; get; } - - public bool EncapsulateWithUDT + public IEncapsulateFieldStrategy EncapsulationStrategy { - set + get { - if ((value && EncapsulationStrategy is EncapsulateWithBackingUserDefinedType) - || (!value && EncapsulationStrategy is EncapsulateWithBackingFields)) { return; } - - if (value) + if (EncapsulateWithUDT) { - EncapsulationStrategy = new EncapsulateWithBackingUserDefinedType(_targetQMN, _indenter, _validator) + return new EncapsulateWithBackingUserDefinedType(_targetQMN, _indenter, _validator) { StateUDTField = CandidateFactory.CreateStateUDTField(_targetQMN) }; } - else - { - EncapsulationStrategy = new EncapsulateWithBackingFields(_targetQMN, _indenter, _validator); - } + return new EncapsulateWithBackingFields(_targetQMN, _indenter, _validator); } - - get => EncapsulationStrategy is EncapsulateWithBackingUserDefinedType; } + public bool EncapsulateWithUDT { set; get; } + public string PreviewRefactoring() => _previewDelegate(this); public int? CodeSectionStartIndex diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs index 8a6d5e5fea..3c85df3a9f 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs @@ -37,9 +37,10 @@ public interface IEncapsulateFieldCandidate IEnumerable PropertyGenerationSpecs { get; } IEnumerable> ReferenceReplacements { get; } void LoadReferenceExpressionChanges(); - void AddReferenceReplacement(IdentifierReference idRef, string replacementText); + void SetReferenceRewriteContent(IdentifierReference idRef, string replacementText); RewriteReplacePair ReferenceReplacement(IdentifierReference idRef); - RewriteReplacePair? FindRewriteReplacePair(IdentifierReference idRef); + //RewriteReplacePair? FindRewriteReplacePair(IdentifierReference idRef); + //void ClearIdentifierReferenceExpressionCache(); } public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate @@ -48,7 +49,7 @@ public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate protected QualifiedModuleName _qmn; private string _identifierName; private IEncapsulateFieldNamesValidator _validator; - private Dictionary _idRefRenames { set; get; } = new Dictionary(); + //private Dictionary _idRefRenames { set; get; } = new Dictionary(); private EncapsulationIdentifiers _fieldAndProperty; public EncapsulateFieldCandidate(Declaration declaration, IEncapsulateFieldNamesValidator validator) @@ -110,22 +111,17 @@ public virtual IEnumerable } } - - public RewriteReplacePair? FindRewriteReplacePair(IdentifierReference idRef) + public virtual void SetReferenceRewriteContent(IdentifierReference idRef, string replacementText) { if (IdentifierReplacements.ContainsKey(idRef)) { - return IdentifierReplacements[idRef]; + IdentifierReplacements[idRef] = new RewriteReplacePair(replacementText, idRef.Context); + return; } - return null; - } - - public virtual void AddReferenceReplacement(IdentifierReference idRef, string replacementText) - { IdentifierReplacements.Add(idRef, new RewriteReplacePair(replacementText, idRef.Context)); } - public RewriteReplacePair ReferenceReplacement(IdentifierReference idRef) //, ParserRuleContextExtensions context)] + public RewriteReplacePair ReferenceReplacement(IdentifierReference idRef) { return IdentifierReplacements.Single(r => r.Key == idRef).Value; } @@ -209,7 +205,7 @@ protected virtual void LoadFieldReferenceExpressions() ? $"{field.QualifiedModuleName.ComponentName}.{field.ReferenceExpression()}" : field.ReferenceExpression(); - field.AddReferenceReplacement(idRef, replacementText); + field.SetReferenceRewriteContent(idRef, replacementText); } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeField.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeField.cs index a3be39719d..3ad78d917b 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeField.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeField.cs @@ -107,7 +107,7 @@ private void LoadPrivateUDTFieldReferenceExpressions() if (idRef.QualifiedModuleName == QualifiedModuleName && idRef.Context.Parent.Parent is VBAParser.WithStmtContext wsc) { - AddReferenceReplacement(idRef, NewFieldName); + SetReferenceRewriteContent(idRef, NewFieldName); } } } @@ -121,7 +121,7 @@ private void LoadUDTMemberReferenceExpressions() if (rf.QualifiedModuleName == QualifiedModuleName && !rf.Context.TryGetAncestor(out _)) { - member.AddReferenceReplacement(rf, member.PropertyName); + member.SetReferenceRewriteContent(rf, member.PropertyName); } else { @@ -131,7 +131,7 @@ private void LoadUDTMemberReferenceExpressions() ? string.Empty : $"{QualifiedModuleName.ComponentName}"; - member.AddReferenceReplacement(rf, $"{moduleQualifier}.{member.PropertyName}"); + member.SetReferenceRewriteContent(rf, $"{moduleQualifier}.{member.PropertyName}"); } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeMember.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeMember.cs index 35844a83c2..fe657f4f40 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeMember.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeMember.cs @@ -48,27 +48,19 @@ public bool FieldQualifyPropertyName public override string TargetID => $"{Parent.IdentifierName}.{IdentifierName}"; - public override IEnumerable References - { - get - { - //var references = new List(); - //foreach (var member in Members) - //{ - //references.AddRange(GetUDTMemberReferencesForField(this, Parent)); - //} - return GetUDTMemberReferencesForField(this, Parent); - } - } + public override IEnumerable References + => GetUDTMemberReferencesForField(this, Parent); - public override void AddReferenceReplacement(IdentifierReference idRef, string replacementText) + public override void SetReferenceRewriteContent(IdentifierReference idRef, string replacementText) { Debug.Assert(idRef.Context.Parent is ParserRuleContext, "idRef.Context.Parent is not convertable to ParserRuleContext"); - //if (idRef.Context.Parent is ParserRuleContext prContext) - //{ - IdentifierReplacements.Add(idRef, new RewriteReplacePair(replacementText, idRef.Context.Parent as ParserRuleContext)); + + if (IdentifierReplacements.ContainsKey(idRef)) + { + IdentifierReplacements[idRef] = new RewriteReplacePair(replacementText, idRef.Context.Parent as ParserRuleContext); return; - //} + } + IdentifierReplacements.Add(idRef, new RewriteReplacePair(replacementText, idRef.Context.Parent as ParserRuleContext)); } public new IPropertyGeneratorSpecification AsPropertyGeneratorSpec @@ -119,16 +111,5 @@ private IEnumerable GetUDTMemberReferencesForField(IEncapsu } return refs; } - - //private bool RequiresAccessQualification(IdentifierReference idRef) - //{ - // var isLHSOfMemberAccess = - // (idRef.Context.Parent is VBAParser.MemberAccessExprContext - // || idRef.Context.Parent is VBAParser.WithMemberAccessExprContext) - // && !(idRef.Context == idRef.Context.Parent.GetChild(0));// is VBAParser.SimpleNameExprContext)) - - // return idRef.QualifiedModuleName != idRef.Declaration.QualifiedModuleName - // && !isLHSOfMemberAccess; - //} } } From 57af6065a54cd1733c003c5f19484d78b3b3bbb1 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Mon, 9 Dec 2019 11:12:34 -0800 Subject: [PATCH 048/461] Default values creation and validation changes --- .../EncapsulateFieldViewModel.cs | 2 +- .../EncapsulateFieldDeclarationFactory.cs | 41 +++++- .../EncapsulateField/EncapsulateFieldModel.cs | 6 +- .../EncapsulateFieldRefactoring.cs | 9 +- .../EncapsulateFieldValidator.cs | 125 +++++++----------- .../EncapsulatedFieldDeclaration.cs | 107 ++++++++++----- .../EncapsulatedUserDefinedTypeField.cs | 6 + .../EncapsulationIdentifiers.cs | 49 +++---- .../EncapsulateField/StateUDTField.cs | 34 +++++ .../EncapsulateWithBackingFields.cs | 2 +- .../EncapsulateWithBackingUserDefinedType.cs | 2 +- .../Strategies/EncapsulationStrategiesBase.cs | 4 +- .../UDTDeclarationGenerator.cs | 15 ++- .../EncapsulateFieldValidatorTests.cs | 123 +++++++++++++++++ .../EncapsulateUsingStateUDTTests.cs | 33 ++++- .../EncapsulatedFieldTests.cs | 113 ++-------------- .../EncapsulatedUDTFieldTests.cs | 93 ++++++------- .../EncapsulateField/TestSupport.cs | 34 ++++- .../Refactoring/EncapsulateFieldTests.cs | 37 ++---- 19 files changed, 501 insertions(+), 334 deletions(-) create mode 100644 Rubberduck.Refactorings/EncapsulateField/StateUDTField.cs diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs index 4645c6c126..aa01d9bc81 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs @@ -106,7 +106,7 @@ public bool TargetsHaveValidEncapsulationSettings => Model.FieldCandidates.Where(efd => efd.EncapsulateFlag) .Any(ff => !ff.HasValidEncapsulationAttributes); - public IEncapsulateFieldNamesValidator RefactoringValidator { set; get; } + public IEncapsulateFieldValidator RefactoringValidator { set; get; } //TODO: hook the validation scheme backup public bool HasValidNames => true; diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs index 5791926b61..1a1f22381c 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs @@ -30,8 +30,21 @@ public EncapsulationCandidateFactory(IDeclarationFinderProvider declarationFinde public IEncapsulateFieldCandidate CreateStateUDTField(QualifiedModuleName qmn, string identifier = DEFAULT_STATE_UDT_FIELD_IDENTIFIER, string asTypeName = DEFAULT_STATE_UDT_IDENTIFIER) { - //var unselectableAttributes = new NeverEncapsulateAttributes(identifier, asTypeName, qmn, _validator); - return new EncapsulateFieldCandidate(identifier, asTypeName, qmn, _validator, true); + var stateUDT = new StateUDTField(identifier, asTypeName, qmn, _validator); + var isConflictingFieldIdentifier = _validator.HasConflictingFieldIdentifier(stateUDT); + for (var count = 1; count < 10 && isConflictingFieldIdentifier; count++) + { + stateUDT.NewFieldName = EncapsulationIdentifiers.IncrementIdentifier(stateUDT.NewFieldName); + isConflictingFieldIdentifier = _validator.HasConflictingFieldIdentifier(stateUDT); + } + + var isConflictingUserDefinedTypeIdentifier = _validator.IsConflictingStateUDTIdentifier(stateUDT); + for (var count = 1; count < 10 && isConflictingUserDefinedTypeIdentifier; count++) + { + stateUDT.AsTypeName = EncapsulationIdentifiers.IncrementIdentifier(stateUDT.AsTypeName); + isConflictingUserDefinedTypeIdentifier = _validator.IsConflictingStateUDTIdentifier(stateUDT); + } + return stateUDT; } public IEnumerable CreateEncapsulationCandidates(IEnumerable candidateFields) @@ -39,7 +52,16 @@ public IEnumerable CreateEncapsulationCandidates(IEn var candidates = new List(); foreach (var field in candidateFields) { - _encapsulatedFields.Add(EncapsulateDeclaration(field, _validator)); + var encapuslatedField = EncapsulateDeclaration(field, _validator); + + var isConflictingPropertyIdentifier = _validator.HasConflictingPropertyIdentifier(encapuslatedField); + for (var count = 1; count < 10 && isConflictingPropertyIdentifier; count++) + { + encapuslatedField.PropertyName = $"{encapuslatedField.IdentifierName}{count}"; + isConflictingPropertyIdentifier = _validator.HasConflictingPropertyIdentifier(encapuslatedField); + } + + _encapsulatedFields.Add(encapuslatedField); } var udtFieldToUdtDeclarationMap = candidateFields @@ -51,12 +73,19 @@ public IEnumerable CreateEncapsulationCandidates(IEn { var encapsulatedUDTField = _encapsulatedFields.Where(ef => ef.Declaration == udtField).Single() as IEncapsulatedUserDefinedTypeField; - //var parent = encapsulatedUDTField as IEncapsulatedUserDefinedTypeField; encapsulatedUDTField.TypeDeclarationIsPrivate = udtFieldToUdtDeclarationMap[udtField].UserDefinedType.Accessibility.Equals(Accessibility.Private); foreach (var udtMember in udtFieldToUdtDeclarationMap[udtField].Item2) { var encapsulatedUDTMember = new EncapsulatedUserDefinedTypeMember(udtMember, encapsulatedUDTField, _validator) as IEncapsulatedUserDefinedTypeMember; + + var isConflictingPropertyIdentifier = _validator.HasConflictingFieldIdentifier(encapsulatedUDTMember); + for (var count = 1; count < 10 && isConflictingPropertyIdentifier; count++) + { + encapsulatedUDTMember.PropertyName = $"{encapsulatedUDTMember.IdentifierName}{count}"; + isConflictingPropertyIdentifier = _validator.HasConflictingPropertyIdentifier(encapsulatedUDTMember); + } + encapsulatedUDTMember = ApplyTypeSpecificAttributes(encapsulatedUDTMember); encapsulatedUDTField.AddMember(encapsulatedUDTMember); encapsulatedUDTMember.PropertyAccessExpression = @@ -72,7 +101,7 @@ public IEnumerable CreateEncapsulationCandidates(IEn return _encapsulatedFields; } - private IEncapsulateFieldCandidate EncapsulateDeclaration(Declaration target, IEncapsulateFieldNamesValidator validator) + public static IEncapsulateFieldCandidate EncapsulateDeclaration(Declaration target, IEncapsulateFieldNamesValidator validator) { Debug.Assert(!target.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)); @@ -100,7 +129,7 @@ private IEncapsulateFieldCandidate EncapsulateDeclaration(Declaration target, IE return (udtVariable, userDefinedTypeDeclaration, udtMembers); } - private T ApplyTypeSpecificAttributes(T candidate) where T: IEncapsulateFieldCandidate + private static T ApplyTypeSpecificAttributes(T candidate) where T: IEncapsulateFieldCandidate { var target = candidate.Declaration; if (target.IsUserDefinedTypeField()) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index a7951b8d74..2ad26ad9f5 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -24,16 +24,17 @@ public class EncapsulateFieldModel : IRefactoringModel private IDictionary)> _udtFieldToUdtDeclarationMap = new Dictionary)>(); - public EncapsulateFieldModel(Declaration target, IDeclarationFinderProvider declarationFinderProvider, IIndenter indenter, IEncapsulateFieldNamesValidator validator, Func previewDelegate) + public EncapsulateFieldModel(Declaration target, IDeclarationFinderProvider declarationFinderProvider, IIndenter indenter, Func previewDelegate) { _declarationFinderProvider = declarationFinderProvider; _indenter = indenter; - _validator = validator; _previewDelegate = previewDelegate; _targetQMN = target.QualifiedModuleName; _useNewStructure = File.Exists("C:\\Users\\Brian\\Documents\\UseNewUDTStructure.txt"); + _validator = new EncapsulateFieldNamesValidator(_declarationFinderProvider, () => FieldCandidates); + CandidateFactory = new EncapsulationCandidateFactory(declarationFinderProvider, _validator); var encapsulationCandidateFields = _declarationFinderProvider.DeclarationFinder .Members(_targetQMN) @@ -43,7 +44,6 @@ public EncapsulateFieldModel(Declaration target, IDeclarationFinderProvider decl FieldCandidates.AddRange(candidates); - //EncapsulationStrategy = new EncapsulateWithBackingFields(_targetQMN, _indenter, _validator); this[target].EncapsulateFlag = true; } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 894b5b4478..fd1104d316 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -11,6 +11,8 @@ using System.Collections.Generic; using System; using Rubberduck.Parsing; +using Rubberduck.Refactorings.Common; +using System.IO; namespace Rubberduck.Refactorings.EncapsulateField { @@ -20,7 +22,6 @@ public class EncapsulateFieldRefactoring : InteractiveRefactoringBase CandidateFields() => Model?.FieldCandidates ?? Enumerable.Empty(); - protected override void RefactorImpl(EncapsulateFieldModel model) { var strategy = model.EncapsulationStrategy; diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs index 1159187823..86295cb146 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -13,80 +13,82 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface IEncapsulateFieldNamesValidator + public interface IEncapsulateFieldValidator { - bool HasValidEncapsulationAttributes(IEncapsulateFieldCandidate attributes, QualifiedModuleName qmn, IEnumerable ignore, DeclarationType declarationType); - void ForceNonConflictEncapsulationAttributes(IEncapsulateFieldCandidate attributes, QualifiedModuleName qmn, Declaration target); - void ForceNonConflictPropertyName(IEncapsulateFieldCandidate attributes, QualifiedModuleName qmn, Declaration target); + bool HasValidEncapsulationAttributes(IEncapsulateFieldCandidate candidate, IEnumerable ignore); + bool IsValidVBAIdentifier(string identifier, DeclarationType declarationType); + bool HasConflictingPropertyIdentifier(IEncapsulateFieldCandidate candidate); + bool HasConflictingFieldIdentifier(IEncapsulateFieldCandidate candidate); + bool IsConflictingFieldIdentifier(string fieldName, IEncapsulateFieldCandidate candidate); + } + + public interface IEncapsulateFieldNamesValidator : IEncapsulateFieldValidator + { + bool HasIdentifierConflicts(string identifier, DeclarationType declarationType); + bool IsConflictingStateUDTIdentifier(IEncapsulatedUserDefinedTypeField candidate); } public class EncapsulateFieldNamesValidator : IEncapsulateFieldNamesValidator { private readonly IDeclarationFinderProvider _declarationFinderProvider; - private Func> _candidateFieldsRetriever; - public EncapsulateFieldNamesValidator(IDeclarationFinderProvider declarationFinderProvider, Func> selectedFieldsRetriever = null) + + private Lazy> _fieldCandidates; + + private List FieldCandidates => _fieldCandidates.Value; + + public EncapsulateFieldNamesValidator(IDeclarationFinderProvider declarationFinderProvider, Func> retrieveCandidateFields = null) { _declarationFinderProvider = declarationFinderProvider; - _candidateFieldsRetriever = selectedFieldsRetriever; + _fieldCandidates = new Lazy>(retrieveCandidateFields ?? (() => new List())); } private DeclarationFinder DeclarationFinder => _declarationFinderProvider.DeclarationFinder; - public void ForceNonConflictEncapsulationAttributes(IEncapsulateFieldCandidate candidate, QualifiedModuleName qmn, Declaration target) + public bool IsValidVBAIdentifier(string identifier, DeclarationType declarationType) + => VBAIdentifierValidator.IsValidIdentifier(identifier, declarationType); + + public bool HasConflictingPropertyIdentifier(IEncapsulateFieldCandidate candidate) { - if (target?.DeclarationType.HasFlag(DeclarationType.UserDefinedTypeMember) ?? false) - { - ForceNonConflictPropertyName(candidate, qmn, target); - return; - } - ForceNonConflictNewName(candidate, qmn, target); + var members = _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) + .Where(d => d != candidate.Declaration); + + return members.Any(m => m.IdentifierName.EqualsVBAIdentifier(candidate.PropertyName)); } - public void ForceNonConflictNewName(IEncapsulateFieldCandidate candidate, QualifiedModuleName qmn, Declaration target) + public bool HasConflictingFieldIdentifier(IEncapsulateFieldCandidate candidate) { - //var attributes = candidate.EncapsulationAttributes; - var identifier = candidate.NewFieldName; - var ignore = target is null ? Enumerable.Empty() : new Declaration[] { target }; + var members = _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) + .Where(d => d != candidate.Declaration); - var isValidAttributeSet = HasValidEncapsulationAttributes(candidate, qmn, ignore); - for (var idx = 1; idx < 9 && !isValidAttributeSet; idx++) - { - candidate.NewFieldName = $"{identifier}{idx}"; - isValidAttributeSet = HasValidEncapsulationAttributes(candidate, qmn, ignore); - } + return members.Any(m => m.IdentifierName.EqualsVBAIdentifier(candidate.NewFieldName)); } - public void ForceNonConflictPropertyName(IEncapsulateFieldCandidate candidate, QualifiedModuleName qmn, Declaration target) + public bool IsConflictingFieldIdentifier(string fieldName, IEncapsulateFieldCandidate candidate) { - //var attributes = candidate.EncapsulationAttributes; - var identifier = candidate.PropertyName; - var ignore = target is null ? Enumerable.Empty() : new Declaration[] { target }; - var isValidAttributeSet = HasValidEncapsulationAttributes(candidate, qmn, ignore); - for (var idx = 1; idx < 9 && !isValidAttributeSet; idx++) - { - candidate.PropertyName = $"{identifier}{idx}"; - isValidAttributeSet = HasValidEncapsulationAttributes(candidate, qmn, ignore); - } + var members = _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) + .Where(d => d != candidate.Declaration); + + return members.Any(m => m.IdentifierName.EqualsVBAIdentifier(fieldName) || candidate.PropertyName.EqualsVBAIdentifier(fieldName)); } - public bool HasValidEncapsulationAttributes(IEncapsulateFieldCandidate candidate, QualifiedModuleName qmn, IEnumerable ignore, DeclarationType declaration = DeclarationType.Variable) + public bool IsConflictingStateUDTIdentifier(IEncapsulatedUserDefinedTypeField candidate) { - //var attributes = candidate.EncapsulationAttributes; - var hasValidIdentifiers = HasValidIdentifiers(candidate, declaration); - var hasInternalNameConflicts = HasInternalNameConflicts(candidate); + var members = _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName); - var isSelfConsistent = hasValidIdentifiers || hasInternalNameConflicts; + return members.Any(m => m.IdentifierName.EqualsVBAIdentifier(candidate.AsTypeName)); + } - if (!isSelfConsistent) { return false; } + public bool HasValidEncapsulationAttributes(IEncapsulateFieldCandidate candidate, IEnumerable ignore) + { + if (!candidate.EncapsulateFlag) { return true; } + var internalValidations = candidate as IEncapsulateFieldCandidateValidations; - if (!candidate.FieldNameIsExemptFromValidation) + if (!internalValidations.IsSelfConsistent + || HasConflictingPropertyIdentifier(candidate)) { - if (HasNewFieldNameConflicts(candidate, qmn, ignore) > 0) { return false; } + return false; } - - if (HasNewPropertyNameConflicts(candidate, qmn, ignore) > 0) { return false; } - return true; } @@ -112,8 +114,7 @@ public int HasNewPropertyNameConflicts(IEncapsulateFieldCandidate attributes, Qu var candidates = new List(); var candidateMatches = new List(); - var fields = _candidateFieldsRetriever is null ? Enumerable.Empty() : _candidateFieldsRetriever(); - foreach (var efd in fields) + foreach (var efd in FieldCandidates) { var matches = candidates.Where(c => c.PropertyName.EqualsVBAIdentifier(efd.PropertyName)); if (matches.Any()) @@ -126,36 +127,12 @@ public int HasNewPropertyNameConflicts(IEncapsulateFieldCandidate attributes, Qu return identifierMatches.Count() + candidateMatches.Count(); } - //FieldNames are always Private, so only look within the same module as the field to encapsulate - public int HasNewFieldNameConflicts(IEncapsulateFieldCandidate attributes, QualifiedModuleName qmn, IEnumerable declarationsToIgnore) + public bool HasIdentifierConflicts(string identifier, DeclarationType declarationType) { - var rawmatches = DeclarationFinder.MatchName(attributes.NewFieldName); - var identifierMatches = DeclarationFinder.MatchName(attributes.NewFieldName) - .Where(match => match.QualifiedModuleName == qmn - && !declarationsToIgnore.Contains(match) - && !IsEnumOrUDTMemberDeclaration(match) - && !match.IsLocalVariable()).ToList(); - - var candidates = new List(); - var candidateMatches = new List(); - var fields = _candidateFieldsRetriever is null - ? Enumerable.Empty() - : _candidateFieldsRetriever(); - - foreach (var efd in fields) - { - var matches = candidates.Where(c => c.EncapsulateFlag && c.NewFieldName.EqualsVBAIdentifier(efd.NewFieldName) - || c.IdentifierName.EqualsVBAIdentifier(efd.NewFieldName)); - if (matches.Where(m => m.TargetID != efd.TargetID).Any()) - { - candidateMatches.Add(efd); - } - candidates.Add(efd); - } - - return identifierMatches.Count() + candidateMatches.Count(); + return true; } + private bool IsEnumOrUDTMemberDeclaration(Declaration candidate) { return candidate.DeclarationType == DeclarationType.EnumerationMember diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs index 3c85df3a9f..98b88c42a5 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs @@ -33,45 +33,43 @@ public interface IEncapsulateFieldCandidate Func PropertyAccessExpression { set; get; } bool FieldNameIsExemptFromValidation { get; } Func ReferenceExpression { set; get; } - //IPropertyGeneratorSpecification AsPropertyGeneratorSpec { get; } IEnumerable PropertyGenerationSpecs { get; } IEnumerable> ReferenceReplacements { get; } void LoadReferenceExpressionChanges(); void SetReferenceRewriteContent(IdentifierReference idRef, string replacementText); RewriteReplacePair ReferenceReplacement(IdentifierReference idRef); - //RewriteReplacePair? FindRewriteReplacePair(IdentifierReference idRef); - //void ClearIdentifierReferenceExpressionCache(); } - public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate + public interface IEncapsulateFieldCandidateValidations + { + bool HasVBACompliantPropertyIdentifier { get; } + bool HasVBACompliantFieldIdentifier { get; } + bool HasVBACompliantParameterIdentifier { get; } + bool IsSelfConsistent { get; } + bool HasConflictingPropertyIdentifier { get; } + bool HasConflictingFieldIdentifier { get; } + } + + + public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate, IEncapsulateFieldCandidateValidations { protected Declaration _target; protected QualifiedModuleName _qmn; private string _identifierName; - private IEncapsulateFieldNamesValidator _validator; - //private Dictionary _idRefRenames { set; get; } = new Dictionary(); - private EncapsulationIdentifiers _fieldAndProperty; + protected IEncapsulateFieldNamesValidator _validator; + protected EncapsulationIdentifiers _fieldAndProperty; public EncapsulateFieldCandidate(Declaration declaration, IEncapsulateFieldNamesValidator validator) + : this(declaration.IdentifierName, declaration.AsTypeName, declaration.QualifiedModuleName, validator) { _target = declaration; - AsTypeName = _target.AsTypeName; - - _fieldAndProperty = new EncapsulationIdentifiers(_target); - IdentifierName = _target.IdentifierName; - _qmn = _target.QualifiedModuleName; - PropertyAccessExpression = () => NewFieldName; - ReferenceExpression = () => PropertyName; - - _validator = validator; - _validator.ForceNonConflictEncapsulationAttributes(this, _target.QualifiedModuleName, _target); } - public EncapsulateFieldCandidate(string identifier, string asTypeName, QualifiedModuleName qmn,/*IFieldEncapsulationAttributes attributes,*/ IEncapsulateFieldNamesValidator validator, bool neverEncapsulate = false) + public EncapsulateFieldCandidate(string identifier, string asTypeName, QualifiedModuleName qmn, IEncapsulateFieldNamesValidator validator) { _target = null; - _fieldAndProperty = new EncapsulationIdentifiers(identifier, neverEncapsulate); + _fieldAndProperty = new EncapsulationIdentifiers(identifier); IdentifierName = identifier; AsTypeName = asTypeName; _qmn = qmn; @@ -79,20 +77,41 @@ public EncapsulateFieldCandidate(string identifier, string asTypeName, Qualified ReferenceExpression = () => PropertyName; _validator = validator; - _validator.ForceNonConflictEncapsulationAttributes(this, qmn, _target); } protected Dictionary IdentifierReplacements { get; } = new Dictionary(); public Declaration Declaration => _target; + + public bool HasVBACompliantPropertyIdentifier => _validator.IsValidVBAIdentifier(PropertyName, DeclarationType.Property); + + public bool HasVBACompliantFieldIdentifier => _validator.IsValidVBAIdentifier(NewFieldName, Declaration?.DeclarationType ?? DeclarationType.Variable); + + public bool HasVBACompliantParameterIdentifier => _validator.IsValidVBAIdentifier(NewFieldName, Declaration?.DeclarationType ?? DeclarationType.Variable); + + public virtual bool IsSelfConsistent => _validator.IsValidVBAIdentifier(PropertyName, DeclarationType.Property) + && !(PropertyName.EqualsVBAIdentifier(NewFieldName) + || PropertyName.EqualsVBAIdentifier(ParameterName) + || NewFieldName.EqualsVBAIdentifier(ParameterName)); + + public bool HasConflictingPropertyIdentifier + => _validator.HasConflictingPropertyIdentifier(this); + + public bool HasConflictingFieldIdentifier + => _validator.HasConflictingFieldIdentifier(this); + public bool HasValidEncapsulationAttributes { get { - var declarationsToIgnore = _target != null ? new Declaration[] { _target } : Enumerable.Empty(); - var declarationType = _target != null ? _target.DeclarationType : DeclarationType.Variable; - return _validator.HasValidEncapsulationAttributes(this, QualifiedModuleName, declarationsToIgnore, declarationType); + if (!EncapsulateFlag) { return true; } + + return IsSelfConsistent; // _validator.IsValidVBAIdentifier(PropertyName, DeclarationType.Property) + + //var declarationsToIgnore = _target != null ? new Declaration[] { _target } : Enumerable.Empty(); + //var declarationType = _target != null ? _target.DeclarationType : DeclarationType.Variable; + //return _validator.HasValidEncapsulationAttributes(this, QualifiedModuleName, declarationsToIgnore, declarationType); } } @@ -132,18 +151,44 @@ public RewriteReplacePair ReferenceReplacement(IdentifierReference idRef) public bool IsReadOnly { set; get; } public bool CanBeReadWrite { set; get; } - public string PropertyName + public virtual string NewFieldName { - get => _fieldAndProperty.Property; - set => _fieldAndProperty.Property = value; + get => _fieldAndProperty.Field; + set => _fieldAndProperty.Field = value; } - public bool IsEditableReadWriteFieldIdentifier { set; get; } = true; + public virtual string PropertyName + { + get => _fieldAndProperty.Property; + set + { + _fieldAndProperty.Property = value; - public string NewFieldName + TryRestoreNewFieldNameAsOriginalFieldIdentifierName(); + } + } + + //The preferred NewFieldName is the original Identifier + private void TryRestoreNewFieldNameAsOriginalFieldIdentifierName() { - get => _fieldAndProperty.Field; - set => _fieldAndProperty.Field = value; + var canNowUseOriginalFieldName = !_validator.IsConflictingFieldIdentifier(_fieldAndProperty.TargetFieldName, this); + + if (canNowUseOriginalFieldName) + { + _fieldAndProperty.Field = _fieldAndProperty.TargetFieldName; + return; + } + + if (_fieldAndProperty.Field.EqualsVBAIdentifier(_fieldAndProperty.TargetFieldName)) + { + _fieldAndProperty.Field = _fieldAndProperty.DefaultNewFieldName; + var isConflictingFieldIdentifier = _validator.HasConflictingFieldIdentifier(this); + for (var count = 1; count < 10 && isConflictingFieldIdentifier; count++) + { + NewFieldName = EncapsulationIdentifiers.IncrementIdentifier(NewFieldName); + isConflictingFieldIdentifier = _validator.HasConflictingFieldIdentifier(this); + } + } } public string AsTypeName { set; get; } @@ -214,7 +259,7 @@ protected bool RequiresAccessQualification(IdentifierReference idRef) var isLHSOfMemberAccess = (idRef.Context.Parent is VBAParser.MemberAccessExprContext || idRef.Context.Parent is VBAParser.WithMemberAccessExprContext) - && !(idRef.Context == idRef.Context.Parent.GetChild(0));// is VBAParser.SimpleNameExprContext)) + && !(idRef.Context == idRef.Context.Parent.GetChild(0)); return idRef.QualifiedModuleName != idRef.Declaration.QualifiedModuleName && !isLHSOfMemberAccess; diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeField.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeField.cs index 3ad78d917b..c181cabc95 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeField.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeField.cs @@ -35,6 +35,12 @@ public void AddMember(IEncapsulatedUserDefinedTypeMember member) public bool TypeDeclarationIsPrivate { set; get; } + public override string NewFieldName + { + get => TypeDeclarationIsPrivate ? _fieldAndProperty.TargetFieldName : _fieldAndProperty.Field; + set => _fieldAndProperty.Field = value; + } + public bool FieldQualifyMemberPropertyNames { set diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationIdentifiers.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationIdentifiers.cs index a7a57172ff..f8b5c60bf0 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationIdentifiers.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationIdentifiers.cs @@ -5,55 +5,46 @@ namespace Rubberduck.Refactorings.EncapsulateField { - //public struct EncapsulationAttributeIdentifier - //{ - // public EncapsulationAttributeIdentifier(string name, bool isImmutable = false) - // { - // Name = name; - // IsImmutable = isImmutable; - // } - // public string Name; - // public bool IsImmutable; - //} - public class EncapsulationIdentifiers { private static string DEFAULT_WRITE_PARAMETER = "value"; private KeyValuePair _fieldAndProperty; - //private EncapsulationAttributeIdentifier _targetIdentifier; private string _targetIdentifier; private string _defaultPropertyName; - private string _defaultFieldName; private string _setLetParameter; - private bool _cannotEncapsulate; public EncapsulationIdentifiers(Declaration target) : this(target.IdentifierName) { } - public EncapsulationIdentifiers(string field, bool cannotBeEncapsulated = false) + public EncapsulationIdentifiers(string field) { - //_targetIdentifier = new EncapsulationAttributeIdentifier(field, true); _targetIdentifier = field; - _defaultPropertyName = cannotBeEncapsulated ? $"{field}99" : field.Capitalize(); - _defaultFieldName = cannotBeEncapsulated ? field : $"{field.UnCapitalize()}1"; - _fieldAndProperty = new KeyValuePair(_defaultFieldName, _defaultPropertyName); + _defaultPropertyName = field.Capitalize(); + DefaultNewFieldName = IncrementIdentifier(field.UnCapitalize()); + _fieldAndProperty = new KeyValuePair(DefaultNewFieldName, _defaultPropertyName); _setLetParameter = DEFAULT_WRITE_PARAMETER; - _cannotEncapsulate = cannotBeEncapsulated; } - public EncapsulationIdentifiers(string field, string fieldName, string propertyName) + public static string IncrementIdentifier(string identifier) { - //_targetIdentifier = new EncapsulationAttributeIdentifier(field); - _targetIdentifier = field; - _defaultPropertyName = field.Capitalize(); - _defaultFieldName = $"{field.UnCapitalize()}1"; - _fieldAndProperty = new KeyValuePair(fieldName, propertyName); - _setLetParameter = DEFAULT_WRITE_PARAMETER; + var fragments = identifier.Split('_'); + if (fragments.Length == 1) { return $"{identifier}_1"; } + + var lastFragment = fragments[fragments.Length - 1]; + if (long.TryParse(lastFragment, out var number)) + { + fragments[fragments.Length - 1] = (number + 1).ToString(); + + return string.Join("_", fragments); + } + return $"{identifier}_1"; ; } public string TargetFieldName => _targetIdentifier; + public string DefaultNewFieldName { private set; get; } + public string Field { get => _fieldAndProperty.Key; @@ -70,10 +61,10 @@ public string Property set { var fieldIdentifier = Field.EqualsVBAIdentifier(value) - ? _defaultFieldName + ? DefaultNewFieldName : _targetIdentifier; - _fieldAndProperty = new KeyValuePair(fieldIdentifier, value); + _fieldAndProperty = new KeyValuePair(_fieldAndProperty.Key, value); GenerateNonConflictParamIdentifier(); } diff --git a/Rubberduck.Refactorings/EncapsulateField/StateUDTField.cs b/Rubberduck.Refactorings/EncapsulateField/StateUDTField.cs new file mode 100644 index 0000000000..89d196d467 --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/StateUDTField.cs @@ -0,0 +1,34 @@ +using Rubberduck.Parsing.Symbols; +using Rubberduck.VBEditor; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + public class StateUDTField : EncapsulateFieldCandidate, IEncapsulatedUserDefinedTypeField + { + public StateUDTField(string identifier, string asTypeName, QualifiedModuleName qmn, IEncapsulateFieldNamesValidator validator) + : base(identifier, asTypeName, qmn, validator) + { + PropertyName = identifier; + NewFieldName = identifier; + AsTypeName = asTypeName; + } + + public override string PropertyName { set; get; } + + public override string NewFieldName { set; get; } + + public override bool IsSelfConsistent => _validator.IsValidVBAIdentifier(PropertyName, DeclarationType.Property) + && !(PropertyName.EqualsVBAIdentifier(ParameterName) + || PropertyName.EqualsVBAIdentifier(ParameterName)); + + public IEnumerable Members { get; } + public void AddMember(IEncapsulatedUserDefinedTypeMember member) { throw new NotImplementedException(); } + public bool FieldQualifyMemberPropertyNames { set; get; } + public bool TypeDeclarationIsPrivate { set; get; } = true; + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs index bb60f02dca..a3e84a4cf2 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs @@ -14,7 +14,7 @@ namespace Rubberduck.Refactorings.EncapsulateField.Strategies { public class EncapsulateWithBackingFields : EncapsulateFieldStrategiesBase { - public EncapsulateWithBackingFields(QualifiedModuleName qmn, IIndenter indenter, IEncapsulateFieldNamesValidator validator) + public EncapsulateWithBackingFields(QualifiedModuleName qmn, IIndenter indenter, IEncapsulateFieldValidator validator) : base(qmn, indenter, validator) { } diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs index 8af0f064fb..21ef97c1cb 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs @@ -18,7 +18,7 @@ public interface IEncapsulateWithBackingUserDefinedType : IEncapsulateFieldStrat public class EncapsulateWithBackingUserDefinedType : EncapsulateFieldStrategiesBase, IEncapsulateWithBackingUserDefinedType { - public EncapsulateWithBackingUserDefinedType(QualifiedModuleName qmn, IIndenter indenter, IEncapsulateFieldNamesValidator validator) + public EncapsulateWithBackingUserDefinedType(QualifiedModuleName qmn, IIndenter indenter, IEncapsulateFieldValidator validator) : base(qmn, indenter, validator) { } protected override IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs index d81855ba1c..4db7d332b7 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs @@ -19,10 +19,10 @@ public interface IEncapsulateFieldStrategy public abstract class EncapsulateFieldStrategiesBase : IEncapsulateFieldStrategy { - private IEncapsulateFieldNamesValidator _validator; + private IEncapsulateFieldValidator _validator; protected static string DoubleSpace => $"{Environment.NewLine}{Environment.NewLine}"; - public EncapsulateFieldStrategiesBase(QualifiedModuleName qmn, IIndenter indenter, IEncapsulateFieldNamesValidator validator) + public EncapsulateFieldStrategiesBase(QualifiedModuleName qmn, IIndenter indenter, IEncapsulateFieldValidator validator) { TargetQMN = qmn; Indenter = indenter; diff --git a/Rubberduck.Refactorings/EncapsulateField/UDTDeclarationGenerator.cs b/Rubberduck.Refactorings/EncapsulateField/UDTDeclarationGenerator.cs index cb8b13708a..ff61da0e0f 100644 --- a/Rubberduck.Refactorings/EncapsulateField/UDTDeclarationGenerator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/UDTDeclarationGenerator.cs @@ -28,7 +28,16 @@ public UDTDeclarationGenerator(string typeIdentifierName) public string FieldDeclaration(string identifierName, Accessibility accessibility = Accessibility.Private) => $"{accessibility} {identifierName} {Tokens.As} {_typeIdentifierName}"; - public string TypeDeclarationBlock(IIndenter indenter, Accessibility accessibility = Accessibility.Private) + public string TypeDeclarationBlock(IIndenter indenter = null, Accessibility accessibility = Accessibility.Private) + { + if (indenter != null) + { + return string.Join(Environment.NewLine, indenter.Indent(BlockLines(accessibility), true)); + } + return string.Join(Environment.NewLine, BlockLines(accessibility)); + } + + public IEnumerable BlockLines(Accessibility accessibility) { var blockLines = new List(); @@ -38,7 +47,7 @@ public string TypeDeclarationBlock(IIndenter indenter, Accessibility accessibili blockLines.Add("End Type"); - return string.Join(Environment.NewLine, indenter.Indent(blockLines, true)); - } + return blockLines; + } } } diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs index d31c5c47b0..fb4847b9a7 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs @@ -21,6 +21,129 @@ public class EncapsulateFieldValidatorTests : InteractiveRefactoringTestBase m.DeclarationType.Equals(declarationType)).Single(); - return new EncapsulateFieldCandidate(match, new EncapsulateFieldNamesValidator(state)) as IEncapsulateFieldCandidate; - } - } - - private static IIndenter CreateIndenter(IVBE vbe = null) - { - return new Indenter(vbe, () => Settings.IndenterSettingsTests.GetMockIndenterSettings()); - } } } diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs index 743d757ebb..6a8819a357 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs @@ -34,15 +34,15 @@ End Type var presenterAction = Support.UserAcceptsDefaults(); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - StringAssert.Contains("Private this1 As TBar", actualCode); - StringAssert.DoesNotContain("this1 = value", actualCode); - StringAssert.DoesNotContain($"This = this1", actualCode); + StringAssert.Contains("Private this As TBar", actualCode); + StringAssert.DoesNotContain("this = value", actualCode); + StringAssert.DoesNotContain($"This = this", actualCode); StringAssert.Contains($"Public Property Get First", actualCode); StringAssert.Contains($"Public Property Get Second", actualCode); - StringAssert.Contains($"this1.First = value", actualCode); - StringAssert.Contains($"First = this1.First", actualCode); - StringAssert.Contains($"this1.Second = value", actualCode); - StringAssert.Contains($"Second = this1.Second", actualCode); + StringAssert.Contains($"this.First = value", actualCode); + StringAssert.Contains($"First = this.First", actualCode); + StringAssert.Contains($"this.Second = value", actualCode); + StringAssert.Contains($"Second = this.Second", actualCode); } [TestCase(true, true)] @@ -63,60 +63,66 @@ End Type Public th|is As TBar Public that As TBar"; - var userInput = new UserInputDataObject("this", "MyType", encapsulateThis) - .AddAttributeSet("that", "MyOtherType", encapsulateThat); + var expectedThis = new EncapsulationIdentifiers("this"); + var expectedThat = new EncapsulationIdentifiers("that"); - var expectedThis = new EncapsulationIdentifiers("this") { Property = "MyType" }; - var expectedThat = new EncapsulationIdentifiers("that") { Property = "MyOtherType" }; + var userInput = new UserInputDataObject() + .AddAttributeSet(expectedThis.TargetFieldName, encapsulationFlag: encapsulateThis) + .AddAttributeSet(expectedThat.TargetFieldName, encapsulationFlag: encapsulateThat); var presenterAction = Support.SetParameters(userInput); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); if (encapsulateThis && encapsulateThat) { - StringAssert.Contains($"Private {expectedThis.Field} As TBar", actualCode); - StringAssert.Contains($"This_First = {expectedThis.Field}.First", actualCode); - StringAssert.Contains($"This_Second = {expectedThis.Field}.Second", actualCode); - StringAssert.Contains($"{expectedThis.Field}.First = value", actualCode); - StringAssert.Contains($"{expectedThis.Field}.Second = value", actualCode); + //StringAssert.Contains($"Private {expectedThis.TargetFieldName} As TBar", actualCode); + StringAssert.Contains($"This_First = {expectedThis.TargetFieldName}.First", actualCode); + StringAssert.Contains($"This_Second = {expectedThis.TargetFieldName}.Second", actualCode); + StringAssert.Contains($"{expectedThis.TargetFieldName}.First = value", actualCode); + StringAssert.Contains($"{expectedThis.TargetFieldName}.Second = value", actualCode); StringAssert.Contains($"Property Get This_First", actualCode); StringAssert.Contains($"Property Get This_Second", actualCode); - StringAssert.Contains($"Private {expectedThat.Field} As TBar", actualCode); - StringAssert.Contains($"That_First = {expectedThat.Field}.First", actualCode); - StringAssert.Contains($"That_Second = {expectedThat.Field}.Second", actualCode); - StringAssert.Contains($"{expectedThat.Field}.First = value", actualCode); - StringAssert.Contains($"{expectedThat.Field}.Second = value", actualCode); + StringAssert.Contains($"Private {expectedThat.TargetFieldName} As TBar", actualCode); + StringAssert.Contains($"That_First = {expectedThat.TargetFieldName}.First", actualCode); + StringAssert.Contains($"That_Second = {expectedThat.TargetFieldName}.Second", actualCode); + StringAssert.Contains($"{expectedThat.TargetFieldName}.First = value", actualCode); + StringAssert.Contains($"{expectedThat.TargetFieldName}.Second = value", actualCode); StringAssert.Contains($"Property Get That_First", actualCode); StringAssert.Contains($"Property Get That_Second", actualCode); + + StringAssert.Contains($"Private {expectedThis.TargetFieldName} As TBar", actualCode); + StringAssert.Contains($"Private {expectedThat.TargetFieldName} As TBar", actualCode); } else if (encapsulateThis && !encapsulateThat) { - StringAssert.Contains($"Private {expectedThis.Field} As TBar", actualCode); - StringAssert.Contains($"First = {expectedThis.Field}.First", actualCode); - StringAssert.Contains($"Second = {expectedThis.Field}.Second", actualCode); - StringAssert.Contains($"{expectedThis.Field}.First = value", actualCode); - StringAssert.Contains($"{expectedThis.Field}.Second = value", actualCode); + //StringAssert.Contains($"Private {expectedThis.TargetFieldName} As TBar", actualCode); + StringAssert.Contains($"First = {expectedThis.TargetFieldName}.First", actualCode); + StringAssert.Contains($"Second = {expectedThis.TargetFieldName}.Second", actualCode); + StringAssert.Contains($"{expectedThis.TargetFieldName}.First = value", actualCode); + StringAssert.Contains($"{expectedThis.TargetFieldName}.Second = value", actualCode); StringAssert.Contains($"Property Get First", actualCode); StringAssert.Contains($"Property Get Second", actualCode); - StringAssert.Contains($"Public that As TBar", actualCode); + StringAssert.Contains($"Private {expectedThis.TargetFieldName} As TBar", actualCode); + StringAssert.Contains($"Public {expectedThat.TargetFieldName} As TBar", actualCode); } else if (!encapsulateThis && encapsulateThat) { - StringAssert.Contains($"Private {expectedThat.Field} As TBar", actualCode); - StringAssert.Contains($"First = {expectedThat.Field}.First", actualCode); - StringAssert.Contains($"Second = {expectedThat.Field}.Second", actualCode); - StringAssert.Contains($"{expectedThat.Field}.First = value", actualCode); - StringAssert.Contains($"{expectedThat.Field}.Second = value", actualCode); + //StringAssert.Contains($"Private {expectedThat.TargetFieldName} As TBar", actualCode); + StringAssert.Contains($"First = {expectedThat.TargetFieldName}.First", actualCode); + StringAssert.Contains($"Second = {expectedThat.TargetFieldName}.Second", actualCode); + StringAssert.Contains($"{expectedThat.TargetFieldName}.First = value", actualCode); + StringAssert.Contains($"{expectedThat.TargetFieldName}.Second = value", actualCode); StringAssert.Contains($"Property Get First", actualCode); StringAssert.Contains($"Property Get Second", actualCode); - StringAssert.Contains($"Public this As TBar", actualCode); + StringAssert.Contains($"Public {expectedThis.TargetFieldName} As TBar", actualCode); + StringAssert.Contains($"Private {expectedThat.TargetFieldName} As TBar", actualCode); } else { - StringAssert.Contains($"Public this As TBar", actualCode); - StringAssert.Contains($"Public that As TBar", actualCode); + StringAssert.Contains($"Public {expectedThis.TargetFieldName} As TBar", actualCode); + StringAssert.Contains($"Public {expectedThat.TargetFieldName} As TBar", actualCode); } } @@ -145,18 +151,15 @@ End Sub "; - //var userInput = new UserInputDataObject("this"); var presenterAction = Support.UserAcceptsDefaults(); - //var presenterAction = Support.SetParameters(userInput); - var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - StringAssert.Contains("this1.First = value", actualCode); - StringAssert.Contains($"First = this1.First", actualCode); - StringAssert.Contains("this1.Second = value", actualCode); - StringAssert.Contains($"Second = this1.Second", actualCode); - StringAssert.Contains($"First = arg1", actualCode); - StringAssert.Contains($"Second = arg2", actualCode); + StringAssert.Contains("this.First = value", actualCode); + StringAssert.Contains($"First = this.First", actualCode); + StringAssert.Contains("this.Second = value", actualCode); + StringAssert.Contains($"Second = this.Second", actualCode); + StringAssert.Contains($" First = arg1", actualCode); + StringAssert.Contains($" Second = arg2", actualCode); StringAssert.Contains($"that.First = arg1", actualCode); StringAssert.Contains($"that.Second = arg2", actualCode); } @@ -199,7 +202,7 @@ End Sub StringAssert.DoesNotContain($" Second = arg2", actualCode); StringAssert.Contains($" .First = arg1", actualCode); StringAssert.Contains($" .Second = arg2", actualCode); - StringAssert.Contains("With this1", actualCode); + StringAssert.Contains("With this", actualCode); } [Test] diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index 5c8cfdddeb..95fd068a9d 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -1,5 +1,6 @@ using Moq; using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.UIContext; using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings; @@ -8,6 +9,7 @@ using Rubberduck.VBEditor; using Rubberduck.VBEditor.SafeComWrappers.Abstract; using Rubberduck.VBEditor.Utility; +using RubberduckTests.Mocks; using System; using System.Collections.Generic; using System.Linq; @@ -93,7 +95,35 @@ public IRefactoring SupportTestRefactoring(IRewritingManager rewritingManager, R return new EncapsulateFieldRefactoring(state, indenter, factory, rewritingManager, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); } - private static IIndenter CreateIndenter(IVBE vbe = null) + public IEncapsulateFieldCandidate RetrieveEncapsulatedField(string inputCode, string fieldName) + { + var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; + + var selectedComponentName = vbe.SelectedVBComponent.Name; + + var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); + using (state) + { + var match = state.DeclarationFinder.MatchName(fieldName).Single(); + return new EncapsulateFieldCandidate(match, new EncapsulateFieldNamesValidator(state)) as IEncapsulateFieldCandidate; + } + } + + public IEncapsulateFieldCandidate RetrieveEncapsulatedField(string inputCode, string fieldName, DeclarationType declarationType) + { + var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; + + var selectedComponentName = vbe.SelectedVBComponent.Name; + + var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); + using (state) + { + var match = state.DeclarationFinder.MatchName(fieldName).Where(m => m.DeclarationType.Equals(declarationType)).Single(); + return new EncapsulateFieldCandidate(match, new EncapsulateFieldNamesValidator(state)) as IEncapsulateFieldCandidate; + } + } + + public static IIndenter CreateIndenter(IVBE vbe = null) { return new Indenter(vbe, () => Settings.IndenterSettingsTests.GetMockIndenterSettings()); } @@ -147,6 +177,8 @@ public UserInputDataObject AddAttributeSet(string fieldName, string propertyName { var attrs = new TestEncapsulationAttributes(fieldName, encapsulationFlag, isReadOnly); attrs.PropertyName = propertyName ?? attrs.PropertyName; + attrs.EncapsulateFlag = encapsulationFlag; + attrs.IsReadOnly = isReadOnly; _userInput.Add(attrs); return this; diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index c4b9b780f8..9bc1961856 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -339,26 +339,6 @@ End Property Assert.AreEqual(expectedCode, actualCode); } - [Test] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void EncapsulatePrivateField_ReadOnlyRequiresSet() - { - const string inputCode = - @"|Private fizz As Collection"; - - const string expectedCode = - @"Private fizz As Collection - -Public Property Get Name() As Collection - Set Name = fizz -End Property -"; - var presenterAction = Support.SetParametersForSingleTarget("fizz", "Name", isReadonly: true); - var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - Assert.AreEqual(expectedCode, actualCode); - } - [Test] [Category("Refactorings")] [Category("Encapsulate Field")] @@ -391,7 +371,8 @@ End Property fields.Add(efd); efd.PropertyName = "Name"; - var hasConflict = !validator.HasValidEncapsulationAttributes(efd, efd.QualifiedModuleName, new Declaration[] { efd.Declaration }); + //var hasConflict = !validator.HasValidEncapsulationAttributes(efd, efd.QualifiedModuleName, new Declaration[] { efd.Declaration }); + var hasConflict = validator.HasConflictingPropertyIdentifier(efd); Assert.IsTrue(hasConflict); } } @@ -419,14 +400,14 @@ public void EncapsulatePrivateField_Defaults() @"|Private fizz As Integer"; const string expectedCode = - @"Private fizz1 As Integer + @"Private fizz_1 As Integer Public Property Get Fizz() As Integer - Fizz = fizz1 + Fizz = fizz_1 End Property Public Property Let Fizz(ByVal value As Integer) - fizz1 = value + fizz_1 = value End Property "; var presenterAction = Support.UserAcceptsDefaults(); @@ -470,12 +451,12 @@ Sub Bar(ByVal name As Integer) var enapsulationIdentifiers = new EncapsulationIdentifiers("fizz") { Property = "Name" }; var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - StringAssert.AreEqualIgnoringCase(enapsulationIdentifiers.Field, "fizz"); - StringAssert.Contains($"Private {enapsulationIdentifiers.Field} As Integer", actualCode); + StringAssert.AreEqualIgnoringCase(enapsulationIdentifiers.TargetFieldName, "fizz"); + StringAssert.Contains($"Private {enapsulationIdentifiers.TargetFieldName} As Integer", actualCode); StringAssert.Contains("Property Get Name", actualCode); StringAssert.Contains("Property Let Name", actualCode); - StringAssert.Contains($"Name = {enapsulationIdentifiers.Field}", actualCode); - StringAssert.Contains($"{enapsulationIdentifiers.Field} = value", actualCode); + StringAssert.Contains($"Name = {enapsulationIdentifiers.TargetFieldName}", actualCode); + StringAssert.Contains($"{enapsulationIdentifiers.TargetFieldName} = value", actualCode); } [Test] From 57f0428cf316ccfac701518569381b6a5ebefc0c Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Tue, 10 Dec 2019 16:01:00 -0800 Subject: [PATCH 049/461] WIP - working towards removing strategies --- .../EncapsulateFieldViewModel.cs | 6 +- .../EncapsulateFieldDeclarationFactory.cs | 174 +++++++------- .../EncapsulateField/EncapsulateFieldModel.cs | 41 ++-- .../EncapsulateFieldNewContent.cs | 224 +++++++++--------- .../EncapsulateFieldRefactoring.cs | 22 +- .../EncapsulateFieldRewriter.cs | 48 ++-- .../EncapsulateFieldValidator.cs | 19 +- .../EncapsulatedFieldDeclaration.cs | 10 +- .../EncapsulateField/PropertyGenerator.cs | 12 + .../EncapsulateWithBackingFields.cs | 67 +++--- .../EncapsulateWithBackingUserDefinedType.cs | 41 ++-- .../Strategies/EncapsulationStrategiesBase.cs | 79 +++--- .../UDTDeclarationGenerator.cs | 2 +- .../EncapsulateFieldValidatorTests.cs | 104 ++++---- .../EncapsulateField/TestSupport.cs | 17 ++ .../Refactoring/EncapsulateFieldTests.cs | 19 +- 16 files changed, 461 insertions(+), 424 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs index aa01d9bc81..b555fd4172 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs @@ -28,10 +28,10 @@ public ObservableCollection EncapsulationFields { get { - var flaggedFields = Model.FlaggedEncapsulationFields + var flaggedFields = Model.SelectedFieldCandidates .OrderBy(efd => efd.Declaration.IdentifierName); - var orderedFields = Model.FieldCandidates.Except(flaggedFields) + var orderedFields = Model.EncapsulationCandidates.Except(flaggedFields) .OrderBy(efd => efd.Declaration.IdentifierName); var viewableFields = new ObservableCollection(); @@ -103,7 +103,7 @@ public string EncapsulateAsUDT_FieldName } public bool TargetsHaveValidEncapsulationSettings - => Model.FieldCandidates.Where(efd => efd.EncapsulateFlag) + => Model.EncapsulationCandidates.Where(efd => efd.EncapsulateFlag) .Any(ff => !ff.HasValidEncapsulationAttributes); public IEncapsulateFieldValidator RefactoringValidator { set; get; } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs index 1a1f22381c..a6fe7f8877 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs @@ -20,124 +20,109 @@ public class EncapsulationCandidateFactory private readonly IDeclarationFinderProvider _declarationFinderProvider; private readonly IEncapsulateFieldNamesValidator _validator; private List _encapsulatedFields = new List(); + //private IEnumerable _fieldCandidates; + private QualifiedModuleName _targetQMN; - public EncapsulationCandidateFactory(IDeclarationFinderProvider declarationFinderProvider, IEncapsulateFieldNamesValidator validator) + public EncapsulationCandidateFactory(IDeclarationFinderProvider declarationFinderProvider, QualifiedModuleName targetQMN, IEncapsulateFieldNamesValidator validator) { - _declarationFinderProvider = declarationFinderProvider; _validator = validator; + _targetQMN = targetQMN; } - public IEncapsulateFieldCandidate CreateStateUDTField(QualifiedModuleName qmn, string identifier = DEFAULT_STATE_UDT_FIELD_IDENTIFIER, string asTypeName = DEFAULT_STATE_UDT_IDENTIFIER) + public IEncapsulateFieldCandidate CreateStateUDTField(string identifier = DEFAULT_STATE_UDT_FIELD_IDENTIFIER, string asTypeName = DEFAULT_STATE_UDT_IDENTIFIER) { - var stateUDT = new StateUDTField(identifier, asTypeName, qmn, _validator); - var isConflictingFieldIdentifier = _validator.HasConflictingFieldIdentifier(stateUDT); - for (var count = 1; count < 10 && isConflictingFieldIdentifier; count++) - { - stateUDT.NewFieldName = EncapsulationIdentifiers.IncrementIdentifier(stateUDT.NewFieldName); - isConflictingFieldIdentifier = _validator.HasConflictingFieldIdentifier(stateUDT); - } + var stateUDT = new StateUDTField(identifier, asTypeName, _targetQMN, _validator); + _validator.RegisterFieldCandidate(stateUDT); - var isConflictingUserDefinedTypeIdentifier = _validator.IsConflictingStateUDTIdentifier(stateUDT); - for (var count = 1; count < 10 && isConflictingUserDefinedTypeIdentifier; count++) - { - stateUDT.AsTypeName = EncapsulationIdentifiers.IncrementIdentifier(stateUDT.AsTypeName); - isConflictingUserDefinedTypeIdentifier = _validator.IsConflictingStateUDTIdentifier(stateUDT); - } + stateUDT = SetNonConflictIdentifier(stateUDT, c => { return _validator.HasConflictingFieldIdentifier(stateUDT); }, (s) => { stateUDT.NewFieldName = s; }, () => stateUDT.IdentifierName, _validator); + + stateUDT = SetNonConflictIdentifier(stateUDT, c => { return _validator.IsConflictingStateUDTIdentifier(stateUDT); }, (s) => { stateUDT.AsTypeName = s; }, () => stateUDT.AsTypeName, _validator); return stateUDT; } - public IEnumerable CreateEncapsulationCandidates(IEnumerable candidateFields) + public IEncapsulateFieldCandidate CreateEncapsulationCandidate(Declaration target) { - var candidates = new List(); - foreach (var field in candidateFields) - { - var encapuslatedField = EncapsulateDeclaration(field, _validator); + Debug.Assert(!target.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)); - var isConflictingPropertyIdentifier = _validator.HasConflictingPropertyIdentifier(encapuslatedField); - for (var count = 1; count < 10 && isConflictingPropertyIdentifier; count++) - { - encapuslatedField.PropertyName = $"{encapuslatedField.IdentifierName}{count}"; - isConflictingPropertyIdentifier = _validator.HasConflictingPropertyIdentifier(encapuslatedField); - } + var candidate = target.IsUserDefinedTypeField() + ? new EncapsulatedUserDefinedTypeField(target, _validator) + : new EncapsulateFieldCandidate(target, _validator); - _encapsulatedFields.Add(encapuslatedField); - } + _validator.RegisterFieldCandidate(candidate); + + candidate = ApplyTypeSpecificAttributes(candidate); + candidate = SetNonConflictIdentifier(candidate, c => { return _validator.HasConflictingPropertyIdentifier(candidate); }, (s) => { candidate.PropertyName = s; }, () => candidate.IdentifierName, _validator); - var udtFieldToUdtDeclarationMap = candidateFields - .Where(v => v.IsUserDefinedTypeField()) - .Select(uv => CreateUDTTuple(uv)) - .ToDictionary(key => key.UDTVariable, element => (element.UserDefinedType, element.UDTMembers)); - foreach ( var udtField in udtFieldToUdtDeclarationMap.Keys) + if (candidate is IEncapsulatedUserDefinedTypeField udtVariable) { - var encapsulatedUDTField = _encapsulatedFields.Where(ef => ef.Declaration == udtField).Single() as IEncapsulatedUserDefinedTypeField; + (Declaration udt, IEnumerable udtMembers) = GetUDTAndMembersForField(udtVariable); - encapsulatedUDTField.TypeDeclarationIsPrivate = udtFieldToUdtDeclarationMap[udtField].UserDefinedType.Accessibility.Equals(Accessibility.Private); + udtVariable.TypeDeclarationIsPrivate = udt.Accessibility == Accessibility.Private; - foreach (var udtMember in udtFieldToUdtDeclarationMap[udtField].Item2) + foreach (var udtMember in udtMembers) { - var encapsulatedUDTMember = new EncapsulatedUserDefinedTypeMember(udtMember, encapsulatedUDTField, _validator) as IEncapsulatedUserDefinedTypeMember; - - var isConflictingPropertyIdentifier = _validator.HasConflictingFieldIdentifier(encapsulatedUDTMember); - for (var count = 1; count < 10 && isConflictingPropertyIdentifier; count++) - { - encapsulatedUDTMember.PropertyName = $"{encapsulatedUDTMember.IdentifierName}{count}"; - isConflictingPropertyIdentifier = _validator.HasConflictingPropertyIdentifier(encapsulatedUDTMember); - } - - encapsulatedUDTMember = ApplyTypeSpecificAttributes(encapsulatedUDTMember); - encapsulatedUDTField.AddMember(encapsulatedUDTMember); - encapsulatedUDTMember.PropertyAccessExpression = + var candidateUDTMember = new EncapsulatedUserDefinedTypeMember(udtMember, udtVariable, _validator) as IEncapsulatedUserDefinedTypeMember; + + candidateUDTMember = ApplyTypeSpecificAttributes(candidateUDTMember); + + candidateUDTMember = SetNonConflictIdentifier(candidateUDTMember, c => { return _validator.HasConflictingPropertyIdentifier(candidate); }, (s) => { candidateUDTMember.PropertyName = s; }, () => candidate.IdentifierName, _validator); + + candidateUDTMember.PropertyAccessExpression = () => { - var prefix = encapsulatedUDTField.EncapsulateFlag - ? encapsulatedUDTField.NewFieldName - : encapsulatedUDTField.IdentifierName; - return $"{prefix}.{encapsulatedUDTMember.IdentifierName}"; + var prefix = udtVariable.EncapsulateFlag + ? udtVariable.NewFieldName + : udtVariable.IdentifierName; + return $"{prefix}.{candidateUDTMember.IdentifierName}"; }; + + udtVariable.AddMember(candidateUDTMember); } } - return _encapsulatedFields; + return candidate; } - public static IEncapsulateFieldCandidate EncapsulateDeclaration(Declaration target, IEncapsulateFieldNamesValidator validator) + public IEnumerable CreateEncapsulationCandidates() //IEnumerable candidateFields) { - Debug.Assert(!target.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)); + var fieldDeclarations = _declarationFinderProvider.DeclarationFinder + .Members(_targetQMN) + .Where(v => v.IsMemberVariable() && !v.IsWithEvents); + //_fieldCandidates = candidateFields; - var candidate = target.IsUserDefinedTypeField() - ? new EncapsulatedUserDefinedTypeField(target, validator) - : new EncapsulateFieldCandidate(target, validator); + var candidates = new List(); + foreach (var field in fieldDeclarations) + { + var fieldEncapsulationCandidate = CreateEncapsulationCandidate(field); - return ApplyTypeSpecificAttributes(candidate); + candidates.Add(fieldEncapsulationCandidate); + //_encapsulatedFields.Add(encapuslatedField); + } + + return candidates; } - private (Declaration UDTVariable, Declaration UserDefinedType, IEnumerable UDTMembers) CreateUDTTuple(Declaration udtVariable) + private T SetNonConflictIdentifier(T candidate, Predicate conflictDetector, Action setValue, Func getIdentifier, IEncapsulateFieldNamesValidator validator) where T : IEncapsulateFieldCandidate { - var userDefinedTypeDeclaration = _declarationFinderProvider.DeclarationFinder - .UserDeclarations(DeclarationType.UserDefinedType) - .Where(ut => ut.IdentifierName.Equals(udtVariable.AsTypeName) - && (ut.Accessibility.Equals(Accessibility.Private) - && ut.QualifiedModuleName == udtVariable.QualifiedModuleName) - || (ut.Accessibility != Accessibility.Private)) - .SingleOrDefault(); - - var udtMembers = _declarationFinderProvider.DeclarationFinder - .UserDeclarations(DeclarationType.UserDefinedTypeMember) - .Where(utm => userDefinedTypeDeclaration == utm.ParentDeclaration); - - return (udtVariable, userDefinedTypeDeclaration, udtMembers); + var isConflictingIdentifier = conflictDetector(candidate); + for (var count = 1; count < 10 && isConflictingIdentifier; count++) + { + setValue(EncapsulationIdentifiers.IncrementIdentifier(getIdentifier())); + isConflictingIdentifier = conflictDetector(candidate); + } + return candidate; } - private static T ApplyTypeSpecificAttributes(T candidate) where T: IEncapsulateFieldCandidate + private T ApplyTypeSpecificAttributes(T candidate) where T: IEncapsulateFieldCandidate { var target = candidate.Declaration; - if (target.IsUserDefinedTypeField()) - { - candidate.ImplementLetSetterType = true; - candidate.ImplementSetSetterType = false; - } - else if (target.IsArray) + //if (target.IsUserDefinedTypeField()) + //{ + // candidate.ImplementLetSetterType = true; + // candidate.ImplementSetSetterType = false; + //} + if (target.IsArray) { candidate.ImplementLetSetterType = false; candidate.ImplementSetSetterType = false; @@ -155,12 +140,29 @@ private static T ApplyTypeSpecificAttributes(T candidate) where T: IEncapsula candidate.ImplementLetSetterType = false; candidate.ImplementSetSetterType = true; } - else - { - candidate.ImplementLetSetterType = true; - candidate.ImplementSetSetterType = false; - } + //else + //{ + // candidate.ImplementLetSetterType = true; + // candidate.ImplementSetSetterType = false; + //} return candidate; } + + private (Declaration TypeDeclaration, IEnumerable Members) GetUDTAndMembersForField(IEncapsulatedUserDefinedTypeField udtField) + { + var userDefinedTypeDeclaration = _declarationFinderProvider.DeclarationFinder + .UserDeclarations(DeclarationType.UserDefinedType) + .Where(ut => ut.IdentifierName.Equals(udtField.AsTypeName) + && (ut.Accessibility.Equals(Accessibility.Private) + && ut.QualifiedModuleName == udtField.QualifiedModuleName) + || (ut.Accessibility != Accessibility.Private)) + .SingleOrDefault(); + + var udtMembers = _declarationFinderProvider.DeclarationFinder + .UserDeclarations(DeclarationType.UserDefinedTypeMember) + .Where(utm => userDefinedTypeDeclaration == utm.ParentDeclaration); + + return (userDefinedTypeDeclaration, udtMembers); + } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index 2ad26ad9f5..cb654ae080 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -24,7 +24,9 @@ public class EncapsulateFieldModel : IRefactoringModel private IDictionary)> _udtFieldToUdtDeclarationMap = new Dictionary)>(); - public EncapsulateFieldModel(Declaration target, IDeclarationFinderProvider declarationFinderProvider, IIndenter indenter, Func previewDelegate) + private EncapsulationCandidateFactory _fieldCandidateFactory; + + public EncapsulateFieldModel(Declaration target, IDeclarationFinderProvider declarationFinderProvider, IIndenter indenter, IEnumerable candidates, Func previewDelegate) { _declarationFinderProvider = declarationFinderProvider; _indenter = indenter; @@ -33,46 +35,33 @@ public EncapsulateFieldModel(Declaration target, IDeclarationFinderProvider decl _useNewStructure = File.Exists("C:\\Users\\Brian\\Documents\\UseNewUDTStructure.txt"); - _validator = new EncapsulateFieldNamesValidator(_declarationFinderProvider, () => FieldCandidates); - - CandidateFactory = new EncapsulationCandidateFactory(declarationFinderProvider, _validator); - var encapsulationCandidateFields = _declarationFinderProvider.DeclarationFinder - .Members(_targetQMN) - .Where(v => v.IsMemberVariable() && !v.IsWithEvents); - - var candidates = CandidateFactory.CreateEncapsulationCandidates(encapsulationCandidateFields); - - FieldCandidates.AddRange(candidates); + _validator = new EncapsulateFieldNamesValidator(_declarationFinderProvider); //, () => EncapsulationCandidates); + EncapsulationCandidates = candidates.ToList(); + _fieldCandidateFactory = new EncapsulationCandidateFactory(declarationFinderProvider, _targetQMN, _validator); this[target].EncapsulateFlag = true; - } - public EncapsulationCandidateFactory CandidateFactory { private set; get; } - - public List FieldCandidates { set; get; } = new List(); + public List EncapsulationCandidates { set; get; } = new List(); - public IEnumerable FlaggedFieldCandidates - => FieldCandidates.Where(v => v.EncapsulateFlag); + public IEnumerable SelectedFieldCandidates + => EncapsulationCandidates.Where(v => v.EncapsulateFlag); public IEnumerable UDTFieldCandidates - => FieldCandidates + => EncapsulationCandidates .Where(v => v is IEncapsulatedUserDefinedTypeField) .Cast(); - public IEnumerable FlaggedUDTFieldCandidates - => FlaggedFieldCandidates + public IEnumerable SelectedUDTFieldCandidates + => SelectedFieldCandidates .Where(v => v is IEncapsulatedUserDefinedTypeField) .Cast(); - public IEnumerable FlaggedEncapsulationFields - => FlaggedFieldCandidates; - public IEncapsulateFieldCandidate this[string encapsulatedFieldTargetID] - => FieldCandidates.Where(c => c.TargetID.Equals(encapsulatedFieldTargetID)).Single(); + => EncapsulationCandidates.Where(c => c.TargetID.Equals(encapsulatedFieldTargetID)).Single(); public IEncapsulateFieldCandidate this[Declaration fieldDeclaration] - => FieldCandidates.Where(c => c.Declaration == fieldDeclaration).Single(); + => EncapsulationCandidates.Where(c => c.Declaration == fieldDeclaration).Single(); public IEncapsulateFieldStrategy EncapsulationStrategy { @@ -82,7 +71,7 @@ public IEncapsulateFieldStrategy EncapsulationStrategy { return new EncapsulateWithBackingUserDefinedType(_targetQMN, _indenter, _validator) { - StateUDTField = CandidateFactory.CreateStateUDTField(_targetQMN) + StateUDTField = _fieldCandidateFactory.CreateStateUDTField() }; } return new EncapsulateWithBackingFields(_targetQMN, _indenter, _validator); diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldNewContent.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldNewContent.cs index bcefd7177b..1af168a3fd 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldNewContent.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldNewContent.cs @@ -9,116 +9,116 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface IEncapsulateFieldNewContentProvider - { - void AddDeclarationBlock(string declarationBlock); - void AddCodeBlock(string codeBlock); - List Declarations { get; } - List CodeBlocks { get; } - string PreCodeSectionContent { get; } - bool HasNewContent { get; } - string CodeSectionContent { get; } - string AsSingleTextBlock { get; } - int CountOfProcLines { get; } - } - - public class EncapsulateFieldNewContent : IEncapsulateFieldNewContentProvider - { - protected static string DoubleSpace => $"{Environment.NewLine}{Environment.NewLine}"; - protected static string SingleSpace => $"{Environment.NewLine}"; - - private IEnumerable SourceModuleElements { get; } - - public void AddTypeDeclarationBlock(string declarationBlock) - { - if (declarationBlock.Length > 0) - { - TypeDeclarations.Add(declarationBlock); - } - } - - public void AddDeclarationBlock(string declarationBlock) - { - if (declarationBlock.Length > 0) - { - Declarations.Add(declarationBlock); - } - } - - public void AddCodeBlock(string codeBlock) - { - if (codeBlock.Length > 0) - { - CodeBlocks.Add(codeBlock); - } - } - - private string _postPendComment; - public string PostPendComment - { - get => _postPendComment; - set - { - if (value.Length > 0) - { - _postPendComment = value.StartsWith("'") ? value : $"'{value}"; - } - } - } - - public List TypeDeclarations { get; } = new List(); - - public List Declarations { get; } = new List(); - - public List CodeBlocks { get; } = new List(); - - public string PreCodeSectionContent - { - get - { - var allDeclarations = Enumerable.Empty().Concat(TypeDeclarations).Concat(Declarations); - var preCodeSectionContent = new List(allDeclarations); - if (preCodeSectionContent.Any()) - { - var preCodeSection = string.Join(SingleSpace, preCodeSectionContent); - return preCodeSection; - } - return string.Empty; - } - } - - public bool HasNewContent => Declarations.Any() || CodeBlocks.Any(); - - public string CodeSectionContent => CodeBlocks.Any() ? string.Join($"{DoubleSpace}", CodeBlocks) : string.Empty; - - public string AsSingleTextBlock - { - get - { - if (!HasNewContent) { return string.Empty; } - - var content = string.Empty; - if (PreCodeSectionContent.Length > 0) - { - content = CodeSectionContent.Length > 0 - ? $"{PreCodeSectionContent}{DoubleSpace}{CodeSectionContent}" - : $"{PreCodeSectionContent}"; - } - else - { - content = CodeSectionContent.Length > 0 - ? $"{SingleSpace}{CodeSectionContent}" - : string.Empty; - } - - if (PostPendComment != null && PostPendComment.Length > 0) - { - content = $"{content}{SingleSpace}{PostPendComment}{SingleSpace}"; - } - return content; - } - } - - public int CountOfProcLines => CodeSectionContent.Split(new string[] {SingleSpace}, StringSplitOptions.None).Count(); - } + //public interface IEncapsulateFieldNewContentProvider + //{ + // void AddDeclarationBlock(string declarationBlock); + // void AddCodeBlock(string codeBlock); + // List Declarations { get; } + // List CodeBlocks { get; } + // string PreCodeSectionContent { get; } + // bool HasNewContent { get; } + // string CodeSectionContent { get; } + // string AsSingleTextBlock { get; } + // int CountOfProcLines { get; } + //} + + //public class EncapsulateFieldNewContent : IEncapsulateFieldNewContentProvider + //{ + // protected static string DoubleSpace => $"{Environment.NewLine}{Environment.NewLine}"; + // protected static string SingleSpace => $"{Environment.NewLine}"; + + // private IEnumerable SourceModuleElements { get; } + + // public void AddTypeDeclarationBlock(string declarationBlock) + // { + // if (declarationBlock.Length > 0) + // { + // TypeDeclarations.Add(declarationBlock); + // } + // } + + // public void AddDeclarationBlock(string declarationBlock) + // { + // if (declarationBlock.Length > 0) + // { + // Declarations.Add(declarationBlock); + // } + // } + + // public void AddCodeBlock(string codeBlock) + // { + // if (codeBlock.Length > 0) + // { + // CodeBlocks.Add(codeBlock); + // } + // } + + // private string _postPendComment; + // public string PostPendComment + // { + // get => _postPendComment; + // set + // { + // if (value.Length > 0) + // { + // _postPendComment = value.StartsWith("'") ? value : $"'{value}"; + // } + // } + // } + + // public List TypeDeclarations { get; } = new List(); + + // public List Declarations { get; } = new List(); + + // public List CodeBlocks { get; } = new List(); + + // public string PreCodeSectionContent + // { + // get + // { + // var allDeclarations = Enumerable.Empty().Concat(TypeDeclarations).Concat(Declarations); + // var preCodeSectionContent = new List(allDeclarations); + // if (preCodeSectionContent.Any()) + // { + // var preCodeSection = string.Join(SingleSpace, preCodeSectionContent); + // return preCodeSection; + // } + // return string.Empty; + // } + // } + + // public bool HasNewContent => Declarations.Any() || CodeBlocks.Any(); + + // public string CodeSectionContent => CodeBlocks.Any() ? string.Join($"{DoubleSpace}", CodeBlocks) : string.Empty; + + // public string AsSingleTextBlock + // { + // get + // { + // if (!HasNewContent) { return string.Empty; } + + // var content = string.Empty; + // if (PreCodeSectionContent.Length > 0) + // { + // content = CodeSectionContent.Length > 0 + // ? $"{PreCodeSectionContent}{DoubleSpace}{CodeSectionContent}" + // : $"{PreCodeSectionContent}"; + // } + // else + // { + // content = CodeSectionContent.Length > 0 + // ? $"{SingleSpace}{CodeSectionContent}" + // : string.Empty; + // } + + // if (PostPendComment != null && PostPendComment.Length > 0) + // { + // content = $"{content}{SingleSpace}{PostPendComment}{SingleSpace}"; + // } + // return content; + // } + // } + + // public int CountOfProcLines => CodeSectionContent.Split(new string[] {SingleSpace}, StringSplitOptions.None).Count(); + //} } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index fd1104d316..da57b220b9 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -16,13 +16,19 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public class EncapsulateFieldRefactoring : InteractiveRefactoringBase + public interface IEncapsulateFieldRefactoringTestAccess + { + EncapsulateFieldModel TestUserInteractionOnly(Declaration target, Func userInteraction); + } + + public class EncapsulateFieldRefactoring : InteractiveRefactoringBase, IEncapsulateFieldRefactoringTestAccess { private readonly IDeclarationFinderProvider _declarationFinderProvider; private readonly ISelectedDeclarationProvider _selectedDeclarationProvider; private readonly IIndenter _indenter; private QualifiedModuleName _targetQMN; - private EncapsulateFieldModel Model { set; get; } + private EncapsulationCandidateFactory _encapsulationCandidateFactory; + private IEncapsulateFieldNamesValidator _validator; public EncapsulateFieldRefactoring( IDeclarationFinderProvider declarationFinderProvider, @@ -37,9 +43,12 @@ public EncapsulateFieldRefactoring( _declarationFinderProvider = declarationFinderProvider; _selectedDeclarationProvider = selectedDeclarationProvider; _indenter = indenter; + _validator = new EncapsulateFieldNamesValidator(_declarationFinderProvider);//, () => FieldCandidates); //_useNewValidationScheme = File.Exists("C:\\Users\\Brian\\Documents\\UseNewUDTStructure.txt"); } + public EncapsulateFieldModel Model { set; get; } + protected override Declaration FindTargetDeclaration(QualifiedSelection targetSelection) { var selectedDeclaration = _selectedDeclarationProvider.SelectedDeclaration(targetSelection); @@ -53,6 +62,12 @@ protected override Declaration FindTargetDeclaration(QualifiedSelection targetSe return selectedDeclaration; } + public EncapsulateFieldModel TestUserInteractionOnly(Declaration target, Func userInteraction) + { + var model = InitializeModel(target); + return userInteraction(model); + } + protected override EncapsulateFieldModel InitializeModel(Declaration target) { if (target == null) @@ -67,10 +82,13 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) _targetQMN = target.QualifiedModuleName; + _encapsulationCandidateFactory = new EncapsulationCandidateFactory(_declarationFinderProvider, _targetQMN, _validator); + Model = new EncapsulateFieldModel( target, _declarationFinderProvider, _indenter, + _encapsulationCandidateFactory.CreateEncapsulationCandidates(), PreviewRewrite); return Model; diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs index 7a8490df9f..c005ed5b8b 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs @@ -11,20 +11,8 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public struct RewriteReplacePair - { - public RewriteReplacePair(string text, ParserRuleContext context) - { - Text = text; - Context = context; - } - public string Text { private set; get; } - public ParserRuleContext Context { private set; get; } - } - public interface IEncapsulateFieldRewriter : IModuleRewriter { - void InsertNewContent(int? codeSectionStartIndex, IEncapsulateFieldNewContentProvider newContent); void SetVariableVisiblity(Declaration element, string visibilityToken); void Rename(Declaration element, string newName); void MakeImplicitDeclarationTypeExplicit(Declaration element); @@ -33,14 +21,19 @@ public interface IEncapsulateFieldRewriter : IModuleRewriter void Replace(RewriteReplacePair pair); } - public class EncapsulateFieldRewriter : IEncapsulateFieldRewriter + public struct RewriteReplacePair { - public static IEncapsulateFieldRewriter CheckoutModuleRewriter(IRewriteSession rewriteSession, QualifiedModuleName qmn) + public RewriteReplacePair(string text, ParserRuleContext context) { - var rewriter = rewriteSession.CheckOutModuleRewriter(qmn); - return new EncapsulateFieldRewriter(rewriter); - } + Text = text; + Context = context; + } + public string Text { private set; get; } + public ParserRuleContext Context { private set; get; } + } + public class EncapsulateFieldRewriter : IEncapsulateFieldRewriter + { private IModuleRewriter _rewriter; public EncapsulateFieldRewriter(IModuleRewriter rewriter) @@ -48,25 +41,16 @@ public EncapsulateFieldRewriter(IModuleRewriter rewriter) _rewriter = rewriter; } - public void InsertNewContent(int? codeSectionStartIndex, IEncapsulateFieldNewContentProvider newContent) + public static IEncapsulateFieldRewriter CheckoutModuleRewriter(IRewriteSession rewriteSession, QualifiedModuleName qmn) { - var allContent = newContent.AsSingleTextBlock; - if (codeSectionStartIndex.HasValue && newContent.HasNewContent) - { - _rewriter.InsertBefore(codeSectionStartIndex.Value, $"{Environment.NewLine}{allContent}{Environment.NewLine}"); - } - else - { - InsertAtEndOfFile($"{Environment.NewLine}{allContent}"); - } + var rewriter = rewriteSession.CheckOutModuleRewriter(qmn); + return new EncapsulateFieldRewriter(rewriter); } public void InsertAtEndOfFile(string content) { - if (content == string.Empty) - { - return; - } + if (content == string.Empty) { return; } + _rewriter.InsertBefore(_rewriter.TokenStream.Size - 1, content); } @@ -111,7 +95,6 @@ public string GetText(int maxConsecutiveNewLines) return preview; } - public bool IsDirty => _rewriter.IsDirty; public Selection? Selection { get => _rewriter.Selection; set => _rewriter.Selection = value; } @@ -154,4 +137,5 @@ public string GetText(int maxConsecutiveNewLines) public void Replace(Interval tokenInterval, string content) => _rewriter.Replace(tokenInterval, content); } + } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs index 86295cb146..1ae9bba926 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -15,6 +15,7 @@ namespace Rubberduck.Refactorings.EncapsulateField { public interface IEncapsulateFieldValidator { + void RegisterFieldCandidate(IEncapsulateFieldCandidate candidate); bool HasValidEncapsulationAttributes(IEncapsulateFieldCandidate candidate, IEnumerable ignore); bool IsValidVBAIdentifier(string identifier, DeclarationType declarationType); bool HasConflictingPropertyIdentifier(IEncapsulateFieldCandidate candidate); @@ -32,14 +33,19 @@ public class EncapsulateFieldNamesValidator : IEncapsulateFieldNamesValidator { private readonly IDeclarationFinderProvider _declarationFinderProvider; - private Lazy> _fieldCandidates; + private List _registeredCandidates; - private List FieldCandidates => _fieldCandidates.Value; + private List FieldCandidates => _registeredCandidates; // _fieldCandidates.Value; public EncapsulateFieldNamesValidator(IDeclarationFinderProvider declarationFinderProvider, Func> retrieveCandidateFields = null) { _declarationFinderProvider = declarationFinderProvider; - _fieldCandidates = new Lazy>(retrieveCandidateFields ?? (() => new List())); + _registeredCandidates = new List(); + } + + public void RegisterFieldCandidate(IEncapsulateFieldCandidate candidate) + { + _registeredCandidates.Add(candidate); } private DeclarationFinder DeclarationFinder => _declarationFinderProvider.DeclarationFinder; @@ -52,7 +58,12 @@ public bool HasConflictingPropertyIdentifier(IEncapsulateFieldCandidate candidat var members = _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) .Where(d => d != candidate.Declaration); - return members.Any(m => m.IdentifierName.EqualsVBAIdentifier(candidate.PropertyName)); + var edits = FieldCandidates.Where(fc => fc.EncapsulateFlag && fc.Declaration != candidate.Declaration).Select(fc => fc.PropertyName); + edits = edits.Concat(FieldCandidates.Where(fc => fc.EncapsulateFlag && fc.Declaration != candidate.Declaration).Select(fc => fc.NewFieldName)); + + + return members.Any(m => m.IdentifierName.EqualsVBAIdentifier(candidate.PropertyName)) + || edits.Any(ed => ed.EqualsVBAIdentifier(candidate.PropertyName)); } public bool HasConflictingFieldIdentifier(IEncapsulateFieldCandidate candidate) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs index 98b88c42a5..b57c1ecfa9 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs @@ -63,6 +63,9 @@ public EncapsulateFieldCandidate(Declaration declaration, IEncapsulateFieldNames : this(declaration.IdentifierName, declaration.AsTypeName, declaration.QualifiedModuleName, validator) { _target = declaration; + ImplementLetSetterType = true; + ImplementSetSetterType = false; + CanBeReadWrite = true; } public EncapsulateFieldCandidate(string identifier, string asTypeName, QualifiedModuleName qmn, IEncapsulateFieldNamesValidator validator) @@ -107,11 +110,8 @@ public bool HasValidEncapsulationAttributes { if (!EncapsulateFlag) { return true; } - return IsSelfConsistent; // _validator.IsValidVBAIdentifier(PropertyName, DeclarationType.Property) - - //var declarationsToIgnore = _target != null ? new Declaration[] { _target } : Enumerable.Empty(); - //var declarationType = _target != null ? _target.DeclarationType : DeclarationType.Variable; - //return _validator.HasValidEncapsulationAttributes(this, QualifiedModuleName, declarationsToIgnore, declarationType); + return IsSelfConsistent + && !_validator.HasConflictingPropertyIdentifier(this); } } diff --git a/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs b/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs index 1a5156afa1..35389178a2 100644 --- a/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs @@ -59,6 +59,18 @@ public string AsPropertyBlock(IIndenter indenter) return string.Join(Environment.NewLine, indenter.Indent(AsEnumerableLines, true)); } + public string AsPropertyBlock(IPropertyGeneratorSpecification spec, IIndenter indenter) + { + PropertyName = spec.PropertyName; + BackingField = spec.BackingField; + AsTypeName = spec.AsTypeName; + ParameterName = spec.ParameterName; + GenerateLetter = spec.GenerateLetter; + GenerateSetter = spec.GenerateSetter; + UsesSetAssignment = spec.UsesSetAssignment; + return string.Join(Environment.NewLine, indenter.Indent(AsEnumerableLines, true)); + } + private string GetterCode { get diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs index a3e84a4cf2..5230cc9179 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs @@ -15,58 +15,49 @@ namespace Rubberduck.Refactorings.EncapsulateField.Strategies public class EncapsulateWithBackingFields : EncapsulateFieldStrategiesBase { public EncapsulateWithBackingFields(QualifiedModuleName qmn, IIndenter indenter, IEncapsulateFieldValidator validator) - : base(qmn, indenter, validator) - { - } + : base(qmn, indenter, validator) { } - protected override void ModifyField(IEncapsulateFieldCandidate field, IRewriteSession rewriteSession) + protected override void ModifyFields(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) { - var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); - - if (field.Declaration.Accessibility == Accessibility.Private && field.NewFieldName.Equals(field.Declaration.IdentifierName)) + foreach (var field in model.SelectedFieldCandidates) { - rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); - return; - } + var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); + + if (field.Declaration.Accessibility == Accessibility.Private && field.NewFieldName.Equals(field.Declaration.IdentifierName)) + { + rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); + continue; + } + + if (field.Declaration.IsDeclaredInList()) + { + RewriterRemoveWorkAround.Remove(field.Declaration, rewriter); + //rewriter.Remove(target.Declaration); + continue; + } - if (field.Declaration.IsDeclaredInList()) - { - RewriterRemoveWorkAround.Remove(field.Declaration, rewriter); - //rewriter.Remove(target.Declaration); - } - else - { rewriter.Rename(field.Declaration, field.NewFieldName); rewriter.SetVariableVisiblity(field.Declaration, Accessibility.Private.TokenString()); rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); } - return; } - protected override EncapsulateFieldNewContent LoadNewDeclarationBlocks(EncapsulateFieldNewContent newContent, EncapsulateFieldModel model) + protected override void LoadNewDeclarationBlocks(EncapsulateFieldModel model) { - foreach (var field in model.FlaggedFieldCandidates) - { - - if (field.Declaration.Accessibility == Accessibility.Private && field.NewFieldName.Equals(field.Declaration.IdentifierName)) - { - continue; - } + //New field declarations created here were removed from their list within ModifyFields(...) + var fieldsRequiringNewDeclaration = model.SelectedFieldCandidates + .Where(field => field.Declaration.IsDeclaredInList() + && field.Declaration.Accessibility != Accessibility.Private); - //Fields within a list (where Accessibility is 'Public' - //are removed from the list (within ModifyField(...)) and - //inserted as a new Declaration - if (field.Declaration.IsDeclaredInList()) - { - var targetIdentifier = field.Declaration.Context.GetText().Replace(field.IdentifierName, field.NewFieldName); - var newField = field.Declaration.IsTypeSpecified - ? $"{Tokens.Private} {targetIdentifier}" - : $"{Tokens.Private} {targetIdentifier} {Tokens.As} {field.Declaration.AsTypeName}"; + foreach (var field in fieldsRequiringNewDeclaration) + { + var targetIdentifier = field.Declaration.Context.GetText().Replace(field.IdentifierName, field.NewFieldName); + var newField = field.Declaration.IsTypeSpecified + ? $"{Tokens.Private} {targetIdentifier}" + : $"{Tokens.Private} {targetIdentifier} {Tokens.As} {field.Declaration.AsTypeName}"; - newContent.AddDeclarationBlock(newField); - } + AddCodeBlock(NewContentTypes.DeclarationBlock, newField); } - return newContent; } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs index 21ef97c1cb..773e301a34 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs @@ -21,54 +21,51 @@ public class EncapsulateWithBackingUserDefinedType : EncapsulateFieldStrategiesB public EncapsulateWithBackingUserDefinedType(QualifiedModuleName qmn, IIndenter indenter, IEncapsulateFieldValidator validator) : base(qmn, indenter, validator) { } + public IEncapsulateFieldCandidate StateUDTField { set; get; } + protected override IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) { - foreach (var field in model.FlaggedFieldCandidates) + foreach (var field in model.SelectedFieldCandidates) { if (field is IEncapsulatedUserDefinedTypeField udt) { udt.PropertyAccessExpression = () => $"{StateUDTField.PropertyAccessExpression()}.{udt.PropertyName}"; - udt.ReferenceExpression = udt.PropertyAccessExpression; foreach (var member in udt.Members) { member.PropertyAccessExpression = () => $"{udt.PropertyAccessExpression()}.{member.PropertyName}"; - member.ReferenceExpression = () => $"{udt.PropertyAccessExpression()}.{member.PropertyName}"; + member.ReferenceExpression = member.PropertyAccessExpression; } + continue; } - else - { - field.PropertyAccessExpression = () => $"{StateUDTField.PropertyAccessExpression()}.{field.PropertyName}"; - field.ReferenceExpression = field.PropertyAccessExpression; - } + + field.PropertyAccessExpression = () => $"{StateUDTField.PropertyAccessExpression()}.{field.PropertyName}"; + field.ReferenceExpression = field.PropertyAccessExpression; } return base.RefactorRewrite(model, rewriteSession, asPreview); } - public IEncapsulateFieldCandidate StateUDTField { set; get; } - - protected override void ModifyField(IEncapsulateFieldCandidate field, IRewriteSession rewriteSession) + protected override void ModifyFields(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) { - var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); + foreach (var field in model.SelectedFieldCandidates) + { + var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); - RewriterRemoveWorkAround.Remove(field.Declaration, rewriter); - //rewriter.Remove(target.Declaration); - return; + RewriterRemoveWorkAround.Remove(field.Declaration, rewriter); + //rewriter.Remove(target.Declaration); + } } - protected override EncapsulateFieldNewContent LoadNewDeclarationBlocks(EncapsulateFieldNewContent newContent, EncapsulateFieldModel model) + protected override void LoadNewDeclarationBlocks(EncapsulateFieldModel model) { var udt = new UDTDeclarationGenerator(StateUDTField.AsTypeName); - udt.AddMembers(model.FlaggedFieldCandidates); - - newContent.AddTypeDeclarationBlock(udt.TypeDeclarationBlock(Indenter)); - - newContent.AddDeclarationBlock(udt.FieldDeclaration(StateUDTField.NewFieldName)); + udt.AddMembers(model.SelectedFieldCandidates); - return newContent; + AddCodeBlock(NewContentTypes.TypeDeclarationBlock, udt.TypeDeclarationBlock(Indenter)); + AddCodeBlock(NewContentTypes.DeclarationBlock, udt.FieldDeclarationBlock(StateUDTField.NewFieldName)); } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs index 4db7d332b7..3cff0bba8c 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Linq; namespace Rubberduck.Refactorings.EncapsulateField.Strategies @@ -19,37 +20,51 @@ public interface IEncapsulateFieldStrategy public abstract class EncapsulateFieldStrategiesBase : IEncapsulateFieldStrategy { + protected enum NewContentTypes { TypeDeclarationBlock, DeclarationBlock, MethodBlock, PostContentMessage }; + private IEncapsulateFieldValidator _validator; - protected static string DoubleSpace => $"{Environment.NewLine}{Environment.NewLine}"; + private static string DoubleSpace => $"{Environment.NewLine}{Environment.NewLine}"; + private Dictionary> _newContent { set; get; } public EncapsulateFieldStrategiesBase(QualifiedModuleName qmn, IIndenter indenter, IEncapsulateFieldValidator validator) { TargetQMN = qmn; Indenter = indenter; _validator = validator; + + _newContent = new Dictionary> + { + { NewContentTypes.PostContentMessage, new List() }, + { NewContentTypes.DeclarationBlock, new List() }, + { NewContentTypes.MethodBlock, new List() }, + { NewContentTypes.TypeDeclarationBlock, new List() } + }; } + protected void AddCodeBlock(NewContentTypes contentType, string block) + => _newContent[contentType].Add(block); + protected QualifiedModuleName TargetQMN {private set; get;} protected IIndenter Indenter { private set; get; } public IExecutableRewriteSession GeneratePreview(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) { - if (!model.FlaggedEncapsulationFields.Any()) { return rewriteSession; } + if (!model.SelectedFieldCandidates.Any()) { return rewriteSession; } return RefactorRewrite(model, rewriteSession, asPreview: true); } public IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) { - if (!model.FlaggedEncapsulationFields.Any()) { return rewriteSession; } + if (!model.SelectedFieldCandidates.Any()) { return rewriteSession; } return RefactorRewrite(model, rewriteSession, asPreview: false); } - protected abstract void ModifyField(IEncapsulateFieldCandidate target, IRewriteSession rewriteSession); + protected abstract void ModifyFields(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession); - protected abstract EncapsulateFieldNewContent LoadNewDeclarationBlocks(EncapsulateFieldNewContent newContent, EncapsulateFieldModel model); + protected abstract void LoadNewDeclarationBlocks(EncapsulateFieldModel model); protected virtual IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) { @@ -68,25 +83,17 @@ protected virtual IExecutableRewriteSession RefactorRewrite(EncapsulateFieldMode protected void ConfigureSelectedEncapsulationObjects(EncapsulateFieldModel model) { - foreach (var udtField in model.FlaggedUDTFieldCandidates) + foreach (var udtField in model.SelectedUDTFieldCandidates) { - udtField.FieldQualifyMemberPropertyNames = model.FlaggedUDTFieldCandidates.Where(f => f.AsTypeName.Equals(udtField.AsTypeName)).Count() > 1; + udtField.FieldQualifyMemberPropertyNames = model.SelectedUDTFieldCandidates.Where(f => f.AsTypeName.Equals(udtField.AsTypeName)).Count() > 1; } StageReferenceReplacementExpressions(model); } - protected void ModifyFields(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) - { - foreach (var field in model.FlaggedEncapsulationFields) - { - ModifyField(field, rewriteSession); - } - } - protected void ModifyReferences(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) { - foreach (var rewriteReplacement in model.FlaggedEncapsulationFields.SelectMany(fld => fld.ReferenceReplacements)) + foreach (var rewriteReplacement in model.SelectedFieldCandidates.SelectMany(fld => fld.ReferenceReplacements)) { var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, rewriteReplacement.Key.QualifiedModuleName); rewriter.Replace(rewriteReplacement.Value); @@ -95,7 +102,7 @@ protected void ModifyReferences(EncapsulateFieldModel model, IExecutableRewriteS protected void StageReferenceReplacementExpressions(EncapsulateFieldModel model) { - foreach (var field in model.FlaggedEncapsulationFields) + foreach (var field in model.SelectedFieldCandidates) { field.LoadReferenceExpressionChanges(); } @@ -105,31 +112,43 @@ protected void InsertNewContent(EncapsulateFieldModel model, IExecutableRewriteS { var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); - var newContent = new EncapsulateFieldNewContent() + LoadNewDeclarationBlocks(model); + + LoadNewPropertyBlocks(model); + + if (postPendPreviewMessage) { - PostPendComment = postPendPreviewMessage ? "'<===== All Changes above this line =====>" : string.Empty, - }; + _newContent[NewContentTypes.PostContentMessage].Add("'<===== All Changes above this line =====>"); + } - newContent = LoadNewDeclarationBlocks(newContent, model); + var newContentBlock = string.Join(DoubleSpace, + (_newContent[NewContentTypes.TypeDeclarationBlock]) + .Concat(_newContent[NewContentTypes.DeclarationBlock]) + .Concat(_newContent[NewContentTypes.MethodBlock]) + .Concat(_newContent[NewContentTypes.PostContentMessage])) + .Trim(); - newContent = LoadNewPropertyBlocks(newContent, model); - rewriter.InsertNewContent(model.CodeSectionStartIndex, newContent); + if (model.CodeSectionStartIndex.HasValue) + { + rewriter.InsertBefore(model.CodeSectionStartIndex.Value, $"{newContentBlock}{DoubleSpace}"); + } + else + { + rewriter.InsertAtEndOfFile($"{DoubleSpace}{newContentBlock}"); + } } - private EncapsulateFieldNewContent LoadNewPropertyBlocks(EncapsulateFieldNewContent newContent, EncapsulateFieldModel model) //, string postScript = null) + private void LoadNewPropertyBlocks(EncapsulateFieldModel model) { - if (!model.FlaggedEncapsulationFields.Any()) { return newContent; } - - var propertyBlocks = new List(); - var propertyGenerationSpecs = model.FlaggedEncapsulationFields + var propertyGenerationSpecs = model.SelectedFieldCandidates .SelectMany(f => f.PropertyGenerationSpecs); + var generator = new PropertyGenerator(); foreach (var spec in propertyGenerationSpecs) { - newContent.AddCodeBlock(new PropertyGenerator(spec).AsPropertyBlock(Indenter)); + AddCodeBlock(NewContentTypes.MethodBlock, generator.AsPropertyBlock(spec, Indenter)); } - return newContent; } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/UDTDeclarationGenerator.cs b/Rubberduck.Refactorings/EncapsulateField/UDTDeclarationGenerator.cs index ff61da0e0f..11d3e3064b 100644 --- a/Rubberduck.Refactorings/EncapsulateField/UDTDeclarationGenerator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/UDTDeclarationGenerator.cs @@ -25,7 +25,7 @@ public UDTDeclarationGenerator(string typeIdentifierName) public void AddMembers(IEnumerable fields) => _members.AddRange(fields); - public string FieldDeclaration(string identifierName, Accessibility accessibility = Accessibility.Private) + public string FieldDeclarationBlock(string identifierName, Accessibility accessibility = Accessibility.Private) => $"{accessibility} {identifierName} {Tokens.As} {_typeIdentifierName}"; public string TypeDeclarationBlock(IIndenter indenter = null, Accessibility accessibility = Accessibility.Private) diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs index fb4847b9a7..0f49e662a2 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs @@ -70,7 +70,7 @@ End Property "; var presenterAction = Support.SetParametersForSingleTarget("fizz", "Name", isReadonly: true); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - Assert.AreEqual(expectedCode, actualCode); + Assert.AreEqual(expectedCode.Trim(), actualCode); } [Test] @@ -124,7 +124,7 @@ Private Function First() As String [Test] [Category("Refactorings")] [Category("Encapsulate Field")] - public void FieldNameAttributeValidation_DefaultsToAvailablePropertyName() + public void FieldNameDefaultsToNonConflictName() { string inputCode = $@"Public fizz As String @@ -132,11 +132,11 @@ public void FieldNameAttributeValidation_DefaultsToAvailablePropertyName() Private fizzle As String 'fizz1 is the initial default name for encapsulating 'fizz' - Public Property Get Fizz1() As String - Fizz1 = fizzle + Public Property Get Fizz_1() As String + Fizz_1 = fizzle End Property - Public Property Let Fizz1(ByVal value As String) + Public Property Let Fizz_1(ByVal value As String) fizzle = value End Property "; @@ -144,44 +144,64 @@ End Property Assert.IsTrue(encapsulatedField.HasValidEncapsulationAttributes); } - [TestCase("Number")] - [TestCase("Test")] + [TestCase("Name")] + [TestCase("mName")] [Category("Refactorings")] [Category("Encapsulate Field")] - public void EncapsulateMultipleFields_PropertyNameConflicts(string modifiedPropertyName) + public void UserEntersConflictingName(string userModifiedPropertyName) + { + string inputCode = +$@"Public fizz As String + + Private mName As String + + Public Property Get Name() As String + Name = mName + End Property + + Public Property Let Name(ByVal value As String) + mName = value + End Property + "; + + var userInput = new UserInputDataObject("fizz", userModifiedPropertyName, true); + + var presenterAction = Support.SetParameters(userInput); + + var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, "fizz", DeclarationType.Variable, presenterAction, "fizz"); + + Assert.IsFalse(model["fizz"].HasValidEncapsulationAttributes); + } + + [TestCase("Number", "Bazzle", true, true)] + [TestCase("Number", "Number", false, false)] + [TestCase("Test", "Number", false, true)] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserModificationIsExistingPropertyNameConflicts(string fizz_modifiedPropertyName, string bazz_modifiedPropertyName, bool fizz_expectedResult, bool bazz_expectedResult) { string inputCode = $@"Public fizz As Integer Public bazz As Integer Public buzz As Integer + Private mTest As Integer Public Property Get Test() As Integer Test = mTest End Property"; - var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; - var selectedComponentName = vbe.SelectedVBComponent.Name; - - var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); - using (state) - { - var mockFizz = CreateEncapsulatedFieldMock("fizz", "Integer", vbe.SelectedVBComponent, modifiedPropertyName); - var mockBazz = CreateEncapsulatedFieldMock("bazz", "Integer", vbe.SelectedVBComponent, "Whole"); - var mockBuzz = CreateEncapsulatedFieldMock("buzz", "Integer", vbe.SelectedVBComponent, modifiedPropertyName); + var userInput = new UserInputDataObject() + .AddAttributeSet("fizz", fizz_modifiedPropertyName, true) + .AddAttributeSet("bazz", bazz_modifiedPropertyName, true); - var validator = new EncapsulateFieldNamesValidator( - state, - () => new List() - { - mockFizz, - mockBazz, - mockBuzz - }); + var presenterAction = Support.SetParameters(userInput); + var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, "fizz", DeclarationType.Variable, presenterAction, "fizz", "bazz", "buzz"); - //Assert.Less(0, validator.HasNewPropertyNameConflicts(mockFizz.EncapsulationAttributes, mockFizz.QualifiedModuleName, Enumerable.Empty())); - Assert.Less(0, validator.HasNewPropertyNameConflicts(mockFizz, mockFizz.QualifiedModuleName, Enumerable.Empty())); - } + Assert.AreEqual(fizz_expectedResult, model["fizz"].HasValidEncapsulationAttributes, "fizz failed"); + Assert.AreEqual(bazz_expectedResult, model["bazz"].HasValidEncapsulationAttributes, "bazz failed"); } [Test] @@ -202,28 +222,6 @@ Public that As TBar "; var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; - CreateAndParse(vbe, ThisTest); - //var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; - //var selectedComponentName = vbe.SelectedVBComponent.Name; - - void ThisTest(IDeclarationFinderProvider declarationProviderProvider) - { - var declarationThis = declarationProviderProvider.DeclarationFinder.MatchName("this").Single(); - var declarationThat = declarationProviderProvider.DeclarationFinder.MatchName("that").Single(); - var declarationTBar = declarationProviderProvider.DeclarationFinder.MatchName("TBar").Single(); - var declarationFirst = declarationProviderProvider.DeclarationFinder.MatchName("First").Single(); - - var fields = new List(); - - - var validator = new EncapsulateFieldNamesValidator(declarationProviderProvider, () => fields); - - var encapsulatedThis = new EncapsulateFieldCandidate(declarationThis, validator); - var encapsulatedThat = new EncapsulateFieldCandidate(declarationThat, validator); - fields.Add(encapsulatedThis); - fields.Add(encapsulatedThat); - } - var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); using (state) { @@ -237,9 +235,10 @@ void ThisTest(IDeclarationFinderProvider declarationProviderProvider) thisField, thatField, }); + validator.RegisterFieldCandidate(thisField); + validator.RegisterFieldCandidate(thatField); - //Assert.Less(0, validator.HasNewPropertyNameConflicts(thisField.EncapsulationAttributes, thisField.QualifiedModuleName, Enumerable.Empty())); Assert.Less(0, validator.HasNewPropertyNameConflicts(thisField, thisField.QualifiedModuleName, Enumerable.Empty())); } } @@ -271,16 +270,13 @@ void ThisTest(IDeclarationFinderProvider declarationProviderProvider) fields.Add(new EncapsulateFieldCandidate(wholeNumber, validator)); fields.Add(new EncapsulateFieldCandidate(longValue, validator)); - //encapsulatedWholeNumber.EncapsulationAttributes.PropertyName = "LongValue"; encapsulatedWholeNumber.PropertyName = "LongValue"; - //Assert.Less(0, validator.HasNewPropertyNameConflicts(encapsulatedWholeNumber.EncapsulationAttributes, encapsulatedWholeNumber.QualifiedModuleName, new Declaration[] { encapsulatedWholeNumber.Declaration })); Assert.Less(0, validator.HasNewPropertyNameConflicts(encapsulatedWholeNumber, encapsulatedWholeNumber.QualifiedModuleName, new Declaration[] { encapsulatedWholeNumber.Declaration })); } } private void CreateAndParse(IVBE vbe, Action theTest) { - //var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); var state = MockParser.CreateAndParse(vbe); using (state) { diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index 95fd068a9d..5fd16e9bfb 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -123,6 +123,23 @@ public IEncapsulateFieldCandidate RetrieveEncapsulatedField(string inputCode, st } } + public EncapsulateFieldModel RetrieveUserModifiedModelPriorToRefactoring(IVBE vbe, string declarationName, DeclarationType declarationType, Func presenterAdjustment, params string[] fieldIdentifiers) + { + var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); + using (state) + { + var target = state.DeclarationFinder.DeclarationsWithType(declarationType) + .Single(declaration => declaration.IdentifierName == declarationName); + + var refactoring = TestRefactoring(rewritingManager, state, presenterAdjustment); + if (refactoring is IEncapsulateFieldRefactoringTestAccess concrete) + { + return concrete.TestUserInteractionOnly(target, presenterAdjustment); + } + throw new InvalidCastException(); + } + } + public static IIndenter CreateIndenter(IVBE vbe = null) { return new Indenter(vbe, () => Settings.IndenterSettingsTests.GetMockIndenterSettings()); diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index 9bc1961856..13ec0fdbde 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -198,7 +198,7 @@ End Property "; var presenterAction = Support.SetParametersForSingleTarget("fizz", "Name"); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - Assert.AreEqual(expectedCode, actualCode); + Assert.AreEqual(expectedCode.Trim(), actualCode); } @@ -219,7 +219,7 @@ End Property "; var presenterAction = Support.SetParametersForSingleTarget("fizz", "Name", isReadonly: true); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - Assert.AreEqual(expectedCode, actualCode); + Assert.AreEqual(expectedCode.Trim(), actualCode); } [Test] @@ -289,7 +289,7 @@ End Property "; var presenterAction = Support.SetParametersForSingleTarget("fizz", "Name"); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - Assert.AreEqual(expectedCode, actualCode); + Assert.AreEqual(expectedCode.Trim(), actualCode); } [TestCase(1, 10, "fizz", "Public buzz", "Private fizz As Variant", "Public fizz")] @@ -336,7 +336,7 @@ End Property "; var presenterAction = Support.SetParametersForSingleTarget("fizz", "Name"); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - Assert.AreEqual(expectedCode, actualCode); + Assert.AreEqual(expectedCode.Trim(), actualCode); } [Test] @@ -412,7 +412,7 @@ End Property "; var presenterAction = Support.UserAcceptsDefaults(); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - Assert.AreEqual(expectedCode, actualCode); + Assert.AreEqual(expectedCode.Trim(), actualCode); } [Test] @@ -565,7 +565,7 @@ End Property "; var presenterAction = Support.SetParametersForSingleTarget("foo", "Name"); var actualCode = RefactoredCode(inputCode, "foo", DeclarationType.Variable, presenterAction); - Assert.AreEqual(expectedCode, actualCode); + Assert.AreEqual(expectedCode.Trim(), actualCode); } [Test] @@ -593,7 +593,7 @@ End Property "; var presenterAction = Support.SetParametersForSingleTarget("Foo", "bar"); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - Assert.AreEqual(expectedCode, actualCode); + Assert.AreEqual(expectedCode.Trim(), actualCode); } [TestCase("Private", "mArray(5) As String", "mArray(5) As String")] @@ -630,7 +630,7 @@ End Property var presenterAction = Support.SetParameters(userInput); var actualCode = RefactoredCode(inputCode, selection, presenterAction); - Assert.AreEqual(expectedCode, actualCode); + Assert.AreEqual(expectedCode.Trim(), actualCode); } [TestCase("5")] @@ -684,6 +684,7 @@ public void EncapsulateArray_newFieldNameForFieldInList(string declarationList, $@"Option Explicit Public mNextVar As Long + {expectedDeclaration} Public Property Get MyArray() As Variant @@ -692,7 +693,7 @@ End Property "; var presenterAction = Support.SetParametersForSingleTarget("mArray", "MyArray"); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - Assert.AreEqual(expectedCode, actualCode); + Assert.AreEqual(expectedCode.Trim(), actualCode); } [TestCase(false)] From 0eb99dd16281a4111528f82000e9a346735b4999 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Tue, 10 Dec 2019 17:28:29 -0800 Subject: [PATCH 050/461] WIP - all tests pass. Before deleting some files Deleting all strategy classes and their folder. Deleting NewContent class file. --- .../EncapsulateFieldViewModel.cs | 18 +- .../EncapsulateField/EncapsulateFieldModel.cs | 73 ++-- .../EncapsulateFieldRefactoring.cs | 248 +++++++++++- .../EncapsulateWithBackingFields.cs | 96 ++--- .../EncapsulateWithBackingUserDefinedType.cs | 92 ++--- .../Strategies/EncapsulationStrategiesBase.cs | 367 +++++++++++------- 6 files changed, 609 insertions(+), 285 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs index b555fd4172..f73a81f18f 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs @@ -3,7 +3,7 @@ using NLog; using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings.EncapsulateField; -using Rubberduck.Refactorings.EncapsulateField.Strategies; +//using Rubberduck.Refactorings.EncapsulateField.Strategies; using Rubberduck.UI.Command; namespace Rubberduck.UI.Refactorings.EncapsulateField @@ -66,17 +66,17 @@ public string EncapsulateAsUDT_TypeIdentifier { get { - if (Model.EncapsulationStrategy is IEncapsulateWithBackingUserDefinedType udtStrategy) + if (Model.EncapsulateWithUDT) { - return udtStrategy.StateUDTField.AsTypeName; + return Model.StateUDTField.AsTypeName; } return string.Empty; } set { - if (Model.EncapsulationStrategy is IEncapsulateWithBackingUserDefinedType udtStrategy) + if (Model.EncapsulateWithUDT) { - udtStrategy.StateUDTField.AsTypeName = value; + Model.StateUDTField.AsTypeName = value; } UpdatePreview(); } @@ -86,17 +86,17 @@ public string EncapsulateAsUDT_FieldName { get { - if (Model.EncapsulationStrategy is IEncapsulateWithBackingUserDefinedType udtStrategy) + if (Model.EncapsulateWithUDT) { - return udtStrategy.StateUDTField.NewFieldName; + return Model.StateUDTField.NewFieldName; } return string.Empty; } set { - if (Model.EncapsulationStrategy is IEncapsulateWithBackingUserDefinedType udtStrategy) + if (Model.EncapsulateWithUDT) { - udtStrategy.StateUDTField.NewFieldName = value; + Model.StateUDTField.NewFieldName = value; } UpdatePreview(); } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index cb654ae080..a608efd7bc 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -14,9 +14,9 @@ namespace Rubberduck.Refactorings.EncapsulateField { public class EncapsulateFieldModel : IRefactoringModel { - private readonly IIndenter _indenter; - private readonly IDeclarationFinderProvider _declarationFinderProvider; - private readonly IEncapsulateFieldNamesValidator _validator; + //private readonly IIndenter _indenter; + //private readonly IDeclarationFinderProvider _declarationFinderProvider; + //private readonly IEncapsulateFieldNamesValidator _validator; private readonly Func _previewDelegate; private QualifiedModuleName _targetQMN; @@ -24,21 +24,22 @@ public class EncapsulateFieldModel : IRefactoringModel private IDictionary)> _udtFieldToUdtDeclarationMap = new Dictionary)>(); - private EncapsulationCandidateFactory _fieldCandidateFactory; + //private EncapsulationCandidateFactory _fieldCandidateFactory; - public EncapsulateFieldModel(Declaration target, IDeclarationFinderProvider declarationFinderProvider, IIndenter indenter, IEnumerable candidates, Func previewDelegate) + public EncapsulateFieldModel(Declaration target, /*IDeclarationFinderProvider declarationFinderProvider, IIndenter indenter,*/ IEnumerable candidates, IEncapsulateFieldCandidate stateUDT, Func previewDelegate) { - _declarationFinderProvider = declarationFinderProvider; - _indenter = indenter; + //_declarationFinderProvider = declarationFinderProvider; + //_indenter = indenter; _previewDelegate = previewDelegate; _targetQMN = target.QualifiedModuleName; _useNewStructure = File.Exists("C:\\Users\\Brian\\Documents\\UseNewUDTStructure.txt"); - _validator = new EncapsulateFieldNamesValidator(_declarationFinderProvider); //, () => EncapsulationCandidates); + //_validator = new EncapsulateFieldNamesValidator(_declarationFinderProvider); //, () => EncapsulationCandidates); EncapsulationCandidates = candidates.ToList(); - _fieldCandidateFactory = new EncapsulationCandidateFactory(declarationFinderProvider, _targetQMN, _validator); + StateUDTField = stateUDT; + //_fieldCandidateFactory = new EncapsulationCandidateFactory(declarationFinderProvider, _targetQMN, _validator); this[target].EncapsulateFlag = true; } @@ -63,38 +64,40 @@ public IEncapsulateFieldCandidate this[string encapsulatedFieldTargetID] public IEncapsulateFieldCandidate this[Declaration fieldDeclaration] => EncapsulationCandidates.Where(c => c.Declaration == fieldDeclaration).Single(); - public IEncapsulateFieldStrategy EncapsulationStrategy - { - get - { - if (EncapsulateWithUDT) - { - return new EncapsulateWithBackingUserDefinedType(_targetQMN, _indenter, _validator) - { - StateUDTField = _fieldCandidateFactory.CreateStateUDTField() - }; - } - return new EncapsulateWithBackingFields(_targetQMN, _indenter, _validator); - } - } + //public IEncapsulateFieldStrategy EncapsulationStrategy { set; get; } + //{ + // get + // { + // if (EncapsulateWithUDT) + // { + // return new EncapsulateWithBackingUserDefinedType(_targetQMN, _indenter, _validator) + // { + // StateUDTField = _fieldCandidateFactory.CreateStateUDTField() + // }; + // } + // return new EncapsulateWithBackingFields(_targetQMN, _indenter, _validator); + // } + //} public bool EncapsulateWithUDT { set; get; } + public IEncapsulateFieldCandidate StateUDTField { set; get; } + public string PreviewRefactoring() => _previewDelegate(this); - public int? CodeSectionStartIndex - { - get - { - var moduleMembers = _declarationFinderProvider.DeclarationFinder - .Members(_targetQMN).Where(m => m.IsMember()); + //public int? CodeSectionStartIndex { set; get; } + //{ + // get + // { + // var moduleMembers = _declarationFinderProvider.DeclarationFinder + // .Members(_targetQMN).Where(m => m.IsMember()); - int? codeSectionStartIndex - = moduleMembers.OrderBy(c => c.Selection) - .FirstOrDefault()?.Context.Start.TokenIndex ?? null; + // int? codeSectionStartIndex + // = moduleMembers.OrderBy(c => c.Selection) + // .FirstOrDefault()?.Context.Start.TokenIndex ?? null; - return codeSectionStartIndex; - } - } + // return codeSectionStartIndex; + // } + //} } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index da57b220b9..e02d67a402 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -13,6 +13,7 @@ using Rubberduck.Parsing; using Rubberduck.Refactorings.Common; using System.IO; +using Rubberduck.Refactorings.EncapsulateField.Strategies; namespace Rubberduck.Refactorings.EncapsulateField { @@ -30,6 +31,13 @@ public class EncapsulateFieldRefactoring : InteractiveRefactoringBase> _newContent { set; get; } + + private int? _codeSectionStartIndex; + + private static string DoubleSpace => $"{Environment.NewLine}{Environment.NewLine}"; + public EncapsulateFieldRefactoring( IDeclarationFinderProvider declarationFinderProvider, IIndenter indenter, @@ -45,6 +53,14 @@ public EncapsulateFieldRefactoring( _indenter = indenter; _validator = new EncapsulateFieldNamesValidator(_declarationFinderProvider);//, () => FieldCandidates); //_useNewValidationScheme = File.Exists("C:\\Users\\Brian\\Documents\\UseNewUDTStructure.txt"); + + _codeSectionStartIndex = _declarationFinderProvider.DeclarationFinder + .Members(_targetQMN).Where(m => m.IsMember()) + .OrderBy(c => c.Selection) + .FirstOrDefault()?.Context.Start.TokenIndex ?? null; ; + + //_codeSectionStartIndex = moduleMembers.OrderBy(c => c.Selection) + // .FirstOrDefault()?.Context.Start.TokenIndex ?? null; } public EncapsulateFieldModel Model { set; get; } @@ -86,19 +102,30 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) Model = new EncapsulateFieldModel( target, - _declarationFinderProvider, - _indenter, + //_declarationFinderProvider, + //_indenter, _encapsulationCandidateFactory.CreateEncapsulationCandidates(), + _encapsulationCandidateFactory.CreateStateUDTField(), PreviewRewrite); + //Model.StateUDTField = _encapsulationCandidateFactory.CreateStateUDTField(); + + var moduleMembers = _declarationFinderProvider.DeclarationFinder + .Members(_targetQMN).Where(m => m.IsMember()); + + _codeSectionStartIndex + = moduleMembers.OrderBy(c => c.Selection) + .FirstOrDefault()?.Context.Start.TokenIndex ?? null; + + //Model.CodeSectionStartIndex = codeSectionStartIndex; + return Model; } protected override void RefactorImpl(EncapsulateFieldModel model) { - var strategy = model.EncapsulationStrategy; - - var rewriteSession = strategy.RefactorRewrite(model, RewritingManager.CheckOutCodePaneSession()); + //var strategy = new EncapsulateFieldStrategiesBase(_targetQMN, _indenter, _validator, StateUDTField); + var rewriteSession = RefactorRewrite(model, RewritingManager.CheckOutCodePaneSession()); if (!rewriteSession.TryRewrite()) { @@ -108,13 +135,218 @@ protected override void RefactorImpl(EncapsulateFieldModel model) private string PreviewRewrite(EncapsulateFieldModel model) { - var strategy = model.EncapsulationStrategy; - - var scratchPadRewriteSession = strategy.GeneratePreview(model, RewritingManager.CheckOutCodePaneSession()); + //var strategy = new EncapsulateFieldStrategiesBase(_targetQMN, _indenter, _validator, StateUDTField); + var scratchPadRewriteSession = GeneratePreview(model, RewritingManager.CheckOutCodePaneSession()); var previewRewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(scratchPadRewriteSession, _targetQMN); return previewRewriter.GetText(maxConsecutiveNewLines: 3); } + + private IEncapsulateFieldCandidate StateUDTField + => Model.EncapsulateWithUDT ? Model.StateUDTField : null; + + + public IExecutableRewriteSession GeneratePreview(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) + { + if (!model.SelectedFieldCandidates.Any()) { return rewriteSession; } + + return RefactorRewrite(model, rewriteSession, asPreview: true); + } + + public IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) + { + if (!model.SelectedFieldCandidates.Any()) { return rewriteSession; } + + return RefactorRewrite(model, rewriteSession, asPreview: false); + } + + private IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) + { + _newContent = new Dictionary> + { + { NewContentTypes.PostContentMessage, new List() }, + { NewContentTypes.DeclarationBlock, new List() }, + { NewContentTypes.MethodBlock, new List() }, + { NewContentTypes.TypeDeclarationBlock, new List() } + }; + + ConfigureSelectedEncapsulationObjects(model); + + ModifyFields(model, rewriteSession); + + ModifyReferences(model, rewriteSession); + + RewriterRemoveWorkAround.RemoveFieldsDeclaredInLists(rewriteSession, _targetQMN); + + InsertNewContent(model, rewriteSession, asPreview); + + return rewriteSession; + } + + private void ConfigureSelectedEncapsulationObjects(EncapsulateFieldModel model) + { + if (model.EncapsulateWithUDT) + { + foreach (var field in model.SelectedFieldCandidates) + { + if (field is IEncapsulatedUserDefinedTypeField udt) + { + udt.PropertyAccessExpression = () => $"{StateUDTField.PropertyAccessExpression()}.{udt.PropertyName}"; + udt.ReferenceExpression = udt.PropertyAccessExpression; + + foreach (var member in udt.Members) + { + member.PropertyAccessExpression = () => $"{udt.PropertyAccessExpression()}.{member.PropertyName}"; + member.ReferenceExpression = member.PropertyAccessExpression; + } + continue; + } + + field.PropertyAccessExpression = () => $"{StateUDTField.PropertyAccessExpression()}.{field.PropertyName}"; + field.ReferenceExpression = field.PropertyAccessExpression; + } + } + + foreach (var udtField in model.SelectedUDTFieldCandidates) + { + udtField.FieldQualifyMemberPropertyNames = model.SelectedUDTFieldCandidates.Where(f => f.AsTypeName.Equals(udtField.AsTypeName)).Count() > 1; + } + + //StageReferenceReplacementExpressions(model); + foreach (var field in model.SelectedFieldCandidates) + { + field.LoadReferenceExpressionChanges(); + } + } + + private void ModifyReferences(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) + { + foreach (var rewriteReplacement in model.SelectedFieldCandidates.SelectMany(fld => fld.ReferenceReplacements)) + { + var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, rewriteReplacement.Key.QualifiedModuleName); + rewriter.Replace(rewriteReplacement.Value); + } + } + + //private void StageReferenceReplacementExpressions(EncapsulateFieldModel model) + //{ + // foreach (var field in model.SelectedFieldCandidates) + // { + // field.LoadReferenceExpressionChanges(); + // } + //} + + private void ModifyFields(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) + { + if (model.EncapsulateWithUDT) + { + foreach (var field in model.SelectedFieldCandidates) + { + var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, _targetQMN); + + RewriterRemoveWorkAround.Remove(field.Declaration, rewriter); + //rewriter.Remove(target.Declaration); + } + return; + } + + foreach (var field in model.SelectedFieldCandidates) + { + var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, _targetQMN); + + if (field.Declaration.Accessibility == Accessibility.Private && field.NewFieldName.Equals(field.Declaration.IdentifierName)) + { + rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); + continue; + } + + if (field.Declaration.IsDeclaredInList()) + { + RewriterRemoveWorkAround.Remove(field.Declaration, rewriter); + //rewriter.Remove(target.Declaration); + continue; + } + + rewriter.Rename(field.Declaration, field.NewFieldName); + rewriter.SetVariableVisiblity(field.Declaration, Accessibility.Private.TokenString()); + rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); + } + } + + private void InsertNewContent(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool postPendPreviewMessage = false) + { + var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, _targetQMN); + + LoadNewDeclarationBlocks(model); + + LoadNewPropertyBlocks(model); + + if (postPendPreviewMessage) + { + _newContent[NewContentTypes.PostContentMessage].Add("'<===== All Changes above this line =====>"); + } + + var newContentBlock = string.Join(DoubleSpace, + (_newContent[NewContentTypes.TypeDeclarationBlock]) + .Concat(_newContent[NewContentTypes.DeclarationBlock]) + .Concat(_newContent[NewContentTypes.MethodBlock]) + .Concat(_newContent[NewContentTypes.PostContentMessage])) + .Trim(); + + + if (_codeSectionStartIndex.HasValue) + { + rewriter.InsertBefore(_codeSectionStartIndex.Value, $"{newContentBlock}{DoubleSpace}"); + } + else + { + rewriter.InsertAtEndOfFile($"{DoubleSpace}{newContentBlock}"); + } + } + + private void LoadNewDeclarationBlocks(EncapsulateFieldModel model) + { + if (model.EncapsulateWithUDT) + { + var udt = new UDTDeclarationGenerator(StateUDTField.AsTypeName); + + udt.AddMembers(model.SelectedFieldCandidates); + + AddCodeBlock(NewContentTypes.TypeDeclarationBlock, udt.TypeDeclarationBlock(_indenter)); + AddCodeBlock(NewContentTypes.DeclarationBlock, udt.FieldDeclarationBlock(StateUDTField.NewFieldName)); + return; + } + + //New field declarations created here were removed from their list within ModifyFields(...) + var fieldsRequiringNewDeclaration = model.SelectedFieldCandidates + .Where(field => field.Declaration.IsDeclaredInList() + && field.Declaration.Accessibility != Accessibility.Private); + + foreach (var field in fieldsRequiringNewDeclaration) + { + var targetIdentifier = field.Declaration.Context.GetText().Replace(field.IdentifierName, field.NewFieldName); + var newField = field.Declaration.IsTypeSpecified + ? $"{Tokens.Private} {targetIdentifier}" + : $"{Tokens.Private} {targetIdentifier} {Tokens.As} {field.Declaration.AsTypeName}"; + + AddCodeBlock(NewContentTypes.DeclarationBlock, newField); + } + } + + private void LoadNewPropertyBlocks(EncapsulateFieldModel model) + { + var propertyGenerationSpecs = model.SelectedFieldCandidates + .SelectMany(f => f.PropertyGenerationSpecs); + + var generator = new PropertyGenerator(); + foreach (var spec in propertyGenerationSpecs) + { + AddCodeBlock(NewContentTypes.MethodBlock, generator.AsPropertyBlock(spec, _indenter)); + } + } + + private void AddCodeBlock(NewContentTypes contentType, string block) + => _newContent[contentType].Add(block); } } diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs index 5230cc9179..c1396e92b3 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs @@ -12,52 +12,52 @@ namespace Rubberduck.Refactorings.EncapsulateField.Strategies { - public class EncapsulateWithBackingFields : EncapsulateFieldStrategiesBase - { - public EncapsulateWithBackingFields(QualifiedModuleName qmn, IIndenter indenter, IEncapsulateFieldValidator validator) - : base(qmn, indenter, validator) { } - - protected override void ModifyFields(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) - { - foreach (var field in model.SelectedFieldCandidates) - { - var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); - - if (field.Declaration.Accessibility == Accessibility.Private && field.NewFieldName.Equals(field.Declaration.IdentifierName)) - { - rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); - continue; - } - - if (field.Declaration.IsDeclaredInList()) - { - RewriterRemoveWorkAround.Remove(field.Declaration, rewriter); - //rewriter.Remove(target.Declaration); - continue; - } - - rewriter.Rename(field.Declaration, field.NewFieldName); - rewriter.SetVariableVisiblity(field.Declaration, Accessibility.Private.TokenString()); - rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); - } - } - - protected override void LoadNewDeclarationBlocks(EncapsulateFieldModel model) - { - //New field declarations created here were removed from their list within ModifyFields(...) - var fieldsRequiringNewDeclaration = model.SelectedFieldCandidates - .Where(field => field.Declaration.IsDeclaredInList() - && field.Declaration.Accessibility != Accessibility.Private); - - foreach (var field in fieldsRequiringNewDeclaration) - { - var targetIdentifier = field.Declaration.Context.GetText().Replace(field.IdentifierName, field.NewFieldName); - var newField = field.Declaration.IsTypeSpecified - ? $"{Tokens.Private} {targetIdentifier}" - : $"{Tokens.Private} {targetIdentifier} {Tokens.As} {field.Declaration.AsTypeName}"; - - AddCodeBlock(NewContentTypes.DeclarationBlock, newField); - } - } - } + //public class EncapsulateWithBackingFields : EncapsulateFieldStrategiesBase + //{ + // public EncapsulateWithBackingFields(QualifiedModuleName qmn, IIndenter indenter, IEncapsulateFieldValidator validator) + // : base(qmn, indenter, validator) { } + + // //protected override void ModifyFields(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) + // //{ + // // foreach (var field in model.SelectedFieldCandidates) + // // { + // // var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); + + // // if (field.Declaration.Accessibility == Accessibility.Private && field.NewFieldName.Equals(field.Declaration.IdentifierName)) + // // { + // // rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); + // // continue; + // // } + + // // if (field.Declaration.IsDeclaredInList()) + // // { + // // RewriterRemoveWorkAround.Remove(field.Declaration, rewriter); + // // //rewriter.Remove(target.Declaration); + // // continue; + // // } + + // // rewriter.Rename(field.Declaration, field.NewFieldName); + // // rewriter.SetVariableVisiblity(field.Declaration, Accessibility.Private.TokenString()); + // // rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); + // // } + // //} + + // //protected override void LoadNewDeclarationBlocks(EncapsulateFieldModel model) + // //{ + // // //New field declarations created here were removed from their list within ModifyFields(...) + // // var fieldsRequiringNewDeclaration = model.SelectedFieldCandidates + // // .Where(field => field.Declaration.IsDeclaredInList() + // // && field.Declaration.Accessibility != Accessibility.Private); + + // // foreach (var field in fieldsRequiringNewDeclaration) + // // { + // // var targetIdentifier = field.Declaration.Context.GetText().Replace(field.IdentifierName, field.NewFieldName); + // // var newField = field.Declaration.IsTypeSpecified + // // ? $"{Tokens.Private} {targetIdentifier}" + // // : $"{Tokens.Private} {targetIdentifier} {Tokens.As} {field.Declaration.AsTypeName}"; + + // // AddCodeBlock(NewContentTypes.DeclarationBlock, newField); + // // } + // //} + //} } diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs index 773e301a34..4d7011d29a 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs @@ -11,61 +11,61 @@ namespace Rubberduck.Refactorings.EncapsulateField.Strategies { - public interface IEncapsulateWithBackingUserDefinedType : IEncapsulateFieldStrategy - { - IEncapsulateFieldCandidate StateUDTField { set; get; } - } + //public interface IEncapsulateWithBackingUserDefinedType : IEncapsulateFieldStrategy + //{ + // //IEncapsulateFieldCandidate StateUDTField { set; get; } + //} - public class EncapsulateWithBackingUserDefinedType : EncapsulateFieldStrategiesBase, IEncapsulateWithBackingUserDefinedType - { - public EncapsulateWithBackingUserDefinedType(QualifiedModuleName qmn, IIndenter indenter, IEncapsulateFieldValidator validator) - : base(qmn, indenter, validator) { } + //public class EncapsulateWithBackingUserDefinedType : EncapsulateFieldStrategiesBase, IEncapsulateWithBackingUserDefinedType + //{ + // public EncapsulateWithBackingUserDefinedType(QualifiedModuleName qmn, IIndenter indenter, IEncapsulateFieldValidator validator) + // : base(qmn, indenter, validator) { } - public IEncapsulateFieldCandidate StateUDTField { set; get; } + // //public IEncapsulateFieldCandidate StateUDTField { set; get; } - protected override IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) - { - foreach (var field in model.SelectedFieldCandidates) - { - if (field is IEncapsulatedUserDefinedTypeField udt) - { - udt.PropertyAccessExpression = () => $"{StateUDTField.PropertyAccessExpression()}.{udt.PropertyName}"; - udt.ReferenceExpression = udt.PropertyAccessExpression; + // //protected override IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) + // //{ + // //foreach (var field in model.SelectedFieldCandidates) + // //{ + // // if (field is IEncapsulatedUserDefinedTypeField udt) + // // { + // // udt.PropertyAccessExpression = () => $"{StateUDTField.PropertyAccessExpression()}.{udt.PropertyName}"; + // // udt.ReferenceExpression = udt.PropertyAccessExpression; - foreach (var member in udt.Members) - { - member.PropertyAccessExpression = () => $"{udt.PropertyAccessExpression()}.{member.PropertyName}"; - member.ReferenceExpression = member.PropertyAccessExpression; - } - continue; - } + // // foreach (var member in udt.Members) + // // { + // // member.PropertyAccessExpression = () => $"{udt.PropertyAccessExpression()}.{member.PropertyName}"; + // // member.ReferenceExpression = member.PropertyAccessExpression; + // // } + // // continue; + // // } - field.PropertyAccessExpression = () => $"{StateUDTField.PropertyAccessExpression()}.{field.PropertyName}"; - field.ReferenceExpression = field.PropertyAccessExpression; - } + // // field.PropertyAccessExpression = () => $"{StateUDTField.PropertyAccessExpression()}.{field.PropertyName}"; + // // field.ReferenceExpression = field.PropertyAccessExpression; + // //} - return base.RefactorRewrite(model, rewriteSession, asPreview); - } + // //return base.RefactorRewrite(model, rewriteSession, asPreview); + // //} - protected override void ModifyFields(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) - { - foreach (var field in model.SelectedFieldCandidates) - { - var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); + // //protected override void ModifyFields(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) + // //{ + // // foreach (var field in model.SelectedFieldCandidates) + // // { + // // var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); - RewriterRemoveWorkAround.Remove(field.Declaration, rewriter); - //rewriter.Remove(target.Declaration); - } - } + // // RewriterRemoveWorkAround.Remove(field.Declaration, rewriter); + // // //rewriter.Remove(target.Declaration); + // // } + // //} - protected override void LoadNewDeclarationBlocks(EncapsulateFieldModel model) - { - var udt = new UDTDeclarationGenerator(StateUDTField.AsTypeName); + // //protected override void LoadNewDeclarationBlocks(EncapsulateFieldModel model) + // //{ + // // var udt = new UDTDeclarationGenerator(StateUDTField.AsTypeName); - udt.AddMembers(model.SelectedFieldCandidates); + // // udt.AddMembers(model.SelectedFieldCandidates); - AddCodeBlock(NewContentTypes.TypeDeclarationBlock, udt.TypeDeclarationBlock(Indenter)); - AddCodeBlock(NewContentTypes.DeclarationBlock, udt.FieldDeclarationBlock(StateUDTField.NewFieldName)); - } - } + // // AddCodeBlock(NewContentTypes.TypeDeclarationBlock, udt.TypeDeclarationBlock(Indenter)); + // // AddCodeBlock(NewContentTypes.DeclarationBlock, udt.FieldDeclarationBlock(StateUDTField.NewFieldName)); + // //} + //} } diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs index 3cff0bba8c..e8d486155d 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs @@ -12,143 +12,232 @@ namespace Rubberduck.Refactorings.EncapsulateField.Strategies { - public interface IEncapsulateFieldStrategy - { - IExecutableRewriteSession GeneratePreview(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession); - IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession); - } - - public abstract class EncapsulateFieldStrategiesBase : IEncapsulateFieldStrategy - { - protected enum NewContentTypes { TypeDeclarationBlock, DeclarationBlock, MethodBlock, PostContentMessage }; - - private IEncapsulateFieldValidator _validator; - private static string DoubleSpace => $"{Environment.NewLine}{Environment.NewLine}"; - private Dictionary> _newContent { set; get; } - - public EncapsulateFieldStrategiesBase(QualifiedModuleName qmn, IIndenter indenter, IEncapsulateFieldValidator validator) - { - TargetQMN = qmn; - Indenter = indenter; - _validator = validator; - - _newContent = new Dictionary> - { - { NewContentTypes.PostContentMessage, new List() }, - { NewContentTypes.DeclarationBlock, new List() }, - { NewContentTypes.MethodBlock, new List() }, - { NewContentTypes.TypeDeclarationBlock, new List() } - }; - } - - protected void AddCodeBlock(NewContentTypes contentType, string block) - => _newContent[contentType].Add(block); - - protected QualifiedModuleName TargetQMN {private set; get;} - - protected IIndenter Indenter { private set; get; } - - public IExecutableRewriteSession GeneratePreview(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) - { - if (!model.SelectedFieldCandidates.Any()) { return rewriteSession; } - - return RefactorRewrite(model, rewriteSession, asPreview: true); - } - - public IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) - { - if (!model.SelectedFieldCandidates.Any()) { return rewriteSession; } - - return RefactorRewrite(model, rewriteSession, asPreview: false); - } - - protected abstract void ModifyFields(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession); - - protected abstract void LoadNewDeclarationBlocks(EncapsulateFieldModel model); - - protected virtual IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) - { - ConfigureSelectedEncapsulationObjects(model); - - ModifyFields(model, rewriteSession); - - ModifyReferences(model, rewriteSession); - - RewriterRemoveWorkAround.RemoveFieldsDeclaredInLists(rewriteSession, TargetQMN); - - InsertNewContent(model, rewriteSession, asPreview); - - return rewriteSession; - } - - protected void ConfigureSelectedEncapsulationObjects(EncapsulateFieldModel model) - { - foreach (var udtField in model.SelectedUDTFieldCandidates) - { - udtField.FieldQualifyMemberPropertyNames = model.SelectedUDTFieldCandidates.Where(f => f.AsTypeName.Equals(udtField.AsTypeName)).Count() > 1; - } - - StageReferenceReplacementExpressions(model); - } - - protected void ModifyReferences(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) - { - foreach (var rewriteReplacement in model.SelectedFieldCandidates.SelectMany(fld => fld.ReferenceReplacements)) - { - var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, rewriteReplacement.Key.QualifiedModuleName); - rewriter.Replace(rewriteReplacement.Value); - } - } - - protected void StageReferenceReplacementExpressions(EncapsulateFieldModel model) - { - foreach (var field in model.SelectedFieldCandidates) - { - field.LoadReferenceExpressionChanges(); - } - } - - protected void InsertNewContent(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool postPendPreviewMessage = false) - { - var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); - - LoadNewDeclarationBlocks(model); - - LoadNewPropertyBlocks(model); - - if (postPendPreviewMessage) - { - _newContent[NewContentTypes.PostContentMessage].Add("'<===== All Changes above this line =====>"); - } - - var newContentBlock = string.Join(DoubleSpace, - (_newContent[NewContentTypes.TypeDeclarationBlock]) - .Concat(_newContent[NewContentTypes.DeclarationBlock]) - .Concat(_newContent[NewContentTypes.MethodBlock]) - .Concat(_newContent[NewContentTypes.PostContentMessage])) - .Trim(); - - - if (model.CodeSectionStartIndex.HasValue) - { - rewriter.InsertBefore(model.CodeSectionStartIndex.Value, $"{newContentBlock}{DoubleSpace}"); - } - else - { - rewriter.InsertAtEndOfFile($"{DoubleSpace}{newContentBlock}"); - } - } - - private void LoadNewPropertyBlocks(EncapsulateFieldModel model) - { - var propertyGenerationSpecs = model.SelectedFieldCandidates - .SelectMany(f => f.PropertyGenerationSpecs); - - var generator = new PropertyGenerator(); - foreach (var spec in propertyGenerationSpecs) - { - AddCodeBlock(NewContentTypes.MethodBlock, generator.AsPropertyBlock(spec, Indenter)); - } - } - } + //public interface IEncapsulateFieldStrategy + //{ + // IExecutableRewriteSession GeneratePreview(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession); + // IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession); + // //IEncapsulateFieldCandidate StateUDTField { set; get; } + //} + + //public class EncapsulateFieldStrategiesBase : IEncapsulateFieldStrategy + //{ + // protected enum NewContentTypes { TypeDeclarationBlock, DeclarationBlock, MethodBlock, PostContentMessage }; + + // private IEncapsulateFieldValidator _validator; + // private static string DoubleSpace => $"{Environment.NewLine}{Environment.NewLine}"; + // private Dictionary> _newContent { set; get; } + + // public EncapsulateFieldStrategiesBase(QualifiedModuleName qmn, IIndenter indenter, IEncapsulateFieldValidator validator, IEncapsulateFieldCandidate stateUDT = null) + // { + // TargetQMN = qmn; + // Indenter = indenter; + // _validator = validator; + // StateUDTField = stateUDT; + + // _newContent = new Dictionary> + // { + // { NewContentTypes.PostContentMessage, new List() }, + // { NewContentTypes.DeclarationBlock, new List() }, + // { NewContentTypes.MethodBlock, new List() }, + // { NewContentTypes.TypeDeclarationBlock, new List() } + // }; + // } + + // protected void AddCodeBlock(NewContentTypes contentType, string block) + // => _newContent[contentType].Add(block); + + // protected QualifiedModuleName TargetQMN {private set; get;} + + // protected IIndenter Indenter { private set; get; } + + // private IEncapsulateFieldCandidate StateUDTField { set; get; } + + // public IExecutableRewriteSession GeneratePreview(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) + // { + // if (!model.SelectedFieldCandidates.Any()) { return rewriteSession; } + + // return RefactorRewrite(model, rewriteSession, asPreview: true); + // } + + // public IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) + // { + // if (!model.SelectedFieldCandidates.Any()) { return rewriteSession; } + + // return RefactorRewrite(model, rewriteSession, asPreview: false); + // } + + // protected virtual IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) + // { + // ConfigureSelectedEncapsulationObjects(model); + + // ModifyFields(model, rewriteSession); + + // ModifyReferences(model, rewriteSession); + + // RewriterRemoveWorkAround.RemoveFieldsDeclaredInLists(rewriteSession, TargetQMN); + + // InsertNewContent(model, rewriteSession, asPreview); + + // return rewriteSession; + // } + + // protected void ConfigureSelectedEncapsulationObjects(EncapsulateFieldModel model) + // { + // if (model.EncapsulateWithUDT) + // { + // foreach (var field in model.SelectedFieldCandidates) + // { + // if (field is IEncapsulatedUserDefinedTypeField udt) + // { + // udt.PropertyAccessExpression = () => $"{StateUDTField.PropertyAccessExpression()}.{udt.PropertyName}"; + // udt.ReferenceExpression = udt.PropertyAccessExpression; + + // foreach (var member in udt.Members) + // { + // member.PropertyAccessExpression = () => $"{udt.PropertyAccessExpression()}.{member.PropertyName}"; + // member.ReferenceExpression = member.PropertyAccessExpression; + // } + // continue; + // } + + // field.PropertyAccessExpression = () => $"{StateUDTField.PropertyAccessExpression()}.{field.PropertyName}"; + // field.ReferenceExpression = field.PropertyAccessExpression; + // } + // } + + // foreach (var udtField in model.SelectedUDTFieldCandidates) + // { + // udtField.FieldQualifyMemberPropertyNames = model.SelectedUDTFieldCandidates.Where(f => f.AsTypeName.Equals(udtField.AsTypeName)).Count() > 1; + // } + + // StageReferenceReplacementExpressions(model); + // } + + // protected void ModifyReferences(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) + // { + // foreach (var rewriteReplacement in model.SelectedFieldCandidates.SelectMany(fld => fld.ReferenceReplacements)) + // { + // var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, rewriteReplacement.Key.QualifiedModuleName); + // rewriter.Replace(rewriteReplacement.Value); + // } + // } + + // protected void StageReferenceReplacementExpressions(EncapsulateFieldModel model) + // { + // foreach (var field in model.SelectedFieldCandidates) + // { + // field.LoadReferenceExpressionChanges(); + // } + // } + + // private void ModifyFields(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) + // { + // if (model.EncapsulateWithUDT) + // { + // foreach (var field in model.SelectedFieldCandidates) + // { + // var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); + + // RewriterRemoveWorkAround.Remove(field.Declaration, rewriter); + // //rewriter.Remove(target.Declaration); + // } + // return; + // } + + // foreach (var field in model.SelectedFieldCandidates) + // { + // var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); + + // if (field.Declaration.Accessibility == Accessibility.Private && field.NewFieldName.Equals(field.Declaration.IdentifierName)) + // { + // rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); + // continue; + // } + + // if (field.Declaration.IsDeclaredInList()) + // { + // RewriterRemoveWorkAround.Remove(field.Declaration, rewriter); + // //rewriter.Remove(target.Declaration); + // continue; + // } + + // rewriter.Rename(field.Declaration, field.NewFieldName); + // rewriter.SetVariableVisiblity(field.Declaration, Accessibility.Private.TokenString()); + // rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); + // } + // } + + // protected void InsertNewContent(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool postPendPreviewMessage = false) + // { + // var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); + + // LoadNewDeclarationBlocks(model); + + // LoadNewPropertyBlocks(model); + + // if (postPendPreviewMessage) + // { + // _newContent[NewContentTypes.PostContentMessage].Add("'<===== All Changes above this line =====>"); + // } + + // var newContentBlock = string.Join(DoubleSpace, + // (_newContent[NewContentTypes.TypeDeclarationBlock]) + // .Concat(_newContent[NewContentTypes.DeclarationBlock]) + // .Concat(_newContent[NewContentTypes.MethodBlock]) + // .Concat(_newContent[NewContentTypes.PostContentMessage])) + // .Trim(); + + + // if (model.CodeSectionStartIndex.HasValue) + // { + // rewriter.InsertBefore(model.CodeSectionStartIndex.Value, $"{newContentBlock}{DoubleSpace}"); + // } + // else + // { + // rewriter.InsertAtEndOfFile($"{DoubleSpace}{newContentBlock}"); + // } + // } + + // private void LoadNewDeclarationBlocks(EncapsulateFieldModel model) + // { + // if (model.EncapsulateWithUDT) + // { + // var udt = new UDTDeclarationGenerator(StateUDTField.AsTypeName); + + // udt.AddMembers(model.SelectedFieldCandidates); + + // AddCodeBlock(NewContentTypes.TypeDeclarationBlock, udt.TypeDeclarationBlock(Indenter)); + // AddCodeBlock(NewContentTypes.DeclarationBlock, udt.FieldDeclarationBlock(StateUDTField.NewFieldName)); + // return; + // } + + // //New field declarations created here were removed from their list within ModifyFields(...) + // var fieldsRequiringNewDeclaration = model.SelectedFieldCandidates + // .Where(field => field.Declaration.IsDeclaredInList() + // && field.Declaration.Accessibility != Accessibility.Private); + + // foreach (var field in fieldsRequiringNewDeclaration) + // { + // var targetIdentifier = field.Declaration.Context.GetText().Replace(field.IdentifierName, field.NewFieldName); + // var newField = field.Declaration.IsTypeSpecified + // ? $"{Tokens.Private} {targetIdentifier}" + // : $"{Tokens.Private} {targetIdentifier} {Tokens.As} {field.Declaration.AsTypeName}"; + + // AddCodeBlock(NewContentTypes.DeclarationBlock, newField); + // } + // } + + + // private void LoadNewPropertyBlocks(EncapsulateFieldModel model) + // { + // var propertyGenerationSpecs = model.SelectedFieldCandidates + // .SelectMany(f => f.PropertyGenerationSpecs); + + // var generator = new PropertyGenerator(); + // foreach (var spec in propertyGenerationSpecs) + // { + // AddCodeBlock(NewContentTypes.MethodBlock, generator.AsPropertyBlock(spec, Indenter)); + // } + // } + //} } From 431749b5e45c7b3fa19fc95add6e8d0f0891438a Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Wed, 11 Dec 2019 15:20:04 -0800 Subject: [PATCH 051/461] WIP - Refactored to remove some files and classes --- .../ViewableEncapsulatedField.cs | 6 +- ...ration.cs => EncapsulateFieldCandidate.cs} | 123 +++++---- .../EncapsulateFieldDeclarationExtensions.cs | 51 ---- .../EncapsulateFieldDeclarationFactory.cs | 36 +-- .../EncapsulateFieldExtensions.cs | 173 +++++++++++++ .../EncapsulateField/EncapsulateFieldModel.cs | 60 +---- .../EncapsulateFieldNewContent.cs | 124 --------- .../EncapsulateFieldRefactoring.cs | 108 +++----- .../EncapsulateFieldRewriter.cs | 141 ---------- .../EncapsulateFieldValidator.cs | 84 +++--- .../EncapsulationIdentifiers.cs | 32 +-- .../FieldEncapsulationAttributes.cs | 189 -------------- .../IEncapsulateFieldDialog.cs | 20 -- .../EncapsulateField/PropertyGenerator.cs | 8 +- .../RewriterRemoveWorkaround.cs | 78 ------ .../EncapsulateField/StateUDTField.cs | 69 ++++- .../EncapsulateWithBackingFields.cs | 63 ----- .../EncapsulateWithBackingUserDefinedType.cs | 71 ----- .../Strategies/EncapsulationStrategiesBase.cs | 243 ------------------ .../EncapsulateField/StringExtensions.cs | 20 -- .../UDTDeclarationGenerator.cs | 53 ---- ...peField.cs => UserDefinedTypeCandidate.cs} | 87 ++++--- ...r.cs => UserDefinedTypeMemberCandidate.cs} | 67 +++-- .../Rubberduck.Refactorings.csproj | 3 + .../EncapsulateFieldValidatorTests.cs | 7 +- .../EncapsulatedFieldTests.cs | 10 +- .../Refactoring/EncapsulateFieldTests.cs | 25 ++ 27 files changed, 569 insertions(+), 1382 deletions(-) rename Rubberduck.Refactorings/EncapsulateField/{EncapsulatedFieldDeclaration.cs => EncapsulateFieldCandidate.cs} (72%) delete mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationExtensions.cs create mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldExtensions.cs delete mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldNewContent.cs delete mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs delete mode 100644 Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs delete mode 100644 Rubberduck.Refactorings/EncapsulateField/IEncapsulateFieldDialog.cs delete mode 100644 Rubberduck.Refactorings/EncapsulateField/RewriterRemoveWorkaround.cs delete mode 100644 Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs delete mode 100644 Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs delete mode 100644 Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs delete mode 100644 Rubberduck.Refactorings/EncapsulateField/StringExtensions.cs delete mode 100644 Rubberduck.Refactorings/EncapsulateField/UDTDeclarationGenerator.cs rename Rubberduck.Refactorings/EncapsulateField/{EncapsulatedUserDefinedTypeField.cs => UserDefinedTypeCandidate.cs} (54%) rename Rubberduck.Refactorings/EncapsulateField/{EncapsulatedUserDefinedTypeMember.cs => UserDefinedTypeMemberCandidate.cs} (53%) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs index f0232b9bbb..55196b6965 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs @@ -31,7 +31,7 @@ public ViewableEncapsulatedField(IEncapsulateFieldCandidate efd) _efd = efd; } - public Visibility FieldNameVisibility => _efd.IsUDTMember || !_efd.EncapsulateFlag ? Visibility.Collapsed : Visibility.Visible; + public Visibility FieldNameVisibility => (_efd is IUserDefinedTypeMemberCandidate) /*.IsUDTMember*/ || !_efd.EncapsulateFlag ? Visibility.Collapsed : Visibility.Visible; public Visibility PropertyNameVisibility => !_efd.EncapsulateFlag ? Visibility.Collapsed : Visibility.Visible; public bool HasValidEncapsulationAttributes => _efd.HasValidEncapsulationAttributes; public string TargetID { get => _efd.TargetID; } @@ -39,7 +39,7 @@ public ViewableEncapsulatedField(IEncapsulateFieldCandidate efd) public bool IsReadOnly { get => _efd.IsReadOnly; set => _efd.IsReadOnly = value; } public bool CanBeReadWrite => _efd.CanBeReadWrite; public string PropertyName { get => _efd.PropertyName; set => _efd.PropertyName = value; } - public bool IsEditableReadWriteFieldIdentifier { get => !_efd.IsUDTMember; } // set => _efd.IsEditableReadWriteFieldIdentifier = value; } + public bool IsEditableReadWriteFieldIdentifier { get => !(_efd is IUserDefinedTypeMemberCandidate); }// .IsUDTMember; } // set => _efd.IsEditableReadWriteFieldIdentifier = value; } public bool EncapsulateFlag { get => _efd.EncapsulateFlag; set => _efd.EncapsulateFlag = value; } public string NewFieldName { get => _efd.NewFieldName; }// set => _efd.NewFieldName = value; } //TODO: Change name of AsTypeName property to FieldDescriptor(?) -> and does it belong on IEncapsulatedField? @@ -53,7 +53,7 @@ public string AsTypeName var prefix = string.Empty; var descriptor = string.Empty; - if (_efd.IsUDTMember) + if (_efd is IUserDefinedTypeMemberCandidate) //.IsUDTMember) { prefix = "UserDefinedType"; } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldCandidate.cs similarity index 72% rename from Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs rename to Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldCandidate.cs index b57c1ecfa9..4fde4cbc20 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedFieldDeclaration.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldCandidate.cs @@ -21,25 +21,24 @@ public interface IEncapsulateFieldCandidate bool EncapsulateFlag { get; set; } string NewFieldName { set; get; } bool CanBeReadWrite { set; get; } - bool IsUDTMember { get; } + //bool IsUDTMember { get; } bool HasValidEncapsulationAttributes { get; } QualifiedModuleName QualifiedModuleName { get; } - IEnumerable References { get; } string PropertyName { get; set; } string AsTypeName { get; set; } string ParameterName { get; } bool ImplementLetSetterType { get; set; } bool ImplementSetSetterType { get; set; } - Func PropertyAccessExpression { set; get; } - bool FieldNameIsExemptFromValidation { get; } - Func ReferenceExpression { set; get; } - IEnumerable PropertyGenerationSpecs { get; } - IEnumerable> ReferenceReplacements { get; } - void LoadReferenceExpressionChanges(); + IEnumerable PropertyAttributeSets { get; } + IEnumerable> ReferenceReplacements { get; } void SetReferenceRewriteContent(IdentifierReference idRef, string replacementText); - RewriteReplacePair ReferenceReplacement(IdentifierReference idRef); + string ReferenceQualifier { set; get; } + string ReferenceWithinNewProperty { get; } + void SetupReferenceReplacements(IStateUDTField stateUDT = null); } + public enum AccessorTokens { Field, Property } + public interface IEncapsulateFieldCandidateValidations { bool HasVBACompliantPropertyIdentifier { get; } @@ -63,9 +62,6 @@ public EncapsulateFieldCandidate(Declaration declaration, IEncapsulateFieldNames : this(declaration.IdentifierName, declaration.AsTypeName, declaration.QualifiedModuleName, validator) { _target = declaration; - ImplementLetSetterType = true; - ImplementSetSetterType = false; - CanBeReadWrite = true; } public EncapsulateFieldCandidate(string identifier, string asTypeName, QualifiedModuleName qmn, IEncapsulateFieldNamesValidator validator) @@ -76,13 +72,25 @@ public EncapsulateFieldCandidate(string identifier, string asTypeName, Qualified IdentifierName = identifier; AsTypeName = asTypeName; _qmn = qmn; - PropertyAccessExpression = () => NewFieldName; - ReferenceExpression = () => PropertyName; + PropertyAccessor = AccessorTokens.Field; + ReferenceAccessor = AccessorTokens.Property; _validator = validator; + + ImplementLetSetterType = true; + ImplementSetSetterType = false; + CanBeReadWrite = true; + } + + public virtual void SetupReferenceReplacements(IStateUDTField stateUDT = null) + { + PropertyAccessor = stateUDT is null ? AccessorTokens.Field : AccessorTokens.Property; + ReferenceAccessor = AccessorTokens.Property; + ReferenceQualifier = stateUDT?.NewFieldName ?? null; + LoadFieldReferenceContextReplacements(); } - protected Dictionary IdentifierReplacements { get; } = new Dictionary(); + protected Dictionary IdentifierReplacements { get; } = new Dictionary(); public Declaration Declaration => _target; @@ -115,14 +123,14 @@ public bool HasValidEncapsulationAttributes } } - public virtual IEnumerable> ReferenceReplacements + public virtual IEnumerable> ReferenceReplacements { get { - var results = new List>(); + var results = new List>(); foreach (var replacement in IdentifierReplacements) { - var kv = new KeyValuePair + var kv = new KeyValuePair (replacement.Key, replacement.Value); results.Add(kv); } @@ -134,15 +142,10 @@ public virtual void SetReferenceRewriteContent(IdentifierReference idRef, string { if (IdentifierReplacements.ContainsKey(idRef)) { - IdentifierReplacements[idRef] = new RewriteReplacePair(replacementText, idRef.Context); + IdentifierReplacements[idRef] = (idRef.Context, replacementText); return; } - IdentifierReplacements.Add(idRef, new RewriteReplacePair(replacementText, idRef.Context)); - } - - public RewriteReplacePair ReferenceReplacement(IdentifierReference idRef) - { - return IdentifierReplacements.Single(r => r.Key == idRef).Value; + IdentifierReplacements.Add(idRef, (idRef.Context, replacementText)); } public virtual string TargetID => _target?.IdentifierName ?? IdentifierName; @@ -185,7 +188,7 @@ private void TryRestoreNewFieldNameAsOriginalFieldIdentifierName() var isConflictingFieldIdentifier = _validator.HasConflictingFieldIdentifier(this); for (var count = 1; count < 10 && isConflictingFieldIdentifier; count++) { - NewFieldName = EncapsulationIdentifiers.IncrementIdentifier(NewFieldName); + NewFieldName = NewFieldName.IncrementIdentifier(); isConflictingFieldIdentifier = _validator.HasConflictingFieldIdentifier(this); } } @@ -193,12 +196,8 @@ private void TryRestoreNewFieldNameAsOriginalFieldIdentifierName() public string AsTypeName { set; get; } - public bool IsUDTMember => _target?.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember) ?? false; - public QualifiedModuleName QualifiedModuleName => _qmn; - public virtual IEnumerable References => Declaration?.References ?? Enumerable.Empty(); - public string IdentifierName { get => Declaration?.IdentifierName ?? _identifierName; @@ -214,19 +213,55 @@ public string IdentifierName public bool ImplementSetSetterType { get => !IsReadOnly && _implSet; set => _implSet = value; } - public Func PropertyAccessExpression { set; get; } + protected AccessorTokens PropertyAccessor { set; get; } - public virtual IEnumerable PropertyGenerationSpecs - => new List() { AsPropertyGeneratorSpec }; + protected AccessorTokens ReferenceAccessor { set; get; } - protected virtual IPropertyGeneratorSpecification AsPropertyGeneratorSpec + protected string _referenceQualifier; + public virtual string ReferenceQualifier + { + set => _referenceQualifier = value; + get => _referenceQualifier; + } + + public virtual string ReferenceWithinNewProperty => AccessorTokenToContent(PropertyAccessor); + + protected virtual string ReferenceForPreExistingReferences => AccessorTokenToContent(ReferenceAccessor); + + protected string AccessorTokenToContent(AccessorTokens token) + { + var accessor = string.Empty; + switch (token) + { + case AccessorTokens.Field: + accessor = NewFieldName; + break; + case AccessorTokens.Property: + accessor = PropertyName; + break; + default: + accessor = NewFieldName; + break; + } + + if ((ReferenceQualifier?.Length ?? 0) > 0) + { + return $"{ReferenceQualifier}.{accessor}"; + } + return accessor; + } + + public virtual IEnumerable PropertyAttributeSets + => new List() { AsPropertyGeneratorSpec }; + + protected virtual IPropertyGeneratorAttributes AsPropertyGeneratorSpec { get { return new PropertyGeneratorSpecification() { PropertyName = PropertyName, - BackingField = PropertyAccessExpression(), + BackingField = ReferenceWithinNewProperty, AsTypeName = AsTypeName, ParameterName = ParameterName, GenerateLetter = ImplementLetSetterType, @@ -236,19 +271,14 @@ protected virtual IPropertyGeneratorSpecification AsPropertyGeneratorSpec } } - public virtual void LoadReferenceExpressionChanges() - { - LoadFieldReferenceExpressions(); - } - - protected virtual void LoadFieldReferenceExpressions() + protected virtual void LoadFieldReferenceContextReplacements() { var field = this; - foreach (var idRef in field.References) + foreach (var idRef in field.Declaration.References) { var replacementText = RequiresAccessQualification(idRef) - ? $"{field.QualifiedModuleName.ComponentName}.{field.ReferenceExpression()}" - : field.ReferenceExpression(); + ? $"{field.QualifiedModuleName.ComponentName}.{field.ReferenceForPreExistingReferences}" + : field.ReferenceForPreExistingReferences; field.SetReferenceRewriteContent(idRef, replacementText); } @@ -264,10 +294,5 @@ protected bool RequiresAccessQualification(IdentifierReference idRef) return idRef.QualifiedModuleName != idRef.Declaration.QualifiedModuleName && !isLHSOfMemberAccess; } - - public Func ReferenceExpression { set; get; } - - public bool FieldNameIsExemptFromValidation - => Declaration?.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember) ?? false; } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationExtensions.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationExtensions.cs deleted file mode 100644 index 1ac6f64b38..0000000000 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationExtensions.cs +++ /dev/null @@ -1,51 +0,0 @@ -using Rubberduck.Parsing; -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.EncapsulateField -{ - public static class EncapsulateFieldDeclarationExtensions - { - public static bool IsVariable(this Declaration declaration) - => declaration.DeclarationType.HasFlag(DeclarationType.Variable); - - public static bool IsMemberVariable(this Declaration declaration) - => declaration.IsVariable() && !declaration.ParentDeclaration.IsMember(); - - public static bool IsLocalVariable(this Declaration declaration) - => declaration.IsVariable() && declaration.ParentDeclaration.IsMember(); - - public static bool IsLocalConstant(this Declaration declaration) - => declaration.IsConstant() && declaration.ParentDeclaration.IsMember(); - - public static bool HasPrivateAccessibility(this Declaration declaration) - => declaration.Accessibility.Equals(Accessibility.Private); - - public static bool IsMember(this Declaration declaration) - => declaration.DeclarationType.HasFlag(DeclarationType.Member); - - public static bool IsConstant(this Declaration declaration) - => declaration.DeclarationType.HasFlag(DeclarationType.Constant); - - public static bool IsUserDefinedTypeField(this Declaration declaration) - => declaration.IsMemberVariable() && (declaration.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.UserDefinedType) ?? false); - - public static bool IsDeclaredInList(this Declaration declaration) - { - return declaration.Context.TryGetAncestor(out var varList) - && varList.ChildCount > 1; - } - - public static IEnumerable AllReferences(this IEnumerable declarations) - { - return from dec in declarations - from reference in dec.References - select reference; - } - } -} diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs index a6fe7f8877..cd57041928 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs @@ -19,8 +19,6 @@ public class EncapsulationCandidateFactory private readonly IDeclarationFinderProvider _declarationFinderProvider; private readonly IEncapsulateFieldNamesValidator _validator; - private List _encapsulatedFields = new List(); - //private IEnumerable _fieldCandidates; private QualifiedModuleName _targetQMN; public EncapsulationCandidateFactory(IDeclarationFinderProvider declarationFinderProvider, QualifiedModuleName targetQMN, IEncapsulateFieldNamesValidator validator) @@ -46,7 +44,7 @@ public IEncapsulateFieldCandidate CreateEncapsulationCandidate(Declaration targe Debug.Assert(!target.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)); var candidate = target.IsUserDefinedTypeField() - ? new EncapsulatedUserDefinedTypeField(target, _validator) + ? new UserDefinedTypeCandidate(target, _validator) : new EncapsulateFieldCandidate(target, _validator); _validator.RegisterFieldCandidate(candidate); @@ -55,7 +53,7 @@ public IEncapsulateFieldCandidate CreateEncapsulationCandidate(Declaration targe candidate = SetNonConflictIdentifier(candidate, c => { return _validator.HasConflictingPropertyIdentifier(candidate); }, (s) => { candidate.PropertyName = s; }, () => candidate.IdentifierName, _validator); - if (candidate is IEncapsulatedUserDefinedTypeField udtVariable) + if (candidate is IUserDefinedTypeCandidate udtVariable) { (Declaration udt, IEnumerable udtMembers) = GetUDTAndMembersForField(udtVariable); @@ -63,33 +61,23 @@ public IEncapsulateFieldCandidate CreateEncapsulationCandidate(Declaration targe foreach (var udtMember in udtMembers) { - var candidateUDTMember = new EncapsulatedUserDefinedTypeMember(udtMember, udtVariable, _validator) as IEncapsulatedUserDefinedTypeMember; + var candidateUDTMember = new UserDefinedTypeMemberCandidate(udtMember, udtVariable, _validator) as IUserDefinedTypeMemberCandidate; candidateUDTMember = ApplyTypeSpecificAttributes(candidateUDTMember); candidateUDTMember = SetNonConflictIdentifier(candidateUDTMember, c => { return _validator.HasConflictingPropertyIdentifier(candidate); }, (s) => { candidateUDTMember.PropertyName = s; }, () => candidate.IdentifierName, _validator); - candidateUDTMember.PropertyAccessExpression = - () => - { - var prefix = udtVariable.EncapsulateFlag - ? udtVariable.NewFieldName - : udtVariable.IdentifierName; - return $"{prefix}.{candidateUDTMember.IdentifierName}"; - }; - udtVariable.AddMember(candidateUDTMember); } } return candidate; } - public IEnumerable CreateEncapsulationCandidates() //IEnumerable candidateFields) + public IEnumerable CreateEncapsulationCandidates() { var fieldDeclarations = _declarationFinderProvider.DeclarationFinder .Members(_targetQMN) .Where(v => v.IsMemberVariable() && !v.IsWithEvents); - //_fieldCandidates = candidateFields; var candidates = new List(); foreach (var field in fieldDeclarations) @@ -97,7 +85,6 @@ public IEnumerable CreateEncapsulationCandidates() / var fieldEncapsulationCandidate = CreateEncapsulationCandidate(field); candidates.Add(fieldEncapsulationCandidate); - //_encapsulatedFields.Add(encapuslatedField); } return candidates; @@ -108,7 +95,7 @@ private T SetNonConflictIdentifier(T candidate, Predicate conflictDetector var isConflictingIdentifier = conflictDetector(candidate); for (var count = 1; count < 10 && isConflictingIdentifier; count++) { - setValue(EncapsulationIdentifiers.IncrementIdentifier(getIdentifier())); + setValue(getIdentifier().IncrementIdentifier()); isConflictingIdentifier = conflictDetector(candidate); } return candidate; @@ -117,11 +104,7 @@ private T SetNonConflictIdentifier(T candidate, Predicate conflictDetector private T ApplyTypeSpecificAttributes(T candidate) where T: IEncapsulateFieldCandidate { var target = candidate.Declaration; - //if (target.IsUserDefinedTypeField()) - //{ - // candidate.ImplementLetSetterType = true; - // candidate.ImplementSetSetterType = false; - //} + if (target.IsArray) { candidate.ImplementLetSetterType = false; @@ -140,15 +123,10 @@ private T ApplyTypeSpecificAttributes(T candidate) where T: IEncapsulateField candidate.ImplementLetSetterType = false; candidate.ImplementSetSetterType = true; } - //else - //{ - // candidate.ImplementLetSetterType = true; - // candidate.ImplementSetSetterType = false; - //} return candidate; } - private (Declaration TypeDeclaration, IEnumerable Members) GetUDTAndMembersForField(IEncapsulatedUserDefinedTypeField udtField) + private (Declaration TypeDeclaration, IEnumerable Members) GetUDTAndMembersForField(IUserDefinedTypeCandidate udtField) { var userDefinedTypeDeclaration = _declarationFinderProvider.DeclarationFinder .UserDeclarations(DeclarationType.UserDefinedType) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldExtensions.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldExtensions.cs new file mode 100644 index 0000000000..70b508cc00 --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldExtensions.cs @@ -0,0 +1,173 @@ +using Rubberduck.Parsing; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; +using Rubberduck.VBEditor; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + public static class EncapsulateFieldExtensions + { + public static bool IsVariable(this Declaration declaration) + => declaration.DeclarationType.HasFlag(DeclarationType.Variable); + + public static bool IsMemberVariable(this Declaration declaration) + => declaration.IsVariable() && !declaration.ParentDeclaration.IsMember(); + + public static bool IsLocalVariable(this Declaration declaration) + => declaration.IsVariable() && declaration.ParentDeclaration.IsMember(); + + public static bool IsLocalConstant(this Declaration declaration) + => declaration.IsConstant() && declaration.ParentDeclaration.IsMember(); + + public static bool HasPrivateAccessibility(this Declaration declaration) + => declaration.Accessibility.Equals(Accessibility.Private); + + public static bool IsMember(this Declaration declaration) + => declaration.DeclarationType.HasFlag(DeclarationType.Member); + + public static bool IsConstant(this Declaration declaration) + => declaration.DeclarationType.HasFlag(DeclarationType.Constant); + + public static bool IsUserDefinedTypeField(this Declaration declaration) + => declaration.IsMemberVariable() && (declaration.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.UserDefinedType) ?? false); + + public static bool IsDeclaredInList(this Declaration declaration) + { + return declaration.Context.TryGetAncestor(out var varList) + && varList.ChildCount > 1; + } + + public static IEnumerable AllReferences(this IEnumerable declarations) + { + return from dec in declarations + from reference in dec.References + select reference; + } + + public static string Capitalize(this string input) + => $"{char.ToUpperInvariant(input[0]) + input.Substring(1, input.Length - 1)}"; + + public static string UnCapitalize(this string input) + => $"{char.ToLowerInvariant(input[0]) + input.Substring(1, input.Length - 1)}"; + + public static bool EqualsVBAIdentifier(this string lhs, string identifier) + => lhs.Equals(identifier, StringComparison.InvariantCultureIgnoreCase); + + public static string GetText(this IModuleRewriter rewriter, int maxConsecutiveNewLines) + { + var result = rewriter.GetText(); + var target = string.Join(string.Empty, Enumerable.Repeat(Environment.NewLine, maxConsecutiveNewLines).ToList()); + var replacement = string.Join(string.Empty, Enumerable.Repeat(Environment.NewLine, maxConsecutiveNewLines - 1).ToList()); + for (var counter = 1; counter < 10 && result.Contains(target); counter++) + { + result = result.Replace(target, replacement); + } + return result; + } + + public static string IncrementIdentifier(this string identifier) + { + var fragments = identifier.Split('_'); + if (fragments.Length == 1) { return $"{identifier}_1"; } + + var lastFragment = fragments[fragments.Length - 1]; + if (long.TryParse(lastFragment, out var number)) + { + fragments[fragments.Length - 1] = (number + 1).ToString(); + + return string.Join("_", fragments); + } + return $"{identifier}_1"; ; + } + + public static void InsertAtEndOfFile(this IModuleRewriter rewriter, string content) + { + if (content == string.Empty) { return; } + + rewriter.InsertBefore(rewriter.TokenStream.Size - 1, content); + } + + public static void MakeImplicitDeclarationTypeExplicit(this IModuleRewriter rewriter, Declaration element) + { + if (!element.Context.TryGetChildContext(out _)) + { + rewriter.InsertAfter(element.Context.Stop.TokenIndex, $" {Tokens.As} {element.AsTypeName}"); + } + } + + public static void Rename(this IModuleRewriter rewriter, Declaration target, string newName) + { + if (target.Context is IIdentifierContext context) + { + rewriter.Replace(context.IdentifierTokens, newName); + } + } + + public static void SetVariableVisiblity(this IModuleRewriter rewriter, Declaration element, string visibility) + { + if (!element.IsVariable()) { throw new ArgumentException(); } + + var variableStmtContext = element.Context.GetAncestor(); + var visibilityContext = variableStmtContext.GetChild(); + + if (visibilityContext != null) + { + rewriter.Replace(visibilityContext, visibility); + return; + } + rewriter.InsertBefore(element.Context.Start.TokenIndex, $"{visibility} "); + } + } + + //If all variables are removed from a list one by one, then the + //Accessiblity token is left behind. + //FIXME: this class needs to go away when the issue described above is resolved + public static class RewriterRemoveWorkAround + { + private static Dictionary> RemovedVariables { set; get; } = new Dictionary>(); + + public static void Remove(Declaration target, IModuleRewriter rewriter) + { + var varList = target.Context.GetAncestor(); + if (varList.children.Where(ch => ch is VBAParser.VariableSubStmtContext).Count() == 1) + { + rewriter.Remove(target); + return; + } + + if (!RemovedVariables.ContainsKey(varList)) + { + RemovedVariables.Add(varList, new HashSet()); + } + RemovedVariables[varList].Add(target); + } + + public static void RemoveFieldsDeclaredInLists(IExecutableRewriteSession rewriteSession, QualifiedModuleName qmn) + { + var rewriter = rewriteSession.CheckOutModuleRewriter(qmn); + + foreach (var key in RemovedVariables.Keys) + { + var variables = key.children.Where(ch => ch is VBAParser.VariableSubStmtContext); + if (variables.Count() == RemovedVariables[key].Count) + { + rewriter.Remove(key.Parent); + } + else + { + foreach (var dec in RemovedVariables[key]) + { + rewriter.Remove(dec); + } + } + } + RemovedVariables = new Dictionary>(); + } + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index a608efd7bc..c1b7e512fd 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -6,7 +6,6 @@ using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings.Common; -using Rubberduck.Refactorings.EncapsulateField.Strategies; using Rubberduck.SmartIndenter; using Rubberduck.VBEditor; @@ -14,9 +13,6 @@ namespace Rubberduck.Refactorings.EncapsulateField { public class EncapsulateFieldModel : IRefactoringModel { - //private readonly IIndenter _indenter; - //private readonly IDeclarationFinderProvider _declarationFinderProvider; - //private readonly IEncapsulateFieldNamesValidator _validator; private readonly Func _previewDelegate; private QualifiedModuleName _targetQMN; @@ -24,22 +20,15 @@ public class EncapsulateFieldModel : IRefactoringModel private IDictionary)> _udtFieldToUdtDeclarationMap = new Dictionary)>(); - //private EncapsulationCandidateFactory _fieldCandidateFactory; - - public EncapsulateFieldModel(Declaration target, /*IDeclarationFinderProvider declarationFinderProvider, IIndenter indenter,*/ IEnumerable candidates, IEncapsulateFieldCandidate stateUDT, Func previewDelegate) + public EncapsulateFieldModel(Declaration target, IEnumerable candidates, IEncapsulateFieldCandidate stateUDTField, Func previewDelegate) { - //_declarationFinderProvider = declarationFinderProvider; - //_indenter = indenter; _previewDelegate = previewDelegate; _targetQMN = target.QualifiedModuleName; _useNewStructure = File.Exists("C:\\Users\\Brian\\Documents\\UseNewUDTStructure.txt"); - //_validator = new EncapsulateFieldNamesValidator(_declarationFinderProvider); //, () => EncapsulationCandidates); - EncapsulationCandidates = candidates.ToList(); - StateUDTField = stateUDT; - //_fieldCandidateFactory = new EncapsulationCandidateFactory(declarationFinderProvider, _targetQMN, _validator); + StateUDTField = stateUDTField; this[target].EncapsulateFlag = true; } @@ -48,15 +37,18 @@ public EncapsulateFieldModel(Declaration target, /*IDeclarationFinderProvider de public IEnumerable SelectedFieldCandidates => EncapsulationCandidates.Where(v => v.EncapsulateFlag); - public IEnumerable UDTFieldCandidates + public IEnumerable UDTFieldCandidates => EncapsulationCandidates - .Where(v => v is IEncapsulatedUserDefinedTypeField) - .Cast(); + .Where(v => v is IUserDefinedTypeCandidate) + .Cast(); - public IEnumerable SelectedUDTFieldCandidates + public IEnumerable SelectedUDTFieldCandidates => SelectedFieldCandidates - .Where(v => v is IEncapsulatedUserDefinedTypeField) - .Cast(); + .Where(v => v is IUserDefinedTypeCandidate) + .Cast(); + + public bool HasSelectedMultipleUDTFieldsOfType(string asTypeName) + => SelectedUDTFieldCandidates.Where(f => f.AsTypeName.Equals(asTypeName)).Count() > 1; public IEncapsulateFieldCandidate this[string encapsulatedFieldTargetID] => EncapsulationCandidates.Where(c => c.TargetID.Equals(encapsulatedFieldTargetID)).Single(); @@ -64,40 +56,10 @@ public IEncapsulateFieldCandidate this[string encapsulatedFieldTargetID] public IEncapsulateFieldCandidate this[Declaration fieldDeclaration] => EncapsulationCandidates.Where(c => c.Declaration == fieldDeclaration).Single(); - //public IEncapsulateFieldStrategy EncapsulationStrategy { set; get; } - //{ - // get - // { - // if (EncapsulateWithUDT) - // { - // return new EncapsulateWithBackingUserDefinedType(_targetQMN, _indenter, _validator) - // { - // StateUDTField = _fieldCandidateFactory.CreateStateUDTField() - // }; - // } - // return new EncapsulateWithBackingFields(_targetQMN, _indenter, _validator); - // } - //} - public bool EncapsulateWithUDT { set; get; } public IEncapsulateFieldCandidate StateUDTField { set; get; } public string PreviewRefactoring() => _previewDelegate(this); - - //public int? CodeSectionStartIndex { set; get; } - //{ - // get - // { - // var moduleMembers = _declarationFinderProvider.DeclarationFinder - // .Members(_targetQMN).Where(m => m.IsMember()); - - // int? codeSectionStartIndex - // = moduleMembers.OrderBy(c => c.Selection) - // .FirstOrDefault()?.Context.Start.TokenIndex ?? null; - - // return codeSectionStartIndex; - // } - //} } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldNewContent.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldNewContent.cs deleted file mode 100644 index 1af168a3fd..0000000000 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldNewContent.cs +++ /dev/null @@ -1,124 +0,0 @@ -using Rubberduck.Common; -using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Symbols; -using Rubberduck.VBEditor; -using Rubberduck.VBEditor.SafeComWrappers; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Rubberduck.Refactorings.EncapsulateField -{ - //public interface IEncapsulateFieldNewContentProvider - //{ - // void AddDeclarationBlock(string declarationBlock); - // void AddCodeBlock(string codeBlock); - // List Declarations { get; } - // List CodeBlocks { get; } - // string PreCodeSectionContent { get; } - // bool HasNewContent { get; } - // string CodeSectionContent { get; } - // string AsSingleTextBlock { get; } - // int CountOfProcLines { get; } - //} - - //public class EncapsulateFieldNewContent : IEncapsulateFieldNewContentProvider - //{ - // protected static string DoubleSpace => $"{Environment.NewLine}{Environment.NewLine}"; - // protected static string SingleSpace => $"{Environment.NewLine}"; - - // private IEnumerable SourceModuleElements { get; } - - // public void AddTypeDeclarationBlock(string declarationBlock) - // { - // if (declarationBlock.Length > 0) - // { - // TypeDeclarations.Add(declarationBlock); - // } - // } - - // public void AddDeclarationBlock(string declarationBlock) - // { - // if (declarationBlock.Length > 0) - // { - // Declarations.Add(declarationBlock); - // } - // } - - // public void AddCodeBlock(string codeBlock) - // { - // if (codeBlock.Length > 0) - // { - // CodeBlocks.Add(codeBlock); - // } - // } - - // private string _postPendComment; - // public string PostPendComment - // { - // get => _postPendComment; - // set - // { - // if (value.Length > 0) - // { - // _postPendComment = value.StartsWith("'") ? value : $"'{value}"; - // } - // } - // } - - // public List TypeDeclarations { get; } = new List(); - - // public List Declarations { get; } = new List(); - - // public List CodeBlocks { get; } = new List(); - - // public string PreCodeSectionContent - // { - // get - // { - // var allDeclarations = Enumerable.Empty().Concat(TypeDeclarations).Concat(Declarations); - // var preCodeSectionContent = new List(allDeclarations); - // if (preCodeSectionContent.Any()) - // { - // var preCodeSection = string.Join(SingleSpace, preCodeSectionContent); - // return preCodeSection; - // } - // return string.Empty; - // } - // } - - // public bool HasNewContent => Declarations.Any() || CodeBlocks.Any(); - - // public string CodeSectionContent => CodeBlocks.Any() ? string.Join($"{DoubleSpace}", CodeBlocks) : string.Empty; - - // public string AsSingleTextBlock - // { - // get - // { - // if (!HasNewContent) { return string.Empty; } - - // var content = string.Empty; - // if (PreCodeSectionContent.Length > 0) - // { - // content = CodeSectionContent.Length > 0 - // ? $"{PreCodeSectionContent}{DoubleSpace}{CodeSectionContent}" - // : $"{PreCodeSectionContent}"; - // } - // else - // { - // content = CodeSectionContent.Length > 0 - // ? $"{SingleSpace}{CodeSectionContent}" - // : string.Empty; - // } - - // if (PostPendComment != null && PostPendComment.Length > 0) - // { - // content = $"{content}{SingleSpace}{PostPendComment}{SingleSpace}"; - // } - // return content; - // } - // } - - // public int CountOfProcLines => CodeSectionContent.Split(new string[] {SingleSpace}, StringSplitOptions.None).Count(); - //} -} diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index e02d67a402..556092a66a 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -13,7 +13,7 @@ using Rubberduck.Parsing; using Rubberduck.Refactorings.Common; using System.IO; -using Rubberduck.Refactorings.EncapsulateField.Strategies; +using Antlr4.Runtime; namespace Rubberduck.Refactorings.EncapsulateField { @@ -38,6 +38,7 @@ private enum NewContentTypes { TypeDeclarationBlock, DeclarationBlock, MethodBlo private static string DoubleSpace => $"{Environment.NewLine}{Environment.NewLine}"; + private bool _useNewScheme; public EncapsulateFieldRefactoring( IDeclarationFinderProvider declarationFinderProvider, IIndenter indenter, @@ -51,16 +52,14 @@ public EncapsulateFieldRefactoring( _declarationFinderProvider = declarationFinderProvider; _selectedDeclarationProvider = selectedDeclarationProvider; _indenter = indenter; - _validator = new EncapsulateFieldNamesValidator(_declarationFinderProvider);//, () => FieldCandidates); - //_useNewValidationScheme = File.Exists("C:\\Users\\Brian\\Documents\\UseNewUDTStructure.txt"); + _validator = new EncapsulateFieldNamesValidator(_declarationFinderProvider); + + _useNewScheme = File.Exists("C:\\Users\\Brian\\Documents\\UseNewUDTStructure.txt"); _codeSectionStartIndex = _declarationFinderProvider.DeclarationFinder .Members(_targetQMN).Where(m => m.IsMember()) .OrderBy(c => c.Selection) - .FirstOrDefault()?.Context.Start.TokenIndex ?? null; ; - - //_codeSectionStartIndex = moduleMembers.OrderBy(c => c.Selection) - // .FirstOrDefault()?.Context.Start.TokenIndex ?? null; + .FirstOrDefault()?.Context.Start.TokenIndex ?? null; } public EncapsulateFieldModel Model { set; get; } @@ -102,29 +101,20 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) Model = new EncapsulateFieldModel( target, - //_declarationFinderProvider, - //_indenter, _encapsulationCandidateFactory.CreateEncapsulationCandidates(), _encapsulationCandidateFactory.CreateStateUDTField(), PreviewRewrite); - //Model.StateUDTField = _encapsulationCandidateFactory.CreateStateUDTField(); - - var moduleMembers = _declarationFinderProvider.DeclarationFinder - .Members(_targetQMN).Where(m => m.IsMember()); - - _codeSectionStartIndex - = moduleMembers.OrderBy(c => c.Selection) + _codeSectionStartIndex = _declarationFinderProvider.DeclarationFinder + .Members(_targetQMN).Where(m => m.IsMember()) + .OrderBy(c => c.Selection) .FirstOrDefault()?.Context.Start.TokenIndex ?? null; - //Model.CodeSectionStartIndex = codeSectionStartIndex; - return Model; } protected override void RefactorImpl(EncapsulateFieldModel model) { - //var strategy = new EncapsulateFieldStrategiesBase(_targetQMN, _indenter, _validator, StateUDTField); var rewriteSession = RefactorRewrite(model, RewritingManager.CheckOutCodePaneSession()); if (!rewriteSession.TryRewrite()) @@ -135,10 +125,9 @@ protected override void RefactorImpl(EncapsulateFieldModel model) private string PreviewRewrite(EncapsulateFieldModel model) { - //var strategy = new EncapsulateFieldStrategiesBase(_targetQMN, _indenter, _validator, StateUDTField); var scratchPadRewriteSession = GeneratePreview(model, RewritingManager.CheckOutCodePaneSession()); - var previewRewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(scratchPadRewriteSession, _targetQMN); + var previewRewriter = scratchPadRewriteSession.CheckOutModuleRewriter(_targetQMN); return previewRewriter.GetText(maxConsecutiveNewLines: 3); } @@ -171,7 +160,10 @@ private IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, I { NewContentTypes.TypeDeclarationBlock, new List() } }; - ConfigureSelectedEncapsulationObjects(model); + foreach (var udtField in model.SelectedUDTFieldCandidates) + { + udtField.FieldQualifyUDTMemberPropertyName = model.HasSelectedMultipleUDTFieldsOfType(udtField.AsTypeName); + } ModifyFields(model, rewriteSession); @@ -184,76 +176,41 @@ private IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, I return rewriteSession; } - private void ConfigureSelectedEncapsulationObjects(EncapsulateFieldModel model) + private void ModifyReferences(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) { - if (model.EncapsulateWithUDT) - { - foreach (var field in model.SelectedFieldCandidates) - { - if (field is IEncapsulatedUserDefinedTypeField udt) - { - udt.PropertyAccessExpression = () => $"{StateUDTField.PropertyAccessExpression()}.{udt.PropertyName}"; - udt.ReferenceExpression = udt.PropertyAccessExpression; - - foreach (var member in udt.Members) - { - member.PropertyAccessExpression = () => $"{udt.PropertyAccessExpression()}.{member.PropertyName}"; - member.ReferenceExpression = member.PropertyAccessExpression; - } - continue; - } - - field.PropertyAccessExpression = () => $"{StateUDTField.PropertyAccessExpression()}.{field.PropertyName}"; - field.ReferenceExpression = field.PropertyAccessExpression; - } - } - - foreach (var udtField in model.SelectedUDTFieldCandidates) - { - udtField.FieldQualifyMemberPropertyNames = model.SelectedUDTFieldCandidates.Where(f => f.AsTypeName.Equals(udtField.AsTypeName)).Count() > 1; - } + var stateUDT = model.EncapsulateWithUDT + ? model.StateUDTField as IStateUDTField + : null; - //StageReferenceReplacementExpressions(model); - foreach (var field in model.SelectedFieldCandidates) + foreach (var field in model.EncapsulationCandidates) { - field.LoadReferenceExpressionChanges(); + field.SetupReferenceReplacements(stateUDT); } - } - private void ModifyReferences(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) - { foreach (var rewriteReplacement in model.SelectedFieldCandidates.SelectMany(fld => fld.ReferenceReplacements)) { - var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, rewriteReplacement.Key.QualifiedModuleName); - rewriter.Replace(rewriteReplacement.Value); + (ParserRuleContext Context, string Text) = rewriteReplacement.Value; + var rewriter = rewriteSession.CheckOutModuleRewriter(rewriteReplacement.Key.QualifiedModuleName); + rewriter.Replace(Context, Text); } } - //private void StageReferenceReplacementExpressions(EncapsulateFieldModel model) - //{ - // foreach (var field in model.SelectedFieldCandidates) - // { - // field.LoadReferenceExpressionChanges(); - // } - //} - private void ModifyFields(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) { if (model.EncapsulateWithUDT) { foreach (var field in model.SelectedFieldCandidates) { - var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, _targetQMN); + var rewriter = rewriteSession.CheckOutModuleRewriter(_targetQMN); RewriterRemoveWorkAround.Remove(field.Declaration, rewriter); - //rewriter.Remove(target.Declaration); } return; } foreach (var field in model.SelectedFieldCandidates) { - var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, _targetQMN); + var rewriter = rewriteSession.CheckOutModuleRewriter(_targetQMN); if (field.Declaration.Accessibility == Accessibility.Private && field.NewFieldName.Equals(field.Declaration.IdentifierName)) { @@ -261,7 +218,7 @@ private void ModifyFields(EncapsulateFieldModel model, IExecutableRewriteSession continue; } - if (field.Declaration.IsDeclaredInList()) + if (field.Declaration.IsDeclaredInList() && !field.Declaration.HasPrivateAccessibility()) { RewriterRemoveWorkAround.Remove(field.Declaration, rewriter); //rewriter.Remove(target.Declaration); @@ -276,7 +233,7 @@ private void ModifyFields(EncapsulateFieldModel model, IExecutableRewriteSession private void InsertNewContent(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool postPendPreviewMessage = false) { - var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, _targetQMN); + var rewriter = rewriteSession.CheckOutModuleRewriter(_targetQMN); LoadNewDeclarationBlocks(model); @@ -309,12 +266,11 @@ private void LoadNewDeclarationBlocks(EncapsulateFieldModel model) { if (model.EncapsulateWithUDT) { - var udt = new UDTDeclarationGenerator(StateUDTField.AsTypeName); - - udt.AddMembers(model.SelectedFieldCandidates); + var stateUDT = StateUDTField as IStateUDTField; + stateUDT.AddMembers(model.SelectedFieldCandidates); - AddCodeBlock(NewContentTypes.TypeDeclarationBlock, udt.TypeDeclarationBlock(_indenter)); - AddCodeBlock(NewContentTypes.DeclarationBlock, udt.FieldDeclarationBlock(StateUDTField.NewFieldName)); + AddCodeBlock(NewContentTypes.TypeDeclarationBlock, stateUDT.TypeDeclarationBlock(_indenter)); // udt.TypeDeclarationBlock(_indenter)); + AddCodeBlock(NewContentTypes.DeclarationBlock, stateUDT.FieldDeclarationBlock); // udt.FieldDeclarationBlock(StateUDTField.NewFieldName)); return; } @@ -337,7 +293,7 @@ private void LoadNewDeclarationBlocks(EncapsulateFieldModel model) private void LoadNewPropertyBlocks(EncapsulateFieldModel model) { var propertyGenerationSpecs = model.SelectedFieldCandidates - .SelectMany(f => f.PropertyGenerationSpecs); + .SelectMany(f => f.PropertyAttributeSets); var generator = new PropertyGenerator(); foreach (var spec in propertyGenerationSpecs) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs deleted file mode 100644 index c005ed5b8b..0000000000 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriter.cs +++ /dev/null @@ -1,141 +0,0 @@ -using Antlr4.Runtime; -using Antlr4.Runtime.Misc; -using Antlr4.Runtime.Tree; -using Rubberduck.Parsing; -using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Rewriter; -using Rubberduck.Parsing.Symbols; -using Rubberduck.VBEditor; -using System; -using System.Linq; - -namespace Rubberduck.Refactorings.EncapsulateField -{ - public interface IEncapsulateFieldRewriter : IModuleRewriter - { - void SetVariableVisiblity(Declaration element, string visibilityToken); - void Rename(Declaration element, string newName); - void MakeImplicitDeclarationTypeExplicit(Declaration element); - void InsertAtEndOfFile(string content); - string GetText(int maxConsecutiveNewLines); - void Replace(RewriteReplacePair pair); - } - - public struct RewriteReplacePair - { - public RewriteReplacePair(string text, ParserRuleContext context) - { - Text = text; - Context = context; - } - public string Text { private set; get; } - public ParserRuleContext Context { private set; get; } - } - - public class EncapsulateFieldRewriter : IEncapsulateFieldRewriter - { - private IModuleRewriter _rewriter; - - public EncapsulateFieldRewriter(IModuleRewriter rewriter) - { - _rewriter = rewriter; - } - - public static IEncapsulateFieldRewriter CheckoutModuleRewriter(IRewriteSession rewriteSession, QualifiedModuleName qmn) - { - var rewriter = rewriteSession.CheckOutModuleRewriter(qmn); - return new EncapsulateFieldRewriter(rewriter); - } - - public void InsertAtEndOfFile(string content) - { - if (content == string.Empty) { return; } - - _rewriter.InsertBefore(_rewriter.TokenStream.Size - 1, content); - } - - public void SetVariableVisiblity(Declaration element, string visibility) - { - if (!element.IsVariable()) { return; } - - var variableStmtContext = element.Context.GetAncestor(); - var visibilityContext = variableStmtContext.GetChild(); - - if (visibilityContext != null) - { - _rewriter.Replace(visibilityContext, visibility); - return; - } - _rewriter.InsertBefore(element.Context.Start.TokenIndex, $"{visibility} "); - } - - public void Rename(Declaration element, string newName) - { - var identifierContext = element.Context.GetChild(); - _rewriter.Replace(identifierContext, newName); - } - - public void MakeImplicitDeclarationTypeExplicit(Declaration element) - { - if (!element.Context.TryGetChildContext(out _)) - { - _rewriter.InsertAfter(element.Context.Stop.TokenIndex, $" {Tokens.As} {element.AsTypeName}"); - } - } - - public string GetText(int maxConsecutiveNewLines) - { - var preview = GetText(); - var target = string.Join(string.Empty, Enumerable.Repeat(Environment.NewLine, maxConsecutiveNewLines).ToList()); - var replacement = string.Join(string.Empty, Enumerable.Repeat(Environment.NewLine, maxConsecutiveNewLines - 1).ToList()); - for (var counter = 1; counter < 10 && preview.Contains(target); counter++) - { - preview = preview.Replace(target, replacement); - } - return preview; - } - - public bool IsDirty => _rewriter.IsDirty; - - public Selection? Selection { get => _rewriter.Selection; set => _rewriter.Selection = value; } - - public Selection? SelectionOffset { get => _rewriter.SelectionOffset; set => _rewriter.SelectionOffset = value; } - - public ITokenStream TokenStream => _rewriter.TokenStream; - - public string GetText(int startTokenIndex, int stopTokenIndex) => _rewriter.GetText(startTokenIndex, stopTokenIndex); - - public string GetText() => _rewriter.GetText(); - - public void InsertAfter(int tokenIndex, string content) => _rewriter.InsertAfter(tokenIndex, content); - - public void InsertBefore(int tokenIndex, string content) => _rewriter.InsertBefore(tokenIndex, content); - - public void Remove(Declaration target) => _rewriter.Remove(target); - - public void Remove(ParserRuleContext target) => _rewriter.Remove(target); - - public void Remove(IToken target) => _rewriter.Remove(target); - - public void Remove(ITerminalNode target) => _rewriter.Remove(target); - - public void Remove(IParseTree target) => _rewriter.Remove(target); - - public void RemoveRange(int start, int stop) => _rewriter.RemoveRange(start, stop); - - public void Replace(Declaration target, string content) => _rewriter.Replace(target, content); - - public void Replace(RewriteReplacePair pair) => _rewriter.Replace(pair.Context, pair.Text); - - public void Replace(ParserRuleContext target, string content) => _rewriter.Replace(target, content); - - public void Replace(IToken token, string content) => _rewriter.Replace(token, content); - - public void Replace(ITerminalNode target, string content) => _rewriter.Replace(target, content); - - public void Replace(IParseTree target, string content) => _rewriter.Replace(target, content); - - public void Replace(Interval tokenInterval, string content) => _rewriter.Replace(tokenInterval, content); - } - -} diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs index 1ae9bba926..a809eb174f 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -25,8 +25,8 @@ public interface IEncapsulateFieldValidator public interface IEncapsulateFieldNamesValidator : IEncapsulateFieldValidator { - bool HasIdentifierConflicts(string identifier, DeclarationType declarationType); - bool IsConflictingStateUDTIdentifier(IEncapsulatedUserDefinedTypeField candidate); + //bool HasIdentifierConflicts(string identifier, DeclarationType declarationType); + bool IsConflictingStateUDTIdentifier(IUserDefinedTypeCandidate candidate); } public class EncapsulateFieldNamesValidator : IEncapsulateFieldNamesValidator @@ -82,7 +82,7 @@ public bool IsConflictingFieldIdentifier(string fieldName, IEncapsulateFieldCand return members.Any(m => m.IdentifierName.EqualsVBAIdentifier(fieldName) || candidate.PropertyName.EqualsVBAIdentifier(fieldName)); } - public bool IsConflictingStateUDTIdentifier(IEncapsulatedUserDefinedTypeField candidate) + public bool IsConflictingStateUDTIdentifier(IUserDefinedTypeCandidate candidate) { var members = _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName); @@ -103,45 +103,45 @@ public bool HasValidEncapsulationAttributes(IEncapsulateFieldCandidate candidate return true; } - public int HasNewPropertyNameConflicts(IEncapsulateFieldCandidate attributes, QualifiedModuleName qmn, IEnumerable declarationsToIgnore) - { - Predicate IsPrivateAccessiblityInOtherModule = (Declaration dec) => dec.QualifiedModuleName != qmn && dec.Accessibility.Equals(Accessibility.Private); - Predicate IsInSearchScope = null; - if (qmn.ComponentType == ComponentType.ClassModule) - { - IsInSearchScope = (Declaration dec) => dec.QualifiedModuleName == qmn; - } - else - { - IsInSearchScope = (Declaration dec) => dec.QualifiedModuleName.ProjectId == qmn.ProjectId; - } - - var identifierMatches = DeclarationFinder.MatchName(attributes.PropertyName) - .Where(match => IsInSearchScope(match) - && !declarationsToIgnore.Contains(match) - && !IsPrivateAccessiblityInOtherModule(match) - && !IsEnumOrUDTMemberDeclaration(match) - && !match.IsLocalVariable()).ToList(); - - var candidates = new List(); - var candidateMatches = new List(); - foreach (var efd in FieldCandidates) - { - var matches = candidates.Where(c => c.PropertyName.EqualsVBAIdentifier(efd.PropertyName)); - if (matches.Any()) - { - candidateMatches.Add(efd); - } - candidates.Add(efd); - } - - return identifierMatches.Count() + candidateMatches.Count(); - } - - public bool HasIdentifierConflicts(string identifier, DeclarationType declarationType) - { - return true; - } + //public int HasNewPropertyNameConflicts(IEncapsulateFieldCandidate attributes, QualifiedModuleName qmn, IEnumerable declarationsToIgnore) + //{ + // Predicate IsPrivateAccessiblityInOtherModule = (Declaration dec) => dec.QualifiedModuleName != qmn && dec.Accessibility.Equals(Accessibility.Private); + // Predicate IsInSearchScope = null; + // if (qmn.ComponentType == ComponentType.ClassModule) + // { + // IsInSearchScope = (Declaration dec) => dec.QualifiedModuleName == qmn; + // } + // else + // { + // IsInSearchScope = (Declaration dec) => dec.QualifiedModuleName.ProjectId == qmn.ProjectId; + // } + + // var identifierMatches = DeclarationFinder.MatchName(attributes.PropertyName) + // .Where(match => IsInSearchScope(match) + // && !declarationsToIgnore.Contains(match) + // && !IsPrivateAccessiblityInOtherModule(match) + // && !IsEnumOrUDTMemberDeclaration(match) + // && !match.IsLocalVariable()).ToList(); + + // var candidates = new List(); + // var candidateMatches = new List(); + // foreach (var efd in FieldCandidates) + // { + // var matches = candidates.Where(c => c.PropertyName.EqualsVBAIdentifier(efd.PropertyName)); + // if (matches.Any()) + // { + // candidateMatches.Add(efd); + // } + // candidates.Add(efd); + // } + + // return identifierMatches.Count() + candidateMatches.Count(); + //} + + //public bool HasIdentifierConflicts(string identifier, DeclarationType declarationType) + //{ + // return true; + //} private bool IsEnumOrUDTMemberDeclaration(Declaration candidate) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationIdentifiers.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationIdentifiers.cs index f8b5c60bf0..42f98a4c2d 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationIdentifiers.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationIdentifiers.cs @@ -21,25 +21,25 @@ public EncapsulationIdentifiers(string field) { _targetIdentifier = field; _defaultPropertyName = field.Capitalize(); - DefaultNewFieldName = IncrementIdentifier(field.UnCapitalize()); + DefaultNewFieldName = (field.UnCapitalize()).IncrementIdentifier(); _fieldAndProperty = new KeyValuePair(DefaultNewFieldName, _defaultPropertyName); _setLetParameter = DEFAULT_WRITE_PARAMETER; } - public static string IncrementIdentifier(string identifier) - { - var fragments = identifier.Split('_'); - if (fragments.Length == 1) { return $"{identifier}_1"; } + //public static string IncrementIdentifier(string identifier) + //{ + // var fragments = identifier.Split('_'); + // if (fragments.Length == 1) { return $"{identifier}_1"; } - var lastFragment = fragments[fragments.Length - 1]; - if (long.TryParse(lastFragment, out var number)) - { - fragments[fragments.Length - 1] = (number + 1).ToString(); + // var lastFragment = fragments[fragments.Length - 1]; + // if (long.TryParse(lastFragment, out var number)) + // { + // fragments[fragments.Length - 1] = (number + 1).ToString(); - return string.Join("_", fragments); - } - return $"{identifier}_1"; ; - } + // return string.Join("_", fragments); + // } + // return $"{identifier}_1"; ; + //} public string TargetFieldName => _targetIdentifier; @@ -51,7 +51,7 @@ public string Field set { _fieldAndProperty = new KeyValuePair(value, _fieldAndProperty.Value); - GenerateNonConflictParamIdentifier(); + GenerateNonConflictParameterName(); } } @@ -66,13 +66,13 @@ public string Property _fieldAndProperty = new KeyValuePair(_fieldAndProperty.Key, value); - GenerateNonConflictParamIdentifier(); + GenerateNonConflictParameterName(); } } public string SetLetParameter => _setLetParameter; - private void GenerateNonConflictParamIdentifier() + private void GenerateNonConflictParameterName() { _setLetParameter = DEFAULT_WRITE_PARAMETER; diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs b/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs deleted file mode 100644 index 1873964727..0000000000 --- a/Rubberduck.Refactorings/EncapsulateField/FieldEncapsulationAttributes.cs +++ /dev/null @@ -1,189 +0,0 @@ -using Rubberduck.Parsing.Symbols; -using Rubberduck.VBEditor; -using System; -using System.Collections.Generic; - -namespace Rubberduck.Refactorings.EncapsulateField -{ - // PropertyName = field.PropertyName, - //AsTypeName = field.AsTypeName, - //BackingField = field.PropertyAccessExpression(), - //ParameterName = field.ParameterName, - //GenerateSetter = field.ImplementSetSetterType, - //GenerateLetter = field.ImplementLetSetterType - - //public interface IFieldEncapsulationAttributesX //: ISupportPropertyGenerator - //{ - // ////string IdentifierName { get; } - // ////string PropertyName { get; set; } //req'd - // ////bool IsReadOnly { get; set; } - // ////bool EncapsulateFlag { get; set; } - // ////string NewFieldName { set; get; } - // ////bool CanBeReadWrite { set; get; } - // ////string AsTypeName { get; set; } //req'd - // ////string ParameterName { get; } //req'd - // ////bool ImplementLetSetterType { get; set; }//req'd - // ////bool ImplementSetSetterType { get; set; }//req'd - // ////bool FieldNameIsExemptFromValidation { get; } - // //QualifiedModuleName QualifiedModuleName { get; } - // ////Func PropertyAccessExpression { set; get; } //req'd - // //Func ReferenceExpression { set; get; } - //} - - //public interface ISupportPropertyGenerator - //{ - // string PropertyName { get; set; } //req'd - // string AsTypeName { get; set; } //req'd - // string ParameterName { get; } //req'd - // bool ImplementLetSetterType { get; set; }//req'd - // bool ImplementSetSetterType { get; set; }//req'd - // Func PropertyAccessExpression { set; get; } //req'd - //} - - - //Used for declarations that will be added to the code, but will never be encapsulated - //Satifies the IFieldEncapsulationAttributes interface but some properties return n - //public class NeverEncapsulateAttributes //: IFieldEncapsulationAttributes - //{ - // private const string neverUse = "x_x_x_x"; - // private IEncapsulateFieldNamesValidator _validator; - // private QualifiedModuleName _qmn; - - // public NeverEncapsulateAttributes(string identifier, string asTypeName, QualifiedModuleName qmn, IEncapsulateFieldNamesValidator validator) - // { - // _qmn = qmn; - // _validator = validator; - // IdentifierName = identifier; - // NewFieldName = identifier; - // AsTypeName = asTypeName; - // PropertyAccessExpression = () => NewFieldName; - // ReferenceExpression = () => NewFieldName; - // } - - // //public IFieldEncapsulationAttributes ApplyNewFieldName(string newFieldName) - // //{ - // // NewFieldName = newFieldName; - // // return this; - // //} - - // public string IdentifierName { private set; get; } - - // public string NewFieldName { set; get; } - - // string _tossString; - // public string PropertyName { set => _tossString = value; get => $"{neverUse}{IdentifierName}_{neverUse}"; } - - // public Func PropertyAccessExpression { set; get; } - - // public Func ReferenceExpression { set; get; } - - // public string AsTypeName { get; set; } - // public string ParameterName => neverUse; - - // private bool _toss; - // public bool IsReadOnly { get; set; } = false; - // public bool CanBeReadWrite { get => false; set => _toss = value; } - - - // public bool EncapsulateFlag { get => false; set => _toss = value; } - // public bool ImplementLetSetterType { get => false; set => _toss = value; } - // public bool ImplementSetSetterType { get => false; set => _toss = value; } - - // //public bool FieldNameIsExemptFromValidation => false; - // public QualifiedModuleName QualifiedModuleName => _qmn; - //} - - //public class FieldEncapsulationAttributes //: IFieldEncapsulationAttributes - //{ - // private QualifiedModuleName _qmn; - // private bool _fieldNameIsAlwaysValid; - // public FieldEncapsulationAttributes(Declaration target) - // { - // _fieldAndProperty = new EncapsulationIdentifiers(target); - // IdentifierName = target.IdentifierName; - // AsTypeName = target.AsTypeName; - // _qmn = target.QualifiedModuleName; - // PropertyAccessExpression = () => NewFieldName; - // //ReferenceExpression = () => NewFieldName; - // ReferenceExpression = () => PropertyName; - // _fieldNameIsAlwaysValid = target.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember); - // } - - // //public FieldEncapsulationAttributes(string identifier, string asTypeName) - // //{ - // // _fieldAndProperty = new EncapsulationIdentifiers(identifier); - // // AsTypeName = asTypeName; - // // PropertyAccessExpression = () => NewFieldName; - // // ReferenceExpression = () => PropertyName; - // //} - - // //public FieldEncapsulationAttributes(IFieldEncapsulationAttributes attributes) - // //{ - // //_fieldAndProperty = new EncapsulationIdentifiers(attributes.IdentifierName, attributes.NewFieldName, attributes.PropertyName); - // //PropertyName = attributes.PropertyName; - // //IsReadOnly = attributes.IsReadOnly; - // //EncapsulateFlag = attributes.EncapsulateFlag; - // //NewFieldName = attributes.NewFieldName; - // //CanBeReadWrite = attributes.CanBeReadWrite; - // //AsTypeName = attributes.AsTypeName; - // //ImplementLetSetterType = attributes.ImplementLetSetterType; - // //ImplementSetSetterType = attributes.ImplementSetSetterType; - // //QualifiedModuleName = attributes.QualifiedModuleName; - // //PropertyAccessExpression = () => NewFieldName; - // //ReferenceExpression = () => PropertyName; - // //} - - // private EncapsulationIdentifiers _fieldAndProperty; - - // public string IdentifierName { private set; get; } - - // public bool CanBeReadWrite { set; get; } = true; - - // public string NewFieldName - // { - // get => _fieldAndProperty.Field; - // set => _fieldAndProperty.Field = value; - // } - - // public string PropertyName - // { - // get => _fieldAndProperty.Property; - // set => _fieldAndProperty.Property = value; - // } - - // private Func _propertyAccessExpression; - // public Func PropertyAccessExpression - // { - // get - // { - // var test = _propertyAccessExpression(); - // return _propertyAccessExpression; - // } - // set - // { - // _propertyAccessExpression = value; - // var test = value(); - // } - // } - - // public Func ReferenceExpression { set; get; } - - // public string AsTypeName { get; set; } - // public string ParameterName => _fieldAndProperty.SetLetParameter; - // public bool IsReadOnly { get; set; } - // public bool EncapsulateFlag { get; set; } - - // private bool _implLet; - // public bool ImplementLetSetterType { get => !IsReadOnly && _implLet; set => _implLet = value; } - - // private bool _implSet; - // public bool ImplementSetSetterType { get => !IsReadOnly && _implSet; set => _implSet = value; } - - // public bool FieldNameIsExemptFromValidation => _fieldNameIsAlwaysValid || NewFieldName.EqualsVBAIdentifier(IdentifierName); - // public QualifiedModuleName QualifiedModuleName - // { - // get => _qmn; - // set => _qmn = value; - // } - //} -} diff --git a/Rubberduck.Refactorings/EncapsulateField/IEncapsulateFieldDialog.cs b/Rubberduck.Refactorings/EncapsulateField/IEncapsulateFieldDialog.cs deleted file mode 100644 index 56ff8f40b5..0000000000 --- a/Rubberduck.Refactorings/EncapsulateField/IEncapsulateFieldDialog.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Rubberduck.Parsing.Symbols; -using Rubberduck.UI; - -namespace Rubberduck.Refactorings.EncapsulateField -{ - public interface IEncapsulateFieldDialog : IDialogView - { - Declaration TargetDeclaration { get; set; } - - string NewPropertyName { get; set; } - bool CanImplementLetSetterType { get; set; } - bool CanImplementSetSetterType { get; set; } - bool LetSetterSelected { get; } - bool SetSetterSelected { get; } - bool MustImplementLetSetterType { get; } - bool MustImplementSetSetterType { get; } - - string ParameterName { get; set; } - } -} diff --git a/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs b/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs index 35389178a2..ef44911b64 100644 --- a/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs @@ -4,7 +4,7 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface IPropertyGeneratorSpecification + public interface IPropertyGeneratorAttributes { string PropertyName { get; } string BackingField { get; } @@ -15,7 +15,7 @@ public interface IPropertyGeneratorSpecification bool UsesSetAssignment { get; } } - public struct PropertyGeneratorSpecification : IPropertyGeneratorSpecification + public struct PropertyGeneratorSpecification : IPropertyGeneratorAttributes { public string PropertyName { get; set; } public string BackingField { get; set; } @@ -30,7 +30,7 @@ public class PropertyGenerator { public PropertyGenerator() { } - public PropertyGenerator(IPropertyGeneratorSpecification spec) + public PropertyGenerator(IPropertyGeneratorAttributes spec) { PropertyName = spec.PropertyName; BackingField = spec.BackingField; @@ -59,7 +59,7 @@ public string AsPropertyBlock(IIndenter indenter) return string.Join(Environment.NewLine, indenter.Indent(AsEnumerableLines, true)); } - public string AsPropertyBlock(IPropertyGeneratorSpecification spec, IIndenter indenter) + public string AsPropertyBlock(IPropertyGeneratorAttributes spec, IIndenter indenter) { PropertyName = spec.PropertyName; BackingField = spec.BackingField; diff --git a/Rubberduck.Refactorings/EncapsulateField/RewriterRemoveWorkaround.cs b/Rubberduck.Refactorings/EncapsulateField/RewriterRemoveWorkaround.cs deleted file mode 100644 index 5bce43dde7..0000000000 --- a/Rubberduck.Refactorings/EncapsulateField/RewriterRemoveWorkaround.cs +++ /dev/null @@ -1,78 +0,0 @@ -using Rubberduck.Parsing; -using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Rewriter; -using Rubberduck.Parsing.Symbols; -using Rubberduck.VBEditor; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Rubberduck.Refactorings.EncapsulateField -{ - //If all variables are removed from a list one by one the - //Accessiblity token is left behind - public static class RewriterRemoveWorkAround - { - private static Dictionary> RemovedVariables { set; get; } = new Dictionary>(); - - public static void Remove(Declaration target, IEncapsulateFieldRewriter rewriter) - { - var varList = target.Context.GetAncestor(); - if (varList.children.Where(ch => ch is VBAParser.VariableSubStmtContext).Count() == 1) - { - rewriter.Remove(target); - return; - } - - if (!RemovedVariables.ContainsKey(varList)) - { - RemovedVariables.Add(varList, new HashSet()); - } - RemovedVariables[varList].Add(target); - } - - //public static void RemoveFieldsDeclaredInLists(IEncapsulateFieldRewriter rewriter) - //{ - // foreach (var key in RemovedVariables.Keys) - // { - // var variables = key.children.Where(ch => ch is VBAParser.VariableSubStmtContext); - // if (variables.Count() == RemovedVariables[key].Count) - // { - // rewriter.Remove(key.Parent); - // } - // else - // { - // foreach (var dec in RemovedVariables[key]) - // { - // rewriter.Remove(dec); - // } - // } - // } - // RemovedVariables = new Dictionary>(); - //} - - public static void RemoveFieldsDeclaredInLists(IExecutableRewriteSession rewriteSession, QualifiedModuleName qmn) - { - var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, qmn); - - foreach (var key in RemovedVariables.Keys) - { - var variables = key.children.Where(ch => ch is VBAParser.VariableSubStmtContext); - if (variables.Count() == RemovedVariables[key].Count) - { - rewriter.Remove(key.Parent); - } - else - { - foreach (var dec in RemovedVariables[key]) - { - rewriter.Remove(dec); - } - } - } - RemovedVariables = new Dictionary>(); - } - } -} diff --git a/Rubberduck.Refactorings/EncapsulateField/StateUDTField.cs b/Rubberduck.Refactorings/EncapsulateField/StateUDTField.cs index 89d196d467..cd17428e1a 100644 --- a/Rubberduck.Refactorings/EncapsulateField/StateUDTField.cs +++ b/Rubberduck.Refactorings/EncapsulateField/StateUDTField.cs @@ -1,4 +1,6 @@ -using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Symbols; +using Rubberduck.SmartIndenter; using Rubberduck.VBEditor; using System; using System.Collections.Generic; @@ -8,16 +10,38 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public class StateUDTField : EncapsulateFieldCandidate, IEncapsulatedUserDefinedTypeField + public interface IStateUDTField { + string TypeIdentifier { set; get; } + string TypeDeclarationBlock(IIndenter indenter = null); + string FieldDeclarationBlock { get; } + void AddMembers(IEnumerable fields); + void Reset(); + string NewFieldName { get; } + } + + public class StateUDTField : EncapsulateFieldCandidate, IUserDefinedTypeCandidate, IStateUDTField + { + private const string _defaultTypeIdentifier = "This_Type"; + private const string _defaultNewFieldName = "this"; + private List _members; + public StateUDTField(string identifier, string asTypeName, QualifiedModuleName qmn, IEncapsulateFieldNamesValidator validator) : base(identifier, asTypeName, qmn, validator) { PropertyName = identifier; NewFieldName = identifier; AsTypeName = asTypeName; + TypeIdentifier = asTypeName; + _members = new List(); + + PropertyAccessor = AccessorTokens.Field; + ReferenceAccessor = AccessorTokens.Field; + //ReferenceQualifier = Parent.ReferenceWithinNewProperty; } + public string TypeIdentifier { set; get; } + public override string PropertyName { set; get; } public override string NewFieldName { set; get; } @@ -26,9 +50,44 @@ public StateUDTField(string identifier, string asTypeName, QualifiedModuleName q && !(PropertyName.EqualsVBAIdentifier(ParameterName) || PropertyName.EqualsVBAIdentifier(ParameterName)); - public IEnumerable Members { get; } - public void AddMember(IEncapsulatedUserDefinedTypeMember member) { throw new NotImplementedException(); } - public bool FieldQualifyMemberPropertyNames { set; get; } + public IEnumerable Members { get; } + public void AddMember(IUserDefinedTypeMemberCandidate member) { throw new NotImplementedException(); } + public bool FieldQualifyUDTMemberPropertyName { set; get; } public bool TypeDeclarationIsPrivate { set; get; } = true; + + //public void AddMember(IEncapsulateFieldCandidate field) => _members.Add(field); + public void Reset() + { + _members.Clear(); + NewFieldName = _defaultNewFieldName; + TypeIdentifier = _defaultTypeIdentifier; + } + + public void AddMembers(IEnumerable fields) => _members.AddRange(fields); + + public string FieldDeclarationBlock //(string fieldName) // string identifierName, Accessibility accessibility = Accessibility.Private) + => $"{Accessibility.Private} {NewFieldName} {Tokens.As} {AsTypeName}"; + + public string TypeDeclarationBlock(IIndenter indenter = null) //= null, Accessibility accessibility = Accessibility.Private) + { + if (indenter != null) + { + return string.Join(Environment.NewLine, indenter?.Indent(BlockLines(Accessibility.Private) ?? BlockLines(Accessibility.Private), true)); + } + return string.Join(Environment.NewLine, BlockLines(Accessibility.Private)); + } + + private IEnumerable BlockLines(Accessibility accessibility) + { + var blockLines = new List(); + + blockLines.Add($"{accessibility.TokenString()} {Tokens.Type} {AsTypeName}"); + + _members.ForEach(m => blockLines.Add($"{m.PropertyName} As {m.AsTypeName}")); + + blockLines.Add("End Type"); + + return blockLines; + } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs deleted file mode 100644 index c1396e92b3..0000000000 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingFields.cs +++ /dev/null @@ -1,63 +0,0 @@ -using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Rewriter; -using Rubberduck.Parsing.Symbols; -using Rubberduck.Parsing.VBA; -using Rubberduck.SmartIndenter; -using Rubberduck.VBEditor; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Rubberduck.Refactorings.EncapsulateField.Strategies -{ - //public class EncapsulateWithBackingFields : EncapsulateFieldStrategiesBase - //{ - // public EncapsulateWithBackingFields(QualifiedModuleName qmn, IIndenter indenter, IEncapsulateFieldValidator validator) - // : base(qmn, indenter, validator) { } - - // //protected override void ModifyFields(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) - // //{ - // // foreach (var field in model.SelectedFieldCandidates) - // // { - // // var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); - - // // if (field.Declaration.Accessibility == Accessibility.Private && field.NewFieldName.Equals(field.Declaration.IdentifierName)) - // // { - // // rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); - // // continue; - // // } - - // // if (field.Declaration.IsDeclaredInList()) - // // { - // // RewriterRemoveWorkAround.Remove(field.Declaration, rewriter); - // // //rewriter.Remove(target.Declaration); - // // continue; - // // } - - // // rewriter.Rename(field.Declaration, field.NewFieldName); - // // rewriter.SetVariableVisiblity(field.Declaration, Accessibility.Private.TokenString()); - // // rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); - // // } - // //} - - // //protected override void LoadNewDeclarationBlocks(EncapsulateFieldModel model) - // //{ - // // //New field declarations created here were removed from their list within ModifyFields(...) - // // var fieldsRequiringNewDeclaration = model.SelectedFieldCandidates - // // .Where(field => field.Declaration.IsDeclaredInList() - // // && field.Declaration.Accessibility != Accessibility.Private); - - // // foreach (var field in fieldsRequiringNewDeclaration) - // // { - // // var targetIdentifier = field.Declaration.Context.GetText().Replace(field.IdentifierName, field.NewFieldName); - // // var newField = field.Declaration.IsTypeSpecified - // // ? $"{Tokens.Private} {targetIdentifier}" - // // : $"{Tokens.Private} {targetIdentifier} {Tokens.As} {field.Declaration.AsTypeName}"; - - // // AddCodeBlock(NewContentTypes.DeclarationBlock, newField); - // // } - // //} - //} -} diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs deleted file mode 100644 index 4d7011d29a..0000000000 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulateWithBackingUserDefinedType.cs +++ /dev/null @@ -1,71 +0,0 @@ -using Rubberduck.Parsing.Rewriter; -using Rubberduck.Parsing.Symbols; -using Rubberduck.Parsing.VBA; -using Rubberduck.SmartIndenter; -using Rubberduck.VBEditor; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Rubberduck.Refactorings.EncapsulateField.Strategies -{ - //public interface IEncapsulateWithBackingUserDefinedType : IEncapsulateFieldStrategy - //{ - // //IEncapsulateFieldCandidate StateUDTField { set; get; } - //} - - //public class EncapsulateWithBackingUserDefinedType : EncapsulateFieldStrategiesBase, IEncapsulateWithBackingUserDefinedType - //{ - // public EncapsulateWithBackingUserDefinedType(QualifiedModuleName qmn, IIndenter indenter, IEncapsulateFieldValidator validator) - // : base(qmn, indenter, validator) { } - - // //public IEncapsulateFieldCandidate StateUDTField { set; get; } - - // //protected override IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) - // //{ - // //foreach (var field in model.SelectedFieldCandidates) - // //{ - // // if (field is IEncapsulatedUserDefinedTypeField udt) - // // { - // // udt.PropertyAccessExpression = () => $"{StateUDTField.PropertyAccessExpression()}.{udt.PropertyName}"; - // // udt.ReferenceExpression = udt.PropertyAccessExpression; - - // // foreach (var member in udt.Members) - // // { - // // member.PropertyAccessExpression = () => $"{udt.PropertyAccessExpression()}.{member.PropertyName}"; - // // member.ReferenceExpression = member.PropertyAccessExpression; - // // } - // // continue; - // // } - - // // field.PropertyAccessExpression = () => $"{StateUDTField.PropertyAccessExpression()}.{field.PropertyName}"; - // // field.ReferenceExpression = field.PropertyAccessExpression; - // //} - - // //return base.RefactorRewrite(model, rewriteSession, asPreview); - // //} - - // //protected override void ModifyFields(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) - // //{ - // // foreach (var field in model.SelectedFieldCandidates) - // // { - // // var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); - - // // RewriterRemoveWorkAround.Remove(field.Declaration, rewriter); - // // //rewriter.Remove(target.Declaration); - // // } - // //} - - // //protected override void LoadNewDeclarationBlocks(EncapsulateFieldModel model) - // //{ - // // var udt = new UDTDeclarationGenerator(StateUDTField.AsTypeName); - - // // udt.AddMembers(model.SelectedFieldCandidates); - - // // AddCodeBlock(NewContentTypes.TypeDeclarationBlock, udt.TypeDeclarationBlock(Indenter)); - // // AddCodeBlock(NewContentTypes.DeclarationBlock, udt.FieldDeclarationBlock(StateUDTField.NewFieldName)); - // //} - //} -} diff --git a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs b/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs deleted file mode 100644 index e8d486155d..0000000000 --- a/Rubberduck.Refactorings/EncapsulateField/Strategies/EncapsulationStrategiesBase.cs +++ /dev/null @@ -1,243 +0,0 @@ -using Rubberduck.Parsing; -using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Rewriter; -using Rubberduck.Parsing.Symbols; -using Rubberduck.SmartIndenter; -using Rubberduck.VBEditor; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; - -namespace Rubberduck.Refactorings.EncapsulateField.Strategies -{ - //public interface IEncapsulateFieldStrategy - //{ - // IExecutableRewriteSession GeneratePreview(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession); - // IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession); - // //IEncapsulateFieldCandidate StateUDTField { set; get; } - //} - - //public class EncapsulateFieldStrategiesBase : IEncapsulateFieldStrategy - //{ - // protected enum NewContentTypes { TypeDeclarationBlock, DeclarationBlock, MethodBlock, PostContentMessage }; - - // private IEncapsulateFieldValidator _validator; - // private static string DoubleSpace => $"{Environment.NewLine}{Environment.NewLine}"; - // private Dictionary> _newContent { set; get; } - - // public EncapsulateFieldStrategiesBase(QualifiedModuleName qmn, IIndenter indenter, IEncapsulateFieldValidator validator, IEncapsulateFieldCandidate stateUDT = null) - // { - // TargetQMN = qmn; - // Indenter = indenter; - // _validator = validator; - // StateUDTField = stateUDT; - - // _newContent = new Dictionary> - // { - // { NewContentTypes.PostContentMessage, new List() }, - // { NewContentTypes.DeclarationBlock, new List() }, - // { NewContentTypes.MethodBlock, new List() }, - // { NewContentTypes.TypeDeclarationBlock, new List() } - // }; - // } - - // protected void AddCodeBlock(NewContentTypes contentType, string block) - // => _newContent[contentType].Add(block); - - // protected QualifiedModuleName TargetQMN {private set; get;} - - // protected IIndenter Indenter { private set; get; } - - // private IEncapsulateFieldCandidate StateUDTField { set; get; } - - // public IExecutableRewriteSession GeneratePreview(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) - // { - // if (!model.SelectedFieldCandidates.Any()) { return rewriteSession; } - - // return RefactorRewrite(model, rewriteSession, asPreview: true); - // } - - // public IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) - // { - // if (!model.SelectedFieldCandidates.Any()) { return rewriteSession; } - - // return RefactorRewrite(model, rewriteSession, asPreview: false); - // } - - // protected virtual IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) - // { - // ConfigureSelectedEncapsulationObjects(model); - - // ModifyFields(model, rewriteSession); - - // ModifyReferences(model, rewriteSession); - - // RewriterRemoveWorkAround.RemoveFieldsDeclaredInLists(rewriteSession, TargetQMN); - - // InsertNewContent(model, rewriteSession, asPreview); - - // return rewriteSession; - // } - - // protected void ConfigureSelectedEncapsulationObjects(EncapsulateFieldModel model) - // { - // if (model.EncapsulateWithUDT) - // { - // foreach (var field in model.SelectedFieldCandidates) - // { - // if (field is IEncapsulatedUserDefinedTypeField udt) - // { - // udt.PropertyAccessExpression = () => $"{StateUDTField.PropertyAccessExpression()}.{udt.PropertyName}"; - // udt.ReferenceExpression = udt.PropertyAccessExpression; - - // foreach (var member in udt.Members) - // { - // member.PropertyAccessExpression = () => $"{udt.PropertyAccessExpression()}.{member.PropertyName}"; - // member.ReferenceExpression = member.PropertyAccessExpression; - // } - // continue; - // } - - // field.PropertyAccessExpression = () => $"{StateUDTField.PropertyAccessExpression()}.{field.PropertyName}"; - // field.ReferenceExpression = field.PropertyAccessExpression; - // } - // } - - // foreach (var udtField in model.SelectedUDTFieldCandidates) - // { - // udtField.FieldQualifyMemberPropertyNames = model.SelectedUDTFieldCandidates.Where(f => f.AsTypeName.Equals(udtField.AsTypeName)).Count() > 1; - // } - - // StageReferenceReplacementExpressions(model); - // } - - // protected void ModifyReferences(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) - // { - // foreach (var rewriteReplacement in model.SelectedFieldCandidates.SelectMany(fld => fld.ReferenceReplacements)) - // { - // var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, rewriteReplacement.Key.QualifiedModuleName); - // rewriter.Replace(rewriteReplacement.Value); - // } - // } - - // protected void StageReferenceReplacementExpressions(EncapsulateFieldModel model) - // { - // foreach (var field in model.SelectedFieldCandidates) - // { - // field.LoadReferenceExpressionChanges(); - // } - // } - - // private void ModifyFields(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) - // { - // if (model.EncapsulateWithUDT) - // { - // foreach (var field in model.SelectedFieldCandidates) - // { - // var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); - - // RewriterRemoveWorkAround.Remove(field.Declaration, rewriter); - // //rewriter.Remove(target.Declaration); - // } - // return; - // } - - // foreach (var field in model.SelectedFieldCandidates) - // { - // var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); - - // if (field.Declaration.Accessibility == Accessibility.Private && field.NewFieldName.Equals(field.Declaration.IdentifierName)) - // { - // rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); - // continue; - // } - - // if (field.Declaration.IsDeclaredInList()) - // { - // RewriterRemoveWorkAround.Remove(field.Declaration, rewriter); - // //rewriter.Remove(target.Declaration); - // continue; - // } - - // rewriter.Rename(field.Declaration, field.NewFieldName); - // rewriter.SetVariableVisiblity(field.Declaration, Accessibility.Private.TokenString()); - // rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); - // } - // } - - // protected void InsertNewContent(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool postPendPreviewMessage = false) - // { - // var rewriter = EncapsulateFieldRewriter.CheckoutModuleRewriter(rewriteSession, TargetQMN); - - // LoadNewDeclarationBlocks(model); - - // LoadNewPropertyBlocks(model); - - // if (postPendPreviewMessage) - // { - // _newContent[NewContentTypes.PostContentMessage].Add("'<===== All Changes above this line =====>"); - // } - - // var newContentBlock = string.Join(DoubleSpace, - // (_newContent[NewContentTypes.TypeDeclarationBlock]) - // .Concat(_newContent[NewContentTypes.DeclarationBlock]) - // .Concat(_newContent[NewContentTypes.MethodBlock]) - // .Concat(_newContent[NewContentTypes.PostContentMessage])) - // .Trim(); - - - // if (model.CodeSectionStartIndex.HasValue) - // { - // rewriter.InsertBefore(model.CodeSectionStartIndex.Value, $"{newContentBlock}{DoubleSpace}"); - // } - // else - // { - // rewriter.InsertAtEndOfFile($"{DoubleSpace}{newContentBlock}"); - // } - // } - - // private void LoadNewDeclarationBlocks(EncapsulateFieldModel model) - // { - // if (model.EncapsulateWithUDT) - // { - // var udt = new UDTDeclarationGenerator(StateUDTField.AsTypeName); - - // udt.AddMembers(model.SelectedFieldCandidates); - - // AddCodeBlock(NewContentTypes.TypeDeclarationBlock, udt.TypeDeclarationBlock(Indenter)); - // AddCodeBlock(NewContentTypes.DeclarationBlock, udt.FieldDeclarationBlock(StateUDTField.NewFieldName)); - // return; - // } - - // //New field declarations created here were removed from their list within ModifyFields(...) - // var fieldsRequiringNewDeclaration = model.SelectedFieldCandidates - // .Where(field => field.Declaration.IsDeclaredInList() - // && field.Declaration.Accessibility != Accessibility.Private); - - // foreach (var field in fieldsRequiringNewDeclaration) - // { - // var targetIdentifier = field.Declaration.Context.GetText().Replace(field.IdentifierName, field.NewFieldName); - // var newField = field.Declaration.IsTypeSpecified - // ? $"{Tokens.Private} {targetIdentifier}" - // : $"{Tokens.Private} {targetIdentifier} {Tokens.As} {field.Declaration.AsTypeName}"; - - // AddCodeBlock(NewContentTypes.DeclarationBlock, newField); - // } - // } - - - // private void LoadNewPropertyBlocks(EncapsulateFieldModel model) - // { - // var propertyGenerationSpecs = model.SelectedFieldCandidates - // .SelectMany(f => f.PropertyGenerationSpecs); - - // var generator = new PropertyGenerator(); - // foreach (var spec in propertyGenerationSpecs) - // { - // AddCodeBlock(NewContentTypes.MethodBlock, generator.AsPropertyBlock(spec, Indenter)); - // } - // } - //} -} diff --git a/Rubberduck.Refactorings/EncapsulateField/StringExtensions.cs b/Rubberduck.Refactorings/EncapsulateField/StringExtensions.cs deleted file mode 100644 index b2058ecfe9..0000000000 --- a/Rubberduck.Refactorings/EncapsulateField/StringExtensions.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Rubberduck.Refactorings.EncapsulateField -{ - public static class StringExtensions - { - public static string Capitalize(this string input) - => $"{char.ToUpperInvariant(input[0]) + input.Substring(1, input.Length - 1)}"; - - public static string UnCapitalize(this string input) - => $"{char.ToLowerInvariant(input[0]) + input.Substring(1, input.Length - 1)}"; - - public static bool EqualsVBAIdentifier(this string lhs, string identifier) - => lhs.Equals(identifier, StringComparison.InvariantCultureIgnoreCase); - } -} diff --git a/Rubberduck.Refactorings/EncapsulateField/UDTDeclarationGenerator.cs b/Rubberduck.Refactorings/EncapsulateField/UDTDeclarationGenerator.cs deleted file mode 100644 index 11d3e3064b..0000000000 --- a/Rubberduck.Refactorings/EncapsulateField/UDTDeclarationGenerator.cs +++ /dev/null @@ -1,53 +0,0 @@ -using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Symbols; -using Rubberduck.SmartIndenter; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Rubberduck.Refactorings.EncapsulateField -{ - public class UDTDeclarationGenerator - { - private readonly string _typeIdentifierName; - - private List _members; - - public UDTDeclarationGenerator(string typeIdentifierName) - { - _typeIdentifierName = typeIdentifierName; - _members = new List(); - } - - public void AddMember(IEncapsulateFieldCandidate field) => _members.Add(field); - - public void AddMembers(IEnumerable fields) => _members.AddRange(fields); - - public string FieldDeclarationBlock(string identifierName, Accessibility accessibility = Accessibility.Private) - => $"{accessibility} {identifierName} {Tokens.As} {_typeIdentifierName}"; - - public string TypeDeclarationBlock(IIndenter indenter = null, Accessibility accessibility = Accessibility.Private) - { - if (indenter != null) - { - return string.Join(Environment.NewLine, indenter.Indent(BlockLines(accessibility), true)); - } - return string.Join(Environment.NewLine, BlockLines(accessibility)); - } - - public IEnumerable BlockLines(Accessibility accessibility) - { - var blockLines = new List(); - - blockLines.Add($"{accessibility.TokenString()} {Tokens.Type} {_typeIdentifierName}"); - - _members.ForEach(m => blockLines.Add($"{m.PropertyName} As {m.AsTypeName}")); - - blockLines.Add("End Type"); - - return blockLines; - } - } -} diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeField.cs b/Rubberduck.Refactorings/EncapsulateField/UserDefinedTypeCandidate.cs similarity index 54% rename from Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeField.cs rename to Rubberduck.Refactorings/EncapsulateField/UserDefinedTypeCandidate.cs index c181cabc95..8b1ee68bd8 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeField.cs +++ b/Rubberduck.Refactorings/EncapsulateField/UserDefinedTypeCandidate.cs @@ -1,4 +1,5 @@ -using Rubberduck.Parsing; +using Antlr4.Runtime; +using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using System; @@ -9,29 +10,30 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface IEncapsulatedUserDefinedTypeField : IEncapsulateFieldCandidate + public interface IUserDefinedTypeCandidate : IEncapsulateFieldCandidate { - IEnumerable Members { get; } - void AddMember(IEncapsulatedUserDefinedTypeMember member); - bool FieldQualifyMemberPropertyNames { set; get; } + IEnumerable Members { get; } + void AddMember(IUserDefinedTypeMemberCandidate member); + bool FieldQualifyUDTMemberPropertyName { set; get; } bool TypeDeclarationIsPrivate { set; get; } } - public class EncapsulatedUserDefinedTypeField : EncapsulateFieldCandidate, IEncapsulatedUserDefinedTypeField + public class UserDefinedTypeCandidate : EncapsulateFieldCandidate, IUserDefinedTypeCandidate { - public EncapsulatedUserDefinedTypeField(Declaration declaration, IEncapsulateFieldNamesValidator validator) + public UserDefinedTypeCandidate(Declaration declaration, IEncapsulateFieldNamesValidator validator) : base(declaration, validator) { - PropertyAccessExpression = () => EncapsulateFlag ? NewFieldName : IdentifierName; + PropertyAccessor = AccessorTokens.Field; + ReferenceAccessor = AccessorTokens.Field; } - public void AddMember(IEncapsulatedUserDefinedTypeMember member) + public void AddMember(IUserDefinedTypeMemberCandidate member) { _udtMembers.Add(member); } - private List _udtMembers = new List(); - public IEnumerable Members => _udtMembers; + private List _udtMembers = new List(); + public IEnumerable Members => _udtMembers; public bool TypeDeclarationIsPrivate { set; get; } @@ -41,20 +43,32 @@ public override string NewFieldName set => _fieldAndProperty.Field = value; } - public bool FieldQualifyMemberPropertyNames + public override string ReferenceQualifier + { + set + { + _referenceQualifier = value; + PropertyAccessor = (value?.Length ?? 0) == 0 + ? AccessorTokens.Field + : AccessorTokens.Property; + } + get => _referenceQualifier; + } + + public bool FieldQualifyUDTMemberPropertyName { set { foreach (var member in Members) { - member.FieldQualifyPropertyName = value; + member.FieldQualifyUDTMemberPropertyName = value; } } - get => Members.All(m => m.FieldQualifyPropertyName); + get => Members.All(m => m.FieldQualifyUDTMemberPropertyName); } - public override void LoadReferenceExpressionChanges() + protected override void LoadFieldReferenceContextReplacements() { if (TypeDeclarationIsPrivate) { @@ -62,45 +76,56 @@ public override void LoadReferenceExpressionChanges() LoadUDTMemberReferenceExpressions(); return; } - LoadFieldReferenceExpressions(); + base.LoadFieldReferenceContextReplacements(); } - public override IEnumerable PropertyGenerationSpecs + public override IEnumerable PropertyAttributeSets { get { if (TypeDeclarationIsPrivate) { - var specs = new List(); + var specs = new List(); foreach (var member in Members) { specs.Add(member.AsPropertyGeneratorSpec); } return specs; } - return new List() { AsPropertyGeneratorSpec }; + return new List() { AsPropertyGeneratorSpec }; } } - public override IEnumerable> ReferenceReplacements + public override void SetupReferenceReplacements(IStateUDTField stateUDT = null) + { + + PropertyAccessor = stateUDT is null ? AccessorTokens.Field : AccessorTokens.Property; + ReferenceAccessor = AccessorTokens.Property; + ReferenceQualifier = stateUDT?.NewFieldName ?? null; + LoadFieldReferenceContextReplacements(); + foreach (var member in Members) + { + member.SetupReferenceReplacements(stateUDT); + } + } + + public override IEnumerable> ReferenceReplacements { get { - var results = new List>(); + var results = new List>(); foreach (var replacement in IdentifierReplacements) { - var kv = new KeyValuePair + var kv = new KeyValuePair (replacement.Key, replacement.Value); results.Add(kv); } - foreach (var member in Members) + + foreach (var replacement in Members.SelectMany(m => m.IdentifierReplacements)) { - foreach (var replacement in member.IdentifierReplacements) - { - var kv = new KeyValuePair - (replacement.Key, replacement.Value); - results.Add(kv); - } + var kv = new KeyValuePair + (replacement.Key, replacement.Value); + results.Add(kv); } return results; } @@ -108,7 +133,7 @@ public override IEnumerable(out _)) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeMember.cs b/Rubberduck.Refactorings/EncapsulateField/UserDefinedTypeMemberCandidate.cs similarity index 53% rename from Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeMember.cs rename to Rubberduck.Refactorings/EncapsulateField/UserDefinedTypeMemberCandidate.cs index fe657f4f40..fdac0ea564 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulatedUserDefinedTypeMember.cs +++ b/Rubberduck.Refactorings/EncapsulateField/UserDefinedTypeMemberCandidate.cs @@ -11,30 +11,31 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface IEncapsulatedUserDefinedTypeMember : IEncapsulateFieldCandidate + public interface IUserDefinedTypeMemberCandidate : IEncapsulateFieldCandidate { - IEncapsulatedUserDefinedTypeField Parent { get; } - bool FieldQualifyPropertyName { set; get; } - IPropertyGeneratorSpecification AsPropertyGeneratorSpec { get; } - Dictionary IdentifierReplacements { get; } + IUserDefinedTypeCandidate Parent { get; } + bool FieldQualifyUDTMemberPropertyName { set; get; } + IPropertyGeneratorAttributes AsPropertyGeneratorSpec { get; } + Dictionary IdentifierReplacements { get; } + IEnumerable FieldRelatedReferences(IUserDefinedTypeCandidate field); } - public class EncapsulatedUserDefinedTypeMember : EncapsulateFieldCandidate, IEncapsulatedUserDefinedTypeMember + public class UserDefinedTypeMemberCandidate : EncapsulateFieldCandidate, IUserDefinedTypeMemberCandidate { - public EncapsulatedUserDefinedTypeMember(Declaration target, IEncapsulatedUserDefinedTypeField udtVariable, IEncapsulateFieldNamesValidator validator) + public UserDefinedTypeMemberCandidate(Declaration target, IUserDefinedTypeCandidate udtVariable, IEncapsulateFieldNamesValidator validator) : base(target, validator) { Parent = udtVariable; PropertyName = IdentifierName; - PropertyAccessExpression = () => $"{Parent.PropertyAccessExpression()}.{PropertyName}"; - ReferenceExpression = () => $"{Parent.PropertyAccessExpression()}.{PropertyName}"; + PropertyAccessor = AccessorTokens.Property; + ReferenceAccessor = AccessorTokens.Property; } - public IEncapsulatedUserDefinedTypeField Parent { private set; get; } + public IUserDefinedTypeCandidate Parent { private set; get; } private bool _fieldNameQualifyProperty; - public bool FieldQualifyPropertyName + public bool FieldQualifyUDTMemberPropertyName { get => _fieldNameQualifyProperty; set @@ -46,10 +47,18 @@ public bool FieldQualifyPropertyName } } + public override void SetupReferenceReplacements(IStateUDTField stateUDT = null) { } + + public override string ReferenceQualifier + { + set => _referenceQualifier = value; + get => Parent.ReferenceWithinNewProperty; + } + public override string TargetID => $"{Parent.IdentifierName}.{IdentifierName}"; - public override IEnumerable References - => GetUDTMemberReferencesForField(this, Parent); + public IEnumerable FieldRelatedReferences(IUserDefinedTypeCandidate field) + => GetUDTMemberReferencesForField(this, field); public override void SetReferenceRewriteContent(IdentifierReference idRef, string replacementText) { @@ -57,19 +66,39 @@ public override void SetReferenceRewriteContent(IdentifierReference idRef, strin if (IdentifierReplacements.ContainsKey(idRef)) { - IdentifierReplacements[idRef] = new RewriteReplacePair(replacementText, idRef.Context.Parent as ParserRuleContext); + //IdentifierReplacements[idRef] = new RewriteReplacePair(replacementText, idRef.Context.Parent as ParserRuleContext); + IdentifierReplacements[idRef] = (idRef.Context.Parent as ParserRuleContext, replacementText); return; } - IdentifierReplacements.Add(idRef, new RewriteReplacePair(replacementText, idRef.Context.Parent as ParserRuleContext)); + //IdentifierReplacements.Add(idRef, new RewriteReplacePair(replacementText, idRef.Context.Parent as ParserRuleContext)); + IdentifierReplacements.Add(idRef, (idRef.Context.Parent as ParserRuleContext, replacementText)); } - public new IPropertyGeneratorSpecification AsPropertyGeneratorSpec - => base.AsPropertyGeneratorSpec; + public new IPropertyGeneratorAttributes AsPropertyGeneratorSpec + { + get + { + if (_fieldNameQualifyProperty) + { + PropertyAccessor = AccessorTokens.Field; + } - public new Dictionary IdentifierReplacements { get; } = new Dictionary(); + return new PropertyGeneratorSpecification() + { + PropertyName = PropertyName, + BackingField = ReferenceWithinNewProperty, + AsTypeName = AsTypeName, + ParameterName = ParameterName, + GenerateLetter = ImplementLetSetterType, + GenerateSetter = ImplementSetSetterType, + UsesSetAssignment = Declaration.IsObject + }; + } + } + public new Dictionary IdentifierReplacements { get; } = new Dictionary(); - private IEnumerable GetUDTMemberReferencesForField(IEncapsulateFieldCandidate udtMember, IEncapsulatedUserDefinedTypeField field) + private IEnumerable GetUDTMemberReferencesForField(IEncapsulateFieldCandidate udtMember, IUserDefinedTypeCandidate field) { var refs = new List(); foreach (var idRef in udtMember.Declaration.References) diff --git a/Rubberduck.Refactorings/Rubberduck.Refactorings.csproj b/Rubberduck.Refactorings/Rubberduck.Refactorings.csproj index 077a3e0f68..b603ae5502 100644 --- a/Rubberduck.Refactorings/Rubberduck.Refactorings.csproj +++ b/Rubberduck.Refactorings/Rubberduck.Refactorings.csproj @@ -23,4 +23,7 @@ 4.6.4 + + + \ No newline at end of file diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs index 0f49e662a2..7710e39a5f 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs @@ -238,8 +238,8 @@ Public that As TBar validator.RegisterFieldCandidate(thisField); validator.RegisterFieldCandidate(thatField); - - Assert.Less(0, validator.HasNewPropertyNameConflicts(thisField, thisField.QualifiedModuleName, Enumerable.Empty())); + Assert.IsTrue(validator.HasConflictingPropertyIdentifier(thisField)); + //Assert.Less(0, validator.HasNewPropertyNameConflicts(thisField, thisField.QualifiedModuleName, Enumerable.Empty())); } } [Test] @@ -271,7 +271,8 @@ void ThisTest(IDeclarationFinderProvider declarationProviderProvider) fields.Add(new EncapsulateFieldCandidate(longValue, validator)); encapsulatedWholeNumber.PropertyName = "LongValue"; - Assert.Less(0, validator.HasNewPropertyNameConflicts(encapsulatedWholeNumber, encapsulatedWholeNumber.QualifiedModuleName, new Declaration[] { encapsulatedWholeNumber.Declaration })); + Assert.IsTrue(validator.HasConflictingPropertyIdentifier(encapsulatedWholeNumber)); + //Assert.Less(0, validator.HasNewPropertyNameConflicts(encapsulatedWholeNumber, encapsulatedWholeNumber.QualifiedModuleName, new Declaration[] { encapsulatedWholeNumber.Declaration })); } } diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs index 299c93ac28..1ae41c28a1 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs @@ -7,6 +7,7 @@ using System.Linq; using Rubberduck.Parsing.Symbols; using System.Collections.Generic; +using Rubberduck.VBEditor; namespace RubberduckTests.Refactoring.EncapsulateField { @@ -87,10 +88,13 @@ public void CreateUDT() mock.SetupGet(m => m.AsTypeName).Returns("String"); mock.SetupGet(m => m.PropertyName).Returns("Fizz"); - var newUserDefinedType = new UDTDeclarationGenerator("This_Type"); - newUserDefinedType.AddMember(mock.Object); + var stateUDT = new StateUDTField("this", "This_Type", new QualifiedModuleName(), null) as IStateUDTField; + //var newUserDefinedType = new UDTDeclarationGenerator("This_Type"); + stateUDT.AddMembers(new IEncapsulateFieldCandidate[] { mock.Object }); - var result = newUserDefinedType.TypeDeclarationBlock(); + + //var result = newUserDefinedType.TypeDeclarationBlock(); + var result = stateUDT.TypeDeclarationBlock(); StringAssert.Contains("Private Type This_Type", result); StringAssert.Contains("Fizz As String", result); StringAssert.Contains("End Type", result); diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index 13ec0fdbde..60f4e5b093 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -339,6 +339,31 @@ End Property Assert.AreEqual(expectedCode.Trim(), actualCode); } + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulatePrivateFieldInList() + { + const string inputCode = + @"Private fi|zz As Integer, fuzz As Integer, fazz As Integer"; + + const string expectedCode = + @" +Private fizz_1 As Integer, fuzz As Integer, fazz As Integer + +Public Property Get Fizz() As Integer + Fizz = fizz_1 +End Property + +Public Property Let Fizz(ByVal value As Integer) + fizz_1 = value +End Property +"; + var presenterAction = Support.SetParametersForSingleTarget("fizz"); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + Assert.AreEqual(expectedCode.Trim(), actualCode); + } + [Test] [Category("Refactorings")] [Category("Encapsulate Field")] From 562acb90f257ba51b0078c0ab14dbb1702955bcd Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Wed, 11 Dec 2019 17:09:33 -0800 Subject: [PATCH 052/461] More name changes and file changes --- .../EncapsulateFieldViewModel.cs | 8 +- .../ViewableEncapsulatedField.cs | 2 +- ...y.cs => EncapsulateFieldElementFactory.cs} | 46 +++++---- .../EncapsulateField/EncapsulateFieldModel.cs | 4 +- .../EncapsulateFieldRefactoring.cs | 32 +++---- .../EncapsulateFieldValidator.cs | 27 +++++- .../EncapsulateFieldCandidate.cs | 29 +++--- .../EncapsulationIdentifiers.cs | 21 +---- .../UserDefinedTypeCandidate.cs | 14 +-- .../UserDefinedTypeMemberCandidate.cs | 6 +- .../EncapsulateField/PropertyGenerator.cs | 19 +--- .../EncapsulateField/StateUDT.cs | 76 +++++++++++++++ .../EncapsulateField/StateUDTField.cs | 93 ------------------- .../Rubberduck.Refactorings.csproj | 3 - .../EncapsulateFieldValidatorTests.cs | 6 +- .../EncapsulateUsingStateUDTTests.cs | 16 +++- .../EncapsulatedFieldTests.cs | 14 +-- .../EncapsulateField/TestSupport.cs | 9 +- .../Refactoring/EncapsulateFieldTests.cs | 2 +- 19 files changed, 209 insertions(+), 218 deletions(-) rename Rubberduck.Refactorings/EncapsulateField/{EncapsulateFieldDeclarationFactory.cs => EncapsulateFieldElementFactory.cs} (74%) rename Rubberduck.Refactorings/EncapsulateField/{ => FieldCandidates}/EncapsulateFieldCandidate.cs (92%) rename Rubberduck.Refactorings/EncapsulateField/{ => FieldCandidates}/EncapsulationIdentifiers.cs (77%) rename Rubberduck.Refactorings/EncapsulateField/{ => FieldCandidates}/UserDefinedTypeCandidate.cs (92%) rename Rubberduck.Refactorings/EncapsulateField/{ => FieldCandidates}/UserDefinedTypeMemberCandidate.cs (93%) create mode 100644 Rubberduck.Refactorings/EncapsulateField/StateUDT.cs delete mode 100644 Rubberduck.Refactorings/EncapsulateField/StateUDTField.cs diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs index f73a81f18f..34f2425095 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs @@ -68,7 +68,7 @@ public string EncapsulateAsUDT_TypeIdentifier { if (Model.EncapsulateWithUDT) { - return Model.StateUDTField.AsTypeName; + return Model.StateUDTField.TypeIdentifier; } return string.Empty; } @@ -76,7 +76,7 @@ public string EncapsulateAsUDT_TypeIdentifier { if (Model.EncapsulateWithUDT) { - Model.StateUDTField.AsTypeName = value; + Model.StateUDTField.TypeIdentifier = value; } UpdatePreview(); } @@ -88,7 +88,7 @@ public string EncapsulateAsUDT_FieldName { if (Model.EncapsulateWithUDT) { - return Model.StateUDTField.NewFieldName; + return Model.StateUDTField.FieldIdentifier; } return string.Empty; } @@ -96,7 +96,7 @@ public string EncapsulateAsUDT_FieldName { if (Model.EncapsulateWithUDT) { - Model.StateUDTField.NewFieldName = value; + Model.StateUDTField.FieldIdentifier = value; } UpdatePreview(); } diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs index 55196b6965..5ce7ba092a 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs @@ -41,7 +41,7 @@ public ViewableEncapsulatedField(IEncapsulateFieldCandidate efd) public string PropertyName { get => _efd.PropertyName; set => _efd.PropertyName = value; } public bool IsEditableReadWriteFieldIdentifier { get => !(_efd is IUserDefinedTypeMemberCandidate); }// .IsUDTMember; } // set => _efd.IsEditableReadWriteFieldIdentifier = value; } public bool EncapsulateFlag { get => _efd.EncapsulateFlag; set => _efd.EncapsulateFlag = value; } - public string NewFieldName { get => _efd.NewFieldName; }// set => _efd.NewFieldName = value; } + public string NewFieldName { get => _efd.FieldIdentifier; }// set => _efd.NewFieldName = value; } //TODO: Change name of AsTypeName property to FieldDescriptor(?) -> and does it belong on IEncapsulatedField? public string AsTypeName { diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs similarity index 74% rename from Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs rename to Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs index cd57041928..931cb6c086 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldDeclarationFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs @@ -12,30 +12,27 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public class EncapsulationCandidateFactory + public class EncapsulateFieldElementFactory { - private const string DEFAULT_STATE_UDT_IDENTIFIER = "This_Type"; - private const string DEFAULT_STATE_UDT_FIELD_IDENTIFIER = "this"; - private readonly IDeclarationFinderProvider _declarationFinderProvider; private readonly IEncapsulateFieldNamesValidator _validator; private QualifiedModuleName _targetQMN; - public EncapsulationCandidateFactory(IDeclarationFinderProvider declarationFinderProvider, QualifiedModuleName targetQMN, IEncapsulateFieldNamesValidator validator) + public EncapsulateFieldElementFactory(IDeclarationFinderProvider declarationFinderProvider, QualifiedModuleName targetQMN, IEncapsulateFieldNamesValidator validator) { _declarationFinderProvider = declarationFinderProvider; _validator = validator; _targetQMN = targetQMN; } - public IEncapsulateFieldCandidate CreateStateUDTField(string identifier = DEFAULT_STATE_UDT_FIELD_IDENTIFIER, string asTypeName = DEFAULT_STATE_UDT_IDENTIFIER) + public IStateUDT CreateStateUDTField() { - var stateUDT = new StateUDTField(identifier, asTypeName, _targetQMN, _validator); - _validator.RegisterFieldCandidate(stateUDT); + var stateUDT = new StateUDT(_targetQMN, _validator) as IStateUDT; + + stateUDT = SetNonConflictIdentifier(stateUDT, c => { return _validator.IsConflictingStateUDTFieldIdentifier(stateUDT); }, (s) => { stateUDT.FieldIdentifier = s; }, () => stateUDT.FieldIdentifier, _validator); - stateUDT = SetNonConflictIdentifier(stateUDT, c => { return _validator.HasConflictingFieldIdentifier(stateUDT); }, (s) => { stateUDT.NewFieldName = s; }, () => stateUDT.IdentifierName, _validator); + stateUDT = SetNonConflictIdentifier(stateUDT, c => { return _validator.IsConflictingStateUDTTypeIdentifier(stateUDT); }, (s) => { stateUDT.TypeIdentifier = s; }, () => stateUDT.TypeIdentifier, _validator); - stateUDT = SetNonConflictIdentifier(stateUDT, c => { return _validator.IsConflictingStateUDTIdentifier(stateUDT); }, (s) => { stateUDT.AsTypeName = s; }, () => stateUDT.AsTypeName, _validator); return stateUDT; } @@ -50,14 +47,14 @@ public IEncapsulateFieldCandidate CreateEncapsulationCandidate(Declaration targe _validator.RegisterFieldCandidate(candidate); candidate = ApplyTypeSpecificAttributes(candidate); - candidate = SetNonConflictIdentifier(candidate, c => { return _validator.HasConflictingPropertyIdentifier(candidate); }, (s) => { candidate.PropertyName = s; }, () => candidate.IdentifierName, _validator); + candidate = SetNonConflictIdentifier(candidate, c => { return _validator.HasConflictingPropertyIdentifier(candidate); }, (s) => { candidate.PropertyName = s; }, () => candidate.IdentifierName, _validator); if (candidate is IUserDefinedTypeCandidate udtVariable) { - (Declaration udt, IEnumerable udtMembers) = GetUDTAndMembersForField(udtVariable); + (Declaration udtDeclaration, IEnumerable udtMembers) = GetUDTAndMembersForField(udtVariable); - udtVariable.TypeDeclarationIsPrivate = udt.Accessibility == Accessibility.Private; + udtVariable.TypeDeclarationIsPrivate = udtDeclaration.HasPrivateAccessibility(); foreach (var udtMember in udtMembers) { @@ -101,11 +98,26 @@ private T SetNonConflictIdentifier(T candidate, Predicate conflictDetector return candidate; } + private IStateUDT SetNonConflictIdentifier(IStateUDT candidate, Predicate conflictDetector, Action setValue, Func getIdentifier, IEncapsulateFieldNamesValidator validator) + { + var isConflictingIdentifier = conflictDetector(candidate); + for (var count = 1; count < 10 && isConflictingIdentifier; count++) + { + setValue(getIdentifier().IncrementIdentifier()); + isConflictingIdentifier = conflictDetector(candidate); + } + return candidate; + } + private T ApplyTypeSpecificAttributes(T candidate) where T: IEncapsulateFieldCandidate { - var target = candidate.Declaration; + //Default values are + //candidate.ImplementLetSetterType = true; + //candidate.ImplementSetSetterType = false; + //candidate.CanBeReadWrite = true; + //candidate.IsReadOnly = false; - if (target.IsArray) + if (candidate.Declaration.IsArray) { candidate.ImplementLetSetterType = false; candidate.ImplementSetSetterType = false; @@ -113,12 +125,12 @@ private T ApplyTypeSpecificAttributes(T candidate) where T: IEncapsulateField candidate.CanBeReadWrite = false; candidate.IsReadOnly = true; } - else if (target.AsTypeName.Equals(Tokens.Variant)) + else if (candidate.Declaration.AsTypeName.Equals(Tokens.Variant)) { candidate.ImplementLetSetterType = true; candidate.ImplementSetSetterType = true; } - else if (target.IsObject) + else if (candidate.Declaration.IsObject) { candidate.ImplementLetSetterType = false; candidate.ImplementSetSetterType = true; diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index c1b7e512fd..cb3089917f 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -20,7 +20,7 @@ public class EncapsulateFieldModel : IRefactoringModel private IDictionary)> _udtFieldToUdtDeclarationMap = new Dictionary)>(); - public EncapsulateFieldModel(Declaration target, IEnumerable candidates, IEncapsulateFieldCandidate stateUDTField, Func previewDelegate) + public EncapsulateFieldModel(Declaration target, IEnumerable candidates, IStateUDT stateUDTField, Func previewDelegate) { _previewDelegate = previewDelegate; _targetQMN = target.QualifiedModuleName; @@ -58,7 +58,7 @@ public IEncapsulateFieldCandidate this[Declaration fieldDeclaration] public bool EncapsulateWithUDT { set; get; } - public IEncapsulateFieldCandidate StateUDTField { set; get; } + public IStateUDT StateUDTField { set; get; } public string PreviewRefactoring() => _previewDelegate(this); } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 556092a66a..8f8a50edb6 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -28,7 +28,7 @@ public class EncapsulateFieldRefactoring : InteractiveRefactoringBase Model.EncapsulateWithUDT ? Model.StateUDTField : null; @@ -162,7 +162,7 @@ private IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, I foreach (var udtField in model.SelectedUDTFieldCandidates) { - udtField.FieldQualifyUDTMemberPropertyName = model.HasSelectedMultipleUDTFieldsOfType(udtField.AsTypeName); + udtField.FieldQualifyUDTMemberPropertyNames = model.HasSelectedMultipleUDTFieldsOfType(udtField.AsTypeName); } ModifyFields(model, rewriteSession); @@ -179,15 +179,15 @@ private IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, I private void ModifyReferences(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) { var stateUDT = model.EncapsulateWithUDT - ? model.StateUDTField as IStateUDTField + ? model.StateUDTField : null; - foreach (var field in model.EncapsulationCandidates) + foreach (var field in model.SelectedFieldCandidates) { - field.SetupReferenceReplacements(stateUDT); + field.StageFieldReferenceReplacements(stateUDT); } - foreach (var rewriteReplacement in model.SelectedFieldCandidates.SelectMany(fld => fld.ReferenceReplacements)) + foreach (var rewriteReplacement in model.SelectedFieldCandidates.SelectMany(field => field.ReferenceReplacements)) { (ParserRuleContext Context, string Text) = rewriteReplacement.Value; var rewriter = rewriteSession.CheckOutModuleRewriter(rewriteReplacement.Key.QualifiedModuleName); @@ -212,7 +212,7 @@ private void ModifyFields(EncapsulateFieldModel model, IExecutableRewriteSession { var rewriter = rewriteSession.CheckOutModuleRewriter(_targetQMN); - if (field.Declaration.Accessibility == Accessibility.Private && field.NewFieldName.Equals(field.Declaration.IdentifierName)) + if (field.Declaration.HasPrivateAccessibility() && field.FieldIdentifier.Equals(field.Declaration.IdentifierName)) { rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); continue; @@ -225,7 +225,7 @@ private void ModifyFields(EncapsulateFieldModel model, IExecutableRewriteSession continue; } - rewriter.Rename(field.Declaration, field.NewFieldName); + rewriter.Rename(field.Declaration, field.FieldIdentifier); rewriter.SetVariableVisiblity(field.Declaration, Accessibility.Private.TokenString()); rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); } @@ -266,11 +266,11 @@ private void LoadNewDeclarationBlocks(EncapsulateFieldModel model) { if (model.EncapsulateWithUDT) { - var stateUDT = StateUDTField as IStateUDTField; + var stateUDT = StateUDTField as IStateUDT; stateUDT.AddMembers(model.SelectedFieldCandidates); - AddCodeBlock(NewContentTypes.TypeDeclarationBlock, stateUDT.TypeDeclarationBlock(_indenter)); // udt.TypeDeclarationBlock(_indenter)); - AddCodeBlock(NewContentTypes.DeclarationBlock, stateUDT.FieldDeclarationBlock); // udt.FieldDeclarationBlock(StateUDTField.NewFieldName)); + AddCodeBlock(NewContentTypes.TypeDeclarationBlock, stateUDT.TypeDeclarationBlock(_indenter)); + AddCodeBlock(NewContentTypes.DeclarationBlock, stateUDT.FieldDeclarationBlock); return; } @@ -281,7 +281,7 @@ private void LoadNewDeclarationBlocks(EncapsulateFieldModel model) foreach (var field in fieldsRequiringNewDeclaration) { - var targetIdentifier = field.Declaration.Context.GetText().Replace(field.IdentifierName, field.NewFieldName); + var targetIdentifier = field.Declaration.Context.GetText().Replace(field.IdentifierName, field.FieldIdentifier); var newField = field.Declaration.IsTypeSpecified ? $"{Tokens.Private} {targetIdentifier}" : $"{Tokens.Private} {targetIdentifier} {Tokens.As} {field.Declaration.AsTypeName}"; diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs index a809eb174f..8371cec041 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -27,6 +27,8 @@ public interface IEncapsulateFieldNamesValidator : IEncapsulateFieldValidator { //bool HasIdentifierConflicts(string identifier, DeclarationType declarationType); bool IsConflictingStateUDTIdentifier(IUserDefinedTypeCandidate candidate); + bool IsConflictingStateUDTTypeIdentifier(IStateUDT stateUDT); + bool IsConflictingStateUDTFieldIdentifier(IStateUDT stateUDT); } public class EncapsulateFieldNamesValidator : IEncapsulateFieldNamesValidator @@ -59,7 +61,7 @@ public bool HasConflictingPropertyIdentifier(IEncapsulateFieldCandidate candidat .Where(d => d != candidate.Declaration); var edits = FieldCandidates.Where(fc => fc.EncapsulateFlag && fc.Declaration != candidate.Declaration).Select(fc => fc.PropertyName); - edits = edits.Concat(FieldCandidates.Where(fc => fc.EncapsulateFlag && fc.Declaration != candidate.Declaration).Select(fc => fc.NewFieldName)); + edits = edits.Concat(FieldCandidates.Where(fc => fc.EncapsulateFlag && fc.Declaration != candidate.Declaration).Select(fc => fc.FieldIdentifier)); return members.Any(m => m.IdentifierName.EqualsVBAIdentifier(candidate.PropertyName)) @@ -71,7 +73,7 @@ public bool HasConflictingFieldIdentifier(IEncapsulateFieldCandidate candidate) var members = _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) .Where(d => d != candidate.Declaration); - return members.Any(m => m.IdentifierName.EqualsVBAIdentifier(candidate.NewFieldName)); + return members.Any(m => m.IdentifierName.EqualsVBAIdentifier(candidate.FieldIdentifier)); } public bool IsConflictingFieldIdentifier(string fieldName, IEncapsulateFieldCandidate candidate) @@ -82,6 +84,21 @@ public bool IsConflictingFieldIdentifier(string fieldName, IEncapsulateFieldCand return members.Any(m => m.IdentifierName.EqualsVBAIdentifier(fieldName) || candidate.PropertyName.EqualsVBAIdentifier(fieldName)); } + public bool IsConflictingStateUDTTypeIdentifier(IStateUDT stateUDT) + { + var members = _declarationFinderProvider.DeclarationFinder.Members(stateUDT.QualifiedModuleName); + + return members.Any(m => m.IdentifierName.EqualsVBAIdentifier(stateUDT.TypeIdentifier)); + } + + public bool IsConflictingStateUDTFieldIdentifier(IStateUDT stateUDT) + { + var members = _declarationFinderProvider.DeclarationFinder.Members(stateUDT.QualifiedModuleName); + + return members.Any(m => m.IdentifierName.EqualsVBAIdentifier(stateUDT.FieldIdentifier)); + } + + public bool IsConflictingStateUDTIdentifier(IUserDefinedTypeCandidate candidate) { var members = _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName); @@ -158,16 +175,16 @@ private bool UsesScopeResolution(Antlr4.Runtime.RuleContext ruleContext) private bool HasValidIdentifiers(IEncapsulateFieldCandidate attributes, DeclarationType declarationType) { - return VBAIdentifierValidator.IsValidIdentifier(attributes.NewFieldName, declarationType) + return VBAIdentifierValidator.IsValidIdentifier(attributes.FieldIdentifier, declarationType) && VBAIdentifierValidator.IsValidIdentifier(attributes.PropertyName, DeclarationType.Property) && VBAIdentifierValidator.IsValidIdentifier(attributes.ParameterName, DeclarationType.Parameter); } private bool HasInternalNameConflicts(IEncapsulateFieldCandidate attributes) { - return attributes.PropertyName.EqualsVBAIdentifier(attributes.NewFieldName) + return attributes.PropertyName.EqualsVBAIdentifier(attributes.FieldIdentifier) || attributes.PropertyName.EqualsVBAIdentifier(attributes.ParameterName) - || attributes.NewFieldName.EqualsVBAIdentifier(attributes.ParameterName); + || attributes.FieldIdentifier.EqualsVBAIdentifier(attributes.ParameterName); } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs similarity index 92% rename from Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldCandidate.cs rename to Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs index 4fde4cbc20..daa9c2199a 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs @@ -19,9 +19,8 @@ public interface IEncapsulateFieldCandidate string TargetID { get; } bool IsReadOnly { get; set; } bool EncapsulateFlag { get; set; } - string NewFieldName { set; get; } + string FieldIdentifier { set; get; } bool CanBeReadWrite { set; get; } - //bool IsUDTMember { get; } bool HasValidEncapsulationAttributes { get; } QualifiedModuleName QualifiedModuleName { get; } string PropertyName { get; set; } @@ -34,7 +33,7 @@ public interface IEncapsulateFieldCandidate void SetReferenceRewriteContent(IdentifierReference idRef, string replacementText); string ReferenceQualifier { set; get; } string ReferenceWithinNewProperty { get; } - void SetupReferenceReplacements(IStateUDTField stateUDT = null); + void StageFieldReferenceReplacements(IStateUDT stateUDT = null); } public enum AccessorTokens { Field, Property } @@ -82,11 +81,11 @@ public EncapsulateFieldCandidate(string identifier, string asTypeName, Qualified CanBeReadWrite = true; } - public virtual void SetupReferenceReplacements(IStateUDTField stateUDT = null) + public virtual void StageFieldReferenceReplacements(IStateUDT stateUDT = null) { PropertyAccessor = stateUDT is null ? AccessorTokens.Field : AccessorTokens.Property; ReferenceAccessor = AccessorTokens.Property; - ReferenceQualifier = stateUDT?.NewFieldName ?? null; + ReferenceQualifier = stateUDT?.FieldIdentifier ?? null; LoadFieldReferenceContextReplacements(); } @@ -94,17 +93,16 @@ public virtual void SetupReferenceReplacements(IStateUDTField stateUDT = null) public Declaration Declaration => _target; - public bool HasVBACompliantPropertyIdentifier => _validator.IsValidVBAIdentifier(PropertyName, DeclarationType.Property); - public bool HasVBACompliantFieldIdentifier => _validator.IsValidVBAIdentifier(NewFieldName, Declaration?.DeclarationType ?? DeclarationType.Variable); + public bool HasVBACompliantFieldIdentifier => _validator.IsValidVBAIdentifier(FieldIdentifier, Declaration?.DeclarationType ?? DeclarationType.Variable); - public bool HasVBACompliantParameterIdentifier => _validator.IsValidVBAIdentifier(NewFieldName, Declaration?.DeclarationType ?? DeclarationType.Variable); + public bool HasVBACompliantParameterIdentifier => _validator.IsValidVBAIdentifier(FieldIdentifier, Declaration?.DeclarationType ?? DeclarationType.Variable); public virtual bool IsSelfConsistent => _validator.IsValidVBAIdentifier(PropertyName, DeclarationType.Property) - && !(PropertyName.EqualsVBAIdentifier(NewFieldName) + && !(PropertyName.EqualsVBAIdentifier(FieldIdentifier) || PropertyName.EqualsVBAIdentifier(ParameterName) - || NewFieldName.EqualsVBAIdentifier(ParameterName)); + || FieldIdentifier.EqualsVBAIdentifier(ParameterName)); public bool HasConflictingPropertyIdentifier => _validator.HasConflictingPropertyIdentifier(this); @@ -154,7 +152,7 @@ public virtual void SetReferenceRewriteContent(IdentifierReference idRef, string public bool IsReadOnly { set; get; } public bool CanBeReadWrite { set; get; } - public virtual string NewFieldName + public virtual string FieldIdentifier { get => _fieldAndProperty.Field; set => _fieldAndProperty.Field = value; @@ -188,7 +186,7 @@ private void TryRestoreNewFieldNameAsOriginalFieldIdentifierName() var isConflictingFieldIdentifier = _validator.HasConflictingFieldIdentifier(this); for (var count = 1; count < 10 && isConflictingFieldIdentifier; count++) { - NewFieldName = NewFieldName.IncrementIdentifier(); + FieldIdentifier = FieldIdentifier.IncrementIdentifier(); isConflictingFieldIdentifier = _validator.HasConflictingFieldIdentifier(this); } } @@ -234,14 +232,13 @@ protected string AccessorTokenToContent(AccessorTokens token) switch (token) { case AccessorTokens.Field: - accessor = NewFieldName; + accessor = FieldIdentifier; break; case AccessorTokens.Property: accessor = PropertyName; break; default: - accessor = NewFieldName; - break; + throw new ArgumentException(); } if ((ReferenceQualifier?.Length ?? 0) > 0) @@ -258,7 +255,7 @@ protected virtual IPropertyGeneratorAttributes AsPropertyGeneratorSpec { get { - return new PropertyGeneratorSpecification() + return new PropertyAttributeSet() { PropertyName = PropertyName, BackingField = ReferenceWithinNewProperty, diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationIdentifiers.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs similarity index 77% rename from Rubberduck.Refactorings/EncapsulateField/EncapsulationIdentifiers.cs rename to Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs index 42f98a4c2d..ff99ad886b 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationIdentifiers.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs @@ -26,21 +26,6 @@ public EncapsulationIdentifiers(string field) _setLetParameter = DEFAULT_WRITE_PARAMETER; } - //public static string IncrementIdentifier(string identifier) - //{ - // var fragments = identifier.Split('_'); - // if (fragments.Length == 1) { return $"{identifier}_1"; } - - // var lastFragment = fragments[fragments.Length - 1]; - // if (long.TryParse(lastFragment, out var number)) - // { - // fragments[fragments.Length - 1] = (number + 1).ToString(); - - // return string.Join("_", fragments); - // } - // return $"{identifier}_1"; ; - //} - public string TargetFieldName => _targetIdentifier; public string DefaultNewFieldName { private set; get; } @@ -51,7 +36,7 @@ public string Field set { _fieldAndProperty = new KeyValuePair(value, _fieldAndProperty.Value); - GenerateNonConflictParameterName(); + SetNonConflictParameterName(); } } @@ -66,13 +51,13 @@ public string Property _fieldAndProperty = new KeyValuePair(_fieldAndProperty.Key, value); - GenerateNonConflictParameterName(); + SetNonConflictParameterName(); } } public string SetLetParameter => _setLetParameter; - private void GenerateNonConflictParameterName() + private void SetNonConflictParameterName() { _setLetParameter = DEFAULT_WRITE_PARAMETER; diff --git a/Rubberduck.Refactorings/EncapsulateField/UserDefinedTypeCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs similarity index 92% rename from Rubberduck.Refactorings/EncapsulateField/UserDefinedTypeCandidate.cs rename to Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs index 8b1ee68bd8..595fa990e6 100644 --- a/Rubberduck.Refactorings/EncapsulateField/UserDefinedTypeCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs @@ -14,7 +14,7 @@ public interface IUserDefinedTypeCandidate : IEncapsulateFieldCandidate { IEnumerable Members { get; } void AddMember(IUserDefinedTypeMemberCandidate member); - bool FieldQualifyUDTMemberPropertyName { set; get; } + bool FieldQualifyUDTMemberPropertyNames { set; get; } bool TypeDeclarationIsPrivate { set; get; } } @@ -37,7 +37,7 @@ public void AddMember(IUserDefinedTypeMemberCandidate member) public bool TypeDeclarationIsPrivate { set; get; } - public override string NewFieldName + public override string FieldIdentifier { get => TypeDeclarationIsPrivate ? _fieldAndProperty.TargetFieldName : _fieldAndProperty.Field; set => _fieldAndProperty.Field = value; @@ -55,7 +55,7 @@ public override string ReferenceQualifier get => _referenceQualifier; } - public bool FieldQualifyUDTMemberPropertyName + public bool FieldQualifyUDTMemberPropertyNames { set { @@ -96,16 +96,16 @@ public override IEnumerable PropertyAttributeSets } } - public override void SetupReferenceReplacements(IStateUDTField stateUDT = null) + public override void StageFieldReferenceReplacements(IStateUDT stateUDT = null) { PropertyAccessor = stateUDT is null ? AccessorTokens.Field : AccessorTokens.Property; ReferenceAccessor = AccessorTokens.Property; - ReferenceQualifier = stateUDT?.NewFieldName ?? null; + ReferenceQualifier = stateUDT?.FieldIdentifier ?? null; LoadFieldReferenceContextReplacements(); foreach (var member in Members) { - member.SetupReferenceReplacements(stateUDT); + member.StageFieldReferenceReplacements(stateUDT); } } @@ -138,7 +138,7 @@ private void LoadPrivateUDTFieldReferenceExpressions() if (idRef.QualifiedModuleName == QualifiedModuleName && idRef.Context.Parent.Parent is VBAParser.WithStmtContext wsc) { - SetReferenceRewriteContent(idRef, NewFieldName); + SetReferenceRewriteContent(idRef, FieldIdentifier); } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/UserDefinedTypeMemberCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs similarity index 93% rename from Rubberduck.Refactorings/EncapsulateField/UserDefinedTypeMemberCandidate.cs rename to Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs index fdac0ea564..6b5a178823 100644 --- a/Rubberduck.Refactorings/EncapsulateField/UserDefinedTypeMemberCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs @@ -47,7 +47,7 @@ public bool FieldQualifyUDTMemberPropertyName } } - public override void SetupReferenceReplacements(IStateUDTField stateUDT = null) { } + public override void StageFieldReferenceReplacements(IStateUDT stateUDT = null) { } public override string ReferenceQualifier { @@ -66,11 +66,9 @@ public override void SetReferenceRewriteContent(IdentifierReference idRef, strin if (IdentifierReplacements.ContainsKey(idRef)) { - //IdentifierReplacements[idRef] = new RewriteReplacePair(replacementText, idRef.Context.Parent as ParserRuleContext); IdentifierReplacements[idRef] = (idRef.Context.Parent as ParserRuleContext, replacementText); return; } - //IdentifierReplacements.Add(idRef, new RewriteReplacePair(replacementText, idRef.Context.Parent as ParserRuleContext)); IdentifierReplacements.Add(idRef, (idRef.Context.Parent as ParserRuleContext, replacementText)); } @@ -83,7 +81,7 @@ public override void SetReferenceRewriteContent(IdentifierReference idRef, strin PropertyAccessor = AccessorTokens.Field; } - return new PropertyGeneratorSpecification() + return new PropertyAttributeSet() { PropertyName = PropertyName, BackingField = ReferenceWithinNewProperty, diff --git a/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs b/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs index ef44911b64..7e89f9e48f 100644 --- a/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs @@ -15,7 +15,7 @@ public interface IPropertyGeneratorAttributes bool UsesSetAssignment { get; } } - public struct PropertyGeneratorSpecification : IPropertyGeneratorAttributes + public class PropertyAttributeSet : IPropertyGeneratorAttributes { public string PropertyName { get; set; } public string BackingField { get; set; } @@ -30,17 +30,6 @@ public class PropertyGenerator { public PropertyGenerator() { } - public PropertyGenerator(IPropertyGeneratorAttributes spec) - { - PropertyName = spec.PropertyName; - BackingField = spec.BackingField; - AsTypeName = spec.AsTypeName; - ParameterName = spec.ParameterName; - GenerateLetter = spec.GenerateLetter; - GenerateSetter = spec.GenerateSetter; - UsesSetAssignment = spec.UsesSetAssignment; - } - public string PropertyName { get; set; } public string BackingField { get; set; } public string AsTypeName { get; set; } @@ -52,11 +41,11 @@ public PropertyGenerator(IPropertyGeneratorAttributes spec) public string AllPropertyCode => $"{GetterCode}{(GenerateLetter ? LetterCode : string.Empty)}{(GenerateSetter ? SetterCode : string.Empty)}"; - public IEnumerable AsEnumerableLines => AllPropertyCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None); + public IEnumerable AsLines => AllPropertyCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None); public string AsPropertyBlock(IIndenter indenter) { - return string.Join(Environment.NewLine, indenter.Indent(AsEnumerableLines, true)); + return string.Join(Environment.NewLine, indenter.Indent(AsLines, true)); } public string AsPropertyBlock(IPropertyGeneratorAttributes spec, IIndenter indenter) @@ -68,7 +57,7 @@ public string AsPropertyBlock(IPropertyGeneratorAttributes spec, IIndenter inden GenerateLetter = spec.GenerateLetter; GenerateSetter = spec.GenerateSetter; UsesSetAssignment = spec.UsesSetAssignment; - return string.Join(Environment.NewLine, indenter.Indent(AsEnumerableLines, true)); + return string.Join(Environment.NewLine, indenter.Indent(AsLines, true)); } private string GetterCode diff --git a/Rubberduck.Refactorings/EncapsulateField/StateUDT.cs b/Rubberduck.Refactorings/EncapsulateField/StateUDT.cs new file mode 100644 index 0000000000..152248fb62 --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/StateUDT.cs @@ -0,0 +1,76 @@ +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Symbols; +using Rubberduck.SmartIndenter; +using Rubberduck.VBEditor; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + public interface IStateUDT + { + string TypeIdentifier { set; get; } + string FieldIdentifier { set; get; } + string TypeDeclarationBlock(IIndenter indenter = null); + string FieldDeclarationBlock { get; } + void AddMembers(IEnumerable fields); + QualifiedModuleName QualifiedModuleName { set; get; } + } + + public class StateUDT : IStateUDT + { + private const string _defaultNewFieldName = "this"; + private List _members; + private readonly IEncapsulateFieldNamesValidator _validator; + + public StateUDT(QualifiedModuleName qmn, IEncapsulateFieldNamesValidator validator) + :this($"T{qmn.ComponentName.Capitalize()}", validator) + { + QualifiedModuleName = qmn; + } + + public StateUDT(string typeIdentifier, IEncapsulateFieldNamesValidator validator) + { + _validator = validator; + FieldIdentifier = _defaultNewFieldName; + TypeIdentifier = typeIdentifier; + _members = new List(); + } + + public QualifiedModuleName QualifiedModuleName { set; get; } + + public string TypeIdentifier { set; get; } + + public string FieldIdentifier { set; get; } + + public void AddMembers(IEnumerable fields) => _members.AddRange(fields); + + public string FieldDeclarationBlock + => $"{Accessibility.Private} {FieldIdentifier} {Tokens.As} {TypeIdentifier}"; + + public string TypeDeclarationBlock(IIndenter indenter = null) + { + if (indenter != null) + { + return string.Join(Environment.NewLine, indenter?.Indent(BlockLines(Accessibility.Private) ?? BlockLines(Accessibility.Private), true)); + } + return string.Join(Environment.NewLine, BlockLines(Accessibility.Private)); + } + + private IEnumerable BlockLines(Accessibility accessibility) + { + var blockLines = new List(); + + blockLines.Add($"{accessibility.TokenString()} {Tokens.Type} {TypeIdentifier}"); + + _members.ForEach(m => blockLines.Add($"{m.PropertyName} {Tokens.As} {m.AsTypeName}")); + + blockLines.Add($"{Tokens.End} {Tokens.Type}"); + + return blockLines; + } + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/StateUDTField.cs b/Rubberduck.Refactorings/EncapsulateField/StateUDTField.cs deleted file mode 100644 index cd17428e1a..0000000000 --- a/Rubberduck.Refactorings/EncapsulateField/StateUDTField.cs +++ /dev/null @@ -1,93 +0,0 @@ -using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Symbols; -using Rubberduck.SmartIndenter; -using Rubberduck.VBEditor; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Rubberduck.Refactorings.EncapsulateField -{ - public interface IStateUDTField - { - string TypeIdentifier { set; get; } - string TypeDeclarationBlock(IIndenter indenter = null); - string FieldDeclarationBlock { get; } - void AddMembers(IEnumerable fields); - void Reset(); - string NewFieldName { get; } - } - - public class StateUDTField : EncapsulateFieldCandidate, IUserDefinedTypeCandidate, IStateUDTField - { - private const string _defaultTypeIdentifier = "This_Type"; - private const string _defaultNewFieldName = "this"; - private List _members; - - public StateUDTField(string identifier, string asTypeName, QualifiedModuleName qmn, IEncapsulateFieldNamesValidator validator) - : base(identifier, asTypeName, qmn, validator) - { - PropertyName = identifier; - NewFieldName = identifier; - AsTypeName = asTypeName; - TypeIdentifier = asTypeName; - _members = new List(); - - PropertyAccessor = AccessorTokens.Field; - ReferenceAccessor = AccessorTokens.Field; - //ReferenceQualifier = Parent.ReferenceWithinNewProperty; - } - - public string TypeIdentifier { set; get; } - - public override string PropertyName { set; get; } - - public override string NewFieldName { set; get; } - - public override bool IsSelfConsistent => _validator.IsValidVBAIdentifier(PropertyName, DeclarationType.Property) - && !(PropertyName.EqualsVBAIdentifier(ParameterName) - || PropertyName.EqualsVBAIdentifier(ParameterName)); - - public IEnumerable Members { get; } - public void AddMember(IUserDefinedTypeMemberCandidate member) { throw new NotImplementedException(); } - public bool FieldQualifyUDTMemberPropertyName { set; get; } - public bool TypeDeclarationIsPrivate { set; get; } = true; - - //public void AddMember(IEncapsulateFieldCandidate field) => _members.Add(field); - public void Reset() - { - _members.Clear(); - NewFieldName = _defaultNewFieldName; - TypeIdentifier = _defaultTypeIdentifier; - } - - public void AddMembers(IEnumerable fields) => _members.AddRange(fields); - - public string FieldDeclarationBlock //(string fieldName) // string identifierName, Accessibility accessibility = Accessibility.Private) - => $"{Accessibility.Private} {NewFieldName} {Tokens.As} {AsTypeName}"; - - public string TypeDeclarationBlock(IIndenter indenter = null) //= null, Accessibility accessibility = Accessibility.Private) - { - if (indenter != null) - { - return string.Join(Environment.NewLine, indenter?.Indent(BlockLines(Accessibility.Private) ?? BlockLines(Accessibility.Private), true)); - } - return string.Join(Environment.NewLine, BlockLines(Accessibility.Private)); - } - - private IEnumerable BlockLines(Accessibility accessibility) - { - var blockLines = new List(); - - blockLines.Add($"{accessibility.TokenString()} {Tokens.Type} {AsTypeName}"); - - _members.ForEach(m => blockLines.Add($"{m.PropertyName} As {m.AsTypeName}")); - - blockLines.Add("End Type"); - - return blockLines; - } - } -} diff --git a/Rubberduck.Refactorings/Rubberduck.Refactorings.csproj b/Rubberduck.Refactorings/Rubberduck.Refactorings.csproj index b603ae5502..077a3e0f68 100644 --- a/Rubberduck.Refactorings/Rubberduck.Refactorings.csproj +++ b/Rubberduck.Refactorings/Rubberduck.Refactorings.csproj @@ -23,7 +23,4 @@ 4.6.4 - - - \ No newline at end of file diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs index 7710e39a5f..5f109d2723 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs @@ -48,7 +48,7 @@ public void VBAIdentifier_FieldName(string originalFieldName, string newFieldNam var encapsulatedField = Support.RetrieveEncapsulatedField(inputCode, originalFieldName); - encapsulatedField.NewFieldName = newFieldName; + encapsulatedField.FieldIdentifier = newFieldName; var field = encapsulatedField as IEncapsulateFieldCandidateValidations; Assert.AreEqual(expectedResult, field.HasVBACompliantFieldIdentifier); } @@ -292,7 +292,7 @@ private IEncapsulateFieldCandidate CreateEncapsulatedFieldMock(string targetID, var mock = new Mock(); mock.SetupGet(m => m.TargetID).Returns(identifiers.TargetFieldName); - mock.SetupGet(m => m.NewFieldName).Returns(identifiers.Field); + mock.SetupGet(m => m.FieldIdentifier).Returns(identifiers.Field); mock.SetupGet(m => m.PropertyName).Returns(modifiedPropertyName ?? identifiers.Property); mock.SetupGet(m => m.AsTypeName).Returns(asTypeName); mock.SetupGet(m => m.EncapsulateFlag).Returns(encapsulateFlag); @@ -306,7 +306,7 @@ private IEncapsulateFieldCandidate CreateAttributesMock(string targetID, string var identifiers = new EncapsulationIdentifiers(targetID); var mock = new Mock(); mock.SetupGet(m => m.IdentifierName).Returns(identifiers.TargetFieldName); - mock.SetupGet(m => m.NewFieldName).Returns(identifiers.Field); + mock.SetupGet(m => m.FieldIdentifier).Returns(identifiers.Field); mock.SetupGet(m => m.PropertyName).Returns(modifiedPropertyName ?? identifiers.Property); mock.SetupGet(m => m.AsTypeName).Returns(asTypeName); mock.SetupGet(m => m.EncapsulateFlag).Returns(encapsulateFlag); diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs index db7c99a797..0b3c353899 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs @@ -5,6 +5,7 @@ using Rubberduck.Refactorings.EncapsulateField; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.Utility; +using RubberduckTests.Mocks; using System; using System.Collections.Generic; using System.Linq; @@ -39,7 +40,7 @@ End Type var presenterAction = Support.UserAcceptsDefaults(asUDT: true); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.Contains("Private this As Long", actualCode); - StringAssert.Contains("Private this_1 As This_Type", actualCode); + StringAssert.Contains($"Private this_1 As {Support.StateUDTDefaultType}", actualCode); } [Test] @@ -124,8 +125,8 @@ Public foobar As Byte var presenterAction = Support.SetParameters(userInput); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - StringAssert.Contains("Private this As This_Type", actualCode); - StringAssert.Contains("Private Type This_Type", actualCode); + StringAssert.Contains($"Private this As {Support.StateUDTDefaultType}", actualCode); + StringAssert.Contains($"Private Type {Support.StateUDTDefaultType}", actualCode); StringAssert.Contains("Foo As Long", actualCode); StringAssert.Contains("Bar As String", actualCode); StringAssert.Contains("Foobar As Byte", actualCode); @@ -165,12 +166,14 @@ Public myBar As TBar } [TestCase("Public Sub This_Type()\r\nEnd Sub", "This_Type_1")] - [TestCase("Private this_Type As Long\r\nPrivate this_Type_1 As String", "This_Type_2")] + [TestCase("Private This_Type As Long\r\nPrivate This_Type_1 As String", "This_Type_2")] [TestCase("Public Property Get This_Type() As Long\r\nEnd Property", "This_Type_1")] [Category("Refactorings")] [Category("Encapsulate Field")] - public void UserDefinedTypeDefaultNameConflicts(string declaration, string expectedIdentifier) + public void UserDefinedTypeDefaultNameHasConflicts(string declaration, string expectedIdentifier) { + declaration = declaration.Replace("This_Type", $"{Support.StateUDTDefaultType}"); + expectedIdentifier = expectedIdentifier.Replace("This_Type", $"{Support.StateUDTDefaultType}"); string inputCode = $@" @@ -188,7 +191,10 @@ Public myBar As TBar var userInput = new UserInputDataObject() .AddAttributeSet("myBar"); + userInput.EncapsulateAsUDT = true; + //userInput.StateUDT_TypeName = "This_Type"; + //userInput.StateUDT_FieldName = "this"; var presenterAction = Support.SetParameters(userInput); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs index 1ae41c28a1..82a2d09251 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs @@ -47,19 +47,19 @@ public void FieldNameValuesPerSequenceOfPropertyNameChanges() string inputCode = "Public fizz As String"; var encapsulatedField = Support.RetrieveEncapsulatedField(inputCode, "fizz"); - StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.NewFieldName); + StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.FieldIdentifier); encapsulatedField.PropertyName = "Test"; - StringAssert.AreEqualIgnoringCase("fizz", encapsulatedField.NewFieldName); + StringAssert.AreEqualIgnoringCase("fizz", encapsulatedField.FieldIdentifier); encapsulatedField.PropertyName = "Fizz"; - StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.NewFieldName); + StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.FieldIdentifier); encapsulatedField.PropertyName = "Fiz"; - StringAssert.AreEqualIgnoringCase("fizz", encapsulatedField.NewFieldName); + StringAssert.AreEqualIgnoringCase("fizz", encapsulatedField.FieldIdentifier); encapsulatedField.PropertyName = "Fizz"; - StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.NewFieldName); + StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.FieldIdentifier); } [Test] @@ -88,14 +88,14 @@ public void CreateUDT() mock.SetupGet(m => m.AsTypeName).Returns("String"); mock.SetupGet(m => m.PropertyName).Returns("Fizz"); - var stateUDT = new StateUDTField("this", "This_Type", new QualifiedModuleName(), null) as IStateUDTField; + var stateUDT = new StateUDT(Support.StateUDTDefaultType, null) as IStateUDT; //var newUserDefinedType = new UDTDeclarationGenerator("This_Type"); stateUDT.AddMembers(new IEncapsulateFieldCandidate[] { mock.Object }); //var result = newUserDefinedType.TypeDeclarationBlock(); var result = stateUDT.TypeDeclarationBlock(); - StringAssert.Contains("Private Type This_Type", result); + StringAssert.Contains($"Private Type {Support.StateUDTDefaultType}", result); StringAssert.Contains("Fizz As String", result); StringAssert.Contains("End Type", result); } diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index 5fd16e9bfb..13b401f372 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -20,6 +20,8 @@ namespace RubberduckTests.Refactoring.EncapsulateField { public class EncapsulateFieldTestSupport : InteractiveRefactoringTestBase { + public string StateUDTDefaultType => $"T{MockVbeBuilder.TestModuleName}"; + private TestEncapsulationAttributes UserModifiedEncapsulationAttributes(string field, string property = null, bool isReadonly = false, bool encapsulateFlag = true) { var testAttrs = new TestEncapsulationAttributes(field, encapsulateFlag, isReadonly); @@ -51,6 +53,8 @@ public Func SetParameters(UserInpu return model => { model.EncapsulateWithUDT = userInput.EncapsulateAsUDT; + model.StateUDTField.TypeIdentifier = userInput.StateUDT_TypeName ?? model.StateUDTField.TypeIdentifier; + model.StateUDTField.FieldIdentifier = userInput.StateUDT_FieldName ?? model.StateUDTField.FieldIdentifier; foreach (var testModifiedAttribute in userInput.EncapsulateFieldAttributes) { var attrsInitializedByTheRefactoring = model[testModifiedAttribute.TargetFieldName]; //.EncapsulationAttributes; @@ -203,10 +207,13 @@ public UserInputDataObject AddAttributeSet(string fieldName, string propertyName public bool EncapsulateAsUDT { set; get; } + public string StateUDT_TypeName { set; get; } + + public string StateUDT_FieldName { set; get; } + public TestEncapsulationAttributes this[string fieldName] => EncapsulateFieldAttributes.Where(efa => efa.TargetFieldName == fieldName).Single(); - public IEnumerable EncapsulateFieldAttributes => _userInput; //public void AddUDTMemberNameFlagPairs(params (string, string, bool)[] nameFlagPairs) diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index 60f4e5b093..a79b171a58 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -451,7 +451,7 @@ public void EncapsulatePrivateField_DefaultsAsUDT() var presenterAction = Support.UserAcceptsDefaults(asUDT: true); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.Contains("Fizz As Integer", actualCode); - StringAssert.Contains("this As This_Type", actualCode); + StringAssert.Contains($"this As {Support.StateUDTDefaultType}", actualCode); StringAssert.Contains("this.Fizz = value", actualCode); } From 669459b639ca77e41a6940c90ea14222602858b6 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Wed, 11 Dec 2019 17:15:34 -0800 Subject: [PATCH 053/461] A little cleanup --- .../EncapsulateFieldValidator.cs | 42 ------------------- 1 file changed, 42 deletions(-) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs index 8371cec041..c9336e2efd 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -25,7 +25,6 @@ public interface IEncapsulateFieldValidator public interface IEncapsulateFieldNamesValidator : IEncapsulateFieldValidator { - //bool HasIdentifierConflicts(string identifier, DeclarationType declarationType); bool IsConflictingStateUDTIdentifier(IUserDefinedTypeCandidate candidate); bool IsConflictingStateUDTTypeIdentifier(IStateUDT stateUDT); bool IsConflictingStateUDTFieldIdentifier(IStateUDT stateUDT); @@ -120,47 +119,6 @@ public bool HasValidEncapsulationAttributes(IEncapsulateFieldCandidate candidate return true; } - //public int HasNewPropertyNameConflicts(IEncapsulateFieldCandidate attributes, QualifiedModuleName qmn, IEnumerable declarationsToIgnore) - //{ - // Predicate IsPrivateAccessiblityInOtherModule = (Declaration dec) => dec.QualifiedModuleName != qmn && dec.Accessibility.Equals(Accessibility.Private); - // Predicate IsInSearchScope = null; - // if (qmn.ComponentType == ComponentType.ClassModule) - // { - // IsInSearchScope = (Declaration dec) => dec.QualifiedModuleName == qmn; - // } - // else - // { - // IsInSearchScope = (Declaration dec) => dec.QualifiedModuleName.ProjectId == qmn.ProjectId; - // } - - // var identifierMatches = DeclarationFinder.MatchName(attributes.PropertyName) - // .Where(match => IsInSearchScope(match) - // && !declarationsToIgnore.Contains(match) - // && !IsPrivateAccessiblityInOtherModule(match) - // && !IsEnumOrUDTMemberDeclaration(match) - // && !match.IsLocalVariable()).ToList(); - - // var candidates = new List(); - // var candidateMatches = new List(); - // foreach (var efd in FieldCandidates) - // { - // var matches = candidates.Where(c => c.PropertyName.EqualsVBAIdentifier(efd.PropertyName)); - // if (matches.Any()) - // { - // candidateMatches.Add(efd); - // } - // candidates.Add(efd); - // } - - // return identifierMatches.Count() + candidateMatches.Count(); - //} - - //public bool HasIdentifierConflicts(string identifier, DeclarationType declarationType) - //{ - // return true; - //} - - private bool IsEnumOrUDTMemberDeclaration(Declaration candidate) { return candidate.DeclarationType == DeclarationType.EnumerationMember From b01c4610813e71ed67961b476ceff9b242b55057 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Thu, 12 Dec 2019 16:08:31 -0800 Subject: [PATCH 054/461] WIP Incoporated new layout --- .../EncapsulateFieldView.xaml | 460 ++++++++++++------ .../ViewableEncapsulatedField.cs | 6 +- 2 files changed, 305 insertions(+), 161 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml index 8a13e27b98..6ffea12622 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml @@ -27,89 +27,19 @@ + - - - + - + - - @@ -125,8 +55,7 @@ FontWeight="Bold" Margin="0,10,0,0" /> - @@ -162,71 +91,34 @@ VerticalContentAlignment="Center" Text="{Binding EncapsulateAsUDT_FieldName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - + RelativeSource={RelativeSource AncestorType=ListBox}}" /> + --> + + + + + + + + + + + + + + + + + + + + + + + Type Name: + + - - - - - - + + + + + + + + + + + + + User Defined Type Name: + + + + + + User Defined Type Field Name: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property Name: + + + + + + + + + + + + + + - - - --> + _efd.EncapsulateFlag; set => _efd.EncapsulateFlag = value; } public string NewFieldName { get => _efd.FieldIdentifier; }// set => _efd.NewFieldName = value; } //TODO: Change name of AsTypeName property to FieldDescriptor(?) -> and does it belong on IEncapsulatedField? - public string AsTypeName + public string AsTypeName => _efd.AsTypeName; + public string FieldDescriptor { //(Variable: Integer Array) //(Variable: Long) @@ -53,7 +55,7 @@ public string AsTypeName var prefix = string.Empty; var descriptor = string.Empty; - if (_efd is IUserDefinedTypeMemberCandidate) //.IsUDTMember) + if (_efd is IUserDefinedTypeCandidate) //.IsUDTMember) { prefix = "UserDefinedType"; } From 06775d3c003f03061a9e318c998f6a309405f8fa Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Sat, 14 Dec 2019 00:32:43 -0800 Subject: [PATCH 055/461] Updated per latest prototype --- .../EncapsulateFieldView.xaml | 338 ++++++------------ 1 file changed, 115 insertions(+), 223 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml index 6ffea12622..95885c0cb1 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml @@ -16,21 +16,27 @@ UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/cross-circle.png" /> - + + - - @@ -39,58 +45,6 @@ - - - - - - - - - - - - - - - - - - - - - - User Defined Type Name: - - - - User Defined Type Field Name: - - - @@ -102,134 +56,12 @@ - - - - @@ -242,7 +74,6 @@ - - - Type Name: - - @@ -314,7 +132,7 @@ MaxWidth="600" /> - + --> + + + + + + + + + + + + + + + + + + + - @@ -361,10 +214,22 @@ Padding="10,0" Command="{Binding DeselectAllCommand}"> + --> + + - + + + + + + + + + + + + + + + + + + + - - - @@ -447,7 +329,17 @@ - + From 87b1134fcacd9a676cb43d4aa7b82131b2fe308d Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Sat, 14 Dec 2019 00:33:43 -0800 Subject: [PATCH 056/461] WIP changes to support GUI mods --- .../EncapsulateFieldViewModel.cs | 154 +++++++++++++++++- .../ViewableEncapsulatedField.cs | 8 + .../EncapsulateField/StateUDT.cs | 2 +- 3 files changed, 154 insertions(+), 10 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs index 34f2425095..6aa80a836f 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs @@ -1,4 +1,5 @@ -using System.Collections.ObjectModel; +using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; using NLog; using Rubberduck.Parsing.VBA; @@ -16,36 +17,125 @@ public EncapsulateFieldViewModel(EncapsulateFieldModel model, RubberduckParserSt { State = state; + _lastCheckedBoxes = EncapsulationFields.Where(ef => ef.EncapsulateFlag).ToList(); + SelectAllCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), _ => ToggleSelection(true)); DeselectAllCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), _ => ToggleSelection(false)); IsReadOnlyCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), _ => ReloadPreview()); EncapsulateFlagCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), _ => ReloadPreview()); PropertyChangeCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), _ => UpdatePreview()); + EncapsulateFlagChangeCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ManageEncapsulationFlagsAndSelectedItem); + ReadOnlyChangeCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ChangeIsReadOnlyFlag); + + SelectedField = EncapsulationFields.FirstOrDefault(); } public ObservableCollection EncapsulationFields { get { - var flaggedFields = Model.SelectedFieldCandidates - .OrderBy(efd => efd.Declaration.IdentifierName); + //var flaggedFields = Model.SelectedFieldCandidates + // .OrderBy(efd => efd.Declaration.IdentifierName); - var orderedFields = Model.EncapsulationCandidates.Except(flaggedFields) - .OrderBy(efd => efd.Declaration.IdentifierName); + //var orderedFields = Model.EncapsulationCandidates //.Except(flaggedFields) + // .OrderBy(efd => efd.Declaration.IdentifierName); var viewableFields = new ObservableCollection(); - foreach (var efd in flaggedFields.Concat(orderedFields)) + foreach (var efd in Model.EncapsulationCandidates) // flaggedFields.Concat(orderedFields)) { viewableFields.Add(new ViewableEncapsulatedField(efd)); } //TODO: Trying to reset the scroll to the top using SelectedValue is not working...Remove or fix - SelectedValue = viewableFields.FirstOrDefault(); + //SelectedField = viewableFields.FirstOrDefault(); return viewableFields; } } + private IEncapsulatedFieldViewData _selectedField; + public IEncapsulatedFieldViewData SelectedField + { + set + { + _selectedField = value; + PropertyName = _selectedField.PropertyName; + GroupBoxHeaderContent = "Property Name"; + IsReadOnly = _selectedField.IsReadOnly; + OnPropertyChanged(nameof(SelectedField)); + OnPropertyChanged(nameof(PropertyPreview)); + } + get => _selectedField; + } - public IEncapsulatedFieldViewData SelectedValue { set; get; } + string _groupBoxHeader; + public string GroupBoxHeaderContent + { + set + { + _groupBoxHeader = value; + OnPropertyChanged(nameof(GroupBoxHeaderContent)); + } + get => _groupBoxHeader; + } + + string _propertyName; + public string PropertyName + { + set + { + _propertyName = value; + SelectedField.PropertyName = value; + OnPropertyChanged(nameof(PropertyName)); + OnPropertyChanged(nameof(HasValidNames)); + } + get => _propertyName; + } + + private string _fieldDescriptor; + public string FieldDescriptor + { + set + { + _fieldDescriptor = value; + OnPropertyChanged(nameof(FieldDescriptor)); + } + get => _fieldDescriptor; + } + + private string _targetID; + public string TargetID + { + set + { + _targetID = value; + //OnPropertyChanged(nameof(FieldDescriptor)); + } + get => _targetID; + } + + private bool _isReadOnly; + public bool IsReadOnly + { + set + { + _isReadOnly = value; + OnPropertyChanged(nameof(IsReadOnly)); + } + get => _isReadOnly; + } + + public void ValidatePropertyName(string value) + { + SelectedField.PropertyName = value; + OnPropertyChanged(nameof(HasValidNames)); + } + + + //private IEncapsulatedFieldViewData _selectedvalue; + //public IEncapsulatedFieldViewData SelectedValue + //{ + // set; + // get; + //} public bool HideEncapsulateAsUDTFields => !EncapsulateAsUDT; @@ -109,7 +199,15 @@ public bool TargetsHaveValidEncapsulationSettings public IEncapsulateFieldValidator RefactoringValidator { set; get; } //TODO: hook the validation scheme backup - public bool HasValidNames => true; + //public bool HasValidNames => true; + public bool HasValidNames + { + get + { + return EncapsulationFields.All(ef => ef.HasValidEncapsulationAttributes); + //return !_neverUseTheseNames.Any(nm => nm.Equals(SelectedField.PropertyName, StringComparison.InvariantCultureIgnoreCase)); + } + } public string PropertyPreview => Model.PreviewRefactoring(); @@ -128,6 +226,44 @@ private void ToggleSelection(bool value) public CommandBase EncapsulateFlagCommand { get; } public CommandBase PropertyChangeCommand { get; } + public CommandBase EncapsulateFlagChangeCommand { get; } + public CommandBase ReadOnlyChangeCommand { get; } + + + private void ChangeIsReadOnlyFlag(object param) + { + SelectedField.IsReadOnly = !SelectedField.IsReadOnly; + OnPropertyChanged(nameof(IsReadOnly)); + OnPropertyChanged(nameof(PropertyPreview)); + } + + private List _lastCheckedBoxes; + + private void ManageEncapsulationFlagsAndSelectedItem(object param) + { + + var nowChecked = EncapsulationFields.Where(ef => ef.EncapsulateFlag).ToList(); + var beforeChecked = _lastCheckedBoxes.ToList(); + + nowChecked.RemoveAll(c => _lastCheckedBoxes.Select(bc => bc.TargetID).Contains(c.TargetID)); + beforeChecked.RemoveAll(c => EncapsulationFields.Where(ec => ec.EncapsulateFlag).Select(nc => nc.TargetID).Contains(c.TargetID)); + if (nowChecked.Any()) + { + SelectedField = nowChecked.Single(); + //_lastCheckedBoxes = EncapsulationFields.Where(ef => ef.EncapsulateFlag).ToList(); + //return; + } + + //beforeChecked.RemoveAll(c => EncapsulationFields.Select(nc => nc.TargetID).Contains(c.TargetID)); + else if (beforeChecked.Any()) + { + SelectedField = beforeChecked.Single(); + //_lastCheckedBoxes = EncapsulationFields.Where(ef => ef.EncapsulateFlag).ToList(); + //return; + } + _lastCheckedBoxes = EncapsulationFields.Where(ef => ef.EncapsulateFlag).ToList(); + } + private void UpdatePreview() { OnPropertyChanged(nameof(PropertyPreview)); diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs index 21063102c5..128d55541f 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs @@ -22,6 +22,7 @@ public interface IEncapsulatedFieldViewData bool HasValidEncapsulationAttributes { get; } string AsTypeName { get; } string FieldDescriptor { get; } + string TargetDeclarationExpression { set; get; } } public class ViewableEncapsulatedField : IEncapsulatedFieldViewData @@ -72,5 +73,12 @@ public string FieldDescriptor return descriptor; } } + + private string _targetDeclarationExpressions; + public string TargetDeclarationExpression + { + set => _targetDeclarationExpressions = value; + get => $"Private {TargetID} As {AsTypeName}"; + } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/StateUDT.cs b/Rubberduck.Refactorings/EncapsulateField/StateUDT.cs index 152248fb62..535d442a56 100644 --- a/Rubberduck.Refactorings/EncapsulateField/StateUDT.cs +++ b/Rubberduck.Refactorings/EncapsulateField/StateUDT.cs @@ -46,7 +46,7 @@ public StateUDT(string typeIdentifier, IEncapsulateFieldNamesValidator validator public string FieldIdentifier { set; get; } - public void AddMembers(IEnumerable fields) => _members.AddRange(fields); + public void AddMembers(IEnumerable fields) => _members = fields.ToList(); public string FieldDeclarationBlock => $"{Accessibility.Private} {FieldIdentifier} {Tokens.As} {TypeIdentifier}"; From 13b5fd5f2a683ad35ea35a11587b2953ce7dcbac Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Sat, 14 Dec 2019 14:52:58 -0800 Subject: [PATCH 057/461] Reduce checkbox target size --- .../EncapsulateField/EncapsulateFieldView.xaml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml index 95885c0cb1..b6942ec40a 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml @@ -179,22 +179,24 @@ - + - + + Margin="10,0,0,0" + Text="{Binding TargetDeclarationExpression, Mode=OneWay}" + FontWeight="Bold"> + From 15aa8d3f0862e13d5721e7c4b22829611c5fea3f Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Sat, 14 Dec 2019 16:24:35 -0800 Subject: [PATCH 058/461] WIP - validation improvements --- .../EncapsulateFieldViewModel.cs | 21 +-- .../ViewableEncapsulatedField.cs | 2 +- .../EncapsulateFieldElementFactory.cs | 4 +- .../EncapsulateField/EncapsulateFieldModel.cs | 2 +- .../EncapsulateFieldRefactoring.cs | 6 +- .../EncapsulateFieldValidator.cs | 68 ++++----- .../EncapsulateFieldValidatorTests.cs | 140 +++++++++--------- .../EncapsulateField/TestSupport.cs | 7 +- 8 files changed, 128 insertions(+), 122 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs index 6aa80a836f..22a5a7f448 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs @@ -31,26 +31,29 @@ public EncapsulateFieldViewModel(EncapsulateFieldModel model, RubberduckParserSt SelectedField = EncapsulationFields.FirstOrDefault(); } + private ObservableCollection _viewableFields; public ObservableCollection EncapsulationFields { get { //var flaggedFields = Model.SelectedFieldCandidates // .OrderBy(efd => efd.Declaration.IdentifierName); + if (_viewableFields is null) + { + _viewableFields = new ObservableCollection(); - //var orderedFields = Model.EncapsulationCandidates //.Except(flaggedFields) - // .OrderBy(efd => efd.Declaration.IdentifierName); + var orderedFields = Model.EncapsulationCandidates //.Except(flaggedFields) + .OrderBy(efd => efd.Declaration.IdentifierName); - var viewableFields = new ObservableCollection(); - foreach (var efd in Model.EncapsulationCandidates) // flaggedFields.Concat(orderedFields)) - { - viewableFields.Add(new ViewableEncapsulatedField(efd)); + foreach (var efd in orderedFields) // flaggedFields.Concat(orderedFields)) + { + _viewableFields.Add(new ViewableEncapsulatedField(efd)); + } } - //TODO: Trying to reset the scroll to the top using SelectedValue is not working...Remove or fix - //SelectedField = viewableFields.FirstOrDefault(); - return viewableFields; + return _viewableFields; } } + private IEncapsulatedFieldViewData _selectedField; public IEncapsulatedFieldViewData SelectedField { diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs index 128d55541f..66456b3f15 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs @@ -78,7 +78,7 @@ public string FieldDescriptor public string TargetDeclarationExpression { set => _targetDeclarationExpressions = value; - get => $"Private {TargetID} As {AsTypeName}"; + get => $"{TargetID}: Private {TargetID} As {AsTypeName}"; } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs index 931cb6c086..3b8d15c6fb 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs @@ -48,7 +48,7 @@ public IEncapsulateFieldCandidate CreateEncapsulationCandidate(Declaration targe candidate = ApplyTypeSpecificAttributes(candidate); - candidate = SetNonConflictIdentifier(candidate, c => { return _validator.HasConflictingPropertyIdentifier(candidate); }, (s) => { candidate.PropertyName = s; }, () => candidate.IdentifierName, _validator); + candidate = SetNonConflictIdentifier(candidate, c => { return _validator.HasConflictingPropertyIdentifier(candidate); }, (s) => { candidate.PropertyName = s.Capitalize(); }, () => candidate.IdentifierName, _validator); if (candidate is IUserDefinedTypeCandidate udtVariable) { @@ -62,7 +62,7 @@ public IEncapsulateFieldCandidate CreateEncapsulationCandidate(Declaration targe candidateUDTMember = ApplyTypeSpecificAttributes(candidateUDTMember); - candidateUDTMember = SetNonConflictIdentifier(candidateUDTMember, c => { return _validator.HasConflictingPropertyIdentifier(candidate); }, (s) => { candidateUDTMember.PropertyName = s; }, () => candidate.IdentifierName, _validator); + candidateUDTMember = SetNonConflictIdentifier(candidateUDTMember, c => { return _validator.HasConflictingPropertyIdentifier(candidate); }, (s) => { candidateUDTMember.PropertyName = s.Capitalize(); }, () => candidate.IdentifierName, _validator); udtVariable.AddMember(candidateUDTMember); } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index cb3089917f..d3936a41e2 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -29,7 +29,7 @@ public EncapsulateFieldModel(Declaration target, IEnumerable EncapsulationCandidates { set; get; } = new List(); diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 8f8a50edb6..2433f1d5fd 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -99,9 +99,13 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) _encapsulationCandidateFactory = new EncapsulateFieldElementFactory(_declarationFinderProvider, _targetQMN, _validator); + var candidates = _encapsulationCandidateFactory.CreateEncapsulationCandidates(); + var selected = candidates.Single(c => c.Declaration == target); + selected.EncapsulateFlag = true; + Model = new EncapsulateFieldModel( target, - _encapsulationCandidateFactory.CreateEncapsulationCandidates(), + candidates, _encapsulationCandidateFactory.CreateStateUDTField(), PreviewRewrite); diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs index c9336e2efd..3e23724fdb 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -25,7 +25,6 @@ public interface IEncapsulateFieldValidator public interface IEncapsulateFieldNamesValidator : IEncapsulateFieldValidator { - bool IsConflictingStateUDTIdentifier(IUserDefinedTypeCandidate candidate); bool IsConflictingStateUDTTypeIdentifier(IStateUDT stateUDT); bool IsConflictingStateUDTFieldIdentifier(IStateUDT stateUDT); } @@ -34,19 +33,19 @@ public class EncapsulateFieldNamesValidator : IEncapsulateFieldNamesValidator { private readonly IDeclarationFinderProvider _declarationFinderProvider; - private List _registeredCandidates; + private List FieldCandidates { set; get; } - private List FieldCandidates => _registeredCandidates; // _fieldCandidates.Value; + private List FlaggedCandidates => FieldCandidates.Where(rc => rc.EncapsulateFlag).ToList(); public EncapsulateFieldNamesValidator(IDeclarationFinderProvider declarationFinderProvider, Func> retrieveCandidateFields = null) { _declarationFinderProvider = declarationFinderProvider; - _registeredCandidates = new List(); + FieldCandidates = new List(); } public void RegisterFieldCandidate(IEncapsulateFieldCandidate candidate) { - _registeredCandidates.Add(candidate); + FieldCandidates.Add(candidate); } private DeclarationFinder DeclarationFinder => _declarationFinderProvider.DeclarationFinder; @@ -54,57 +53,57 @@ public void RegisterFieldCandidate(IEncapsulateFieldCandidate candidate) public bool IsValidVBAIdentifier(string identifier, DeclarationType declarationType) => VBAIdentifierValidator.IsValidIdentifier(identifier, declarationType); - public bool HasConflictingPropertyIdentifier(IEncapsulateFieldCandidate candidate) + private List GetPotentialConflictMembers(IEncapsulateFieldCandidate candidate) { - var members = _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) - .Where(d => d != candidate.Declaration); + return _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) + .Where(d => d != candidate.Declaration + && !IsAlwaysIgnoreNameConflictType(d)).ToList(); + } - var edits = FieldCandidates.Where(fc => fc.EncapsulateFlag && fc.Declaration != candidate.Declaration).Select(fc => fc.PropertyName); - edits = edits.Concat(FieldCandidates.Where(fc => fc.EncapsulateFlag && fc.Declaration != candidate.Declaration).Select(fc => fc.FieldIdentifier)); + private List GetPotentialConflictMembers(IStateUDT stateUDT) + { + return _declarationFinderProvider.DeclarationFinder.Members(stateUDT.QualifiedModuleName) + .Where(d => !IsAlwaysIgnoreNameConflictType(d)).ToList(); + } + public bool HasConflictingPropertyIdentifier(IEncapsulateFieldCandidate candidate) + { + var members = GetPotentialConflictMembers(candidate); + var newContentNames = FlaggedCandidates.Where(fc => fc.Declaration != candidate.Declaration).Select(fc => fc.PropertyName); + newContentNames = newContentNames.Concat(FlaggedCandidates.Where(fc => fc.Declaration != candidate.Declaration).Select(fc => fc.FieldIdentifier)); return members.Any(m => m.IdentifierName.EqualsVBAIdentifier(candidate.PropertyName)) - || edits.Any(ed => ed.EqualsVBAIdentifier(candidate.PropertyName)); + || newContentNames.Any(ed => ed.EqualsVBAIdentifier(candidate.PropertyName)); } public bool HasConflictingFieldIdentifier(IEncapsulateFieldCandidate candidate) { - var members = _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) - .Where(d => d != candidate.Declaration); + var members = GetPotentialConflictMembers(candidate); return members.Any(m => m.IdentifierName.EqualsVBAIdentifier(candidate.FieldIdentifier)); } public bool IsConflictingFieldIdentifier(string fieldName, IEncapsulateFieldCandidate candidate) { - var members = _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) - .Where(d => d != candidate.Declaration); + var members = GetPotentialConflictMembers(candidate); return members.Any(m => m.IdentifierName.EqualsVBAIdentifier(fieldName) || candidate.PropertyName.EqualsVBAIdentifier(fieldName)); } public bool IsConflictingStateUDTTypeIdentifier(IStateUDT stateUDT) { - var members = _declarationFinderProvider.DeclarationFinder.Members(stateUDT.QualifiedModuleName); + var members = GetPotentialConflictMembers(stateUDT); return members.Any(m => m.IdentifierName.EqualsVBAIdentifier(stateUDT.TypeIdentifier)); } public bool IsConflictingStateUDTFieldIdentifier(IStateUDT stateUDT) { - var members = _declarationFinderProvider.DeclarationFinder.Members(stateUDT.QualifiedModuleName); + var members = GetPotentialConflictMembers(stateUDT); return members.Any(m => m.IdentifierName.EqualsVBAIdentifier(stateUDT.FieldIdentifier)); } - - public bool IsConflictingStateUDTIdentifier(IUserDefinedTypeCandidate candidate) - { - var members = _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName); - - return members.Any(m => m.IdentifierName.EqualsVBAIdentifier(candidate.AsTypeName)); - } - public bool HasValidEncapsulationAttributes(IEncapsulateFieldCandidate candidate, IEnumerable ignore) { if (!candidate.EncapsulateFlag) { return true; } @@ -119,17 +118,20 @@ public bool HasValidEncapsulationAttributes(IEncapsulateFieldCandidate candidate return true; } - private bool IsEnumOrUDTMemberDeclaration(Declaration candidate) + private bool IsAlwaysIgnoreNameConflictType(Declaration d) { - return candidate.DeclarationType == DeclarationType.EnumerationMember - || candidate.DeclarationType == DeclarationType.UserDefinedTypeMember; + //TODO: // candidate.DeclarationType == DeclarationType.EnumerationMember || candidate.DeclarationType == DeclarationType.UserDefinedTypeMember; + //FIXME: once a failing test is written + return d.IsLocalVariable() + || d.IsLocalConstant() + || d.DeclarationType.HasFlag(DeclarationType.Parameter); } - private bool UsesScopeResolution(Antlr4.Runtime.RuleContext ruleContext) - { - return (ruleContext is VBAParser.WithMemberAccessExprContext) - || (ruleContext is VBAParser.MemberAccessExprContext); - } + //private bool UsesScopeResolution(Antlr4.Runtime.RuleContext ruleContext) + //{ + // return (ruleContext is VBAParser.WithMemberAccessExprContext) + // || (ruleContext is VBAParser.MemberAccessExprContext); + //} private bool HasValidIdentifiers(IEncapsulateFieldCandidate attributes, DeclarationType declarationType) { diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs index 5f109d2723..5cd3def755 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs @@ -164,12 +164,13 @@ Public Property Let Name(ByVal value As String) End Property "; + var fieldUT = "fizz"; var userInput = new UserInputDataObject("fizz", userModifiedPropertyName, true); var presenterAction = Support.SetParameters(userInput); var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; - var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, "fizz", DeclarationType.Variable, presenterAction, "fizz"); + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, fieldUT, DeclarationType.Variable, presenterAction); Assert.IsFalse(model["fizz"].HasValidEncapsulationAttributes); } @@ -192,13 +193,16 @@ Public Property Get Test() As Integer Test = mTest End Property"; + var fieldUT = "fizz"; var userInput = new UserInputDataObject() - .AddAttributeSet("fizz", fizz_modifiedPropertyName, true) + .AddAttributeSet(fieldUT, fizz_modifiedPropertyName, true) .AddAttributeSet("bazz", bazz_modifiedPropertyName, true); + var presenterAction = Support.SetParameters(userInput); + var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; - var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, "fizz", DeclarationType.Variable, presenterAction, "fizz", "bazz", "buzz"); + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, fieldUT, DeclarationType.Variable, presenterAction); Assert.AreEqual(fizz_expectedResult, model["fizz"].HasValidEncapsulationAttributes, "fizz failed"); Assert.AreEqual(bazz_expectedResult, model["bazz"].HasValidEncapsulationAttributes, "bazz failed"); @@ -220,28 +224,18 @@ Public this As TBar Public that As TBar "; + var fieldUT = "this"; + var userInput = new UserInputDataObject() + .AddAttributeSet(fieldUT, "That", true); + + var presenterAction = Support.SetParameters(userInput); var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; - var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); - using (state) - { - var thisField = CreateEncapsulatedFieldMock("this.First", "Long", vbe.SelectedVBComponent, "First"); - var thatField = CreateEncapsulatedFieldMock("that.First", "String", vbe.SelectedVBComponent, "First"); - - var validator = new EncapsulateFieldNamesValidator( - state, - () => new List() - { - thisField, - thatField, - }); - validator.RegisterFieldCandidate(thisField); - validator.RegisterFieldCandidate(thatField); - - Assert.IsTrue(validator.HasConflictingPropertyIdentifier(thisField)); - //Assert.Less(0, validator.HasNewPropertyNameConflicts(thisField, thisField.QualifiedModuleName, Enumerable.Empty())); - } + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, fieldUT, DeclarationType.Variable, presenterAction); + + Assert.AreEqual(false, model[fieldUT].HasValidEncapsulationAttributes, $"{fieldUT} failed"); } + [Test] [Category("Refactorings")] [Category("Encapsulate Field")] @@ -253,66 +247,68 @@ Public longValue As Long Public wholeNumber As String "; - var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; - CreateAndParse(vbe, ThisTest); - - void ThisTest(IDeclarationFinderProvider declarationProviderProvider) - { - var wholeNumber = declarationProviderProvider.DeclarationFinder.MatchName("wholeNumber").Single(); - var longValue = declarationProviderProvider.DeclarationFinder.MatchName("longValue").Single(); - - var fields = new List(); + var fieldUT = "longValue"; + var userInput = new UserInputDataObject() + .AddAttributeSet(fieldUT, "WholeNumber", true); - var validator = new EncapsulateFieldNamesValidator(declarationProviderProvider, () => fields); + var presenterAction = Support.SetParameters(userInput); - var encapsulatedWholeNumber = new EncapsulateFieldCandidate(wholeNumber, validator); - var encapsulatedLongValue = new EncapsulateFieldCandidate(longValue, validator); - fields.Add(new EncapsulateFieldCandidate(wholeNumber, validator)); - fields.Add(new EncapsulateFieldCandidate(longValue, validator)); + var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, fieldUT, DeclarationType.Variable, presenterAction); - encapsulatedWholeNumber.PropertyName = "LongValue"; - Assert.IsTrue(validator.HasConflictingPropertyIdentifier(encapsulatedWholeNumber)); - //Assert.Less(0, validator.HasNewPropertyNameConflicts(encapsulatedWholeNumber, encapsulatedWholeNumber.QualifiedModuleName, new Declaration[] { encapsulatedWholeNumber.Declaration })); - } + Assert.AreEqual(false, model[fieldUT].HasValidEncapsulationAttributes, $"{fieldUT} failed"); } - private void CreateAndParse(IVBE vbe, Action theTest) + [TestCase("Dim test As String", "arg")] //Local variable + [TestCase(@"Const test As String = ""Foo""", "arg")] //Local constant + [TestCase(@"Const localTest As String = ""Foo""", "test")] //parameter + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void TargetNameUsedForLimitedScopeDeclarations(string localDeclaration, string parameter) { - var state = MockParser.CreateAndParse(vbe); - using (state) - { - theTest(state as IDeclarationFinderProvider); - } - } + string inputCode = + $@" - private IEncapsulateFieldCandidate CreateEncapsulatedFieldMock(string targetID, string asTypeName, IVBComponent component, string modifiedPropertyName = null, bool encapsulateFlag = true ) - { - var identifiers = new EncapsulationIdentifiers(targetID); - var attributesMock = CreateAttributesMock(targetID, asTypeName, modifiedPropertyName); - - var mock = new Mock(); - mock.SetupGet(m => m.TargetID).Returns(identifiers.TargetFieldName); - mock.SetupGet(m => m.FieldIdentifier).Returns(identifiers.Field); - mock.SetupGet(m => m.PropertyName).Returns(modifiedPropertyName ?? identifiers.Property); - mock.SetupGet(m => m.AsTypeName).Returns(asTypeName); - mock.SetupGet(m => m.EncapsulateFlag).Returns(encapsulateFlag); - //mock.SetupGet(m => m.EncapsulationAttributes).Returns(attributesMock); - mock.SetupGet(m => m.QualifiedModuleName).Returns(new QualifiedModuleName(component)); - return mock.Object; - } +Private te|st As Long - private IEncapsulateFieldCandidate CreateAttributesMock(string targetID, string asTypeName, string modifiedPropertyName = null, bool encapsulateFlag = true) - { - var identifiers = new EncapsulationIdentifiers(targetID); - var mock = new Mock(); - mock.SetupGet(m => m.IdentifierName).Returns(identifiers.TargetFieldName); - mock.SetupGet(m => m.FieldIdentifier).Returns(identifiers.Field); - mock.SetupGet(m => m.PropertyName).Returns(modifiedPropertyName ?? identifiers.Property); - mock.SetupGet(m => m.AsTypeName).Returns(asTypeName); - mock.SetupGet(m => m.EncapsulateFlag).Returns(encapsulateFlag); - return mock.Object; +Private Function Foo({parameter} As String) As String + {localDeclaration} + test = test & ""Foo"" + Foo = test +End Function +"; + var presenterAction = Support.UserAcceptsDefaults(); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.Contains("Test", actualCode); + StringAssert.Contains("test_1", actualCode); + StringAssert.DoesNotContain("Test_1", actualCode); } +// [Test] +// [Category("Refactorings")] +// [Category("Encapsulate Field")] +// public void TargetNameDuplicatedAsLocalVariable_Array() +// { +// const string inputCode = +// @" + +//Private Bou|ndedArray(1 To 100) As Byte + +//Private Function Foo() As Variant +// Dim BoundedArray(1 To 3) As Integer +// BoundedArray(1) = 7 +// BoundedArray(2) = 8 +// BoundedArray(3) = 9 +// Foo = BoundedArray +//End Function +//"; +// var presenterAction = Support.UserAcceptsDefaults(); +// var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); +// StringAssert.Contains("BoundedArray", actualCode); +// StringAssert.Contains("boundedArray_1", actualCode); +// StringAssert.DoesNotContain("BoundedArray_1", actualCode); +// } + protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) { return Support.SupportTestRefactoring(rewritingManager, state, factory, selectionService); diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index 13b401f372..0a4449824b 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -127,13 +127,14 @@ public IEncapsulateFieldCandidate RetrieveEncapsulatedField(string inputCode, st } } - public EncapsulateFieldModel RetrieveUserModifiedModelPriorToRefactoring(IVBE vbe, string declarationName, DeclarationType declarationType, Func presenterAdjustment, params string[] fieldIdentifiers) + public EncapsulateFieldModel RetrieveUserModifiedModelPriorToRefactoring(IVBE vbe, string declarationName, DeclarationType declarationType, Func presenterAdjustment) //, params string[] fieldIdentifiers) { var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); using (state) { - var target = state.DeclarationFinder.DeclarationsWithType(declarationType) - .Single(declaration => declaration.IdentifierName == declarationName); + var targets = state.DeclarationFinder.DeclarationsWithType(declarationType); + + var target = targets.Single(declaration => declaration.IdentifierName == declarationName); var refactoring = TestRefactoring(rewritingManager, state, presenterAdjustment); if (refactoring is IEncapsulateFieldRefactoringTestAccess concrete) From 488becfa7b2515b360ec931a2c5f9acd21d9fec5 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Mon, 16 Dec 2019 07:19:21 -0800 Subject: [PATCH 059/461] Validation improvements and other misc --- .../EncapsulateFieldElementFactory.cs | 5 +- .../EncapsulateFieldValidator.cs | 163 +++++++++++------- .../EncapsulateFieldCandidate.cs | 19 +- .../EncapsulationIdentifiers.cs | 7 +- .../UserDefinedTypeCandidate.cs | 18 +- .../EncapsulateFieldValidatorTests.cs | 151 +++++++++++++--- .../EncapsulateUsingStateUDTTests.cs | 3 +- .../EncapsulatedUDTFieldTests.cs | 83 +++------ .../EncapsulateField/TestSupport.cs | 1 + .../Refactoring/EncapsulateFieldTests.cs | 99 +++++++---- 10 files changed, 343 insertions(+), 206 deletions(-) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs index 3b8d15c6fb..764e9b1148 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs @@ -48,7 +48,8 @@ public IEncapsulateFieldCandidate CreateEncapsulationCandidate(Declaration targe candidate = ApplyTypeSpecificAttributes(candidate); - candidate = SetNonConflictIdentifier(candidate, c => { return _validator.HasConflictingPropertyIdentifier(candidate); }, (s) => { candidate.PropertyName = s.Capitalize(); }, () => candidate.IdentifierName, _validator); + candidate = SetNonConflictIdentifier(candidate, c => { return _validator.HasConflictingIdentifier(candidate, DeclarationType.Property); }, (s) => { candidate.PropertyName = s.Capitalize(); }, () => candidate.PropertyName, _validator); + candidate = SetNonConflictIdentifier(candidate, c => { return _validator.HasConflictingIdentifier(candidate, DeclarationType.Variable); }, (s) => { candidate.FieldIdentifier = s.UnCapitalize(); }, () => candidate.FieldIdentifier, _validator); if (candidate is IUserDefinedTypeCandidate udtVariable) { @@ -62,7 +63,7 @@ public IEncapsulateFieldCandidate CreateEncapsulationCandidate(Declaration targe candidateUDTMember = ApplyTypeSpecificAttributes(candidateUDTMember); - candidateUDTMember = SetNonConflictIdentifier(candidateUDTMember, c => { return _validator.HasConflictingPropertyIdentifier(candidate); }, (s) => { candidateUDTMember.PropertyName = s.Capitalize(); }, () => candidate.IdentifierName, _validator); + candidateUDTMember = SetNonConflictIdentifier(candidateUDTMember, c => { return _validator.HasConflictingIdentifier(candidate, DeclarationType.Property); }, (s) => { candidateUDTMember.PropertyName = s.Capitalize(); }, () => candidate.IdentifierName, _validator); udtVariable.AddMember(candidateUDTMember); } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs index 3e23724fdb..37c1349e95 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -16,11 +16,9 @@ namespace Rubberduck.Refactorings.EncapsulateField public interface IEncapsulateFieldValidator { void RegisterFieldCandidate(IEncapsulateFieldCandidate candidate); - bool HasValidEncapsulationAttributes(IEncapsulateFieldCandidate candidate, IEnumerable ignore); bool IsValidVBAIdentifier(string identifier, DeclarationType declarationType); - bool HasConflictingPropertyIdentifier(IEncapsulateFieldCandidate candidate); - bool HasConflictingFieldIdentifier(IEncapsulateFieldCandidate candidate); - bool IsConflictingFieldIdentifier(string fieldName, IEncapsulateFieldCandidate candidate); + bool HasConflictingIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType); + bool IsConflictingFieldIdentifier(string fieldName, IEncapsulateFieldCandidate candidate, DeclarationType declarationType); } public interface IEncapsulateFieldNamesValidator : IEncapsulateFieldValidator @@ -37,7 +35,7 @@ public class EncapsulateFieldNamesValidator : IEncapsulateFieldNamesValidator private List FlaggedCandidates => FieldCandidates.Where(rc => rc.EncapsulateFlag).ToList(); - public EncapsulateFieldNamesValidator(IDeclarationFinderProvider declarationFinderProvider, Func> retrieveCandidateFields = null) + public EncapsulateFieldNamesValidator(IDeclarationFinderProvider declarationFinderProvider) { _declarationFinderProvider = declarationFinderProvider; FieldCandidates = new List(); @@ -53,98 +51,133 @@ public void RegisterFieldCandidate(IEncapsulateFieldCandidate candidate) public bool IsValidVBAIdentifier(string identifier, DeclarationType declarationType) => VBAIdentifierValidator.IsValidIdentifier(identifier, declarationType); - private List GetPotentialConflictMembers(IEncapsulateFieldCandidate candidate) + private List PotentialConflictIdentifiers(IEncapsulateFieldCandidate candidate, DeclarationType declarationType) { - return _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) - .Where(d => d != candidate.Declaration - && !IsAlwaysIgnoreNameConflictType(d)).ToList(); - } + var members = _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) + .Where(d => d != candidate.Declaration); - private List GetPotentialConflictMembers(IStateUDT stateUDT) - { - return _declarationFinderProvider.DeclarationFinder.Members(stateUDT.QualifiedModuleName) - .Where(d => !IsAlwaysIgnoreNameConflictType(d)).ToList(); + var nameConflictCandidates = members + .Where(d => !IsAlwaysIgnoreNameConflictType(d, declarationType)).ToList(); + + var localReferences = candidate.Declaration.References.Where(rf => rf.QualifiedModuleName == candidate.QualifiedModuleName); + + if (localReferences.Any()) + { + foreach (var idRef in localReferences) + { + var locals = members.Except(nameConflictCandidates) + .Where(localDec => localDec.ParentScopeDeclaration.Equals(idRef.ParentScoping)); + + nameConflictCandidates.AddRange(locals); + } + } + return nameConflictCandidates.Select(c => c.IdentifierName).ToList(); } - public bool HasConflictingPropertyIdentifier(IEncapsulateFieldCandidate candidate) + private List GetPotentialConflictMembers(IStateUDT stateUDT, DeclarationType declarationType) { - var members = GetPotentialConflictMembers(candidate); - var newContentNames = FlaggedCandidates.Where(fc => fc.Declaration != candidate.Declaration).Select(fc => fc.PropertyName); - newContentNames = newContentNames.Concat(FlaggedCandidates.Where(fc => fc.Declaration != candidate.Declaration).Select(fc => fc.FieldIdentifier)); + var potentialDeclarationIdentifierConflicts = new List(); + + var members = _declarationFinderProvider.DeclarationFinder.Members(stateUDT.QualifiedModuleName); - return members.Any(m => m.IdentifierName.EqualsVBAIdentifier(candidate.PropertyName)) - || newContentNames.Any(ed => ed.EqualsVBAIdentifier(candidate.PropertyName)); + var nameConflictCandidates = members + .Where(d => !IsAlwaysIgnoreNameConflictType(d, declarationType)).ToList(); + + potentialDeclarationIdentifierConflicts.AddRange(nameConflictCandidates.Select(d => d.IdentifierName)); + + return potentialDeclarationIdentifierConflicts.ToList(); } - public bool HasConflictingFieldIdentifier(IEncapsulateFieldCandidate candidate) + public bool HasConflictingIdentifier(IEncapsulateFieldCandidate field, DeclarationType declarationType) { - var members = GetPotentialConflictMembers(candidate); + //The declared type of a function declaration may not be a private enum name. + //=>Means encapsulating a private enum field must be 'As Long' + + //If a procedure declaration whose visibility is public has a procedure name + //that is the same as the name of a project or name of a module then + //all references to the procedure name must be explicitly qualified with + //its project or module name unless the reference occurs within the module that defines the procedure. + - return members.Any(m => m.IdentifierName.EqualsVBAIdentifier(candidate.FieldIdentifier)); + var potentialDeclarationIdentifierConflicts = new List(); + potentialDeclarationIdentifierConflicts.AddRange(PotentialConflictIdentifiers(field, declarationType)); + + potentialDeclarationIdentifierConflicts.AddRange(FlaggedCandidates.Where(fc => fc.Declaration != field.Declaration).Select(fc => fc.PropertyName)); + //potentialDeclarationIdentifierConflicts.AddRange(FlaggedCandidates.Where(fc => fc.Declaration != field.Declaration).Select(fc => fc.FieldIdentifier)); + + var identifierToCompare = declarationType.HasFlag(DeclarationType.Property) + ? field.PropertyName + : field.FieldIdentifier; + + return potentialDeclarationIdentifierConflicts.Any(m => m.EqualsVBAIdentifier(identifierToCompare)); } - public bool IsConflictingFieldIdentifier(string fieldName, IEncapsulateFieldCandidate candidate) + public bool IsConflictingFieldIdentifier(string fieldName, IEncapsulateFieldCandidate candidate, DeclarationType declarationType) { - var members = GetPotentialConflictMembers(candidate); + var members = PotentialConflictIdentifiers(candidate, declarationType); - return members.Any(m => m.IdentifierName.EqualsVBAIdentifier(fieldName) || candidate.PropertyName.EqualsVBAIdentifier(fieldName)); + return members.Any(m => m.EqualsVBAIdentifier(fieldName)); } public bool IsConflictingStateUDTTypeIdentifier(IStateUDT stateUDT) { - var members = GetPotentialConflictMembers(stateUDT); + var potentialConflictNames = GetPotentialConflictMembers(stateUDT, DeclarationType.UserDefinedType); - return members.Any(m => m.IdentifierName.EqualsVBAIdentifier(stateUDT.TypeIdentifier)); + return potentialConflictNames.Any(m => m.EqualsVBAIdentifier(stateUDT.TypeIdentifier)); } public bool IsConflictingStateUDTFieldIdentifier(IStateUDT stateUDT) { - var members = GetPotentialConflictMembers(stateUDT); + var potentialConflictNames = GetPotentialConflictMembers(stateUDT, DeclarationType.Variable); - return members.Any(m => m.IdentifierName.EqualsVBAIdentifier(stateUDT.FieldIdentifier)); + return potentialConflictNames.Any(m => m.EqualsVBAIdentifier(stateUDT.FieldIdentifier)); } - public bool HasValidEncapsulationAttributes(IEncapsulateFieldCandidate candidate, IEnumerable ignore) + //The refactoring only inserts elements with the following Accessibilities: + //Variables => Private + //Properties => Public + //UDT => Private + private bool IsAlwaysIgnoreNameConflictType(Declaration d, DeclarationType toEnapsulateDeclarationType) { - if (!candidate.EncapsulateFlag) { return true; } - - var internalValidations = candidate as IEncapsulateFieldCandidateValidations; - - if (!internalValidations.IsSelfConsistent - || HasConflictingPropertyIdentifier(candidate)) + var NeverCauseNameConflictTypes = new List() + { + DeclarationType.Project, + DeclarationType.ProceduralModule, + DeclarationType.ClassModule, + DeclarationType.Parameter, + DeclarationType.EnumerationMember, + DeclarationType.Enumeration, + DeclarationType.UserDefinedTypeMember + }; + + if (toEnapsulateDeclarationType.HasFlag(DeclarationType.Variable)) { - return false; + //5.2.3.4: An enum member name may not be the same as any variable name + //or constant name that is defined within the same module + NeverCauseNameConflictTypes.Remove(DeclarationType.EnumerationMember); } - return true; - } + else if (toEnapsulateDeclarationType.HasFlag(DeclarationType.UserDefinedType)) + { + //5.2.3.3 If an is an element of a its + //UDT name cannot be the same as the enum name of any + //or the UDT name of any other within the same - private bool IsAlwaysIgnoreNameConflictType(Declaration d) - { - //TODO: // candidate.DeclarationType == DeclarationType.EnumerationMember || candidate.DeclarationType == DeclarationType.UserDefinedTypeMember; - //FIXME: once a failing test is written + //5.2.3.4 The enum name of a cannot be the same as the enum name of any other + // or as the UDT name of a within the same . + NeverCauseNameConflictTypes.Remove(DeclarationType.Enumeration); + } + else if (toEnapsulateDeclarationType.HasFlag(DeclarationType.Property)) + { + //Each < subroutine - declaration > and < function - declaration > must have a + //procedure name that is different from any other module variable name, + //module constant name, enum member name, or procedure name that is defined + //within the same module. + + NeverCauseNameConflictTypes.Remove(DeclarationType.EnumerationMember); + } return d.IsLocalVariable() || d.IsLocalConstant() - || d.DeclarationType.HasFlag(DeclarationType.Parameter); - } - - //private bool UsesScopeResolution(Antlr4.Runtime.RuleContext ruleContext) - //{ - // return (ruleContext is VBAParser.WithMemberAccessExprContext) - // || (ruleContext is VBAParser.MemberAccessExprContext); - //} - - private bool HasValidIdentifiers(IEncapsulateFieldCandidate attributes, DeclarationType declarationType) - { - return VBAIdentifierValidator.IsValidIdentifier(attributes.FieldIdentifier, declarationType) - && VBAIdentifierValidator.IsValidIdentifier(attributes.PropertyName, DeclarationType.Property) - && VBAIdentifierValidator.IsValidIdentifier(attributes.ParameterName, DeclarationType.Parameter); - } - - private bool HasInternalNameConflicts(IEncapsulateFieldCandidate attributes) - { - return attributes.PropertyName.EqualsVBAIdentifier(attributes.FieldIdentifier) - || attributes.PropertyName.EqualsVBAIdentifier(attributes.ParameterName) - || attributes.FieldIdentifier.EqualsVBAIdentifier(attributes.ParameterName); + || NeverCauseNameConflictTypes.Contains(d.DeclarationType); } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs index daa9c2199a..022a01b2f1 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs @@ -105,10 +105,10 @@ public virtual void StageFieldReferenceReplacements(IStateUDT stateUDT = null) || FieldIdentifier.EqualsVBAIdentifier(ParameterName)); public bool HasConflictingPropertyIdentifier - => _validator.HasConflictingPropertyIdentifier(this); + => _validator.HasConflictingIdentifier(this, DeclarationType.Property); public bool HasConflictingFieldIdentifier - => _validator.HasConflictingFieldIdentifier(this); + => _validator.HasConflictingIdentifier(this, DeclarationType.Variable); public bool HasValidEncapsulationAttributes { @@ -117,7 +117,7 @@ public bool HasValidEncapsulationAttributes if (!EncapsulateFlag) { return true; } return IsSelfConsistent - && !_validator.HasConflictingPropertyIdentifier(this); + && !_validator.HasConflictingIdentifier(this, DeclarationType.Property); } } @@ -149,7 +149,7 @@ public virtual void SetReferenceRewriteContent(IdentifierReference idRef, string public virtual string TargetID => _target?.IdentifierName ?? IdentifierName; public bool EncapsulateFlag { set; get; } - public bool IsReadOnly { set; get; } + public virtual bool IsReadOnly { set; get; } public bool CanBeReadWrite { set; get; } public virtual string FieldIdentifier @@ -172,7 +172,8 @@ public virtual string PropertyName //The preferred NewFieldName is the original Identifier private void TryRestoreNewFieldNameAsOriginalFieldIdentifierName() { - var canNowUseOriginalFieldName = !_validator.IsConflictingFieldIdentifier(_fieldAndProperty.TargetFieldName, this); + var canNowUseOriginalFieldName = !_fieldAndProperty.TargetFieldName.EqualsVBAIdentifier(_fieldAndProperty.Property) + && !_validator.IsConflictingFieldIdentifier(_fieldAndProperty.TargetFieldName, this, DeclarationType.Variable); if (canNowUseOriginalFieldName) { @@ -183,11 +184,11 @@ private void TryRestoreNewFieldNameAsOriginalFieldIdentifierName() if (_fieldAndProperty.Field.EqualsVBAIdentifier(_fieldAndProperty.TargetFieldName)) { _fieldAndProperty.Field = _fieldAndProperty.DefaultNewFieldName; - var isConflictingFieldIdentifier = _validator.HasConflictingFieldIdentifier(this); + var isConflictingFieldIdentifier = _validator.HasConflictingIdentifier(this, DeclarationType.Variable); for (var count = 1; count < 10 && isConflictingFieldIdentifier; count++) { FieldIdentifier = FieldIdentifier.IncrementIdentifier(); - isConflictingFieldIdentifier = _validator.HasConflictingFieldIdentifier(this); + isConflictingFieldIdentifier = _validator.HasConflictingIdentifier(this, DeclarationType.Variable); } } } @@ -249,9 +250,9 @@ protected string AccessorTokenToContent(AccessorTokens token) } public virtual IEnumerable PropertyAttributeSets - => new List() { AsPropertyGeneratorSpec }; + => new List() { AsPropertyAttributeSet }; - protected virtual IPropertyGeneratorAttributes AsPropertyGeneratorSpec + protected virtual IPropertyGeneratorAttributes AsPropertyAttributeSet { get { diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs index ff99ad886b..84df5c89c5 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs @@ -11,7 +11,6 @@ public class EncapsulationIdentifiers private KeyValuePair _fieldAndProperty; private string _targetIdentifier; - private string _defaultPropertyName; private string _setLetParameter; public EncapsulationIdentifiers(Declaration target) @@ -20,14 +19,16 @@ public EncapsulationIdentifiers(Declaration target) public EncapsulationIdentifiers(string field) { _targetIdentifier = field; - _defaultPropertyName = field.Capitalize(); + DefaultPropertyName = field.Capitalize(); DefaultNewFieldName = (field.UnCapitalize()).IncrementIdentifier(); - _fieldAndProperty = new KeyValuePair(DefaultNewFieldName, _defaultPropertyName); + _fieldAndProperty = new KeyValuePair(DefaultNewFieldName, DefaultPropertyName); _setLetParameter = DEFAULT_WRITE_PARAMETER; } public string TargetFieldName => _targetIdentifier; + public string DefaultPropertyName { private set; get; } + public string DefaultNewFieldName { private set; get; } public string Field diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs index 595fa990e6..95de68ba17 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs @@ -43,6 +43,22 @@ public override string FieldIdentifier set => _fieldAndProperty.Field = value; } + private bool _isReadOnly; + public override bool IsReadOnly + { + get => _isReadOnly; + set + { + _isReadOnly = value; + foreach ( var member in Members) + { + member.IsReadOnly = value; + } + } + } + + + public override string ReferenceQualifier { set @@ -92,7 +108,7 @@ public override IEnumerable PropertyAttributeSets } return specs; } - return new List() { AsPropertyGeneratorSpec }; + return new List() { AsPropertyAttributeSet }; } } diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs index 5cd3def755..44547b1cae 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs @@ -13,6 +13,7 @@ using Rubberduck.VBEditor.Utility; using Rubberduck.Parsing.Symbols; using System; +using Rubberduck.VBEditor.SafeComWrappers; namespace RubberduckTests.Refactoring.EncapsulateField { @@ -233,7 +234,7 @@ Public that As TBar var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, fieldUT, DeclarationType.Variable, presenterAction); - Assert.AreEqual(false, model[fieldUT].HasValidEncapsulationAttributes, $"{fieldUT} failed"); + Assert.AreEqual(false, model[fieldUT].HasValidEncapsulationAttributes); } [Test] @@ -256,7 +257,53 @@ Public wholeNumber As String var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, fieldUT, DeclarationType.Variable, presenterAction); - Assert.AreEqual(false, model[fieldUT].HasValidEncapsulationAttributes, $"{fieldUT} failed"); + Assert.AreEqual(false, model[fieldUT].HasValidEncapsulationAttributes); + } + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulatePrivateField_EnumMemberConflict() + { + //5.2.3.4: An enum member name may not be the same as any variable name, or constant name that is defined within the same module + const string inputCode = + @" + +Public Enum NumberTypes + Whole = -1 + Integral = 0 + Rational_1 = 1 +End Enum + +Private rati|onal As NumberTypes +"; + + var presenterAction = Support.UserAcceptsDefaults(); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.Contains("Public Property Get Rational() As NumberTypes", actualCode); + StringAssert.Contains("Rational = rational_2", actualCode); + } + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulatePrivateField_UDTMemberConflict() + { + const string inputCode = + @" + +Private Type TVehicle + Wheels As Integer + MPG As Double +End Type + +Private whe|els As Integer +"; + + var presenterAction = Support.UserAcceptsDefaults(); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.Contains("Public Property Get Wheels()", actualCode); + StringAssert.Contains("Wheels = wheels_1", actualCode); } [TestCase("Dim test As String", "arg")] //Local variable @@ -267,8 +314,7 @@ Public wholeNumber As String public void TargetNameUsedForLimitedScopeDeclarations(string localDeclaration, string parameter) { string inputCode = - $@" - +$@" Private te|st As Long Private Function Foo({parameter} As String) As String @@ -284,30 +330,79 @@ End Function StringAssert.DoesNotContain("Test_1", actualCode); } -// [Test] -// [Category("Refactorings")] -// [Category("Encapsulate Field")] -// public void TargetNameDuplicatedAsLocalVariable_Array() -// { -// const string inputCode = -// @" - -//Private Bou|ndedArray(1 To 100) As Byte - -//Private Function Foo() As Variant -// Dim BoundedArray(1 To 3) As Integer -// BoundedArray(1) = 7 -// BoundedArray(2) = 8 -// BoundedArray(3) = 9 -// Foo = BoundedArray -//End Function -//"; -// var presenterAction = Support.UserAcceptsDefaults(); -// var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); -// StringAssert.Contains("BoundedArray", actualCode); -// StringAssert.Contains("boundedArray_1", actualCode); -// StringAssert.DoesNotContain("BoundedArray_1", actualCode); -// } + [TestCase("Dim test As String", "arg")] //Local variable + [TestCase(@"Const test As String = ""Foo""", "arg")] //Local constant + [TestCase(@"Const localTest As String = ""Foo""", "test")] //parameter + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void TargetReferenceScopeUsesPropertyName(string localDeclaration, string parameter) + { + string inputCode = +$@" +Private aName As String + +Private Function Foo({parameter} As String) As String + {localDeclaration} + test = aName & test + Foo = test +End Function +"; + var fieldUT = "aName"; + var userInput = new UserInputDataObject() + .AddAttributeSet(fieldUT, "Test", true); + + var presenterAction = Support.SetParameters(userInput); + + var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, fieldUT, DeclarationType.Variable, presenterAction); + + Assert.AreEqual(false, model[fieldUT].HasValidEncapsulationAttributes); + } + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void TargetDefaultFieldIDConflict() + { + string inputCode = +$@" +Private tes|t As String +Private test_1 As String + +Public Sub Foo(arg As String) + test = arg & test_1 +End Sub +"; + var presenterAction = Support.UserAcceptsDefaults(); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.Contains("Test", actualCode); + StringAssert.Contains("Private test_2 As String", actualCode); + StringAssert.DoesNotContain("test_1 = arg & test_1", actualCode); + } + + [TestCase(MockVbeBuilder.TestModuleName)] + [TestCase("TestModule")] + [TestCase("TestClass")] + [TestCase(MockVbeBuilder.TestProjectName)] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void ModuleAndProjectNamesAreValid(string userEnteredName) + { + var fieldUT = "foo"; + var userInput = new UserInputDataObject() + .AddAttributeSet(fieldUT, userEnteredName, true); + + var presenterAction = Support.SetParameters(userInput); + + var vbe = MockVbeBuilder.BuildFromModules( + (MockVbeBuilder.TestModuleName, "Private foo As String", ComponentType.StandardModule), + ("TestModule", "Private foo1 As String", ComponentType.StandardModule), + ("TestClass", "Private foo2 As String", ComponentType.ClassModule)).Object; + + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, fieldUT, DeclarationType.Variable, presenterAction); + + Assert.AreEqual(true, model[fieldUT].HasValidEncapsulationAttributes); + } protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) { diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs index 0b3c353899..20d982fdd9 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs @@ -193,14 +193,13 @@ Public myBar As TBar userInput.EncapsulateAsUDT = true; - //userInput.StateUDT_TypeName = "This_Type"; - //userInput.StateUDT_FieldName = "this"; var presenterAction = Support.SetParameters(userInput); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.Contains($"Private Type {expectedIdentifier}", actualCode); } + protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) { return Support.SupportTestRefactoring(rewritingManager, state, factory, selectionService); diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs index 6a8819a357..5851e9a8c9 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs @@ -237,9 +237,6 @@ End With End Sub "; - //var userInput = new UserInputDataObject("this"); - - //var presenterAction = Support.SetParameters(userInput); var presenterAction = Support.UserAcceptsDefaults(); var codeString = inputCode.ToCodeString(); @@ -526,10 +523,6 @@ End Sub [Category("Encapsulate Field")] public void StdModuleSource_UDTField_StdModuleReferences(string sourceModuleName, string referenceQualifier, string typeDeclarationAccessibility) { - //var sourceModuleName = "SourceModule"; - - //var actualModuleCode = Scenario_StdModuleSource_StandardAndClassReferencingModules(referenceQualifier, typeDeclarationAccessibility, sourceModuleName, userInput); - var sourceModuleCode = $@" {typeDeclarationAccessibility} Type TBar @@ -563,32 +556,6 @@ Public Sub FooBar() End With End Sub "; - - // string classModuleReferencingCode = - //$@"Option Explicit - - //'ClassModule referencing the UDT - - //Private Const foo As String = ""Foo"" - - //Private Const bar As Long = 7 - - //Public Sub Foo() - // {referenceQualifier}.First = foo - //End Sub - - //Public Sub Bar() - // {referenceQualifier}.Second = bar - //End Sub - - //Public Sub FooBar() - // With {sourceModuleName} - // .this.First = foo - // .this.Second = bar - // End With - //End Sub - //"; - var userInput = new UserInputDataObject("this", "MyType"); var presenterAction = Support.SetParameters(userInput); @@ -603,35 +570,12 @@ End Sub ("StdModule", moduleReferencingCode, ComponentType.StandardModule), (sourceModuleName, sourceCodeString.Code, ComponentType.StandardModule)); - //Only Public Types are accessible to ClassModules - //if (typeDeclarationAccessibility.Equals("Public")) - //{ - // actualModuleCode = RefactoredCode( - // sourceModuleName, - // sourceCodeString.CaretPosition.ToOneBased(), - // presenterAction, - // null, - // false, - // ("StdModule", procedureModuleReferencingCode, ComponentType.StandardModule), - // ("ClassModule", classModuleReferencingCode, ComponentType.ClassModule), - // (sourceModuleName, sourceCodeString.Code, ComponentType.StandardModule)); - //} - - //return actualModuleCode; - - - if (typeDeclarationAccessibility.Equals("Public")) { var referencingModuleCode = actualModuleCode["StdModule"]; StringAssert.Contains($"{sourceModuleName}.MyType.First = ", referencingModuleCode); StringAssert.Contains($"{sourceModuleName}.MyType.Second = ", referencingModuleCode); StringAssert.Contains($" .MyType.Second = ", referencingModuleCode); - - //var referencingClassCode = actualModuleCode["ClassModule"]; - //StringAssert.Contains($"{sourceModuleName}.MyType.First = ", referencingClassCode); - //StringAssert.Contains($"{sourceModuleName}.MyType.Second = ", referencingClassCode); - //StringAssert.Contains($" .MyType.Second = ", referencingClassCode); } if (typeDeclarationAccessibility.Equals("Private")) @@ -646,7 +590,6 @@ End Sub private IDictionary Scenario_StdModuleSource_StandardAndClassReferencingModules(string referenceQualifier, string typeDeclarationAccessibility, string sourceModuleName, UserInputDataObject userInput) { - //var referenceQualifier = moduleQualifyReferences ? $"{sourceModuleName}.this" : "this"; var sourceModuleCode = $@" {typeDeclarationAccessibility} Type TBar @@ -730,7 +673,6 @@ End Sub null, false, ("StdModule", procedureModuleReferencingCode, ComponentType.StandardModule), - //("ClassModule", classModuleReferencingCode, ComponentType.ClassModule), (sourceModuleName, sourceCodeString.Code, ComponentType.StandardModule)); return actualModuleCode; @@ -834,6 +776,31 @@ End Sub StringAssert.Contains($" .MyType.Second = ", referencingClassCode); } + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedTypeUserUpdatesToBeReadOnly() + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +Private t|his As TBar"; + + var userInput = new UserInputDataObject() + .AddAttributeSet("this", isReadOnly: true); + + var presenterAction = Support.SetParameters(userInput); + + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + + StringAssert.DoesNotContain("Public Property Let First", actualCode); + StringAssert.DoesNotContain("Public Property Let Second", actualCode); + } + diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index 0a4449824b..014e203541 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -61,6 +61,7 @@ public Func SetParameters(UserInpu attrsInitializedByTheRefactoring.PropertyName = testModifiedAttribute.PropertyName; attrsInitializedByTheRefactoring.EncapsulateFlag = testModifiedAttribute.EncapsulateFlag; + attrsInitializedByTheRefactoring.IsReadOnly = testModifiedAttribute.IsReadOnly; //var currentAttributes = model[testModifiedAttribute.TargetFieldName].EncapsulationAttributes; //currentAttributes.PropertyName = attrsInitializedByTheRefactoring.PropertyName; diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index a79b171a58..1ad3121af7 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -339,6 +339,29 @@ End Property Assert.AreEqual(expectedCode.Trim(), actualCode); } + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulatePrivateField_Enum() + { + const string inputCode = + @" + +Public Enum NumberTypes + Whole = -1 + Integral = 0 + Rational = 1 +End Enum + +Private numberT|ype As NumberTypes +"; + + var presenterAction = Support.UserAcceptsDefaults(); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.Contains("Public Property Get NumberType() As NumberTypes", actualCode); + StringAssert.Contains("NumberType = numberType_1", actualCode); + } + [Test] [Category("Refactorings")] [Category("Encapsulate Field")] @@ -363,44 +386,44 @@ End Property var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); Assert.AreEqual(expectedCode.Trim(), actualCode); } - - [Test] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void EncapsulatePrivateField_NameConflict() - { - const string inputCode = - @"Private fizz As String -Private mName As String - -Public Property Get Name() As String - Name = mName -End Property - -Public Property Let Name(ByVal value As String) - mName = value -End Property -"; - var fieldName = "fizz"; - var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; - - var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); - using (state) - { - IEncapsulateFieldCandidate efd = null; - var fields = new List(); - var validator = new EncapsulateFieldNamesValidator(state, () => fields); - - var match = state.DeclarationFinder.MatchName(fieldName).Single(); - efd = new EncapsulateFieldCandidate(match, validator); - fields.Add(efd); - efd.PropertyName = "Name"; - - //var hasConflict = !validator.HasValidEncapsulationAttributes(efd, efd.QualifiedModuleName, new Declaration[] { efd.Declaration }); - var hasConflict = validator.HasConflictingPropertyIdentifier(efd); - Assert.IsTrue(hasConflict); - } - } +// TODO: this test used the old method of injecting conflict names lists - rework +// [Test] +// [Category("Refactorings")] +// [Category("Encapsulate Field")] +// public void EncapsulatePrivateField_NameConflict() +// { +// const string inputCode = +// @"Private fizz As String +//Private mName As String + +//Public Property Get Name() As String +// Name = mName +//End Property + +//Public Property Let Name(ByVal value As String) +// mName = value +//End Property +//"; +// var fieldName = "fizz"; +// var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; + +// var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); +// using (state) +// { +// IEncapsulateFieldCandidate efd = null; +// var fields = new List(); +// var validator = new EncapsulateFieldNamesValidator(state, () => fields); + +// var match = state.DeclarationFinder.MatchName(fieldName).Single(); +// efd = new EncapsulateFieldCandidate(match, validator); +// fields.Add(efd); +// efd.PropertyName = "Name"; + +// //var hasConflict = !validator.HasValidEncapsulationAttributes(efd, efd.QualifiedModuleName, new Declaration[] { efd.Declaration }); +// var hasConflict = validator.HasConflictingPropertyIdentifier(efd); +// Assert.IsTrue(hasConflict); +// } +// } [Test] [Category("Refactorings")] From 3818e043cd6ba3cda3adbecc31c836b3ffb3fb0d Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Mon, 16 Dec 2019 20:11:39 -0800 Subject: [PATCH 060/461] GUI mods --- .../EncapsulateFieldView.xaml | 42 +++-- .../EncapsulateFieldViewModel.cs | 148 +++++++++--------- .../ViewableEncapsulatedField.cs | 4 +- 3 files changed, 91 insertions(+), 103 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml index b6942ec40a..a3ceaea50d 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml @@ -12,17 +12,17 @@ - - + + @@ -41,16 +33,15 @@ - - @@ -66,35 +57,15 @@ - - - - @@ -103,42 +74,11 @@ - + - - - - + - - - + - - + + - - + + + @@ -288,38 +175,49 @@ - + IsEnabled="{Binding Path=EnableReadOnlyOption}" + Content="Read Only" + Margin="10,5,5,2" + FontWeight="Bold" + IsTabStop="False" + Command="{Binding Path=ReadOnlyChangeCommand}" + CommandParameter="{Binding ElementName=EncapsulationFields, Path=SelectedField}" /> - - + + + + - + + + + + + Height="200" + IsReadOnly="True" + IsTabStop="False" + TabIndex="6" + Text="{Binding PropertyPreview,Mode=OneWay}" /> + @@ -336,13 +234,15 @@ diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs index 3ee448eb79..4028ffbc7f 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs @@ -1,15 +1,63 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using NLog; using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings.EncapsulateField; +using Rubberduck.Resources; using Rubberduck.UI.Command; namespace Rubberduck.UI.Refactorings.EncapsulateField { public class EncapsulateFieldViewModel : RefactoringViewModelBase { + private class MasterDetailSelectionManager + { + private const string _neverATargeID = "_Never_a_TargetID_"; + private bool _detailFieldIsFlagged; + + public MasterDetailSelectionManager(string targetID) + { + SelectionTargetID = targetID; + DetailField = null; + _detailFieldIsFlagged = false; + } + + + private IEncapsulatedFieldViewData _detailField; + public IEncapsulatedFieldViewData DetailField + { + set + { + _detailField = value; + _detailFieldIsFlagged = _detailField?.EncapsulateFlag ?? false; + } + get => _detailField; + } + + public string SelectionTargetID { set; get; } + + public bool DetailUpdateRequired + { + get + { + if (DetailField is null) + { + return true; + } + + if (_detailFieldIsFlagged != DetailField.EncapsulateFlag) + { + _detailFieldIsFlagged = !_detailFieldIsFlagged; + return true; + } + return SelectionTargetID != (DetailField?.TargetID ?? _neverATargeID); + } + } + } + + private MasterDetailSelectionManager _masterDetail; public RubberduckParserState State { get; } public EncapsulateFieldViewModel(EncapsulateFieldModel model, RubberduckParserState state/*, IIndenter indenter*/) : base(model) @@ -24,9 +72,18 @@ public EncapsulateFieldViewModel(EncapsulateFieldModel model, RubberduckParserSt EncapsulateFlagChangeCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ManageEncapsulationFlagsAndSelectedItem); ReadOnlyChangeCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ChangeIsReadOnlyFlag); - //SelectedField = EncapsulationFields.FirstOrDefault(ef => ef.EncapsulateFlag); _lastCheckedBoxes = EncapsulationFields.Where(ef => ef.EncapsulateFlag).ToList(); - ManageEncapsulationFlagsAndSelectedItem(null); + var selectedField = model.SelectedFieldCandidates.FirstOrDefault(); + + _masterDetail = new MasterDetailSelectionManager(selectedField.TargetID); + if (selectedField != null) + { + _masterDetail.DetailField = EncapsulationFields.Where(ef => ef.EncapsulateFlag).Single(); + } + + ManageEncapsulationFlagsAndSelectedItem(selectedField); + + RefreshValidationResults(); } public ObservableCollection EncapsulationFields @@ -47,76 +104,75 @@ public ObservableCollection EncapsulationFields } } - private string _selectedTargetID; public IEncapsulatedFieldViewData SelectedField { set { if (value is null) { return; } - _selectedTargetID = value.TargetID; - var _selectedField = value; - PropertyName = _selectedField.IsPrivateUserDefinedType - ? "Encapsulates UDT Members" - : _selectedField.PropertyName; - - IsReadOnly = _selectedField.IsReadOnly; - - OnPropertyChanged(nameof(EnableReadOnlyOption)); - OnPropertyChanged(nameof(EnablePropertyNameEditor)); - OnPropertyChanged(nameof(HideGroupBox)); - OnPropertyChanged(nameof(GroupBoxHeaderContent)); + _masterDetail.SelectionTargetID = value.TargetID; OnPropertyChanged(nameof(SelectedField)); - OnPropertyChanged(nameof(HasValidNames)); - OnPropertyChanged(nameof(BackingField)); + if (_masterDetail.DetailUpdateRequired) + { + _masterDetail.DetailField = SelectedField; + UpdateDetailForSelection(); + } + OnPropertyChanged(nameof(PropertyPreview)); } - get => EncapsulationFields.FirstOrDefault(f => f.TargetID.Equals(_selectedTargetID)); // _selectedField; + get => EncapsulationFields.FirstOrDefault(f => f.TargetID.Equals(_masterDetail.SelectionTargetID)); // _selectedField; } - public bool HideGroupBox - => !(SelectedField?.EncapsulateFlag ?? true); - - public bool EnablePropertyNameEditor - => !(SelectedField?.IsPrivateUserDefinedType ?? false); - - public bool EnableReadOnlyOption - => !(SelectedField?.IsRequiredToBeReadOnly ?? false); + private void UpdateDetailForSelection() + { - public string GroupBoxHeaderContent - => $"Encapsulation Property for Field: {SelectedField?.TargetID ?? string.Empty}"; + RefreshValidationResults(); - public string BackingField - => $"Backing Field : {SelectedField?.NewFieldName ?? string.Empty}"; + OnPropertyChanged(nameof(SelectedFieldIsNotFlagged)); + OnPropertyChanged(nameof(GroupBoxHeaderContent)); + OnPropertyChanged(nameof(PropertyName)); + OnPropertyChanged(nameof(IsReadOnly)); + OnPropertyChanged(nameof(HasValidNames)); + OnPropertyChanged(nameof(EnableReadOnlyOption)); + OnPropertyChanged(nameof(SelectedFieldIsPrivateUDT)); + OnPropertyChanged(nameof(SelectedFieldHasEditablePropertyName)); + OnPropertyChanged(nameof(SelectionHasValidEncapsulationAttributes)); + OnPropertyChanged(nameof(PropertyPreview)); + OnPropertyChanged(nameof(EncapsulationFields)); + OnPropertyChanged(nameof(ValidationErrorMessage)); + } - string _propertyName; public string PropertyName { set { - if (SelectedField is null) { return; } + if (SelectedField is null || value is null) { return; } - _propertyName = value; - SelectedField.PropertyName = value; - OnPropertyChanged(nameof(PropertyName)); - OnPropertyChanged(nameof(BackingField)); - OnPropertyChanged(nameof(HasValidNames)); - OnPropertyChanged(nameof(HasValidEncapsulationAttributes)); - OnPropertyChanged(nameof(PropertyPreview)); - OnPropertyChanged(nameof(EncapsulationFields)); + _masterDetail.DetailField.PropertyName = value; + UpdateDetailForSelection(); } - get => _propertyName; - } - public bool HasValidEncapsulationAttributes - { - get - { - return SelectedField?.HasValidEncapsulationAttributes ?? false; - } + get => _masterDetail.DetailField?.PropertyName ?? SelectedField?.PropertyName ?? string.Empty; // _propertyName; } + public bool SelectedFieldIsNotFlagged + => !(_masterDetail.DetailField?.EncapsulateFlag ?? false); + + public bool SelectedFieldIsPrivateUDT + => (_masterDetail.DetailField?.IsPrivateUserDefinedType ?? false); + + public bool SelectedFieldHasEditablePropertyName => !SelectedFieldIsPrivateUDT; + + public bool EnableReadOnlyOption + => !(_masterDetail.DetailField?.IsRequiredToBeReadOnly ?? false); + + public string GroupBoxHeaderContent + => $"{_masterDetail.DetailField?.TargetID ?? string.Empty} {EncapsulateFieldResources.GroupBoxHeaderSuffix} "; + + private string _validationErrorMessage; + public string ValidationErrorMessage => _validationErrorMessage; + private string _fieldDescriptor; public string FieldDescriptor { @@ -138,15 +194,14 @@ public string TargetID get => _targetID; } - private bool _isReadOnly; public bool IsReadOnly { set { - _isReadOnly = value; + _masterDetail.DetailField.IsReadOnly = value; OnPropertyChanged(nameof(IsReadOnly)); } - get => _isReadOnly; + get => _masterDetail.DetailField?.IsReadOnly ?? SelectedField?.IsReadOnly ?? false; } public bool EncapsulateAsUDT @@ -159,11 +214,33 @@ public bool EncapsulateAsUDT } } - public bool HasValidNames + private bool _hasValidNames; + public bool HasValidNames => _hasValidNames; + + private bool _selectionHasValidEncapsulationAttributes; + public bool SelectionHasValidEncapsulationAttributes => _selectionHasValidEncapsulationAttributes; + + private Dictionary _failedValidationResults = new Dictionary(); + private void RefreshValidationResults() { - get + _failedValidationResults.Clear(); + _hasValidNames = true; + _selectionHasValidEncapsulationAttributes = true; + _validationErrorMessage = string.Empty; + + foreach (var field in EncapsulationFields.Where(ef => ef.EncapsulateFlag)) { - return EncapsulationFields.All(ef => ef.HasValidEncapsulationAttributes); + if (!field.TryValidateEncapsulationAttributes(out var errorMessage)) + { + _failedValidationResults.Add(field.TargetID, errorMessage); + } + } + + _hasValidNames = !_failedValidationResults.Any(); + if (_failedValidationResults.TryGetValue(_masterDetail.SelectionTargetID, out var errorMsg)) + { + _validationErrorMessage = errorMsg; + _selectionHasValidEncapsulationAttributes = false; } } @@ -179,7 +256,17 @@ private void ToggleSelection(bool value) item.EncapsulateFlag = value; } _lastCheckedBoxes = EncapsulationFields.Where(ef => ef.EncapsulateFlag).ToList(); + if (value) + { + SelectedField = _lastCheckedBoxes.FirstOrDefault(); + } + else + { + _masterDetail.DetailField = null; + } ReloadListAndPreview(); + RefreshValidationResults(); + UpdateDetailForSelection(); } public CommandBase IsReadOnlyCommand { get; } @@ -188,24 +275,37 @@ private void ToggleSelection(bool value) public CommandBase EncapsulateFlagChangeCommand { get; } public CommandBase ReadOnlyChangeCommand { get; } + public string Caption + => EncapsulateFieldResources.Caption; + + public string InstructionText + => EncapsulateFieldResources.InstructionText; + + public string Preview + => EncapsulateFieldResources.Preview; + + public string TitleText + => EncapsulateFieldResources.TitleText; + + public string PrivateUDTPropertyText + => EncapsulateFieldResources.PrivateUDTPropertyText; + private void ChangeIsReadOnlyFlag(object param) { if (SelectedField is null) { return; } - SelectedField.IsReadOnly = !SelectedField.IsReadOnly; + _masterDetail.DetailField.IsReadOnly = SelectedField.IsReadOnly; OnPropertyChanged(nameof(IsReadOnly)); OnPropertyChanged(nameof(PropertyPreview)); } - private List _lastCheckedBoxes; - + private List _lastCheckedBoxes = new List(); private void ManageEncapsulationFlagsAndSelectedItem(object param) { var selected = _lastCheckedBoxes.FirstOrDefault(); - if (_lastCheckedBoxes.Count == EncapsulationFields.Count) + if (_lastCheckedBoxes.Count == EncapsulationFields.Where(f => f.EncapsulateFlag).Count()) { - SelectedField = selected; return; } @@ -223,7 +323,14 @@ private void ManageEncapsulationFlagsAndSelectedItem(object param) selected = beforeChecked.First(); } _lastCheckedBoxes = EncapsulationFields.Where(ef => ef.EncapsulateFlag).ToList(); - SelectedField = selected; + + _masterDetail.SelectionTargetID = selected.TargetID; + OnPropertyChanged(nameof(SelectedField)); + if (_masterDetail.DetailUpdateRequired) + { + _masterDetail.DetailField = SelectedField; + UpdateDetailForSelection(); + } } private void UpdatePreview() diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs index 8d859d3122..d96f8a0c29 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs @@ -11,9 +11,9 @@ namespace Rubberduck.UI.Refactorings.EncapsulateField { public interface IEncapsulatedFieldViewData { - string TargetID { get; } // set; } + string TargetID { get; } string PropertyName { set; get; } - string NewFieldName { get; } // { set; get; } + string NewFieldName { get; } bool EncapsulateFlag { set; get; } bool IsReadOnly { set; get; } bool CanBeReadWrite { get; } @@ -21,20 +21,22 @@ public interface IEncapsulatedFieldViewData Visibility FieldNameVisibility { get; } Visibility PropertyNameVisibility { get; } bool HasValidEncapsulationAttributes { get; } - bool HasInvalidEncapsulationAttributes { get; } string AsTypeName { get; } - string FieldDescriptor { get; } string TargetDeclarationExpression { set; get; } bool IsPrivateUserDefinedType { get; } bool IsRequiredToBeReadOnly { get; } + string ValidationErrorMessage { get; } + bool TryValidateEncapsulationAttributes(out string errorMessage); } public class ViewableEncapsulatedField : IEncapsulatedFieldViewData { private IEncapsulateFieldCandidate _efd; + private readonly int _hashCode; public ViewableEncapsulatedField(IEncapsulateFieldCandidate efd) { _efd = efd; + _hashCode = efd.TargetID.GetHashCode(); } public override bool Equals(object obj) @@ -46,57 +48,66 @@ public override bool Equals(object obj) return false; } - public Visibility FieldNameVisibility => (_efd is IUserDefinedTypeMemberCandidate) /*.IsUDTMember*/ || !_efd.EncapsulateFlag ? Visibility.Collapsed : Visibility.Visible; - public Visibility PropertyNameVisibility => !_efd.EncapsulateFlag ? Visibility.Collapsed : Visibility.Visible; - public bool HasValidEncapsulationAttributes => IsPrivateUserDefinedType || _efd.HasValidEncapsulationAttributes; - public bool HasInvalidEncapsulationAttributes => !HasValidEncapsulationAttributes; - public string TargetID { get => _efd.TargetID; } - //set => _efd.TargetID = value; } - public bool IsReadOnly { get => _efd.IsReadOnly; set => _efd.IsReadOnly = value; } - public bool CanBeReadWrite => _efd.CanBeReadWrite; - public string PropertyName { get => _efd.PropertyName; set => _efd.PropertyName = value; } - public bool IsEditableReadWriteFieldIdentifier { get => !(_efd is IUserDefinedTypeMemberCandidate); }// .IsUDTMember; } // set => _efd.IsEditableReadWriteFieldIdentifier = value; } - public bool EncapsulateFlag { get => _efd.EncapsulateFlag; set => _efd.EncapsulateFlag = value; } - public string NewFieldName { get => _efd.FieldIdentifier; }// set => _efd.NewFieldName = value; } - //TODO: Change name of AsTypeName property to FieldDescriptor(?) -> and does it belong on IEncapsulatedField? - public string AsTypeName => _efd.AsTypeName; - public bool IsPrivateUserDefinedType => _efd is IUserDefinedTypeCandidate udt && udt.TypeDeclarationIsPrivate; - public bool IsRequiredToBeReadOnly => !_efd.CanBeReadWrite; // is ArrayCandidate; + public override int GetHashCode() + { + return _hashCode; + } + public Visibility FieldNameVisibility => (_efd is IUserDefinedTypeMemberCandidate) || !_efd.EncapsulateFlag ? Visibility.Collapsed : Visibility.Visible; - public string FieldDescriptor + public Visibility PropertyNameVisibility => !_efd.EncapsulateFlag ? Visibility.Collapsed : Visibility.Visible; + + public bool HasValidEncapsulationAttributes { - //(Variable: Integer Array) - //(Variable: Long) - //(UserDefinedType Member: Long) get { - var prefix = string.Empty; - - var descriptor = string.Empty; - if (_efd is IUserDefinedTypeCandidate) //.IsUDTMember) + if (!TryValidateEncapsulationAttributes(out var errorMessage)) { - prefix = "UserDefinedType"; - } - else - { - prefix = "Variable"; + _errorMessage = errorMessage; + return false; } + return true; + } + } - descriptor = $"{prefix}: {_efd.Declaration.AsTypeName}"; - if (_efd.Declaration.IsArray) - { - descriptor = $"{descriptor} Array"; - } - return descriptor; + public bool TryValidateEncapsulationAttributes(out string errorMessage) + { + errorMessage = string.Empty; + if (IsPrivateUserDefinedType) + { + return true; } + return _efd.TryValidateEncapsulationAttributes(out errorMessage); } + private string _errorMessage; + public string ValidationErrorMessage => _errorMessage; + + public string TargetID { get => _efd.TargetID; } + + public bool IsReadOnly { get => _efd.IsReadOnly; set => _efd.IsReadOnly = value; } + + public bool CanBeReadWrite => _efd.CanBeReadWrite; + + public string PropertyName { get => _efd.PropertyName; set => _efd.PropertyName = value; } + + public bool IsEditableReadWriteFieldIdentifier { get => !(_efd is IUserDefinedTypeMemberCandidate); } + + public bool EncapsulateFlag { get => _efd.EncapsulateFlag; set => _efd.EncapsulateFlag = value; } + + public string NewFieldName { get => _efd.FieldIdentifier; } + + public string AsTypeName => _efd.AsTypeName_Field; + + public bool IsPrivateUserDefinedType => _efd is IUserDefinedTypeCandidate udt && udt.TypeDeclarationIsPrivate; + + public bool IsRequiredToBeReadOnly => !_efd.CanBeReadWrite; + private string _targetDeclarationExpressions; public string TargetDeclarationExpression { set => _targetDeclarationExpressions = value; - get => $"{_efd.Declaration.Accessibility} {_efd.Declaration.Context.GetText()}"; //$"{TargetID}: Private {TargetID} As {AsTypeName}"; + get => $"{_efd.Declaration.Accessibility} {_efd.Declaration.Context.GetText()}"; } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs new file mode 100644 index 0000000000..1145901b25 --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs @@ -0,0 +1,49 @@ +using Rubberduck.Resources; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + //TODO: All the raw strings here will be assigned keys in RubberduckUI.resx when the 'WIP' annotation is removed + public class EncapsulateFieldResources + { + public static string PreviewEndOfChangesMarker + => "'<===== No Changes below this line =====>"; + + public static string DefaultPropertyParameter => "value"; + + public static string DefaultStateUDTFieldName => "this"; + + public static string StateUserDefinedTypeIdentifierPrefix => "T"; + + public static string GroupBoxHeaderSuffix = "Encapsulation Property Name:"; + + public static string Caption + => RubberduckUI.EncapsulateField_Caption; + + public static string InstructionText /* => RubberduckUI.EncapsulateField_InstructionText*/ + => "Select one or more fields to encapsulate. Optionally edit property names or accept the default value(s)"; + + public static string Preview + => RubberduckUI.EncapsulateField_Preview; + + public static string TitleText + => RubberduckUI.EncapsulateField_TitleText; + + public static string PrivateUDTPropertyText + => "Encapsulates Each UDT Member"; + + public static string Conflict => "Conflict"; + + public static string Property => "Property"; + + public static string Field => "Field"; + + public static string Parameter => "Parameter"; + + public static string NameConflictDetected => "Name Conflict Detected"; + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs index 8df51fb612..3b987bde4a 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs @@ -41,48 +41,29 @@ public IEncapsulateFieldCandidate CreateEncapsulationCandidate(Declaration targe Debug.Assert(!target.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)); IEncapsulateFieldCandidate candidate = CreateCandidate(target); - //= target.IsUserDefinedTypeField() - // ? new UserDefinedTypeCandidate(target, _validator) - // : new EncapsulateFieldCandidate(target, _validator); - - //if (target.IsUserDefinedTypeField()) - //{ - // candidate = new UserDefinedTypeCandidate(target, _validator); - //} - //else if (target.IsArray) - //{ - // candidate = new ArrayCandidate(target, _validator); - //} - //else - //{ - // candidate = new EncapsulateFieldCandidate(target, _validator); - //} - - _validator.RegisterFieldCandidate(candidate); candidate = ApplyTypeSpecificAttributes(candidate); - - candidate = SetNonConflictIdentifier(candidate, c => { return _validator.HasConflictingIdentifier(candidate, DeclarationType.Property); }, (s) => { candidate.PropertyName = s.Capitalize(); }, () => candidate.PropertyName, _validator); - candidate = SetNonConflictIdentifier(candidate, c => { return _validator.HasConflictingIdentifier(candidate, DeclarationType.Variable); }, (s) => { candidate.FieldIdentifier = s.UnCapitalize(); }, () => candidate.FieldIdentifier, _validator); - if (candidate is IUserDefinedTypeCandidate udtVariable) { (Declaration udtDeclaration, IEnumerable udtMembers) = GetUDTAndMembersForField(udtVariable); udtVariable.TypeDeclarationIsPrivate = udtDeclaration.HasPrivateAccessibility(); - foreach (var udtMember in udtMembers) + foreach (var udtMemberDeclaration in udtMembers) { - //var udtCandidate = CreateCandidate(udtMember); - var candidateUDTMember = new UserDefinedTypeMemberCandidate(CreateCandidate(udtMember), udtVariable, _validator) as IUserDefinedTypeMemberCandidate; + var candidateUDTMember = new UserDefinedTypeMemberCandidate(CreateCandidate(udtMemberDeclaration), udtVariable, _validator) as IUserDefinedTypeMemberCandidate; candidateUDTMember = ApplyTypeSpecificAttributes(candidateUDTMember); - candidateUDTMember = SetNonConflictIdentifier(candidateUDTMember, c => { return _validator.HasConflictingIdentifier(candidate, DeclarationType.Property); }, (s) => { candidateUDTMember.PropertyName = s.Capitalize(); }, () => candidate.IdentifierName, _validator); - udtVariable.AddMember(candidateUDTMember); } } + + _validator.RegisterFieldCandidate(candidate); + + candidate = _validator.AssignNoConflictIdentifier(candidate, DeclarationType.Property); + candidate = _validator.AssignNoConflictIdentifier(candidate, DeclarationType.Variable); + return candidate; } @@ -96,11 +77,7 @@ private IEncapsulateFieldCandidate CreateCandidate(Declaration target) { return new ArrayCandidate(target, _validator); } - //else - //{ - return new EncapsulateFieldCandidate(target, _validator); - //} - + return new EncapsulateFieldCandidate(target, _validator); } public IEnumerable CreateEncapsulationCandidates() @@ -120,23 +97,12 @@ public IEnumerable CreateEncapsulationCandidates() return candidates; } - private T SetNonConflictIdentifier(T candidate, Predicate conflictDetector, Action setValue, Func getIdentifier, IEncapsulateFieldNamesValidator validator) where T : IEncapsulateFieldCandidate - { - var isConflictingIdentifier = conflictDetector(candidate); - for (var count = 1; count < 10 && isConflictingIdentifier; count++) - { - setValue(getIdentifier().IncrementIdentifier()); - isConflictingIdentifier = conflictDetector(candidate); - } - return candidate; - } - private IStateUDT SetNonConflictIdentifier(IStateUDT candidate, Predicate conflictDetector, Action setValue, Func getIdentifier, IEncapsulateFieldNamesValidator validator) { var isConflictingIdentifier = conflictDetector(candidate); for (var count = 1; count < 10 && isConflictingIdentifier; count++) { - setValue(getIdentifier().IncrementIdentifier()); + setValue(getIdentifier().IncrementEncapsulationIdentifier()); isConflictingIdentifier = conflictDetector(candidate); } return candidate; @@ -144,21 +110,14 @@ private IStateUDT SetNonConflictIdentifier(IStateUDT candidate, Predicate(T candidate) where T: IEncapsulateFieldCandidate { - //Default values are - //candidate.ImplementLetSetterType = true; - //candidate.ImplementSetSetterType = false; - //candidate.CanBeReadWrite = true; - //candidate.IsReadOnly = false; - - //if (candidate.Declaration.IsArray) - //{ - // candidate.ImplementLetSetterType = false; - // candidate.ImplementSetSetterType = false; - // //candidate.AsTypeName = Tokens.Variant; - // candidate.AsTypeName_Property = Tokens.Variant; - // candidate.CanBeReadWrite = false; - // candidate.IsReadOnly = true; - //} + /* + * Default values are: + * candidate.ImplementLetSetterType = true; + * candidate.ImplementSetSetterType = false; + * candidate.CanBeReadWrite = true; + * candidate.IsReadOnly = false; + */ + if (candidate.Declaration.IsEnumField()) { //5.3.1 The declared type of a function declaration may not be a private enum name. @@ -170,13 +129,13 @@ private T ApplyTypeSpecificAttributes(T candidate) where T: IEncapsulateField else if (candidate.Declaration.AsTypeName.Equals(Tokens.Variant) && !candidate.Declaration.IsArray) { - candidate.ImplementLetSetterType = true; - candidate.ImplementSetSetterType = true; + candidate.ImplementLet = true; + candidate.ImplementSet = true; } else if (candidate.Declaration.IsObject) { - candidate.ImplementLetSetterType = false; - candidate.ImplementSetSetterType = true; + candidate.ImplementLet = false; + candidate.ImplementSet = true; } return candidate; } @@ -185,11 +144,19 @@ private T ApplyTypeSpecificAttributes(T candidate) where T: IEncapsulateField { var userDefinedTypeDeclaration = _declarationFinderProvider.DeclarationFinder .UserDeclarations(DeclarationType.UserDefinedType) - .Where(ut => ut.IdentifierName.Equals(udtField.AsTypeName) - && (ut.Accessibility.Equals(Accessibility.Private) - && ut.QualifiedModuleName == udtField.QualifiedModuleName) - || (ut.Accessibility != Accessibility.Private)) - .SingleOrDefault(); + .Where(ut => ut.IdentifierName.Equals(udtField.AsTypeName_Field) + && ut.QualifiedModuleName == udtField.QualifiedModuleName) + .SingleOrDefault(); + + if (userDefinedTypeDeclaration is null) + { + userDefinedTypeDeclaration = _declarationFinderProvider.DeclarationFinder + .UserDeclarations(DeclarationType.UserDefinedType) + .Where(ut => ut.IdentifierName.Equals(udtField.AsTypeName_Field) + && ut.ProjectId == udtField.Declaration.ProjectId + && ut.Accessibility != Accessibility.Private) + .SingleOrDefault(); + } var udtMembers = _declarationFinderProvider.DeclarationFinder .UserDeclarations(DeclarationType.UserDefinedTypeMember) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldExtensions.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldExtensions.cs index dd622ad67e..53da0a5ca6 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldExtensions.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldExtensions.cs @@ -59,7 +59,7 @@ public static string Capitalize(this string input) public static string UnCapitalize(this string input) => $"{char.ToLowerInvariant(input[0]) + input.Substring(1, input.Length - 1)}"; - public static bool EqualsVBAIdentifier(this string lhs, string identifier) + public static bool IsEquivalentVBAIdentifierTo(this string lhs, string identifier) => lhs.Equals(identifier, StringComparison.InvariantCultureIgnoreCase); public static string GetText(this IModuleRewriter rewriter, int maxConsecutiveNewLines) @@ -74,7 +74,7 @@ public static string GetText(this IModuleRewriter rewriter, int maxConsecutiveNe return result; } - public static string IncrementIdentifier(this string identifier) + public static string IncrementEncapsulationIdentifier(this string identifier) { var fragments = identifier.Split('_'); if (fragments.Length == 1) { return $"{identifier}_1"; } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index d3936a41e2..7b330054bd 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -16,8 +16,6 @@ public class EncapsulateFieldModel : IRefactoringModel private readonly Func _previewDelegate; private QualifiedModuleName _targetQMN; - private bool _useNewStructure; - private IDictionary)> _udtFieldToUdtDeclarationMap = new Dictionary)>(); public EncapsulateFieldModel(Declaration target, IEnumerable candidates, IStateUDT stateUDTField, Func previewDelegate) @@ -25,11 +23,8 @@ public EncapsulateFieldModel(Declaration target, IEnumerable EncapsulationCandidates { set; get; } = new List(); @@ -48,7 +43,7 @@ public IEnumerable SelectedUDTFieldCandidates .Cast(); public bool HasSelectedMultipleUDTFieldsOfType(string asTypeName) - => SelectedUDTFieldCandidates.Where(f => f.AsTypeName.Equals(asTypeName)).Count() > 1; + => SelectedUDTFieldCandidates.Where(f => f.AsTypeName_Field.Equals(asTypeName)).Count() > 1; public IEncapsulateFieldCandidate this[string encapsulatedFieldTargetID] => EncapsulationCandidates.Where(c => c.TargetID.Equals(encapsulatedFieldTargetID)).Single(); diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 2433f1d5fd..26ee6b240a 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -29,7 +29,6 @@ public class EncapsulateFieldRefactoring : InteractiveRefactoringBase> _newContent { set; get; } @@ -38,7 +37,6 @@ private enum NewContentTypes { TypeDeclarationBlock, DeclarationBlock, MethodBlo private static string DoubleSpace => $"{Environment.NewLine}{Environment.NewLine}"; - private bool _useNewScheme; public EncapsulateFieldRefactoring( IDeclarationFinderProvider declarationFinderProvider, IIndenter indenter, @@ -52,9 +50,6 @@ public EncapsulateFieldRefactoring( _declarationFinderProvider = declarationFinderProvider; _selectedDeclarationProvider = selectedDeclarationProvider; _indenter = indenter; - _validator = new EncapsulateFieldNamesValidator(_declarationFinderProvider); - - _useNewScheme = File.Exists("C:\\Users\\Brian\\Documents\\UseNewUDTStructure.txt"); _codeSectionStartIndex = _declarationFinderProvider.DeclarationFinder .Members(_targetQMN).Where(m => m.IsMember()) @@ -97,7 +92,8 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) _targetQMN = target.QualifiedModuleName; - _encapsulationCandidateFactory = new EncapsulateFieldElementFactory(_declarationFinderProvider, _targetQMN, _validator); + var validator = new EncapsulateFieldNamesValidator(_declarationFinderProvider); + _encapsulationCandidateFactory = new EncapsulateFieldElementFactory(_declarationFinderProvider, _targetQMN, validator); var candidates = _encapsulationCandidateFactory.CreateEncapsulationCandidates(); var selected = candidates.Single(c => c.Declaration == target); @@ -164,11 +160,6 @@ private IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, I { NewContentTypes.TypeDeclarationBlock, new List() } }; - foreach (var udtField in model.SelectedUDTFieldCandidates) - { - udtField.FieldQualifyUDTMemberPropertyNames = model.HasSelectedMultipleUDTFieldsOfType(udtField.AsTypeName); - } - ModifyFields(model, rewriteSession); ModifyReferences(model, rewriteSession); @@ -224,8 +215,8 @@ private void ModifyFields(EncapsulateFieldModel model, IExecutableRewriteSession if (field.Declaration.IsDeclaredInList() && !field.Declaration.HasPrivateAccessibility()) { + //FIXME: the call here should be: rewriter.Remove(field.Declaration); RewriterRemoveWorkAround.Remove(field.Declaration, rewriter); - //rewriter.Remove(target.Declaration); continue; } @@ -245,7 +236,7 @@ private void InsertNewContent(EncapsulateFieldModel model, IExecutableRewriteSes if (postPendPreviewMessage) { - _newContent[NewContentTypes.PostContentMessage].Add("'<===== All Changes above this line =====>"); + _newContent[NewContentTypes.PostContentMessage].Add(EncapsulateFieldResources.PreviewEndOfChangesMarker); } var newContentBlock = string.Join(DoubleSpace, diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs index 37c1349e95..56fba97214 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -13,18 +13,17 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface IEncapsulateFieldValidator + public interface IEncapsulateFieldNamesValidator { void RegisterFieldCandidate(IEncapsulateFieldCandidate candidate); - bool IsValidVBAIdentifier(string identifier, DeclarationType declarationType); - bool HasConflictingIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType); + bool IsValidVBAIdentifier(string identifier, DeclarationType declarationType, out string errorMessage); + bool HasConflictingIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType, out string errorMessage); + bool IsSelfConsistent(IEncapsulateFieldCandidate candidate, out string errorMessage); bool IsConflictingFieldIdentifier(string fieldName, IEncapsulateFieldCandidate candidate, DeclarationType declarationType); - } - - public interface IEncapsulateFieldNamesValidator : IEncapsulateFieldValidator - { + bool HasValidEncapsulationIdentifiers(IEncapsulateFieldCandidate candidate, out string errorMessage); bool IsConflictingStateUDTTypeIdentifier(IStateUDT stateUDT); bool IsConflictingStateUDTFieldIdentifier(IStateUDT stateUDT); + IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType); } public class EncapsulateFieldNamesValidator : IEncapsulateFieldNamesValidator @@ -33,23 +32,70 @@ public class EncapsulateFieldNamesValidator : IEncapsulateFieldNamesValidator private List FieldCandidates { set; get; } + private List UDTMemberCandidates { set; get; } + private List FlaggedCandidates => FieldCandidates.Where(rc => rc.EncapsulateFlag).ToList(); public EncapsulateFieldNamesValidator(IDeclarationFinderProvider declarationFinderProvider) { _declarationFinderProvider = declarationFinderProvider; FieldCandidates = new List(); + UDTMemberCandidates = new List(); } public void RegisterFieldCandidate(IEncapsulateFieldCandidate candidate) { FieldCandidates.Add(candidate); + if (candidate is IUserDefinedTypeCandidate udt) + { + foreach (var member in udt.Members) + { + UDTMemberCandidates.Add(member); + } + } } private DeclarationFinder DeclarationFinder => _declarationFinderProvider.DeclarationFinder; - public bool IsValidVBAIdentifier(string identifier, DeclarationType declarationType) - => VBAIdentifierValidator.IsValidIdentifier(identifier, declarationType); + + public bool HasValidEncapsulationIdentifiers(IEncapsulateFieldCandidate candidate, out string errorMessage) + { + if (VBAIdentifierValidator.TryMatchInvalidIdentifierCriteria(candidate.PropertyName, DeclarationType.Property, out errorMessage)) + { + return false; + } + if (!IsSelfConsistent(candidate, out errorMessage)) + { + return false; + } + return true; + } + + public bool IsValidVBAIdentifier(string identifier, DeclarationType declarationType, out string errorMessage) + { + return !VBAIdentifierValidator.TryMatchInvalidIdentifierCriteria(identifier, declarationType, out errorMessage); + } + + public bool IsSelfConsistent(IEncapsulateFieldCandidate candidate, out string errorMessage) + { + errorMessage = string.Empty; + if (candidate.PropertyName.IsEquivalentVBAIdentifierTo(candidate.FieldIdentifier)) + { + errorMessage = $"{EncapsulateFieldResources.Conflict}: {EncapsulateFieldResources.Property}({candidate.PropertyName}) => {EncapsulateFieldResources.Field}({candidate.FieldIdentifier})"; + return false; + } + if (candidate.PropertyName.IsEquivalentVBAIdentifierTo(candidate.ParameterName)) + { + errorMessage = $"{EncapsulateFieldResources.Conflict}: {EncapsulateFieldResources.Property}({candidate.PropertyName}) => {EncapsulateFieldResources.Parameter}({candidate.ParameterName})"; + return false; + } + if (candidate.FieldIdentifier.IsEquivalentVBAIdentifierTo(candidate.ParameterName)) + { + errorMessage = $"{EncapsulateFieldResources.Conflict}: {EncapsulateFieldResources.Field}({candidate.FieldIdentifier}) => {EncapsulateFieldResources.Parameter}({candidate.ParameterName})"; + return false; + } + return true; + } private List PotentialConflictIdentifiers(IEncapsulateFieldCandidate candidate, DeclarationType declarationType) { @@ -74,7 +120,7 @@ private List PotentialConflictIdentifiers(IEncapsulateFieldCandidate can return nameConflictCandidates.Select(c => c.IdentifierName).ToList(); } - private List GetPotentialConflictMembers(IStateUDT stateUDT, DeclarationType declarationType) + private List PotentialConflictIdentifiers(IStateUDT stateUDT, DeclarationType declarationType) { var potentialDeclarationIdentifierConflicts = new List(); @@ -88,8 +134,9 @@ private List GetPotentialConflictMembers(IStateUDT stateUDT, Declaration return potentialDeclarationIdentifierConflicts.ToList(); } - public bool HasConflictingIdentifier(IEncapsulateFieldCandidate field, DeclarationType declarationType) + public bool HasConflictingIdentifier(IEncapsulateFieldCandidate field, DeclarationType declarationType, out string errorMessage) { + errorMessage = string.Empty; //The declared type of a function declaration may not be a private enum name. //=>Means encapsulating a private enum field must be 'As Long' @@ -102,35 +149,64 @@ public bool HasConflictingIdentifier(IEncapsulateFieldCandidate field, Declarati var potentialDeclarationIdentifierConflicts = new List(); potentialDeclarationIdentifierConflicts.AddRange(PotentialConflictIdentifiers(field, declarationType)); - potentialDeclarationIdentifierConflicts.AddRange(FlaggedCandidates.Where(fc => fc.Declaration != field.Declaration).Select(fc => fc.PropertyName)); - //potentialDeclarationIdentifierConflicts.AddRange(FlaggedCandidates.Where(fc => fc.Declaration != field.Declaration).Select(fc => fc.FieldIdentifier)); + potentialDeclarationIdentifierConflicts.AddRange(FlaggedCandidates.Where(fc => fc != field).Select(fc => fc.PropertyName)); + + potentialDeclarationIdentifierConflicts.AddRange(UDTMemberCandidates.Where(udtm => udtm != field && udtm.EncapsulateFlag).Select(udtm => udtm.PropertyName)); var identifierToCompare = declarationType.HasFlag(DeclarationType.Property) ? field.PropertyName : field.FieldIdentifier; - return potentialDeclarationIdentifierConflicts.Any(m => m.EqualsVBAIdentifier(identifierToCompare)); + if (potentialDeclarationIdentifierConflicts.Any(m => m.IsEquivalentVBAIdentifierTo(identifierToCompare))) + { + errorMessage = EncapsulateFieldResources.NameConflictDetected; + return true; + } + return false; + } + + public IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType) //, Predicate conflictDetector, Action setValue, Func getIdentifier) + { + var isConflictingIdentifier = HasConflictingIdentifier(candidate, declarationType, out _); + for (var count = 1; count < 10 && isConflictingIdentifier; count++) + { + var identifier = declarationType.HasFlag(DeclarationType.Property) + ? candidate.PropertyName + : candidate.FieldIdentifier; + + if (declarationType.HasFlag(DeclarationType.Property)) + { + candidate.PropertyName = identifier.IncrementEncapsulationIdentifier(); + } + else + { + candidate.FieldIdentifier = identifier.IncrementEncapsulationIdentifier(); + } + isConflictingIdentifier = HasConflictingIdentifier(candidate, declarationType, out _); + } + return candidate; } + public bool IsConflictingFieldIdentifier(string fieldName, IEncapsulateFieldCandidate candidate, DeclarationType declarationType) { var members = PotentialConflictIdentifiers(candidate, declarationType); - return members.Any(m => m.EqualsVBAIdentifier(fieldName)); + return members.Any(m => m.IsEquivalentVBAIdentifierTo(fieldName)); } public bool IsConflictingStateUDTTypeIdentifier(IStateUDT stateUDT) { - var potentialConflictNames = GetPotentialConflictMembers(stateUDT, DeclarationType.UserDefinedType); + var potentialConflictNames = PotentialConflictIdentifiers(stateUDT, DeclarationType.UserDefinedType); - return potentialConflictNames.Any(m => m.EqualsVBAIdentifier(stateUDT.TypeIdentifier)); + return potentialConflictNames.Any(m => m.IsEquivalentVBAIdentifierTo(stateUDT.TypeIdentifier)); } public bool IsConflictingStateUDTFieldIdentifier(IStateUDT stateUDT) { - var potentialConflictNames = GetPotentialConflictMembers(stateUDT, DeclarationType.Variable); + var potentialConflictNames = PotentialConflictIdentifiers(stateUDT, DeclarationType.Variable); - return potentialConflictNames.Any(m => m.EqualsVBAIdentifier(stateUDT.FieldIdentifier)); + return potentialConflictNames.Any(m => m.IsEquivalentVBAIdentifierTo(stateUDT.FieldIdentifier)); } //The refactoring only inserts elements with the following Accessibilities: diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs index a1a4f609d6..2fb5c29acb 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs @@ -15,9 +15,9 @@ public class ArrayCandidate : EncapsulateFieldCandidate public ArrayCandidate(Declaration declaration, IEncapsulateFieldNamesValidator validator) :base(declaration, validator) { - ImplementLetSetterType = false; - ImplementSetSetterType = false; - AsTypeName = declaration.AsTypeName; + ImplementLet = false; + ImplementSet = false; + AsTypeName_Field = declaration.AsTypeName; AsTypeName_Property = Tokens.Variant; CanBeReadWrite = false; IsReadOnly = true; @@ -30,6 +30,6 @@ public ArrayCandidate(Declaration declaration, IEncapsulateFieldNamesValidator v } public override string AsUDTMemberDeclaration - => $"{PropertyName}({_subscripts}) {Tokens.As} {AsTypeName}"; + => $"{PropertyName}({_subscripts}) {Tokens.As} {AsTypeName_Field}"; } } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs index eee3f1cf85..f480759b47 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs @@ -21,14 +21,13 @@ public interface IEncapsulateFieldCandidate bool EncapsulateFlag { get; set; } string FieldIdentifier { set; get; } bool CanBeReadWrite { set; get; } - bool HasValidEncapsulationAttributes { get; } QualifiedModuleName QualifiedModuleName { get; } string PropertyName { get; set; } - string AsTypeName { get; set; } + string AsTypeName_Field { get; set; } string AsTypeName_Property { get; set; } string ParameterName { get; } - bool ImplementLetSetterType { get; set; } - bool ImplementSetSetterType { get; set; } + bool ImplementLet { get; set; } + bool ImplementSet { get; set; } IEnumerable PropertyAttributeSets { get; } string AsUDTMemberDeclaration { get; } IEnumerable> ReferenceReplacements { get; } @@ -36,19 +35,16 @@ public interface IEncapsulateFieldCandidate string ReferenceQualifier { set; get; } string ReferenceWithinNewProperty { get; } void StageFieldReferenceReplacements(IStateUDT stateUDT = null); - string AccessorTokenToContent(AccessorTokens token); AccessorTokens PropertyAccessor { set; get; } AccessorTokens ReferenceAccessor { set; get; } + bool TryValidateEncapsulationAttributes(out string errorMessage); + } public enum AccessorTokens { Field, Property } public interface IEncapsulateFieldCandidateValidations { - bool HasVBACompliantPropertyIdentifier { get; } - bool HasVBACompliantFieldIdentifier { get; } - bool HasVBACompliantParameterIdentifier { get; } - bool IsSelfConsistent { get; } bool HasConflictingPropertyIdentifier { get; } bool HasConflictingFieldIdentifier { get; } } @@ -58,6 +54,7 @@ public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate, IEncapsulat { protected Declaration _target; protected QualifiedModuleName _qmn; + protected int _hashCode; private string _identifierName; protected IEncapsulateFieldNamesValidator _validator; protected EncapsulationIdentifiers _fieldAndProperty; @@ -74,7 +71,7 @@ public EncapsulateFieldCandidate(string identifier, string asTypeName, Qualified _fieldAndProperty = new EncapsulationIdentifiers(identifier); IdentifierName = identifier; - AsTypeName = asTypeName; + AsTypeName_Field = asTypeName; AsTypeName_Property = asTypeName; _qmn = qmn; PropertyAccessor = AccessorTokens.Field; @@ -82,9 +79,11 @@ public EncapsulateFieldCandidate(string identifier, string asTypeName, Qualified _validator = validator; - ImplementLetSetterType = true; - ImplementSetSetterType = false; + ImplementLet = true; + ImplementSet = false; CanBeReadWrite = true; + + _hashCode = ($"{_qmn.Name}.{identifier}").GetHashCode(); } public virtual void StageFieldReferenceReplacements(IStateUDT stateUDT = null) @@ -99,32 +98,37 @@ public virtual void StageFieldReferenceReplacements(IStateUDT stateUDT = null) public Declaration Declaration => _target; - public bool HasVBACompliantPropertyIdentifier => _validator.IsValidVBAIdentifier(PropertyName, DeclarationType.Property); - - public bool HasVBACompliantFieldIdentifier => _validator.IsValidVBAIdentifier(FieldIdentifier, Declaration?.DeclarationType ?? DeclarationType.Variable); - - public bool HasVBACompliantParameterIdentifier => _validator.IsValidVBAIdentifier(FieldIdentifier, Declaration?.DeclarationType ?? DeclarationType.Variable); - - public virtual bool IsSelfConsistent => _validator.IsValidVBAIdentifier(PropertyName, DeclarationType.Property) - && !(PropertyName.EqualsVBAIdentifier(FieldIdentifier) - || PropertyName.EqualsVBAIdentifier(ParameterName) - || FieldIdentifier.EqualsVBAIdentifier(ParameterName)); - public bool HasConflictingPropertyIdentifier - => _validator.HasConflictingIdentifier(this, DeclarationType.Property); + => _validator.HasConflictingIdentifier(this, DeclarationType.Property, out var errorMessage); public bool HasConflictingFieldIdentifier - => _validator.HasConflictingIdentifier(this, DeclarationType.Variable); + => _validator.HasConflictingIdentifier(this, DeclarationType.Variable, out var errorMessage); - public bool HasValidEncapsulationAttributes + public virtual bool TryValidateEncapsulationAttributes(out string errorMessage) { - get + errorMessage = string.Empty; + if (!EncapsulateFlag) { return true; } + + if (!_validator.IsValidVBAIdentifier(PropertyName, DeclarationType.Property, out errorMessage)) + { + return false; + } + + if (!_validator.IsSelfConsistent(this, out errorMessage)) { - if (!EncapsulateFlag) { return true; } + return false; + } - return IsSelfConsistent - && !_validator.HasConflictingIdentifier(this, DeclarationType.Property); + if (_validator.HasConflictingIdentifier(this, DeclarationType.Property, out errorMessage)) + { + return false; } + + if (_validator.HasConflictingIdentifier(this, DeclarationType.Variable, out errorMessage)) + { + return false; + } + return true; } public virtual IEnumerable> ReferenceReplacements @@ -154,7 +158,20 @@ public virtual void SetReferenceRewriteContent(IdentifierReference idRef, string public virtual string TargetID => _target?.IdentifierName ?? IdentifierName; - public bool EncapsulateFlag { set; get; } + protected bool _encapsulateFlag; + public virtual bool EncapsulateFlag + { + set + { + _encapsulateFlag = value; + if (!_encapsulateFlag) + { + PropertyName = _fieldAndProperty.DefaultPropertyName; + } + } + get => _encapsulateFlag; + } + public virtual bool IsReadOnly { set; get; } public bool CanBeReadWrite { set; get; } @@ -175,10 +192,19 @@ public virtual string PropertyName } } + public override bool Equals(object obj) + { + return obj != null + && obj is IEncapsulateFieldCandidate + && obj.GetHashCode() == GetHashCode(); + } + + public override int GetHashCode() => _hashCode; + //The preferred NewFieldName is the original Identifier private void TryRestoreNewFieldNameAsOriginalFieldIdentifierName() { - var canNowUseOriginalFieldName = !_fieldAndProperty.TargetFieldName.EqualsVBAIdentifier(_fieldAndProperty.Property) + var canNowUseOriginalFieldName = !_fieldAndProperty.TargetFieldName.IsEquivalentVBAIdentifierTo(_fieldAndProperty.Property) && !_validator.IsConflictingFieldIdentifier(_fieldAndProperty.TargetFieldName, this, DeclarationType.Variable); if (canNowUseOriginalFieldName) @@ -187,19 +213,19 @@ private void TryRestoreNewFieldNameAsOriginalFieldIdentifierName() return; } - if (_fieldAndProperty.Field.EqualsVBAIdentifier(_fieldAndProperty.TargetFieldName)) + if (_fieldAndProperty.Field.IsEquivalentVBAIdentifierTo(_fieldAndProperty.TargetFieldName)) { _fieldAndProperty.Field = _fieldAndProperty.DefaultNewFieldName; - var isConflictingFieldIdentifier = _validator.HasConflictingIdentifier(this, DeclarationType.Variable); + var isConflictingFieldIdentifier = _validator.HasConflictingIdentifier(this, DeclarationType.Variable, out _); for (var count = 1; count < 10 && isConflictingFieldIdentifier; count++) { - FieldIdentifier = FieldIdentifier.IncrementIdentifier(); - isConflictingFieldIdentifier = _validator.HasConflictingIdentifier(this, DeclarationType.Variable); + FieldIdentifier = FieldIdentifier.IncrementEncapsulationIdentifier(); + isConflictingFieldIdentifier = _validator.HasConflictingIdentifier(this, DeclarationType.Variable, out _); } } } - public string AsTypeName { set; get; } + public string AsTypeName_Field { set; get; } public string AsTypeName_Property { get; set; } @@ -214,11 +240,10 @@ public string IdentifierName public string ParameterName => _fieldAndProperty.SetLetParameter; private bool _implLet; - public bool ImplementLetSetterType { get => !IsReadOnly && _implLet; set => _implLet = value; } + public bool ImplementLet { get => !IsReadOnly && _implLet; set => _implLet = value; } private bool _implSet; - public bool ImplementSetSetterType { get => !IsReadOnly && _implSet; set => _implSet = value; } - + public bool ImplementSet { get => !IsReadOnly && _implSet; set => _implSet = value; } public AccessorTokens PropertyAccessor { set; get; } @@ -235,20 +260,22 @@ public virtual string ReferenceQualifier protected virtual string ReferenceForPreExistingReferences => AccessorTokenToContent(ReferenceAccessor); - public string AccessorTokenToContent(AccessorTokens token) + private string AccessorTokenToContent(AccessorTokens token) { - var accessor = string.Empty; - switch (token) - { - case AccessorTokens.Field: - accessor = FieldIdentifier; - break; - case AccessorTokens.Property: - accessor = PropertyName; - break; - default: - throw new ArgumentException(); - } + var accessor = token == AccessorTokens.Field + ? FieldIdentifier + : PropertyName; + //switch (token) + //{ + // case AccessorTokens.Field: + // accessor = FieldIdentifier; + // break; + // case AccessorTokens.Property: + // accessor = PropertyName; + // break; + // default: + // throw new ArgumentException(); + //} if ((ReferenceQualifier?.Length ?? 0) > 0) { @@ -257,14 +284,8 @@ public string AccessorTokenToContent(AccessorTokens token) return accessor; } - public virtual string AsUDTMemberDeclaration - { - get - { - return $"{PropertyName} {Tokens.As} {AsTypeName}"; - } - } - //=> $"{PropertyName} {Tokens.As} {AsTypeName}"; + public virtual string AsUDTMemberDeclaration + => $"{PropertyName} {Tokens.As} {AsTypeName_Field}"; public virtual IEnumerable PropertyAttributeSets => new List() { AsPropertyAttributeSet }; @@ -279,8 +300,8 @@ protected virtual IPropertyGeneratorAttributes AsPropertyAttributeSet BackingField = ReferenceWithinNewProperty, AsTypeName = AsTypeName_Property, ParameterName = ParameterName, - GenerateLetter = ImplementLetSetterType, - GenerateSetter = ImplementSetSetterType, + GenerateLetter = ImplementLet, + GenerateSetter = ImplementSet, UsesSetAssignment = Declaration.IsObject }; } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs index 84df5c89c5..f87db9c376 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs @@ -7,7 +7,7 @@ namespace Rubberduck.Refactorings.EncapsulateField { public class EncapsulationIdentifiers { - private static string DEFAULT_WRITE_PARAMETER = "value"; + private static string DEFAULT_WRITE_PARAMETER = EncapsulateFieldResources.DefaultPropertyParameter; private KeyValuePair _fieldAndProperty; private string _targetIdentifier; @@ -20,7 +20,7 @@ public EncapsulationIdentifiers(string field) { _targetIdentifier = field; DefaultPropertyName = field.Capitalize(); - DefaultNewFieldName = (field.UnCapitalize()).IncrementIdentifier(); + DefaultNewFieldName = (field.UnCapitalize()).IncrementEncapsulationIdentifier(); _fieldAndProperty = new KeyValuePair(DefaultNewFieldName, DefaultPropertyName); _setLetParameter = DEFAULT_WRITE_PARAMETER; } @@ -46,10 +46,6 @@ public string Property get => _fieldAndProperty.Value; set { - var fieldIdentifier = Field.EqualsVBAIdentifier(value) - ? DefaultNewFieldName - : _targetIdentifier; - _fieldAndProperty = new KeyValuePair(_fieldAndProperty.Key, value); SetNonConflictParameterName(); @@ -62,18 +58,18 @@ private void SetNonConflictParameterName() { _setLetParameter = DEFAULT_WRITE_PARAMETER; - if (!(Field.EqualsVBAIdentifier(DEFAULT_WRITE_PARAMETER) - || Property.EqualsVBAIdentifier(DEFAULT_WRITE_PARAMETER))) + if (!(Field.IsEquivalentVBAIdentifierTo(DEFAULT_WRITE_PARAMETER) + || Property.IsEquivalentVBAIdentifierTo(DEFAULT_WRITE_PARAMETER))) { return; } - if (Field.EqualsVBAIdentifier(SetLetParameter)) + if (Field.IsEquivalentVBAIdentifierTo(SetLetParameter)) { _setLetParameter = $"{Field}_{DEFAULT_WRITE_PARAMETER}"; } - if (Property.EqualsVBAIdentifier(SetLetParameter)) + if (Property.IsEquivalentVBAIdentifierTo(SetLetParameter)) { _setLetParameter = $"{Property}_{Field}_{DEFAULT_WRITE_PARAMETER}"; } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs index 74f7cd302c..2268dd2884 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs @@ -14,7 +14,6 @@ public interface IUserDefinedTypeCandidate : IEncapsulateFieldCandidate { IEnumerable Members { get; } void AddMember(IUserDefinedTypeMemberCandidate member); - bool FieldQualifyUDTMemberPropertyNames { set; get; } bool TypeDeclarationIsPrivate { set; get; } } @@ -57,6 +56,31 @@ public override bool IsReadOnly } } + public override bool EncapsulateFlag + { + set + { + if (TypeDeclarationIsPrivate) + { + foreach (var member in Members) + { + member.EncapsulateFlag = value; + if (!_validator.HasConflictingIdentifier(member, DeclarationType.Property, out _)) + { + continue; + } + + //Reaching this line typically implies that there are multiple fields of the same Type within the module. + //Try to use a name involving the parent's identifier to make it unique/meaningful + //before appending incremented value(s). + member.PropertyName = $"{FieldIdentifier.Capitalize()}{member.PropertyName.Capitalize()}"; + _validator.AssignNoConflictIdentifier(member, DeclarationType.Property); + } + } + base.EncapsulateFlag = value; + } + get => _encapsulateFlag; + } public override string ReferenceQualifier @@ -71,18 +95,18 @@ public override string ReferenceQualifier get => _referenceQualifier; } - public bool FieldQualifyUDTMemberPropertyNames - { - set - { - foreach (var member in Members) - { - member.IncludeParentNameWithPropertyIdentifier = value; - } - } + //public bool FieldQualifyUDTMemberPropertyNames + //{ + // set + // { + // foreach (var member in Members) + // { + // member.IncludeParentNameWithPropertyIdentifier = value; + // } + // } - get => Members.All(m => m.IncludeParentNameWithPropertyIdentifier); - } + // get => Members.All(m => m.IncludeParentNameWithPropertyIdentifier); + //} protected override void LoadFieldReferenceContextReplacements() { @@ -147,6 +171,50 @@ public override void StageFieldReferenceReplacements(IStateUDT stateUDT = null) } } + public override bool Equals(object obj) + { + if (obj is IUserDefinedTypeCandidate udt) + { + return udt.TargetID.Equals(TargetID); + } + return false; + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + + public override bool TryValidateEncapsulationAttributes(out string errorMessage) + { + errorMessage = string.Empty; + if (!EncapsulateFlag) { return true; } + + if (!_validator.IsValidVBAIdentifier(PropertyName, DeclarationType.Property, out errorMessage)) + { + return false; + } + + if (!TypeDeclarationIsPrivate && !_validator.IsSelfConsistent(this, out errorMessage)) + { + //if (!_validator.IsSelfConsistent(this, out errorMessage)) + //{ + return false; + //} + } + + if (_validator.HasConflictingIdentifier(this, DeclarationType.Property, out errorMessage)) + { + return false; + } + + if (_validator.HasConflictingIdentifier(this, DeclarationType.Variable, out errorMessage)) + { + return false; + } + return true; + } + private void LoadPrivateUDTFieldReferenceExpressions() { foreach (var idRef in Declaration.References) @@ -172,7 +240,6 @@ private void LoadUDTMemberReferenceExpressions() } else { - //If rf is a WithMemberAccess expression, modify the LExpr. e.g. "With this" => "With " var moduleQualifier = rf.Context.TryGetAncestor(out _) || rf.QualifiedModuleName == QualifiedModuleName ? string.Empty diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs index 530d9e196e..252476dad5 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs @@ -15,16 +15,15 @@ namespace Rubberduck.Refactorings.EncapsulateField public interface IUserDefinedTypeMemberCandidate : IEncapsulateFieldCandidate { IUserDefinedTypeCandidate Parent { get; } - bool IncludeParentNameWithPropertyIdentifier { set; get; } IPropertyGeneratorAttributes AsPropertyGeneratorSpec { get; } Dictionary IdentifierReplacements { get; } IEnumerable FieldRelatedReferences(IUserDefinedTypeCandidate field); } - //public class UserDefinedTypeMemberCandidate : EncapsulateFieldCandidate, IUserDefinedTypeMemberCandidate - public class UserDefinedTypeMemberCandidate : /*IEncapsulateFieldCandidate,*/ IUserDefinedTypeMemberCandidate + public class UserDefinedTypeMemberCandidate : IUserDefinedTypeMemberCandidate { private readonly IEncapsulateFieldNamesValidator _validator; + private int _hashCode; public UserDefinedTypeMemberCandidate(IEncapsulateFieldCandidate efd, IUserDefinedTypeCandidate udtVariable, IEncapsulateFieldNamesValidator validator) { _decoratedField = efd; @@ -33,34 +32,13 @@ public UserDefinedTypeMemberCandidate(IEncapsulateFieldCandidate efd, IUserDefin PropertyName = IdentifierName; PropertyAccessor = AccessorTokens.Property; ReferenceAccessor = AccessorTokens.Property; + _hashCode = ($"{efd.QualifiedModuleName.Name}.{efd.IdentifierName}").GetHashCode(); } - //public UserDefinedTypeMemberCandidate(Declaration target, IUserDefinedTypeCandidate udtVariable, IEncapsulateFieldNamesValidator validator) - // : base(target, validator) - //{ - // Parent = udtVariable; - - // PropertyName = IdentifierName; - // PropertyAccessor = AccessorTokens.Property; - // ReferenceAccessor = AccessorTokens.Property; - //} private IEncapsulateFieldCandidate _decoratedField; public IUserDefinedTypeCandidate Parent { private set; get; } - private bool _includeParentNameWithPropertyIdentifier; - public bool IncludeParentNameWithPropertyIdentifier - { - get => _includeParentNameWithPropertyIdentifier; - set - { - _includeParentNameWithPropertyIdentifier = value; - PropertyName = _includeParentNameWithPropertyIdentifier - ? $"{Parent.IdentifierName.Capitalize()}_{IdentifierName}" - : IdentifierName; - } - } - public void StageFieldReferenceReplacements(IStateUDT stateUDT = null) { } private string _referenceQualifier; @@ -91,27 +69,31 @@ public IPropertyGeneratorAttributes AsPropertyGeneratorSpec { get { - if (_includeParentNameWithPropertyIdentifier) - { - PropertyAccessor = AccessorTokens.Field; - } - return new PropertyAttributeSet() { PropertyName = PropertyName, BackingField = ReferenceWithinNewProperty, AsTypeName = AsTypeName_Property, ParameterName = ParameterName, - GenerateLetter = ImplementLetSetterType, - GenerateSetter = ImplementSetSetterType, + GenerateLetter = ImplementLet, + GenerateSetter = ImplementSet, UsesSetAssignment = Declaration.IsObject }; } } - //public new Dictionary IdentifierReplacements { get; } = new Dictionary(); public Dictionary IdentifierReplacements { get; } = new Dictionary(); + + public override bool Equals(object obj) + { + return obj != null + && obj is IUserDefinedTypeMemberCandidate + && obj.GetHashCode() == GetHashCode(); + } + + public override int GetHashCode() => _hashCode; + private IEnumerable GetUDTMemberReferencesForField(IEncapsulateFieldCandidate udtMember, IUserDefinedTypeCandidate field) { var refs = new List(); @@ -157,79 +139,80 @@ private IEnumerable GetUDTMemberReferencesForField(IEncapsu public Declaration Declaration => _decoratedField.Declaration; public string IdentifierName => _decoratedField.IdentifierName; - //public string TargetID { get; } + + public bool TryValidateEncapsulationAttributes(out string errorMessage) + { + errorMessage = string.Empty; + return true; + } + public bool IsReadOnly { set => _decoratedField.IsReadOnly = value; get => _decoratedField.IsReadOnly; } - public bool EncapsulateFlag //{ get; set; } + public bool EncapsulateFlag { set => _decoratedField.EncapsulateFlag = value; get => _decoratedField.EncapsulateFlag; } - public string FieldIdentifier //{ set; get; } + public string FieldIdentifier { set => _decoratedField.FieldIdentifier = value; get => _decoratedField.FieldIdentifier; } - public bool CanBeReadWrite //{ set; get; } + public bool CanBeReadWrite { set => _decoratedField.CanBeReadWrite = value; get => _decoratedField.CanBeReadWrite; } - public bool HasValidEncapsulationAttributes - => _decoratedField.HasValidEncapsulationAttributes; // { get; } + public bool HasValidEncapsulationAttributes => true; public QualifiedModuleName QualifiedModuleName - => _decoratedField.QualifiedModuleName; // { get; } + => _decoratedField.QualifiedModuleName; - public string PropertyName //{ get; set; } + public string PropertyName { set => _decoratedField.PropertyName = value; get => _decoratedField.PropertyName; } - public string AsTypeName //{ get; set; } + public string AsTypeName_Field { - set => _decoratedField.AsTypeName = value; - get => _decoratedField.AsTypeName; + set => _decoratedField.AsTypeName_Field = value; + get => _decoratedField.AsTypeName_Field; } - public string AsTypeName_Property //{ get; set; } + public string AsTypeName_Property { set => _decoratedField.AsTypeName_Property = value; get => _decoratedField.AsTypeName_Property; } - public string ParameterName => _decoratedField.ParameterName; // { get; } - public bool ImplementLetSetterType //{ get; set; } + public string ParameterName => _decoratedField.ParameterName; + public bool ImplementLet { - set => _decoratedField.ImplementLetSetterType = value; - get => _decoratedField.ImplementLetSetterType; + set => _decoratedField.ImplementLet = value; + get => _decoratedField.ImplementLet; } - public bool ImplementSetSetterType //{ get; set; } + public bool ImplementSet { - set => _decoratedField.ImplementSetSetterType = value; - get => _decoratedField.ImplementSetSetterType; + set => _decoratedField.ImplementSet = value; + get => _decoratedField.ImplementSet; } - public IEnumerable PropertyAttributeSets => _decoratedField.PropertyAttributeSets; // { get; } + public IEnumerable PropertyAttributeSets => _decoratedField.PropertyAttributeSets; public string AsUDTMemberDeclaration { get; } - public IEnumerable> ReferenceReplacements => _decoratedField.ReferenceReplacements; // { get; } - //public void SetReferenceRewriteContent(IdentifierReference idRef, string replacementText); - //public string ReferenceQualifier { set; get; } - public string ReferenceWithinNewProperty => $"{Parent.ReferenceWithinNewProperty}.{_decoratedField.ReferenceWithinNewProperty}"; // { get; } - //public string ReferenceWithinNewProperty => _field.ReferenceWithinNewProperty; // { get; } - //public void StageFieldReferenceReplacements(IStateUDT stateUDT = null); - public AccessorTokens PropertyAccessor //{ set; get; } + + public IEnumerable> ReferenceReplacements => _decoratedField.ReferenceReplacements; + public string ReferenceWithinNewProperty => $"{Parent.ReferenceWithinNewProperty}.{_decoratedField.IdentifierName}"; + + public AccessorTokens PropertyAccessor { set => _decoratedField.PropertyAccessor = value; get => _decoratedField.PropertyAccessor; } - public AccessorTokens ReferenceAccessor //{ set; get; } + public AccessorTokens ReferenceAccessor { set => _decoratedField.ReferenceAccessor = value; get => _decoratedField.ReferenceAccessor; } - - public string AccessorTokenToContent(AccessorTokens token) => _decoratedField.AccessorTokenToContent(token); } } diff --git a/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs b/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs index 7e89f9e48f..115613b376 100644 --- a/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs @@ -38,16 +38,6 @@ public PropertyGenerator() { } public bool GenerateSetter { get; set; } public bool UsesSetAssignment { get; set; } - public string AllPropertyCode => - $"{GetterCode}{(GenerateLetter ? LetterCode : string.Empty)}{(GenerateSetter ? SetterCode : string.Empty)}"; - - public IEnumerable AsLines => AllPropertyCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None); - - public string AsPropertyBlock(IIndenter indenter) - { - return string.Join(Environment.NewLine, indenter.Indent(AsLines, true)); - } - public string AsPropertyBlock(IPropertyGeneratorAttributes spec, IIndenter indenter) { PropertyName = spec.PropertyName; @@ -60,6 +50,11 @@ public string AsPropertyBlock(IPropertyGeneratorAttributes spec, IIndenter inden return string.Join(Environment.NewLine, indenter.Indent(AsLines, true)); } + private string AllPropertyCode => + $"{GetterCode}{(GenerateLetter ? LetterCode : string.Empty)}{(GenerateSetter ? SetterCode : string.Empty)}"; + + private IEnumerable AsLines => AllPropertyCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None); + private string GetterCode { get diff --git a/Rubberduck.Refactorings/EncapsulateField/StateUDT.cs b/Rubberduck.Refactorings/EncapsulateField/StateUDT.cs index 6890c4e2de..a9e941147d 100644 --- a/Rubberduck.Refactorings/EncapsulateField/StateUDT.cs +++ b/Rubberduck.Refactorings/EncapsulateField/StateUDT.cs @@ -20,14 +20,18 @@ public interface IStateUDT QualifiedModuleName QualifiedModuleName { set; get; } } + /* + * StateUDT is the UserDefinedType introduced by this refactoring + * whose members represent object state in lieu of individually declared member variables/fields. + */ public class StateUDT : IStateUDT { - private const string _defaultNewFieldName = "this"; + private static string _defaultNewFieldName = EncapsulateFieldResources.DefaultStateUDTFieldName; private List _members; private readonly IEncapsulateFieldNamesValidator _validator; public StateUDT(QualifiedModuleName qmn, IEncapsulateFieldNamesValidator validator) - :this($"T{qmn.ComponentName.Capitalize()}", validator) + :this($"{EncapsulateFieldResources.StateUserDefinedTypeIdentifierPrefix}{qmn.ComponentName.Capitalize()}", validator) { QualifiedModuleName = qmn; } diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs index 44547b1cae..ca57c7b445 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs @@ -34,25 +34,26 @@ public void VBAIdentifier_Property(string originalFieldName, string newPropertyN var encapsulatedField = Support.RetrieveEncapsulatedField(inputCode, originalFieldName); encapsulatedField.PropertyName = newPropertyName; - var field = encapsulatedField as IEncapsulateFieldCandidateValidations; - Assert.AreEqual(expectedResult, field.HasVBACompliantPropertyIdentifier); + encapsulatedField.EncapsulateFlag = true; + //var field = encapsulatedField as IEncapsulateFieldCandidateValidations; + Assert.AreEqual(expectedResult, encapsulatedField.TryValidateEncapsulationAttributes(out _)); } - [TestCase("fizz", "_Fizz", false)] - [TestCase("fizz", "FizzProp", true)] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void VBAIdentifier_FieldName(string originalFieldName, string newFieldName, bool expectedResult) - { - string inputCode = -$@"Public {originalFieldName} As String"; +// [TestCase("fizz", "_Fizz", false)] +// [TestCase("fizz", "FizzProp", true)] +// [Category("Refactorings")] +// [Category("Encapsulate Field")] +// public void VBAIdentifier_FieldName(string originalFieldName, string newFieldName, bool expectedResult) +// { +// string inputCode = +//$@"Public {originalFieldName} As String"; - var encapsulatedField = Support.RetrieveEncapsulatedField(inputCode, originalFieldName); +// var encapsulatedField = Support.RetrieveEncapsulatedField(inputCode, originalFieldName); - encapsulatedField.FieldIdentifier = newFieldName; - var field = encapsulatedField as IEncapsulateFieldCandidateValidations; - Assert.AreEqual(expectedResult, field.HasVBACompliantFieldIdentifier); - } +// encapsulatedField.FieldIdentifier = newFieldName; +// var field = encapsulatedField as IEncapsulateFieldCandidateValidations; +// Assert.AreEqual(expectedResult, field.HasVBACompliantFieldIdentifier); +// } [Test] [Category("Refactorings")] @@ -101,7 +102,7 @@ public void PropertyNameNotDuplicated() [Test] [Category("Refactorings")] [Category("Encapsulate Field")] - public void UDTMemberPropertyDefaultsToValidValue() + public void UDTMemberPropertyConflictsWithExistingFunction() { string inputCode = $@" @@ -142,7 +143,7 @@ Public Property Let Fizz_1(ByVal value As String) End Property "; var encapsulatedField = Support.RetrieveEncapsulatedField(inputCode, "fizz"); - Assert.IsTrue(encapsulatedField.HasValidEncapsulationAttributes); + Assert.IsTrue(encapsulatedField.TryValidateEncapsulationAttributes(out _)); } [TestCase("Name")] @@ -173,7 +174,7 @@ End Property var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, fieldUT, DeclarationType.Variable, presenterAction); - Assert.IsFalse(model["fizz"].HasValidEncapsulationAttributes); + Assert.IsFalse(model["fizz"].TryValidateEncapsulationAttributes(out _)); } [TestCase("Number", "Bazzle", true, true)] @@ -205,36 +206,40 @@ Public Property Get Test() As Integer var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, fieldUT, DeclarationType.Variable, presenterAction); - Assert.AreEqual(fizz_expectedResult, model["fizz"].HasValidEncapsulationAttributes, "fizz failed"); - Assert.AreEqual(bazz_expectedResult, model["bazz"].HasValidEncapsulationAttributes, "bazz failed"); + Assert.AreEqual(fizz_expectedResult, model["fizz"].TryValidateEncapsulationAttributes(out _), "fizz failed"); + Assert.AreEqual(bazz_expectedResult, model["bazz"].TryValidateEncapsulationAttributes(out _), "bazz failed"); } - [Test] + [TestCase("Private", "Private")] + [TestCase("Public", "Private")] + [TestCase("Private", "Public")] + [TestCase("Public", "Public")] [Category("Refactorings")] [Category("Encapsulate Field")] - public void EncapsulateMultipleFields_UDTConflicts() + public void EncapsulateMultipleUDTFields_DefaultsAreNotInConflict(string udtAccessibility, string fieldAccessibility) { string inputCode = $@" -Private Type TBar +{udtAccessibility} Type TBar First As Long Second As String End Type -Public this As TBar +{fieldAccessibility} this As TBar -Public that As TBar +{fieldAccessibility} that As TBar "; var fieldUT = "this"; var userInput = new UserInputDataObject() - .AddAttributeSet(fieldUT, "That", true); + .AddAttributeSet(fieldUT) + .AddAttributeSet("that"); var presenterAction = Support.SetParameters(userInput); var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, fieldUT, DeclarationType.Variable, presenterAction); - Assert.AreEqual(false, model[fieldUT].HasValidEncapsulationAttributes); + Assert.AreEqual(true, model[fieldUT].TryValidateEncapsulationAttributes(out var message), message); } [Test] @@ -257,7 +262,7 @@ Public wholeNumber As String var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, fieldUT, DeclarationType.Variable, presenterAction); - Assert.AreEqual(false, model[fieldUT].HasValidEncapsulationAttributes); + Assert.AreEqual(false, model[fieldUT].TryValidateEncapsulationAttributes(out _)); } [Test] @@ -356,7 +361,7 @@ End Function var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, fieldUT, DeclarationType.Variable, presenterAction); - Assert.AreEqual(false, model[fieldUT].HasValidEncapsulationAttributes); + Assert.AreEqual(false, model[fieldUT].TryValidateEncapsulationAttributes(out _)); } [Test] @@ -401,9 +406,96 @@ public void ModuleAndProjectNamesAreValid(string userEnteredName) var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, fieldUT, DeclarationType.Variable, presenterAction); - Assert.AreEqual(true, model[fieldUT].HasValidEncapsulationAttributes); + Assert.AreEqual(true, model[fieldUT].TryValidateEncapsulationAttributes(out _)); + } + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void MultipleUserDefinedTypesOfSameNameOtherModule() + { + var moduleOneName = "ModuleOne"; + string inputCode = +$@" +Option Explicit + +Public mF|oo As Long +"; + + string module2Content = +$@" +Public Type TModuleOne + FirstVal As Long + SecondVal As String +End Type +"; + + var fieldUT = "mFoo"; + var userInput = new UserInputDataObject() + .AddAttributeSet(fieldUT); + + userInput.EncapsulateAsUDT = true; + + var presenterAction = Support.SetParameters(userInput); + + var codeString = inputCode.ToCodeString(); + var actualModuleCode = RefactoredCode( + moduleOneName, + codeString.CaretPosition.ToOneBased(), + presenterAction, + null, + false, + ("Module2", module2Content, ComponentType.StandardModule), + (moduleOneName, codeString.Code, ComponentType.StandardModule)); + + var actualCode = actualModuleCode[moduleOneName]; + + StringAssert.Contains($"Private Type TModuleOne", actualCode); } + [TestCase("Public")] + [TestCase("Private")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void MultipleUserDefinedTypesOfSameNameSameModule(string accessibility) + { + var moduleOneName = "ModuleOne"; + string inputCode = +$@" +Option Explicit + +{accessibility} Type TModuleOne + FirstVal As Long + SecondVal As String +End Type + +Public mF|oo As Long +"; + + + var fieldUT = "mFoo"; + var userInput = new UserInputDataObject() + .AddAttributeSet(fieldUT); + + userInput.EncapsulateAsUDT = true; + + var presenterAction = Support.SetParameters(userInput); + + var codeString = inputCode.ToCodeString(); + var actualModuleCode = RefactoredCode( + moduleOneName, + codeString.CaretPosition.ToOneBased(), + presenterAction, + null, + false, + (moduleOneName, codeString.Code, ComponentType.StandardModule)); + + var actualCode = actualModuleCode[moduleOneName]; + + StringAssert.Contains($"Private Type TModuleOne_1", actualCode); + } + + protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) { return Support.SupportTestRefactoring(rewritingManager, state, factory, selectionService); diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs index 2253c90768..fde1c7c561 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs @@ -19,6 +19,20 @@ public class EncapsulateUsingStateUDTTests : InteractiveRefactoringTestBase Date: Fri, 20 Dec 2019 16:37:29 -0800 Subject: [PATCH 064/461] Wrapped RewriteSession to handle variable lists Removing all variables in a list leaves Accessibility tokens behind. --- .../EncapsulateFieldExtensions.cs | 47 ----------- .../EncapsulateFieldRefactoring.cs | 74 ++++++++--------- .../EncapsulateFieldRewriteSession.cs | 82 +++++++++++++++++++ 3 files changed, 117 insertions(+), 86 deletions(-) create mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriteSession.cs diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldExtensions.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldExtensions.cs index 53da0a5ca6..7c2bebda4b 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldExtensions.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldExtensions.cs @@ -6,8 +6,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Rubberduck.Refactorings.EncapsulateField { @@ -128,49 +126,4 @@ public static void SetVariableVisiblity(this IModuleRewriter rewriter, Declarati } } - //If all variables are removed from a list one by one, then the - //Accessiblity token is left behind. - //FIXME: this class needs to go away when the issue described above is resolved - public static class RewriterRemoveWorkAround - { - private static Dictionary> RemovedVariables { set; get; } = new Dictionary>(); - - public static void Remove(Declaration target, IModuleRewriter rewriter) - { - var varList = target.Context.GetAncestor(); - if (varList.children.Where(ch => ch is VBAParser.VariableSubStmtContext).Count() == 1) - { - rewriter.Remove(target); - return; - } - - if (!RemovedVariables.ContainsKey(varList)) - { - RemovedVariables.Add(varList, new HashSet()); - } - RemovedVariables[varList].Add(target); - } - - public static void RemoveFieldsDeclaredInLists(IExecutableRewriteSession rewriteSession, QualifiedModuleName qmn) - { - var rewriter = rewriteSession.CheckOutModuleRewriter(qmn); - - foreach (var key in RemovedVariables.Keys) - { - var variables = key.children.Where(ch => ch is VBAParser.VariableSubStmtContext); - if (variables.Count() == RemovedVariables[key].Count) - { - rewriter.Remove(key.Parent); - } - else - { - foreach (var dec in RemovedVariables[key]) - { - rewriter.Remove(dec); - } - } - } - RemovedVariables = new Dictionary>(); - } - } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 26ee6b240a..16094a2296 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -10,9 +10,6 @@ using Rubberduck.VBEditor.Utility; using System.Collections.Generic; using System; -using Rubberduck.Parsing; -using Rubberduck.Refactorings.Common; -using System.IO; using Antlr4.Runtime; namespace Rubberduck.Refactorings.EncapsulateField @@ -115,19 +112,21 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) protected override void RefactorImpl(EncapsulateFieldModel model) { - var rewriteSession = RefactorRewrite(model, RewritingManager.CheckOutCodePaneSession()); + var refactorRewriteSession = new EncapsulateFieldRewriteSession(RewritingManager.CheckOutCodePaneSession()) as IEncapsulateFieldRewriteSession; + refactorRewriteSession = RefactorRewrite(model, refactorRewriteSession); - if (!rewriteSession.TryRewrite()) + if (!refactorRewriteSession.TryRewrite(_targetQMN)) { - throw new RewriteFailedException(rewriteSession); + throw new RewriteFailedException(refactorRewriteSession.RewriteSession); } } private string PreviewRewrite(EncapsulateFieldModel model) { - var rewriteSession = GeneratePreview(model, RewritingManager.CheckOutCodePaneSession()); + IEncapsulateFieldRewriteSession refactorRewriteSession = new EncapsulateFieldRewriteSession(RewritingManager.CheckOutCodePaneSession()); + refactorRewriteSession = GeneratePreview(model, refactorRewriteSession); - var previewRewriter = rewriteSession.CheckOutModuleRewriter(_targetQMN); + var previewRewriter = refactorRewriteSession.CheckOutModuleRewriter(_targetQMN); return previewRewriter.GetText(maxConsecutiveNewLines: 3); } @@ -136,42 +135,32 @@ private IStateUDT StateUDTField => Model.EncapsulateWithUDT ? Model.StateUDTField : null; - public IExecutableRewriteSession GeneratePreview(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) + public IEncapsulateFieldRewriteSession GeneratePreview(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) { - if (!model.SelectedFieldCandidates.Any()) { return rewriteSession; } + if (!model.SelectedFieldCandidates.Any()) { return refactorRewriteSession; } - return RefactorRewrite(model, rewriteSession, asPreview: true); + return RefactorRewrite(model, refactorRewriteSession, asPreview: true); } - public IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) + public IEncapsulateFieldRewriteSession RefactorRewrite(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) { - if (!model.SelectedFieldCandidates.Any()) { return rewriteSession; } + if (!model.SelectedFieldCandidates.Any()) { return refactorRewriteSession; } - return RefactorRewrite(model, rewriteSession, asPreview: false); + return RefactorRewrite(model, refactorRewriteSession, asPreview: false); } - private IExecutableRewriteSession RefactorRewrite(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool asPreview) + private IEncapsulateFieldRewriteSession RefactorRewrite(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession, bool asPreview) { - _newContent = new Dictionary> - { - { NewContentTypes.PostContentMessage, new List() }, - { NewContentTypes.DeclarationBlock, new List() }, - { NewContentTypes.MethodBlock, new List() }, - { NewContentTypes.TypeDeclarationBlock, new List() } - }; - - ModifyFields(model, rewriteSession); - - ModifyReferences(model, rewriteSession); + ModifyFields(model, refactorRewriteSession); - RewriterRemoveWorkAround.RemoveFieldsDeclaredInLists(rewriteSession, _targetQMN); + ModifyReferences(model, refactorRewriteSession); - InsertNewContent(model, rewriteSession, asPreview); + InsertNewContent(model, refactorRewriteSession, asPreview); - return rewriteSession; + return refactorRewriteSession; } - private void ModifyReferences(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) + private void ModifyReferences(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) { var stateUDT = model.EncapsulateWithUDT ? model.StateUDTField @@ -185,27 +174,27 @@ private void ModifyReferences(EncapsulateFieldModel model, IExecutableRewriteSes foreach (var rewriteReplacement in model.SelectedFieldCandidates.SelectMany(field => field.ReferenceReplacements)) { (ParserRuleContext Context, string Text) = rewriteReplacement.Value; - var rewriter = rewriteSession.CheckOutModuleRewriter(rewriteReplacement.Key.QualifiedModuleName); + var rewriter = refactorRewriteSession.CheckOutModuleRewriter(rewriteReplacement.Key.QualifiedModuleName); rewriter.Replace(Context, Text); } } - private void ModifyFields(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession) + private void ModifyFields(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) { if (model.EncapsulateWithUDT) { foreach (var field in model.SelectedFieldCandidates) { - var rewriter = rewriteSession.CheckOutModuleRewriter(_targetQMN); + var rewriter = refactorRewriteSession.CheckOutModuleRewriter(_targetQMN); - RewriterRemoveWorkAround.Remove(field.Declaration, rewriter); + refactorRewriteSession.Remove(field.Declaration, rewriter); } return; } foreach (var field in model.SelectedFieldCandidates) { - var rewriter = rewriteSession.CheckOutModuleRewriter(_targetQMN); + var rewriter = refactorRewriteSession.CheckOutModuleRewriter(_targetQMN); if (field.Declaration.HasPrivateAccessibility() && field.FieldIdentifier.Equals(field.Declaration.IdentifierName)) { @@ -215,8 +204,7 @@ private void ModifyFields(EncapsulateFieldModel model, IExecutableRewriteSession if (field.Declaration.IsDeclaredInList() && !field.Declaration.HasPrivateAccessibility()) { - //FIXME: the call here should be: rewriter.Remove(field.Declaration); - RewriterRemoveWorkAround.Remove(field.Declaration, rewriter); + refactorRewriteSession.Remove(field.Declaration, rewriter); continue; } @@ -226,9 +214,17 @@ private void ModifyFields(EncapsulateFieldModel model, IExecutableRewriteSession } } - private void InsertNewContent(EncapsulateFieldModel model, IExecutableRewriteSession rewriteSession, bool postPendPreviewMessage = false) + private void InsertNewContent(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession, bool postPendPreviewMessage = false) { - var rewriter = rewriteSession.CheckOutModuleRewriter(_targetQMN); + _newContent = new Dictionary> + { + { NewContentTypes.PostContentMessage, new List() }, + { NewContentTypes.DeclarationBlock, new List() }, + { NewContentTypes.MethodBlock, new List() }, + { NewContentTypes.TypeDeclarationBlock, new List() } + }; + + var rewriter = refactorRewriteSession.CheckOutModuleRewriter(_targetQMN); LoadNewDeclarationBlocks(model); diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriteSession.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriteSession.cs new file mode 100644 index 0000000000..9cd10984bc --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriteSession.cs @@ -0,0 +1,82 @@ +using Rubberduck.Parsing; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; +using Rubberduck.VBEditor; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + public interface IEncapsulateFieldRewriteSession + { + IExecutableRewriteSession RewriteSession { get; } + IModuleRewriter CheckOutModuleRewriter(QualifiedModuleName qmn); + bool TryRewrite(QualifiedModuleName encapsulationModule); + void Remove(Declaration target, IModuleRewriter rewriter); + } + + public class EncapsulateFieldRewriteSession : IEncapsulateFieldRewriteSession + { + private IExecutableRewriteSession _rewriteSession; + private Dictionary> RemovedVariables { set; get; } = new Dictionary>(); + + public EncapsulateFieldRewriteSession(IExecutableRewriteSession rewriteSession) + { + _rewriteSession = rewriteSession; + } + + public IExecutableRewriteSession RewriteSession => _rewriteSession; + + public IModuleRewriter CheckOutModuleRewriter(QualifiedModuleName qmn) + => _rewriteSession.CheckOutModuleRewriter(qmn); + + public bool TryRewrite(QualifiedModuleName targetQMN) + { + HandleRemovedFieldDeclarationsInLists(targetQMN); + + return _rewriteSession.TryRewrite(); + } + + public void Remove(Declaration target, IModuleRewriter rewriter) + { + var varList = target.Context.GetAncestor(); + if (varList.children.Where(ch => ch is VBAParser.VariableSubStmtContext).Count() == 1) + { + rewriter.Remove(target); + return; + } + + if (!RemovedVariables.ContainsKey(varList)) + { + RemovedVariables.Add(varList, new HashSet()); + } + RemovedVariables[varList].Add(target); + } + + private void HandleRemovedFieldDeclarationsInLists(QualifiedModuleName qmn) + { + var rewriter = RewriteSession.CheckOutModuleRewriter(qmn); + + foreach (var key in RemovedVariables.Keys) + { + var variables = key.children.Where(ch => ch is VBAParser.VariableSubStmtContext); + if (variables.Count() == RemovedVariables[key].Count) + { + rewriter.Remove(key.Parent); + } + else + { + foreach (var dec in RemovedVariables[key]) + { + rewriter.Remove(dec); + } + } + } + RemovedVariables = new Dictionary>(); + } + } + } From c75ada4c44020729fdcab9116b275ad17cdab8a4 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Fri, 20 Dec 2019 16:38:35 -0800 Subject: [PATCH 065/461] In source module, use module variable internally --- .../FieldCandidates/ArrayCandidate.cs | 43 ++++++++++++++++--- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs index 2fb5c29acb..94543571eb 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs @@ -1,11 +1,8 @@ -using Rubberduck.Parsing; +using Antlr4.Runtime; +using Rubberduck.Parsing; 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.EncapsulateField { @@ -31,5 +28,41 @@ public ArrayCandidate(Declaration declaration, IEncapsulateFieldNamesValidator v public override string AsUDTMemberDeclaration => $"{PropertyName}({_subscripts}) {Tokens.As} {AsTypeName_Field}"; + + public override void StageFieldReferenceReplacements(IStateUDT stateUDT = null) + { + PropertyAccessor = stateUDT is null ? AccessorTokens.Field : AccessorTokens.Property; + ReferenceAccessor = AccessorTokens.Property; + ReferenceQualifier = stateUDT?.FieldIdentifier ?? null; + LoadFieldReferenceContextReplacements(); + } + + protected override void LoadFieldReferenceContextReplacements() + { + var field = this; + foreach (var idRef in field.Declaration.References) + { + var replacementText = RequiresAccessQualification(idRef) + ? $"{field.QualifiedModuleName.ComponentName}.{field.ReferenceForPreExistingReferences}" + : field.FieldIdentifier; + + field.SetReferenceRewriteContent(idRef, replacementText); + } + } + + public override void SetReferenceRewriteContent(IdentifierReference idRef, string replacementText) + { + var context = idRef.Context; + if (idRef.Context is VBAParser.IndexExprContext idxExpression) + { + context = idxExpression.children.ElementAt(0) as ParserRuleContext; + } + if (IdentifierReplacements.ContainsKey(idRef)) + { + IdentifierReplacements[idRef] = (context, replacementText); + return; + } + IdentifierReplacements.Add(idRef, (context, replacementText)); + } } } From 5e5221ae3c4647ecf6a764a1c657e9d2ba4d0581 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Fri, 20 Dec 2019 16:39:35 -0800 Subject: [PATCH 066/461] Array fields in source module does not use property --- .../Refactoring/EncapsulateFieldTests.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index 21499aa9ff..20c06e6fe9 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -784,6 +784,32 @@ End Property Assert.AreEqual(expectedCode.Trim(), actualCode); } + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulateArray_Redim() + { + string inputCode = + $@"Option Explicit + +Private myA|rray() As Integer + +Private Sub InitializeArray(size As Long) + Redim myArray(size) + For idx = 1 To size + myArray(idx) = idx + Next idx +End Sub +"; + + var presenterAction = Support.UserAcceptsDefaults(); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.Contains("Public Property Get MyArray() As Variant", actualCode); + StringAssert.DoesNotContain("Public Property Let MyArray(", actualCode); + StringAssert.Contains("Redim myArray_1(size)", actualCode); + StringAssert.Contains("myArray_1(idx) = idx", actualCode); + } + [TestCase(false)] [TestCase(true)] [Category("Refactorings")] From fa79c0a7f582c0d704bc3f9169153390d3c14b86 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Fri, 20 Dec 2019 16:39:49 -0800 Subject: [PATCH 067/461] Cleanup --- .../EncapsulateFIeldResources.cs | 3 ++- .../EncapsulateFieldElementFactory.cs | 3 --- .../EncapsulateField/EncapsulateFieldModel.cs | 5 ----- .../EncapsulateFieldValidator.cs | 8 +------ .../EncapsulateFieldCandidate.cs | 6 ------ .../EncapsulationIdentifiers.cs | 2 -- .../UserDefinedTypeCandidate.cs | 21 +------------------ .../UserDefinedTypeMemberCandidate.cs | 3 --- 8 files changed, 4 insertions(+), 47 deletions(-) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs index 1145901b25..de06f08096 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs @@ -7,7 +7,8 @@ namespace Rubberduck.Refactorings.EncapsulateField { - //TODO: All the raw strings here will be assigned keys in RubberduckUI.resx when the 'WIP' annotation is removed + //TODO: All the raw strings here will be assigned keys in RubberduckUI.resx + //just before the 'WIP' annotation is removed public class EncapsulateFieldResources { public static string PreviewEndOfChangesMarker diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs index 3b987bde4a..34f3bdae7f 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs @@ -5,10 +5,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.IO; using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Rubberduck.Refactorings.EncapsulateField { diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index 7b330054bd..2dda35061d 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -1,12 +1,7 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; -using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; -using Rubberduck.Parsing.VBA; -using Rubberduck.Refactorings.Common; -using Rubberduck.SmartIndenter; using Rubberduck.VBEditor; namespace Rubberduck.Refactorings.EncapsulateField diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs index 56fba97214..76bed32079 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -1,15 +1,9 @@ -using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Refactorings.Common; -using Rubberduck.VBEditor; -using Rubberduck.VBEditor.SafeComWrappers; -using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Rubberduck.Refactorings.EncapsulateField { diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs index f480759b47..45e4097bbc 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs @@ -1,14 +1,8 @@ using Antlr4.Runtime; -using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; -using Rubberduck.Refactorings.Common; using Rubberduck.VBEditor; -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Rubberduck.Refactorings.EncapsulateField { diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs index f87db9c376..bb25c27aa8 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs @@ -1,7 +1,5 @@ using Rubberduck.Parsing.Symbols; -using System; using System.Collections.Generic; -using System.IO; namespace Rubberduck.Refactorings.EncapsulateField { diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs index 2268dd2884..9a8c70043f 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs @@ -2,11 +2,8 @@ using Rubberduck.Parsing; 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.EncapsulateField { @@ -95,19 +92,6 @@ public override string ReferenceQualifier get => _referenceQualifier; } - //public bool FieldQualifyUDTMemberPropertyNames - //{ - // set - // { - // foreach (var member in Members) - // { - // member.IncludeParentNameWithPropertyIdentifier = value; - // } - // } - - // get => Members.All(m => m.IncludeParentNameWithPropertyIdentifier); - //} - protected override void LoadFieldReferenceContextReplacements() { if (TypeDeclarationIsPrivate) @@ -197,10 +181,7 @@ public override bool TryValidateEncapsulationAttributes(out string errorMessage) if (!TypeDeclarationIsPrivate && !_validator.IsSelfConsistent(this, out errorMessage)) { - //if (!_validator.IsSelfConsistent(this, out errorMessage)) - //{ - return false; - //} + return false; } if (_validator.HasConflictingIdentifier(this, DeclarationType.Property, out errorMessage)) diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs index 252476dad5..3bfa59553e 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs @@ -3,12 +3,9 @@ using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.VBEditor; -using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Rubberduck.Refactorings.EncapsulateField { From 58e527369c23185bd98736ed9003f08e78afebd0 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Fri, 20 Dec 2019 18:43:17 -0800 Subject: [PATCH 068/461] All RD tests pass --- .../EncapsulateField/EncapsulateFieldModel.cs | 3 --- .../EncapsulateFieldRefactoring.cs | 5 ----- .../EncapsulateField/EncapsulateFieldValidator.cs | 14 ++++---------- 3 files changed, 4 insertions(+), 18 deletions(-) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index 2dda35061d..3b4bd08976 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -37,9 +37,6 @@ public IEnumerable SelectedUDTFieldCandidates .Where(v => v is IUserDefinedTypeCandidate) .Cast(); - public bool HasSelectedMultipleUDTFieldsOfType(string asTypeName) - => SelectedUDTFieldCandidates.Where(f => f.AsTypeName_Field.Equals(asTypeName)).Count() > 1; - public IEncapsulateFieldCandidate this[string encapsulatedFieldTargetID] => EncapsulationCandidates.Where(c => c.TargetID.Equals(encapsulatedFieldTargetID)).Single(); diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 16094a2296..ee1aa26603 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -47,11 +47,6 @@ public EncapsulateFieldRefactoring( _declarationFinderProvider = declarationFinderProvider; _selectedDeclarationProvider = selectedDeclarationProvider; _indenter = indenter; - - _codeSectionStartIndex = _declarationFinderProvider.DeclarationFinder - .Members(_targetQMN).Where(m => m.IsMember()) - .OrderBy(c => c.Selection) - .FirstOrDefault()?.Context.Start.TokenIndex ?? null; } public EncapsulateFieldModel Model { set; get; } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs index 76bed32079..04dfdca75a 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -131,16 +131,8 @@ private List PotentialConflictIdentifiers(IStateUDT stateUDT, Declaratio public bool HasConflictingIdentifier(IEncapsulateFieldCandidate field, DeclarationType declarationType, out string errorMessage) { errorMessage = string.Empty; - //The declared type of a function declaration may not be a private enum name. - //=>Means encapsulating a private enum field must be 'As Long' - //If a procedure declaration whose visibility is public has a procedure name - //that is the same as the name of a project or name of a module then - //all references to the procedure name must be explicitly qualified with - //its project or module name unless the reference occurs within the module that defines the procedure. - - - var potentialDeclarationIdentifierConflicts = new List(); + var potentialDeclarationIdentifierConflicts = new List(); potentialDeclarationIdentifierConflicts.AddRange(PotentialConflictIdentifiers(field, declarationType)); potentialDeclarationIdentifierConflicts.AddRange(FlaggedCandidates.Where(fc => fc != field).Select(fc => fc.PropertyName)); @@ -203,7 +195,7 @@ public bool IsConflictingStateUDTFieldIdentifier(IStateUDT stateUDT) return potentialConflictNames.Any(m => m.IsEquivalentVBAIdentifierTo(stateUDT.FieldIdentifier)); } - //The refactoring only inserts elements with the following Accessibilities: + //The refactoring only inserts new code elements with the following Accessibilities: //Variables => Private //Properties => Public //UDT => Private @@ -217,6 +209,7 @@ private bool IsAlwaysIgnoreNameConflictType(Declaration d, DeclarationType toEna DeclarationType.Parameter, DeclarationType.EnumerationMember, DeclarationType.Enumeration, + DeclarationType.UserDefinedType, DeclarationType.UserDefinedTypeMember }; @@ -231,6 +224,7 @@ private bool IsAlwaysIgnoreNameConflictType(Declaration d, DeclarationType toEna //5.2.3.3 If an is an element of a its //UDT name cannot be the same as the enum name of any //or the UDT name of any other within the same + NeverCauseNameConflictTypes.Remove(DeclarationType.UserDefinedType); //5.2.3.4 The enum name of a cannot be the same as the enum name of any other // or as the UDT name of a within the same . From 6eb77ec055555e07493085c0789f0e78e7381c16 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Fri, 20 Dec 2019 19:08:32 -0800 Subject: [PATCH 069/461] more cleanup --- .../EncapsulateField/EncapsulateFieldValidator.cs | 2 +- .../FieldCandidates/EncapsulateFieldCandidate.cs | 11 ----------- .../FieldCandidates/UserDefinedTypeCandidate.cs | 5 +++-- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs index 04dfdca75a..eae14ff66c 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -151,7 +151,7 @@ public bool HasConflictingIdentifier(IEncapsulateFieldCandidate field, Declarati return false; } - public IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType) //, Predicate conflictDetector, Action setValue, Func getIdentifier) + public IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType) { var isConflictingIdentifier = HasConflictingIdentifier(candidate, declarationType, out _); for (var count = 1; count < 10 && isConflictingIdentifier; count++) diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs index 45e4097bbc..5c261663a8 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs @@ -259,17 +259,6 @@ private string AccessorTokenToContent(AccessorTokens token) var accessor = token == AccessorTokens.Field ? FieldIdentifier : PropertyName; - //switch (token) - //{ - // case AccessorTokens.Field: - // accessor = FieldIdentifier; - // break; - // case AccessorTokens.Property: - // accessor = PropertyName; - // break; - // default: - // throw new ArgumentException(); - //} if ((ReferenceQualifier?.Length ?? 0) > 0) { diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs index 9a8c70043f..3e6510d78c 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs @@ -67,9 +67,10 @@ public override bool EncapsulateFlag continue; } - //Reaching this line typically implies that there are multiple fields of the same Type within the module. + //Reaching this line probably implies that there are multiple fields of the same User Defined + //Type within the module. //Try to use a name involving the parent's identifier to make it unique/meaningful - //before appending incremented value(s). + //before giving up and creating incremented value(s). member.PropertyName = $"{FieldIdentifier.Capitalize()}{member.PropertyName.Capitalize()}"; _validator.AssignNoConflictIdentifier(member, DeclarationType.Property); } From b12f3ad23eb54ac28180120275e0ff13da6d5345 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Sat, 21 Dec 2019 06:12:36 -0800 Subject: [PATCH 070/461] Added handling of HungarianNotation fields --- .../EncapsulateFieldElementFactory.cs | 4 +- .../EncapsulateFieldExtensions.cs | 81 +++++++++++++++++++ .../EncapsulateFieldValidator.cs | 23 ++++-- .../EncapsulateFieldCandidate.cs | 2 + .../EncapsulationIdentifiers.cs | 18 ++++- .../EncapsulateFieldValidatorTests.cs | 47 ++++++++--- .../EncapsulateUsingStateUDTTests.cs | 18 ++--- .../EncapsulatedUDTFieldTests.cs | 50 ++++++------ ...ts.cs => EncapsulationIdentifiersTests.cs} | 5 +- .../EncapsulateField/TestSupport.cs | 34 ++++++-- .../Refactoring/EncapsulateFieldTests.cs | 61 +++----------- 11 files changed, 233 insertions(+), 110 deletions(-) rename RubberduckTests/Refactoring/EncapsulateField/{EncapsulatedFieldTests.cs => EncapsulationIdentifiersTests.cs} (98%) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs index 34f3bdae7f..dbdc334301 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs @@ -58,8 +58,8 @@ public IEncapsulateFieldCandidate CreateEncapsulationCandidate(Declaration targe _validator.RegisterFieldCandidate(candidate); - candidate = _validator.AssignNoConflictIdentifier(candidate, DeclarationType.Property); - candidate = _validator.AssignNoConflictIdentifier(candidate, DeclarationType.Variable); + //candidate = _validator.AssignNoConflictIdentifier(candidate, DeclarationType.Property); + //candidate = _validator.AssignNoConflictIdentifier(candidate, DeclarationType.Variable); return candidate; } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldExtensions.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldExtensions.cs index 7c2bebda4b..3dc7754982 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldExtensions.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldExtensions.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.RegularExpressions; namespace Rubberduck.Refactorings.EncapsulateField { @@ -60,6 +61,86 @@ public static string UnCapitalize(this string input) public static bool IsEquivalentVBAIdentifierTo(this string lhs, string identifier) => lhs.Equals(identifier, StringComparison.InvariantCultureIgnoreCase); + #region HungarianNotation + //From the HungarianNotation Inspection: Where should this code reside to be + //shared by both the Inspection and this refactoring? Rubberduck.Parsing.VBA.Extensions.StringExtensions.cs? + private static readonly List HungarianPrefixes = new List + { + "chk", + "cbo", + "cmd", + "btn", + "fra", + "img", + "lbl", + "lst", + "mnu", + "opt", + "pic", + "shp", + "txt", + "tmr", + "chk", + "dlg", + "drv", + "frm", + "grd", + "obj", + "rpt", + "fld", + "idx", + "tbl", + "tbd", + "bas", + "cls", + "g", + "m", + "bln", + "byt", + "col", + "dtm", + "dbl", + "cur", + "int", + "lng", + "sng", + "str", + "udt", + "vnt", + "var", + "pgr", + "dao", + "b", + "by", + "c", + "chr", + "i", + "l", + "s", + "o", + "n", + "dt", + "dat", + "a", + "arr" + }; + + private static readonly Regex HungarianIdentifierRegex = new Regex($"^({string.Join("|", HungarianPrefixes)})[A-Z0-9].*$"); + + public static bool IsHungarianIdentifier(this string identifier, out string nonHungarianName) + { + nonHungarianName = identifier; + if (HungarianIdentifierRegex.IsMatch(identifier)) + { + var prefixChars = identifier.TakeWhile(c => char.IsLower(c)); + nonHungarianName = identifier.Substring(prefixChars.Count()); + return true; + } + return false; + } + + #endregion //HungarianNotation + public static string GetText(this IModuleRewriter rewriter, int maxConsecutiveNewLines) { var result = rewriter.GetText(); diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs index eae14ff66c..32e1d8816b 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -40,6 +40,9 @@ public EncapsulateFieldNamesValidator(IDeclarationFinderProvider declarationFind public void RegisterFieldCandidate(IEncapsulateFieldCandidate candidate) { FieldCandidates.Add(candidate); + AssignNoConflictIdentifier(candidate, DeclarationType.Property); + AssignNoConflictIdentifier(candidate, DeclarationType.Variable); + if (candidate is IUserDefinedTypeCandidate udt) { foreach (var member in udt.Members) @@ -47,6 +50,7 @@ public void RegisterFieldCandidate(IEncapsulateFieldCandidate candidate) UDTMemberCandidates.Add(member); } } + } private DeclarationFinder DeclarationFinder => _declarationFinderProvider.DeclarationFinder; @@ -128,15 +132,24 @@ private List PotentialConflictIdentifiers(IStateUDT stateUDT, Declaratio return potentialDeclarationIdentifierConflicts.ToList(); } - public bool HasConflictingIdentifier(IEncapsulateFieldCandidate field, DeclarationType declarationType, out string errorMessage) + public bool HasConflictingIdentifier(IEncapsulateFieldCandidate field, DeclarationType declarationType, out string errorMessage) + => InternalHasConflictingIdentifier(field, declarationType, false, out errorMessage); + + private bool InternalHasConflictingIdentifier(IEncapsulateFieldCandidate field, DeclarationType declarationType, bool ignoreEncapsulationFlags, out string errorMessage) { errorMessage = string.Empty; var potentialDeclarationIdentifierConflicts = new List(); potentialDeclarationIdentifierConflicts.AddRange(PotentialConflictIdentifiers(field, declarationType)); - potentialDeclarationIdentifierConflicts.AddRange(FlaggedCandidates.Where(fc => fc != field).Select(fc => fc.PropertyName)); - + if (ignoreEncapsulationFlags) + { + potentialDeclarationIdentifierConflicts.AddRange(FieldCandidates.Where(fc => fc != field).Select(fc => fc.PropertyName)); + } + else + { + potentialDeclarationIdentifierConflicts.AddRange(FlaggedCandidates.Where(fc => fc != field).Select(fc => fc.PropertyName)); + } potentialDeclarationIdentifierConflicts.AddRange(UDTMemberCandidates.Where(udtm => udtm != field && udtm.EncapsulateFlag).Select(udtm => udtm.PropertyName)); var identifierToCompare = declarationType.HasFlag(DeclarationType.Property) @@ -153,7 +166,7 @@ public bool HasConflictingIdentifier(IEncapsulateFieldCandidate field, Declarati public IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType) { - var isConflictingIdentifier = HasConflictingIdentifier(candidate, declarationType, out _); + var isConflictingIdentifier = InternalHasConflictingIdentifier(candidate, declarationType, true, out _); for (var count = 1; count < 10 && isConflictingIdentifier; count++) { var identifier = declarationType.HasFlag(DeclarationType.Property) @@ -168,7 +181,7 @@ public IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncapsulateFieldCa { candidate.FieldIdentifier = identifier.IncrementEncapsulationIdentifier(); } - isConflictingIdentifier = HasConflictingIdentifier(candidate, declarationType, out _); + isConflictingIdentifier = InternalHasConflictingIdentifier(candidate, declarationType, true, out _); } return candidate; } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs index 5c261663a8..05474c88cc 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs @@ -161,6 +161,8 @@ public virtual bool EncapsulateFlag if (!_encapsulateFlag) { PropertyName = _fieldAndProperty.DefaultPropertyName; + _validator.AssignNoConflictIdentifier(this, DeclarationType.Property); + _validator.AssignNoConflictIdentifier(this, DeclarationType.Variable); } } get => _encapsulateFlag; diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs index bb25c27aa8..c5835df14c 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs @@ -1,4 +1,5 @@ using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA.Extensions; using System.Collections.Generic; namespace Rubberduck.Refactorings.EncapsulateField @@ -17,8 +18,21 @@ public EncapsulationIdentifiers(Declaration target) public EncapsulationIdentifiers(string field) { _targetIdentifier = field; - DefaultPropertyName = field.Capitalize(); - DefaultNewFieldName = (field.UnCapitalize()).IncrementEncapsulationIdentifier(); + if (field.IsHungarianIdentifier(out var nonHungarianName)) + { + DefaultPropertyName = nonHungarianName; + DefaultNewFieldName = field; + } + else if (field.StartsWith("m_")) + { + DefaultPropertyName = field.Substring(2).Capitalize(); + DefaultNewFieldName = field; + } + else + { + DefaultPropertyName = field.Capitalize(); + DefaultNewFieldName = (field.UnCapitalize()).IncrementEncapsulationIdentifier(); + } _fieldAndProperty = new KeyValuePair(DefaultNewFieldName, DefaultPropertyName); _setLetParameter = DEFAULT_WRITE_PARAMETER; } diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs index ca57c7b445..49249bf6ab 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs @@ -84,9 +84,9 @@ public void PropertyNameNotDuplicated() @"Public var|iable As Integer, variable1 As Long, variable2 As Integer"; var userInput = new UserInputDataObject() - .AddAttributeSet("variable") - .AddAttributeSet("variable1") - .AddAttributeSet("variable2"); + .UserSelectsField("variable") + .UserSelectsField("variable1") + .UserSelectsField("variable2"); var presenterAction = Support.SetParameters(userInput); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); @@ -167,7 +167,8 @@ End Property "; var fieldUT = "fizz"; - var userInput = new UserInputDataObject("fizz", userModifiedPropertyName, true); + var userInput = new UserInputDataObject() //"fizz", userModifiedPropertyName, true); + .UserSelectsField("fizz", userModifiedPropertyName); var presenterAction = Support.SetParameters(userInput); @@ -197,8 +198,8 @@ Public Property Get Test() As Integer var fieldUT = "fizz"; var userInput = new UserInputDataObject() - .AddAttributeSet(fieldUT, fizz_modifiedPropertyName, true) - .AddAttributeSet("bazz", bazz_modifiedPropertyName, true); + .UserSelectsField(fieldUT, fizz_modifiedPropertyName, true) + .UserSelectsField("bazz", bazz_modifiedPropertyName, true); var presenterAction = Support.SetParameters(userInput); @@ -231,8 +232,8 @@ End Type "; var fieldUT = "this"; var userInput = new UserInputDataObject() - .AddAttributeSet(fieldUT) - .AddAttributeSet("that"); + .UserSelectsField(fieldUT) + .UserSelectsField("that"); var presenterAction = Support.SetParameters(userInput); @@ -255,7 +256,7 @@ Public wholeNumber As String "; var fieldUT = "longValue"; var userInput = new UserInputDataObject() - .AddAttributeSet(fieldUT, "WholeNumber", true); + .UserSelectsField(fieldUT, "WholeNumber", true); var presenterAction = Support.SetParameters(userInput); @@ -311,6 +312,26 @@ Private whe|els As Integer StringAssert.Contains("Wheels = wheels_1", actualCode); } + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void DefaultPropertyNameConflictsResolved() + { + //Both fields default to "Test" as the property name + const string inputCode = + @"Private mTest As Integer +Private strTest As String"; + + var fieldUT = "mTest"; + + var presenterAction = Support.UserAcceptsDefaults(fieldUT, "strTest"); + + var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, fieldUT, DeclarationType.Variable, presenterAction); + + Assert.AreEqual(true, model[fieldUT].TryValidateEncapsulationAttributes(out var errorMsg), errorMsg); + } + [TestCase("Dim test As String", "arg")] //Local variable [TestCase(@"Const test As String = ""Foo""", "arg")] //Local constant [TestCase(@"Const localTest As String = ""Foo""", "test")] //parameter @@ -354,7 +375,7 @@ End Function "; var fieldUT = "aName"; var userInput = new UserInputDataObject() - .AddAttributeSet(fieldUT, "Test", true); + .UserSelectsField(fieldUT, "Test", true); var presenterAction = Support.SetParameters(userInput); @@ -395,7 +416,7 @@ public void ModuleAndProjectNamesAreValid(string userEnteredName) { var fieldUT = "foo"; var userInput = new UserInputDataObject() - .AddAttributeSet(fieldUT, userEnteredName, true); + .UserSelectsField(fieldUT, userEnteredName, true); var presenterAction = Support.SetParameters(userInput); @@ -432,7 +453,7 @@ End Type var fieldUT = "mFoo"; var userInput = new UserInputDataObject() - .AddAttributeSet(fieldUT); + .UserSelectsField(fieldUT); userInput.EncapsulateAsUDT = true; @@ -475,7 +496,7 @@ Public mF|oo As Long var fieldUT = "mFoo"; var userInput = new UserInputDataObject() - .AddAttributeSet(fieldUT); + .UserSelectsField(fieldUT); userInput.EncapsulateAsUDT = true; diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs index fde1c7c561..ddde11d01e 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs @@ -73,7 +73,7 @@ End Type var userInput = new UserInputDataObject() - .AddAttributeSet("myBar"); + .UserSelectsField("myBar"); userInput.EncapsulateAsUDT = true; @@ -108,7 +108,7 @@ Public Sub Foo(newValue As String) var userInput = new UserInputDataObject() - .AddAttributeSet("myBar"); + .UserSelectsField("myBar"); userInput.EncapsulateAsUDT = true; @@ -131,9 +131,9 @@ Public foobar As Byte "; var userInput = new UserInputDataObject() - .AddAttributeSet("foo") - .AddAttributeSet("bar") - .AddAttributeSet("foobar"); + .UserSelectsField("foo") + .UserSelectsField("bar") + .UserSelectsField("foobar"); userInput.EncapsulateAsUDT = true; @@ -164,7 +164,7 @@ Public myBar As TBar "; var userInput = new UserInputDataObject() - .AddAttributeSet("myBar"); + .UserSelectsField("myBar"); userInput.EncapsulateAsUDT = true; @@ -197,7 +197,7 @@ Public numberT|ype As NumberTypes var userInput = new UserInputDataObject() - .AddAttributeSet("numberType"); + .UserSelectsField("numberType"); userInput.EncapsulateAsUDT = true; @@ -222,7 +222,7 @@ public void UserDefinedType_BoundedArrayField(string arrayIdentifier, string dim "; var userInput = new UserInputDataObject() - .AddAttributeSet(arrayIdentifier); + .UserSelectsField(arrayIdentifier); userInput.EncapsulateAsUDT = true; @@ -257,7 +257,7 @@ Public myBar As TBar "; var userInput = new UserInputDataObject() - .AddAttributeSet("myBar"); + .UserSelectsField("myBar"); userInput.EncapsulateAsUDT = true; diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs index c6c2b5b1e5..4cb52eece0 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs @@ -68,8 +68,8 @@ Public th|is As TBar var expectedThat = new EncapsulationIdentifiers("that"); var userInput = new UserInputDataObject() - .AddAttributeSet(expectedThis.TargetFieldName, encapsulationFlag: encapsulateThis) - .AddAttributeSet(expectedThat.TargetFieldName, encapsulationFlag: encapsulateThat); + .AddUserInputSet(expectedThis.TargetFieldName, encapsulationFlag: encapsulateThis) + .AddUserInputSet(expectedThat.TargetFieldName, encapsulationFlag: encapsulateThat); var presenterAction = Support.SetParameters(userInput); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); @@ -96,7 +96,6 @@ Public th|is As TBar } else if (encapsulateThis && !encapsulateThat) { - //StringAssert.Contains($"Private {expectedThis.TargetFieldName} As TBar", actualCode); StringAssert.Contains($"First = {expectedThis.TargetFieldName}.First", actualCode); StringAssert.Contains($"Second = {expectedThis.TargetFieldName}.Second", actualCode); StringAssert.Contains($"{expectedThis.TargetFieldName}.First = value", actualCode); @@ -109,7 +108,6 @@ Public th|is As TBar } else if (!encapsulateThis && encapsulateThat) { - //StringAssert.Contains($"Private {expectedThat.TargetFieldName} As TBar", actualCode); StringAssert.Contains($"First = {expectedThat.TargetFieldName}.First", actualCode); StringAssert.Contains($"Second = {expectedThat.TargetFieldName}.Second", actualCode); StringAssert.Contains($"{expectedThat.TargetFieldName}.First = value", actualCode); @@ -193,11 +191,8 @@ With that End With End Sub "; - //var userInput = new UserInputDataObject("this"); var presenterAction = Support.UserAcceptsDefaults(); - //var presenterAction = Support.SetParameters(userInput); - var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.DoesNotContain($" First = arg1", actualCode); StringAssert.DoesNotContain($" Second = arg2", actualCode); @@ -254,7 +249,6 @@ End Sub var actualCode = actualModuleCode["Module2"]; var sourceCode = actualModuleCode[sourceModuleName]; - //var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.DoesNotContain($" First = arg1", actualCode); StringAssert.DoesNotContain($" Second = arg2", actualCode); StringAssert.Contains($" .First = arg1", actualCode); @@ -282,10 +276,11 @@ Private mFizz {accessibility} t|his As TBar"; - var userInput = new UserInputDataObject("this", "MyType", true); - userInput.AddAttributeSet("mFoo", "Foo", true); - userInput.AddAttributeSet("mBar", "Bar", true); - userInput.AddAttributeSet("mFizz", "Fizz", true); + var userInput = new UserInputDataObject() + .UserSelectsField("this", "MyType") + .UserSelectsField("mFoo", "Foo") + .UserSelectsField("mBar", "Bar") + .UserSelectsField("mFizz", "Fizz"); var presenterAction = Support.SetParameters(userInput); @@ -332,7 +327,8 @@ Public Sub Foo() End Sub "; - var userInput = new UserInputDataObject("this", "MyType", true); + var userInput = new UserInputDataObject() + .UserSelectsField("this", "MyType"); var presenterAction = Support.SetParameters(userInput); @@ -376,7 +372,8 @@ End Type {accessibility} th|is As TBar"; - var userInput = new UserInputDataObject("this", "MyType"); + var userInput = new UserInputDataObject() + .UserSelectsField("this", "MyType"); var presenterAction = Support.SetParameters(userInput); @@ -408,7 +405,8 @@ End Type {accessibility} t|his As TBar"; - var userInput = new UserInputDataObject("this", "MyType"); + var userInput = new UserInputDataObject() + .UserSelectsField("this", "MyType"); var presenterAction = Support.SetParameters(userInput); @@ -445,7 +443,8 @@ Second As Long End Type "; - var userInput = new UserInputDataObject("this", "MyType", true); + var userInput = new UserInputDataObject() + .UserSelectsField("this", "MyType"); var presenterAction = Support.SetParameters(userInput); @@ -510,12 +509,10 @@ End Sub var actualCode = actualModuleCode["Module1"]; - var defaults = new EncapsulationIdentifiers("mTheClass"); - - StringAssert.Contains($"Private {defaults.Field} As Class1", actualCode); - StringAssert.Contains($"Set {defaults.Field} = value", actualCode); - StringAssert.Contains($"MTheClass = {defaults.Field}", actualCode); - StringAssert.Contains($"Public Property Set {defaults.Property}", actualCode); + StringAssert.Contains($"Private mTheClass As Class1", actualCode); + StringAssert.Contains($"Set mTheClass = value", actualCode); + StringAssert.Contains($"Set TheClass = mTheClass", actualCode); + StringAssert.Contains($"Public Property Set TheClass", actualCode); } [TestCase("SourceModule", "this", "Public")] @@ -557,7 +554,9 @@ Public Sub FooBar() End With End Sub "; - var userInput = new UserInputDataObject("this", "MyType"); + var userInput = new UserInputDataObject() + .UserSelectsField("this", "MyType"); + var presenterAction = Support.SetParameters(userInput); var sourceCodeString = sourceModuleCode.ToCodeString(); @@ -750,7 +749,8 @@ End With End Sub "; - var userInput = new UserInputDataObject("this", "MyType"); + var userInput = new UserInputDataObject() + .UserSelectsField("this", "MyType"); var presenterAction = Support.SetParameters(userInput); @@ -792,7 +792,7 @@ End Type Private t|his As TBar"; var userInput = new UserInputDataObject() - .AddAttributeSet("this", isReadOnly: true); + .UserSelectsField("this", isReadOnly: true); var presenterAction = Support.SetParameters(userInput); diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs similarity index 98% rename from RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs rename to RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs index b0aa8dfacc..7dac9687b3 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs @@ -12,7 +12,7 @@ namespace RubberduckTests.Refactoring.EncapsulateField { [TestFixture] - public class EncapsulatedFieldTests + public class EncapsulationIdentifiersTests { private EncapsulateFieldTestSupport Support { get; } = new EncapsulateFieldTestSupport(); @@ -77,5 +77,8 @@ public void PropertyNameChange_UniqueParamName() encapsulatedField.PropertyName = "Value"; StringAssert.AreEqualIgnoringCase("Value_value_1_value", encapsulatedField.ParameterName); } + + + } } } diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index 014e203541..8c79a745f4 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -34,13 +34,25 @@ private TestEncapsulationAttributes UserModifiedEncapsulationAttributes(string f public Func UserAcceptsDefaults(bool asUDT = false) { - return model => + return model => { model.EncapsulateWithUDT = asUDT; return model; }; } + public Func UserAcceptsDefaults(params string[] fieldNames) + { + return model => + { + foreach (var name in fieldNames) + { + model[name].EncapsulateFlag = true; + } + return model; + }; + } + public Func SetParametersForSingleTarget(string field, string property = null, bool isReadonly = false, bool encapsulateFlag = true, bool asUDT = false) { var clientAttrs = UserModifiedEncapsulationAttributes(field, property, isReadonly, encapsulateFlag); @@ -190,13 +202,25 @@ public class UserInputDataObject public UserInputDataObject() { } - public UserInputDataObject(string fieldName, string propertyName = null, bool encapsulationFlag = true, bool isReadOnly = false) - : this() + //public UserInputDataObject(string fieldName, string propertyName = null, /*bool encapsulationFlag = true,*/ bool isReadOnly = false) + // : this() + //{ + // UserSelectsField(fieldName, propertyName/*, encapsulationFlag*/, isReadOnly); + //} + + public UserInputDataObject UserSelectsField(string fieldName, string propertyName = null/*, bool encapsulationFlag = true*/, bool isReadOnly = false) { - AddAttributeSet(fieldName, propertyName, encapsulationFlag, isReadOnly); + //var attrs = new TestEncapsulationAttributes(fieldName, true, isReadOnly); + //attrs.PropertyName = propertyName ?? attrs.PropertyName; + //attrs.EncapsulateFlag = true; + //attrs.IsReadOnly = isReadOnly; + + //_userInput.Add(attrs); + //return this; + return AddUserInputSet(fieldName, propertyName, true, isReadOnly); } - public UserInputDataObject AddAttributeSet(string fieldName, string propertyName = null, bool encapsulationFlag = true, bool isReadOnly = false) + public UserInputDataObject AddUserInputSet(string fieldName, string propertyName = null, bool encapsulationFlag = true, bool isReadOnly = false) { var attrs = new TestEncapsulationAttributes(fieldName, encapsulationFlag, isReadOnly); attrs.PropertyName = propertyName ?? attrs.PropertyName; diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs index 20c06e6fe9..46a8f6a7e5 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateFieldTests.cs @@ -43,9 +43,10 @@ public void EncapsulateMultipleFields( var selection = new Selection(1, 1); - var userInput = new UserInputDataObject(var1, $"{var1}Prop", var1Flag); - userInput.AddAttributeSet(var2, $"{var2}Prop", var2Flag); - userInput.AddAttributeSet(var3, $"{var3}Prop", var3Flag); + var userInput = new UserInputDataObject() + .AddUserInputSet(var1, $"{var1}Prop", var1Flag) + .AddUserInputSet(var2, $"{var2}Prop", var2Flag) + .AddUserInputSet(var3, $"{var3}Prop", var3Flag); var flags = new Dictionary() { @@ -100,10 +101,11 @@ public void EncapsulateMultipleFieldsInList( var selection = new Selection(1, 9); - var userInput = new UserInputDataObject(var1, $"{var1}Prop", var1Flag); - userInput.AddAttributeSet(var2, $"{var2}Prop", var2Flag); - userInput.AddAttributeSet(var3, $"{var3}Prop", var3Flag); - userInput.AddAttributeSet(var4, $"{var4}Prop", var4Flag); + var userInput = new UserInputDataObject() + .AddUserInputSet(var1, $"{var1}Prop", var1Flag) + .AddUserInputSet(var2, $"{var2}Prop", var2Flag) + .AddUserInputSet(var3, $"{var3}Prop", var3Flag) + .AddUserInputSet(var4, $"{var4}Prop", var4Flag); var flags = new Dictionary() { @@ -201,7 +203,6 @@ End Property Assert.AreEqual(expectedCode.Trim(), actualCode); } - [Test] [Category("Refactorings")] [Category("Encapsulate Field")] @@ -440,44 +441,6 @@ End Property var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); Assert.AreEqual(expectedCode.Trim(), actualCode); } -// TODO: this test used the old method of injecting conflict names lists - rework -// [Test] -// [Category("Refactorings")] -// [Category("Encapsulate Field")] -// public void EncapsulatePrivateField_NameConflict() -// { -// const string inputCode = -// @"Private fizz As String -//Private mName As String - -//Public Property Get Name() As String -// Name = mName -//End Property - -//Public Property Let Name(ByVal value As String) -// mName = value -//End Property -//"; -// var fieldName = "fizz"; -// var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; - -// var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); -// using (state) -// { -// IEncapsulateFieldCandidate efd = null; -// var fields = new List(); -// var validator = new EncapsulateFieldNamesValidator(state, () => fields); - -// var match = state.DeclarationFinder.MatchName(fieldName).Single(); -// efd = new EncapsulateFieldCandidate(match, validator); -// fields.Add(efd); -// efd.PropertyName = "Name"; - -// //var hasConflict = !validator.HasValidEncapsulationAttributes(efd, efd.QualifiedModuleName, new Declaration[] { efd.Declaration }); -// var hasConflict = validator.HasConflictingPropertyIdentifier(efd); -// Assert.IsTrue(hasConflict); -// } -// } [Test] [Category("Refactorings")] @@ -714,7 +677,8 @@ Public Property Get MyArray() As Variant MyArray = mArray End Property "; - var userInput = new UserInputDataObject("mArray", "MyArray", true); + var userInput = new UserInputDataObject() + .UserSelectsField("mArray", "MyArray"); var presenterAction = Support.SetParameters(userInput); var actualCode = RefactoredCode(inputCode, selection, presenterAction); @@ -855,7 +819,8 @@ End With End Sub "; - var userInput = new UserInputDataObject("this", "MyProperty", true); + var userInput = new UserInputDataObject() + .UserSelectsField("this", "MyProperty"); var presenterAction = Support.SetParameters(userInput); From b14ebaa3e503b75ff2756c2416b40ac2e05bad77 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Sat, 21 Dec 2019 07:30:45 -0800 Subject: [PATCH 071/461] Moved HungarianNotation matching elements Moved to Rubberduck.JunkDrawer\Output\StringExtensions so it could also be used by EncapsulateField Refactoring --- .../Concrete/HungarianNotationInspection.cs | 66 +------------------ 1 file changed, 2 insertions(+), 64 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/HungarianNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/HungarianNotationInspection.cs index 23fac44b37..1570e0e40c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/HungarianNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/HungarianNotationInspection.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Text.RegularExpressions; using Rubberduck.CodeAnalysis.Settings; +using Rubberduck.Common; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Inspections.Results; @@ -49,69 +50,6 @@ namespace Rubberduck.Inspections.Concrete public sealed class HungarianNotationInspection : InspectionBase { #region statics - private static readonly List HungarianPrefixes = new List - { - "chk", - "cbo", - "cmd", - "btn", - "fra", - "img", - "lbl", - "lst", - "mnu", - "opt", - "pic", - "shp", - "txt", - "tmr", - "chk", - "dlg", - "drv", - "frm", - "grd", - "obj", - "rpt", - "fld", - "idx", - "tbl", - "tbd", - "bas", - "cls", - "g", - "m", - "bln", - "byt", - "col", - "dtm", - "dbl", - "cur", - "int", - "lng", - "sng", - "str", - "udt", - "vnt", - "var", - "pgr", - "dao", - "b", - "by", - "c", - "chr", - "i", - "l", - "s", - "o", - "n", - "dt", - "dat", - "a", - "arr" - }; - - private static readonly Regex HungarianIdentifierRegex = new Regex($"^({string.Join("|", HungarianPrefixes)})[A-Z0-9].*$"); - private static readonly List TargetDeclarationTypes = new List { DeclarationType.Parameter, @@ -154,7 +92,7 @@ protected override IEnumerable DoGetInspectionResults() && TargetDeclarationTypes.Contains(declaration.DeclarationType) && !IgnoredProcedureTypes.Contains(declaration.DeclarationType) && !IgnoredProcedureTypes.Contains(declaration.ParentDeclaration.DeclarationType) - && HungarianIdentifierRegex.IsMatch(declaration.IdentifierName)) + && declaration.IdentifierName.TryMatchHungarianNotationCriteria(out _)) .Select(issue => new DeclarationInspectionResult(this, string.Format(Resources.Inspections.InspectionResults.IdentifierNameInspection, RubberduckUI.ResourceManager.GetString($"DeclarationType_{issue.DeclarationType}", CultureInfo.CurrentUICulture), From 25af04821afd5aa2aabff8f4270ca22d2fe66675 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Sat, 21 Dec 2019 07:32:10 -0800 Subject: [PATCH 072/461] Added Hungarian matching and ToLowerCase Relocated HungarianNotation content from the HungarianNotationInspection so it could be used by the EncapsulatedField Refactoring --- .../Output/StringExtensions.cs | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/Rubberduck.JunkDrawer/Output/StringExtensions.cs b/Rubberduck.JunkDrawer/Output/StringExtensions.cs index b46f26847f..5735121011 100644 --- a/Rubberduck.JunkDrawer/Output/StringExtensions.cs +++ b/Rubberduck.JunkDrawer/Output/StringExtensions.cs @@ -1,5 +1,8 @@ using System; +using System.Collections.Generic; using System.Globalization; +using System.Linq; +using System.Text.RegularExpressions; namespace Rubberduck.Common { @@ -16,6 +19,17 @@ public static string Capitalize(this string input) return string.Join(" ", tokens); } + public static string ToLowerCase(this string input) + { + var tokens = input.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); + if (tokens.Length == 0) + { + return input; + } + tokens[0] = CultureInfo.CurrentUICulture.TextInfo.ToLower(tokens[0]); + return string.Join(" ", tokens); + } + public static string CapitalizeFirstLetter(this string input) { if (input.Length == 0) @@ -25,6 +39,15 @@ public static string CapitalizeFirstLetter(this string input) return input.Capitalize().Substring(0, 1) + input.Substring(1); } + public static string ToLowerCaseFirstLetter(this string input) + { + if (input.Length == 0) + { + return string.Empty; + } + return input.ToLowerCase().Substring(0, 1) + input.Substring(1); + } + public static string UnQuote(this string input) { if (input[0] == '"' && input[input.Length - 1] == '"') @@ -42,5 +65,80 @@ public static string EnQuote(this string input) } return $"\"{input}\""; } + + public static bool TryMatchHungarianNotationCriteria(this string identifier, out string nonHungarianName) + { + nonHungarianName = identifier; + if (HungarianIdentifierRegex.IsMatch(identifier)) + { + var prefixChars = identifier.TakeWhile(c => char.IsLower(c)); + nonHungarianName = identifier.Substring(prefixChars.Count()); + return true; + } + return false; + } + + private static readonly List HungarianPrefixes = new List + { + "chk", + "cbo", + "cmd", + "btn", + "fra", + "img", + "lbl", + "lst", + "mnu", + "opt", + "pic", + "shp", + "txt", + "tmr", + "chk", + "dlg", + "drv", + "frm", + "grd", + "obj", + "rpt", + "fld", + "idx", + "tbl", + "tbd", + "bas", + "cls", + "g", + "m", + "bln", + "byt", + "col", + "dtm", + "dbl", + "cur", + "int", + "lng", + "sng", + "str", + "udt", + "vnt", + "var", + "pgr", + "dao", + "b", + "by", + "c", + "chr", + "i", + "l", + "s", + "o", + "n", + "dt", + "dat", + "a", + "arr" + }; + + private static readonly Regex HungarianIdentifierRegex = new Regex($"^({string.Join("|", HungarianPrefixes)})[A-Z0-9].*$"); } } From 7a7d77261a2d0b9fc7d978938e2ae0d2fd99b4cd Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Sat, 21 Dec 2019 07:33:33 -0800 Subject: [PATCH 073/461] Rearranged extensions files --- .../EncapsulateFieldElementFactory.cs | 1 + .../EncapsulateFieldExtensions.cs | 210 ------------------ .../EncapsulateFieldRefactoring.cs | 1 + .../EncapsulateFieldValidator.cs | 1 + .../Extensions/DeclarationExtensions.cs | 51 +++++ .../Extensions/IModuleRewriterExtensions.cs | 64 ++++++ .../Extensions/StringExtensions.cs | 25 +++ .../EncapsulateFieldCandidate.cs | 1 + .../EncapsulationIdentifiers.cs | 10 +- .../UserDefinedTypeCandidate.cs | 4 +- .../EncapsulateField/StateUDT.cs | 3 +- .../EncapsulationIdentifiersTests.cs | 10 + 12 files changed, 165 insertions(+), 216 deletions(-) delete mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldExtensions.cs create mode 100644 Rubberduck.Refactorings/EncapsulateField/Extensions/DeclarationExtensions.cs create mode 100644 Rubberduck.Refactorings/EncapsulateField/Extensions/IModuleRewriterExtensions.cs create mode 100644 Rubberduck.Refactorings/EncapsulateField/Extensions/StringExtensions.cs diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs index dbdc334301..1a65249fa3 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs @@ -1,6 +1,7 @@ using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Refactorings.EncapsulateField.Extensions; using Rubberduck.VBEditor; using System; using System.Collections.Generic; diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldExtensions.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldExtensions.cs deleted file mode 100644 index 3dc7754982..0000000000 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldExtensions.cs +++ /dev/null @@ -1,210 +0,0 @@ -using Rubberduck.Parsing; -using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Rewriter; -using Rubberduck.Parsing.Symbols; -using Rubberduck.VBEditor; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; - -namespace Rubberduck.Refactorings.EncapsulateField -{ - public static class EncapsulateFieldExtensions - { - public static bool IsVariable(this Declaration declaration) - => declaration.DeclarationType.HasFlag(DeclarationType.Variable); - - public static bool IsMemberVariable(this Declaration declaration) - => declaration.IsVariable() && !declaration.ParentDeclaration.IsMember(); - - public static bool IsLocalVariable(this Declaration declaration) - => declaration.IsVariable() && declaration.ParentDeclaration.IsMember(); - - public static bool IsLocalConstant(this Declaration declaration) - => declaration.IsConstant() && declaration.ParentDeclaration.IsMember(); - - public static bool HasPrivateAccessibility(this Declaration declaration) - => declaration.Accessibility.Equals(Accessibility.Private); - - public static bool IsMember(this Declaration declaration) - => declaration.DeclarationType.HasFlag(DeclarationType.Member); - - public static bool IsConstant(this Declaration declaration) - => declaration.DeclarationType.HasFlag(DeclarationType.Constant); - - public static bool IsUserDefinedTypeField(this Declaration declaration) - => declaration.IsMemberVariable() && (declaration.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.UserDefinedType) ?? false); - - public static bool IsEnumField(this Declaration declaration) - => declaration.IsMemberVariable() && (declaration.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.Enumeration) ?? false); - - public static bool IsDeclaredInList(this Declaration declaration) - { - return declaration.Context.TryGetAncestor(out var varList) - && varList.ChildCount > 1; - } - - public static IEnumerable AllReferences(this IEnumerable declarations) - { - return from dec in declarations - from reference in dec.References - select reference; - } - - public static string Capitalize(this string input) - => $"{char.ToUpperInvariant(input[0]) + input.Substring(1, input.Length - 1)}"; - - public static string UnCapitalize(this string input) - => $"{char.ToLowerInvariant(input[0]) + input.Substring(1, input.Length - 1)}"; - - public static bool IsEquivalentVBAIdentifierTo(this string lhs, string identifier) - => lhs.Equals(identifier, StringComparison.InvariantCultureIgnoreCase); - - #region HungarianNotation - //From the HungarianNotation Inspection: Where should this code reside to be - //shared by both the Inspection and this refactoring? Rubberduck.Parsing.VBA.Extensions.StringExtensions.cs? - private static readonly List HungarianPrefixes = new List - { - "chk", - "cbo", - "cmd", - "btn", - "fra", - "img", - "lbl", - "lst", - "mnu", - "opt", - "pic", - "shp", - "txt", - "tmr", - "chk", - "dlg", - "drv", - "frm", - "grd", - "obj", - "rpt", - "fld", - "idx", - "tbl", - "tbd", - "bas", - "cls", - "g", - "m", - "bln", - "byt", - "col", - "dtm", - "dbl", - "cur", - "int", - "lng", - "sng", - "str", - "udt", - "vnt", - "var", - "pgr", - "dao", - "b", - "by", - "c", - "chr", - "i", - "l", - "s", - "o", - "n", - "dt", - "dat", - "a", - "arr" - }; - - private static readonly Regex HungarianIdentifierRegex = new Regex($"^({string.Join("|", HungarianPrefixes)})[A-Z0-9].*$"); - - public static bool IsHungarianIdentifier(this string identifier, out string nonHungarianName) - { - nonHungarianName = identifier; - if (HungarianIdentifierRegex.IsMatch(identifier)) - { - var prefixChars = identifier.TakeWhile(c => char.IsLower(c)); - nonHungarianName = identifier.Substring(prefixChars.Count()); - return true; - } - return false; - } - - #endregion //HungarianNotation - - public static string GetText(this IModuleRewriter rewriter, int maxConsecutiveNewLines) - { - var result = rewriter.GetText(); - var target = string.Join(string.Empty, Enumerable.Repeat(Environment.NewLine, maxConsecutiveNewLines).ToList()); - var replacement = string.Join(string.Empty, Enumerable.Repeat(Environment.NewLine, maxConsecutiveNewLines - 1).ToList()); - for (var counter = 1; counter < 10 && result.Contains(target); counter++) - { - result = result.Replace(target, replacement); - } - return result; - } - - public static string IncrementEncapsulationIdentifier(this string identifier) - { - var fragments = identifier.Split('_'); - if (fragments.Length == 1) { return $"{identifier}_1"; } - - var lastFragment = fragments[fragments.Length - 1]; - if (long.TryParse(lastFragment, out var number)) - { - fragments[fragments.Length - 1] = (number + 1).ToString(); - - return string.Join("_", fragments); - } - return $"{identifier}_1"; ; - } - - public static void InsertAtEndOfFile(this IModuleRewriter rewriter, string content) - { - if (content == string.Empty) { return; } - - rewriter.InsertBefore(rewriter.TokenStream.Size - 1, content); - } - - public static void MakeImplicitDeclarationTypeExplicit(this IModuleRewriter rewriter, Declaration element) - { - if (!element.Context.TryGetChildContext(out _)) - { - rewriter.InsertAfter(element.Context.Stop.TokenIndex, $" {Tokens.As} {element.AsTypeName}"); - } - } - - public static void Rename(this IModuleRewriter rewriter, Declaration target, string newName) - { - if (target.Context is IIdentifierContext context) - { - rewriter.Replace(context.IdentifierTokens, newName); - } - } - - public static void SetVariableVisiblity(this IModuleRewriter rewriter, Declaration element, string visibility) - { - if (!element.IsVariable()) { throw new ArgumentException(); } - - var variableStmtContext = element.Context.GetAncestor(); - var visibilityContext = variableStmtContext.GetChild(); - - if (visibilityContext != null) - { - rewriter.Replace(visibilityContext, visibility); - return; - } - rewriter.InsertBefore(element.Context.Start.TokenIndex, $"{visibility} "); - } - } - -} diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index ee1aa26603..469b78e1e5 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -11,6 +11,7 @@ using System.Collections.Generic; using System; using Antlr4.Runtime; +using Rubberduck.Refactorings.EncapsulateField.Extensions; namespace Rubberduck.Refactorings.EncapsulateField { diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs index 32e1d8816b..002c2cd57c 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -2,6 +2,7 @@ using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Refactorings.Common; +using Rubberduck.Refactorings.EncapsulateField.Extensions; using System.Collections.Generic; using System.Linq; diff --git a/Rubberduck.Refactorings/EncapsulateField/Extensions/DeclarationExtensions.cs b/Rubberduck.Refactorings/EncapsulateField/Extensions/DeclarationExtensions.cs new file mode 100644 index 0000000000..47510f387f --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/Extensions/DeclarationExtensions.cs @@ -0,0 +1,51 @@ +using Rubberduck.Parsing; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Symbols; +using System.Collections.Generic; +using System.Linq; + +namespace Rubberduck.Refactorings.EncapsulateField.Extensions +{ + public static class DeclarationExtensions + { + public static bool IsVariable(this Declaration declaration) + => declaration.DeclarationType.HasFlag(DeclarationType.Variable); + + public static bool IsMemberVariable(this Declaration declaration) + => declaration.IsVariable() && !declaration.ParentDeclaration.IsMember(); + + public static bool IsLocalVariable(this Declaration declaration) + => declaration.IsVariable() && declaration.ParentDeclaration.IsMember(); + + public static bool IsLocalConstant(this Declaration declaration) + => declaration.IsConstant() && declaration.ParentDeclaration.IsMember(); + + public static bool HasPrivateAccessibility(this Declaration declaration) + => declaration.Accessibility.Equals(Accessibility.Private); + + public static bool IsMember(this Declaration declaration) + => declaration.DeclarationType.HasFlag(DeclarationType.Member); + + public static bool IsConstant(this Declaration declaration) + => declaration.DeclarationType.HasFlag(DeclarationType.Constant); + + public static bool IsUserDefinedTypeField(this Declaration declaration) + => declaration.IsMemberVariable() && (declaration.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.UserDefinedType) ?? false); + + public static bool IsEnumField(this Declaration declaration) + => declaration.IsMemberVariable() && (declaration.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.Enumeration) ?? false); + + public static bool IsDeclaredInList(this Declaration declaration) + { + return declaration.Context.TryGetAncestor(out var varList) + && varList.ChildCount > 1; + } + + public static IEnumerable AllReferences(this IEnumerable declarations) + { + return from dec in declarations + from reference in dec.References + select reference; + } + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/Extensions/IModuleRewriterExtensions.cs b/Rubberduck.Refactorings/EncapsulateField/Extensions/IModuleRewriterExtensions.cs new file mode 100644 index 0000000000..81b2d2b1aa --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/Extensions/IModuleRewriterExtensions.cs @@ -0,0 +1,64 @@ +using Rubberduck.Parsing; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; +using System; +using System.Linq; + +namespace Rubberduck.Refactorings.EncapsulateField.Extensions +{ + public static class IModuleRewriterExtensions + { + public static string GetText(this IModuleRewriter rewriter, int maxConsecutiveNewLines) + { + var result = rewriter.GetText(); + var target = string.Join(string.Empty, Enumerable.Repeat(Environment.NewLine, maxConsecutiveNewLines).ToList()); + var replacement = string.Join(string.Empty, Enumerable.Repeat(Environment.NewLine, maxConsecutiveNewLines - 1).ToList()); + for (var counter = 1; counter < 10 && result.Contains(target); counter++) + { + result = result.Replace(target, replacement); + } + return result; + } + + public static void InsertAtEndOfFile(this IModuleRewriter rewriter, string content) + { + if (content == string.Empty) { return; } + + rewriter.InsertBefore(rewriter.TokenStream.Size - 1, content); + } + + public static void MakeImplicitDeclarationTypeExplicit(this IModuleRewriter rewriter, Declaration element) + { + if (!element.Context.TryGetChildContext(out _)) + { + rewriter.InsertAfter(element.Context.Stop.TokenIndex, $" {Tokens.As} {element.AsTypeName}"); + } + } + + public static void Rename(this IModuleRewriter rewriter, Declaration target, string newName) + { + if (!(target.Context is IIdentifierContext context)) + { + throw new ArgumentException(); + } + + rewriter.Replace(context.IdentifierTokens, newName); + } + + public static void SetVariableVisiblity(this IModuleRewriter rewriter, Declaration element, string visibility) + { + if (!element.IsVariable()) { throw new ArgumentException(); } + + var variableStmtContext = element.Context.GetAncestor(); + var visibilityContext = variableStmtContext.GetChild(); + + if (visibilityContext != null) + { + rewriter.Replace(visibilityContext, visibility); + return; + } + rewriter.InsertBefore(element.Context.Start.TokenIndex, $"{visibility} "); + } + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/Extensions/StringExtensions.cs b/Rubberduck.Refactorings/EncapsulateField/Extensions/StringExtensions.cs new file mode 100644 index 0000000000..f9ec88c9ff --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/Extensions/StringExtensions.cs @@ -0,0 +1,25 @@ +using System; + +namespace Rubberduck.Refactorings.EncapsulateField.Extensions +{ + public static class StringExtensions + { + public static bool IsEquivalentVBAIdentifierTo(this string lhs, string identifier) + => lhs.Equals(identifier, StringComparison.InvariantCultureIgnoreCase); + + public static string IncrementEncapsulationIdentifier(this string identifier) + { + var fragments = identifier.Split('_'); + if (fragments.Length == 1) { return $"{identifier}_1"; } + + var lastFragment = fragments[fragments.Length - 1]; + if (long.TryParse(lastFragment, out var number)) + { + fragments[fragments.Length - 1] = (number + 1).ToString(); + + return string.Join("_", fragments); + } + return $"{identifier}_1"; ; + } + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs index 05474c88cc..89bc4828e8 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs @@ -1,6 +1,7 @@ using Antlr4.Runtime; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; +using Rubberduck.Refactorings.EncapsulateField.Extensions; using Rubberduck.VBEditor; using System.Collections.Generic; diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs index c5835df14c..e21881c6df 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs @@ -1,6 +1,8 @@ using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA.Extensions; +using Rubberduck.Common; using System.Collections.Generic; +using Rubberduck.Refactorings.EncapsulateField.Extensions; namespace Rubberduck.Refactorings.EncapsulateField { @@ -18,20 +20,20 @@ public EncapsulationIdentifiers(Declaration target) public EncapsulationIdentifiers(string field) { _targetIdentifier = field; - if (field.IsHungarianIdentifier(out var nonHungarianName)) + if (field.TryMatchHungarianNotationCriteria(out var nonHungarianName)) { DefaultPropertyName = nonHungarianName; DefaultNewFieldName = field; } else if (field.StartsWith("m_")) { - DefaultPropertyName = field.Substring(2).Capitalize(); + DefaultPropertyName = field.Substring(2).CapitalizeFirstLetter(); DefaultNewFieldName = field; } else { - DefaultPropertyName = field.Capitalize(); - DefaultNewFieldName = (field.UnCapitalize()).IncrementEncapsulationIdentifier(); + DefaultPropertyName = field.CapitalizeFirstLetter(); + DefaultNewFieldName = (field.ToLowerCaseFirstLetter()).IncrementEncapsulationIdentifier(); } _fieldAndProperty = new KeyValuePair(DefaultNewFieldName, DefaultPropertyName); _setLetParameter = DEFAULT_WRITE_PARAMETER; diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs index 3e6510d78c..97c954919c 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs @@ -1,7 +1,9 @@ using Antlr4.Runtime; +using Rubberduck.Common; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; +using Rubberduck.Refactorings.EncapsulateField.Extensions; using System.Collections.Generic; using System.Linq; @@ -71,7 +73,7 @@ public override bool EncapsulateFlag //Type within the module. //Try to use a name involving the parent's identifier to make it unique/meaningful //before giving up and creating incremented value(s). - member.PropertyName = $"{FieldIdentifier.Capitalize()}{member.PropertyName.Capitalize()}"; + member.PropertyName = $"{FieldIdentifier.CapitalizeFirstLetter()}{member.PropertyName.CapitalizeFirstLetter()}"; _validator.AssignNoConflictIdentifier(member, DeclarationType.Property); } } diff --git a/Rubberduck.Refactorings/EncapsulateField/StateUDT.cs b/Rubberduck.Refactorings/EncapsulateField/StateUDT.cs index a9e941147d..c28a8f4512 100644 --- a/Rubberduck.Refactorings/EncapsulateField/StateUDT.cs +++ b/Rubberduck.Refactorings/EncapsulateField/StateUDT.cs @@ -1,5 +1,6 @@ using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; +using Rubberduck.Common; using Rubberduck.SmartIndenter; using Rubberduck.VBEditor; using System; @@ -31,7 +32,7 @@ public class StateUDT : IStateUDT private readonly IEncapsulateFieldNamesValidator _validator; public StateUDT(QualifiedModuleName qmn, IEncapsulateFieldNamesValidator validator) - :this($"{EncapsulateFieldResources.StateUserDefinedTypeIdentifierPrefix}{qmn.ComponentName.Capitalize()}", validator) + :this($"{EncapsulateFieldResources.StateUserDefinedTypeIdentifierPrefix}{qmn.ComponentName.CapitalizeFirstLetter()}", validator) { QualifiedModuleName = qmn; } diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs index 7dac9687b3..30640927cb 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs @@ -78,7 +78,17 @@ public void PropertyNameChange_UniqueParamName() StringAssert.AreEqualIgnoringCase("Value_value_1_value", encapsulatedField.ParameterName); } + [TestCase("strValue", "Value", "strValue")] + [TestCase("m_Text", "Text", "m_Text")] + [TestCase("notAHungarianName", "NotAHungarianName", "notAHungarianName_1")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void AccountsForHungarianNamesAndMemberPrefix(string inputName, string expectedPropertyName, string expectedFieldName) + { + var sut = new EncapsulationIdentifiers(inputName); + Assert.AreEqual(expectedPropertyName, sut.DefaultPropertyName); + Assert.AreEqual(expectedFieldName, sut.DefaultNewFieldName); } } } From 4a490908954c99b439719d37e3cdc87c877a9b83 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Sat, 21 Dec 2019 08:24:21 -0800 Subject: [PATCH 074/461] Some cleanup --- .../ViewableEncapsulatedField.cs | 15 --------------- .../EncapsulateFieldElementFactory.cs | 3 --- .../EncapsulateFieldRefactoring.cs | 2 +- .../EncapsulateFieldRewriteSession.cs | 17 +++++++++++------ .../EncapsulateFieldTests.cs | 4 ---- .../EncapsulateFieldValidatorTests.cs | 19 +------------------ .../EncapsulateField/TestSupport.cs | 5 ----- 7 files changed, 13 insertions(+), 52 deletions(-) rename RubberduckTests/Refactoring/{ => EncapsulateField}/EncapsulateFieldTests.cs (99%) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs index d96f8a0c29..fc4eee5825 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs @@ -13,15 +13,10 @@ public interface IEncapsulatedFieldViewData { string TargetID { get; } string PropertyName { set; get; } - string NewFieldName { get; } bool EncapsulateFlag { set; get; } bool IsReadOnly { set; get; } bool CanBeReadWrite { get; } - bool IsEditableReadWriteFieldIdentifier { get; } - Visibility FieldNameVisibility { get; } - Visibility PropertyNameVisibility { get; } bool HasValidEncapsulationAttributes { get; } - string AsTypeName { get; } string TargetDeclarationExpression { set; get; } bool IsPrivateUserDefinedType { get; } bool IsRequiredToBeReadOnly { get; } @@ -53,10 +48,6 @@ public override int GetHashCode() return _hashCode; } - public Visibility FieldNameVisibility => (_efd is IUserDefinedTypeMemberCandidate) || !_efd.EncapsulateFlag ? Visibility.Collapsed : Visibility.Visible; - - public Visibility PropertyNameVisibility => !_efd.EncapsulateFlag ? Visibility.Collapsed : Visibility.Visible; - public bool HasValidEncapsulationAttributes { get @@ -91,14 +82,8 @@ public bool TryValidateEncapsulationAttributes(out string errorMessage) public string PropertyName { get => _efd.PropertyName; set => _efd.PropertyName = value; } - public bool IsEditableReadWriteFieldIdentifier { get => !(_efd is IUserDefinedTypeMemberCandidate); } - public bool EncapsulateFlag { get => _efd.EncapsulateFlag; set => _efd.EncapsulateFlag = value; } - public string NewFieldName { get => _efd.FieldIdentifier; } - - public string AsTypeName => _efd.AsTypeName_Field; - public bool IsPrivateUserDefinedType => _efd is IUserDefinedTypeCandidate udt && udt.TypeDeclarationIsPrivate; public bool IsRequiredToBeReadOnly => !_efd.CanBeReadWrite; diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs index 1a65249fa3..95a493d79c 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs @@ -59,9 +59,6 @@ public IEncapsulateFieldCandidate CreateEncapsulationCandidate(Declaration targe _validator.RegisterFieldCandidate(candidate); - //candidate = _validator.AssignNoConflictIdentifier(candidate, DeclarationType.Property); - //candidate = _validator.AssignNoConflictIdentifier(candidate, DeclarationType.Variable); - return candidate; } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 469b78e1e5..171d13f109 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -111,7 +111,7 @@ protected override void RefactorImpl(EncapsulateFieldModel model) var refactorRewriteSession = new EncapsulateFieldRewriteSession(RewritingManager.CheckOutCodePaneSession()) as IEncapsulateFieldRewriteSession; refactorRewriteSession = RefactorRewrite(model, refactorRewriteSession); - if (!refactorRewriteSession.TryRewrite(_targetQMN)) + if (!refactorRewriteSession.TryRewrite()) { throw new RewriteFailedException(refactorRewriteSession.RewriteSession); } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriteSession.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriteSession.cs index 9cd10984bc..282808af92 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriteSession.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriteSession.cs @@ -15,7 +15,7 @@ public interface IEncapsulateFieldRewriteSession { IExecutableRewriteSession RewriteSession { get; } IModuleRewriter CheckOutModuleRewriter(QualifiedModuleName qmn); - bool TryRewrite(QualifiedModuleName encapsulationModule); + bool TryRewrite(); void Remove(Declaration target, IModuleRewriter rewriter); } @@ -34,9 +34,9 @@ public EncapsulateFieldRewriteSession(IExecutableRewriteSession rewriteSession) public IModuleRewriter CheckOutModuleRewriter(QualifiedModuleName qmn) => _rewriteSession.CheckOutModuleRewriter(qmn); - public bool TryRewrite(QualifiedModuleName targetQMN) + public bool TryRewrite() { - HandleRemovedFieldDeclarationsInLists(targetQMN); + ExecuteCachedRemoveRequests(); return _rewriteSession.TryRewrite(); } @@ -57,12 +57,17 @@ public void Remove(Declaration target, IModuleRewriter rewriter) RemovedVariables[varList].Add(target); } - private void HandleRemovedFieldDeclarationsInLists(QualifiedModuleName qmn) + private void ExecuteCachedRemoveRequests() { - var rewriter = RewriteSession.CheckOutModuleRewriter(qmn); - foreach (var key in RemovedVariables.Keys) { + if (RemovedVariables[key].Count == 0) + { + continue; + } + + var rewriter = RewriteSession.CheckOutModuleRewriter(RemovedVariables[key].First().QualifiedModuleName); + var variables = key.children.Where(ch => ch is VBAParser.VariableSubStmtContext); if (variables.Count() == RemovedVariables[key].Count) { diff --git a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs similarity index 99% rename from RubberduckTests/Refactoring/EncapsulateFieldTests.cs rename to RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs index 46a8f6a7e5..d4c00e3c8f 100644 --- a/RubberduckTests/Refactoring/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs @@ -3,20 +3,16 @@ using Moq; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; -using Rubberduck.Parsing.UIContext; using Rubberduck.Refactorings; using Rubberduck.Refactorings.EncapsulateField; using Rubberduck.VBEditor; using RubberduckTests.Mocks; -using Rubberduck.SmartIndenter; using Rubberduck.VBEditor.SafeComWrappers; -using Rubberduck.VBEditor.SafeComWrappers.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings.Exceptions; using Rubberduck.VBEditor.Utility; using System.Collections.Generic; using System.Linq; -using Rubberduck.Parsing.Grammar; namespace RubberduckTests.Refactoring.EncapsulateField { diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs index 49249bf6ab..1303135a30 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs @@ -35,26 +35,9 @@ public void VBAIdentifier_Property(string originalFieldName, string newPropertyN encapsulatedField.PropertyName = newPropertyName; encapsulatedField.EncapsulateFlag = true; - //var field = encapsulatedField as IEncapsulateFieldCandidateValidations; Assert.AreEqual(expectedResult, encapsulatedField.TryValidateEncapsulationAttributes(out _)); } -// [TestCase("fizz", "_Fizz", false)] -// [TestCase("fizz", "FizzProp", true)] -// [Category("Refactorings")] -// [Category("Encapsulate Field")] -// public void VBAIdentifier_FieldName(string originalFieldName, string newFieldName, bool expectedResult) -// { -// string inputCode = -//$@"Public {originalFieldName} As String"; - -// var encapsulatedField = Support.RetrieveEncapsulatedField(inputCode, originalFieldName); - -// encapsulatedField.FieldIdentifier = newFieldName; -// var field = encapsulatedField as IEncapsulateFieldCandidateValidations; -// Assert.AreEqual(expectedResult, field.HasVBACompliantFieldIdentifier); -// } - [Test] [Category("Refactorings")] [Category("Encapsulate Field")] @@ -167,7 +150,7 @@ End Property "; var fieldUT = "fizz"; - var userInput = new UserInputDataObject() //"fizz", userModifiedPropertyName, true); + var userInput = new UserInputDataObject() .UserSelectsField("fizz", userModifiedPropertyName); var presenterAction = Support.SetParameters(userInput); diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index 8c79a745f4..d026f8d66a 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -74,11 +74,6 @@ public Func SetParameters(UserInpu attrsInitializedByTheRefactoring.PropertyName = testModifiedAttribute.PropertyName; attrsInitializedByTheRefactoring.EncapsulateFlag = testModifiedAttribute.EncapsulateFlag; attrsInitializedByTheRefactoring.IsReadOnly = testModifiedAttribute.IsReadOnly; - - //var currentAttributes = model[testModifiedAttribute.TargetFieldName].EncapsulationAttributes; - //currentAttributes.PropertyName = attrsInitializedByTheRefactoring.PropertyName; - //currentAttributes.EncapsulateFlag = attrsInitializedByTheRefactoring.EncapsulateFlag; - } return model; }; From 4eaad2da5b70cdd322b3cefca401881ff2ba92a0 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Sat, 21 Dec 2019 10:13:26 -0800 Subject: [PATCH 075/461] tweak gui size --- .../EncapsulateField/EncapsulateFieldPresenter.cs | 2 +- .../Refactorings/EncapsulateField/EncapsulateFieldView.xaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldPresenter.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldPresenter.cs index eae77871b2..029518342c 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldPresenter.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldPresenter.cs @@ -6,7 +6,7 @@ namespace Rubberduck.UI.Refactorings.EncapsulateField internal class EncapsulateFieldPresenter : RefactoringPresenterBase, IEncapsulateFieldPresenter { private static readonly DialogData DialogData = - DialogData.Create(RubberduckUI.EncapsulateField_Caption, 800, 800); + DialogData.Create(RubberduckUI.EncapsulateField_Caption, 800, 1000); public EncapsulateFieldPresenter(EncapsulateFieldModel model, IRefactoringDialogFactory dialogFactory) : base(DialogData, model, dialogFactory) { } diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml index d08774fcdb..ecacbff6b8 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml @@ -7,7 +7,7 @@ xmlns:converters="clr-namespace:Rubberduck.UI.Converters" mc:Ignorable="d" d:DesignHeight="800" - d:DesignWidth="800"> + d:DesignWidth="1000"> @@ -212,7 +212,7 @@ ShowLineNumbers="False" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" - Height="200" + Height="400" IsReadOnly="True" IsTabStop="False" TabIndex="6" From f3caa7419807d56c206de88a7cfce4dfbf2c807b Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Sun, 22 Dec 2019 15:44:43 -0500 Subject: [PATCH 076/461] added quickfix xmldoc, A-P --- .../AccessSheetUsingCodeNameQuickFix.cs | 27 +++++++++++++- .../AddAttributeAnnotationQuickFix.cs | 36 ++++++++++++++++++ .../AddIdentifierToWhiteListQuickFix.cs | 8 ++++ .../QuickFixes/AddMissingAttributeQuickFix.cs | 33 +++++++++++++++++ .../QuickFixes/AddStepOneQuickFix.cs | 29 +++++++++++++++ .../AdjustAttributeAnnotationQuickFix.cs | 35 ++++++++++++++++++ .../AdjustAttributeValuesQuickFix.cs | 37 +++++++++++++++++++ .../ApplicationWorksheetFunctionQuickFix.cs | 23 ++++++++++++ ...gnedByValParameterMakeLocalCopyQuickFix.cs | 29 +++++++++++++++ .../QuickFixes/ChangeDimToPrivateQuickFix.cs | 27 ++++++++++++++ .../QuickFixes/ChangeIntegerToLongQuickFix.cs | 27 ++++++++++++++ .../ChangeProcedureToFunctionQuickFix.cs | 36 ++++++++++++++++++ .../QuickFixes/ConvertToProcedureQuickFix.cs | 36 ++++++++++++++++++ .../DeclareAsExplicitVariantQuickFix.cs | 27 ++++++++++++++ .../QuickFixes/EncapsulateFieldQuickFix.cs | 29 +++++++++++++++ .../QuickFixes/ExpandBangNotationQuickFix.cs | 32 ++++++++++++++++ .../QuickFixes/ExpandDefaultMemberQuickFix.cs | 36 ++++++++++++++++++ .../QuickFixes/IgnoreOnceQuickFix.cs | 30 ++++++++++++--- .../IntroduceLocalVariableQuickFix.cs | 26 +++++++++++++ ...sMissingOnInappropriateArgumentQuickFix.cs | 27 ++++++++++++++ .../MakeSingleLineParameterQuickFix.cs | 22 +++++++++++ .../MoveFieldCloserToUsageQuickFix.cs | 31 ++++++++++++++++ .../QuickFixes/OptionExplicitQuickFix.cs | 26 +++++++++++++ .../PassParameterByReferenceQuickFix.cs | 25 +++++++++++++ .../PassParameterByValueQuickFix.cs | 23 ++++++++++++ 25 files changed, 711 insertions(+), 6 deletions(-) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AccessSheetUsingCodeNameQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/AccessSheetUsingCodeNameQuickFix.cs index 767f044083..2715ccdeda 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AccessSheetUsingCodeNameQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/AccessSheetUsingCodeNameQuickFix.cs @@ -11,7 +11,32 @@ namespace Rubberduck.Inspections.QuickFixes { - public sealed class AccessSheetUsingCodeNameQuickFix : QuickFixBase + /// + /// Modifies a Workbook.Worksheets or Workbook.Sheets call accessing a sheet of ThisWorkbook that exists at compile-time. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public sealed class AccessSheetUsingCodeNameQuickFix : QuickFixBase // fixme: rename as per action(s), not the inspection that uses it { private readonly IDeclarationFinderProvider _declarationFinderProvider; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AddAttributeAnnotationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/AddAttributeAnnotationQuickFix.cs index e688ad8b9c..18dcb03530 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AddAttributeAnnotationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/AddAttributeAnnotationQuickFix.cs @@ -10,6 +10,42 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Adds an annotation comment to document the presence of a hidden module or member attribute. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public class AddAttributeAnnotationQuickFix : QuickFixBase { private readonly IAnnotationUpdater _annotationUpdater; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AddIdentifierToWhiteListQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/AddIdentifierToWhiteListQuickFix.cs index 66ce1e26fc..6d8795bb38 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AddIdentifierToWhiteListQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/AddIdentifierToWhiteListQuickFix.cs @@ -8,6 +8,14 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Adds an identifier or Hungarian Notation prefix to a list of white-listed identifiers and prefixes in Rubberduck's inspection settings. + /// + /// + /// + /// + /// + /// public sealed class AddIdentifierToWhiteListQuickFix : QuickFixBase { private readonly IConfigurationService _settings; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AddMissingAttributeQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/AddMissingAttributeQuickFix.cs index 1f2b811d67..8e30786aea 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AddMissingAttributeQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/AddMissingAttributeQuickFix.cs @@ -9,6 +9,39 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Exports the module, adds the hidden attributes as needed, re-imports the temporary file back into the project. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class AddMissingAttributeQuickFix : QuickFixBase { private readonly IAttributesUpdater _attributesUpdater; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AddStepOneQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/AddStepOneQuickFix.cs index 1eb99baf18..b67f062aef 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AddStepOneQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/AddStepOneQuickFix.cs @@ -7,6 +7,35 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Adds an explicit Step specifier to a For loop instruction. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class AddStepOneQuickFix : QuickFixBase { public AddStepOneQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeAnnotationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeAnnotationQuickFix.cs index 19ffc3a766..45a2fc233a 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeAnnotationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeAnnotationQuickFix.cs @@ -11,6 +11,41 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Adjusts existing Rubberduck annotations to match the corresponding hidden attributes. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public class AdjustAttributeAnnotationQuickFix : QuickFixBase { private readonly IAnnotationUpdater _annotationUpdater; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeValuesQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeValuesQuickFix.cs index 9bf9f0d43e..ba50cdb8c9 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeValuesQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeValuesQuickFix.cs @@ -12,6 +12,43 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Adjusts existing hidden attributes to match the corresponding Rubberduck annotations. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public class AdjustAttributeValuesQuickFix : QuickFixBase { private readonly IAttributesUpdater _attributesUpdater; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ApplicationWorksheetFunctionQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/ApplicationWorksheetFunctionQuickFix.cs index d17b552f66..9a493032f6 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ApplicationWorksheetFunctionQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/ApplicationWorksheetFunctionQuickFix.cs @@ -5,6 +5,29 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Replaces a late-bound Application.{Member} call to the corresponding early-bound Application.WorksheetFunction.{Member} call. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class ApplicationWorksheetFunctionQuickFix : QuickFixBase { public ApplicationWorksheetFunctionQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AssignedByValParameterMakeLocalCopyQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/AssignedByValParameterMakeLocalCopyQuickFix.cs index 71d13b2106..c15115a2ef 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AssignedByValParameterMakeLocalCopyQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/AssignedByValParameterMakeLocalCopyQuickFix.cs @@ -17,6 +17,35 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Introduces a new local variable and assigns it at the top of the procedure scope, then updates all parameter references to refer to the new local variable. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class AssignedByValParameterMakeLocalCopyQuickFix : QuickFixBase { private readonly IAssignedByValParameterQuickFixDialogFactory _dialogFactory; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ChangeDimToPrivateQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/ChangeDimToPrivateQuickFix.cs index 1d9f7e4e2b..b24aad949e 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ChangeDimToPrivateQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/ChangeDimToPrivateQuickFix.cs @@ -6,6 +6,33 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Replaces the Dim keyword with Private in a module-scoped declaration. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class ChangeDimToPrivateQuickFix : QuickFixBase { public ChangeDimToPrivateQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ChangeIntegerToLongQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/ChangeIntegerToLongQuickFix.cs index e57afc1fcb..89f0819dd1 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ChangeIntegerToLongQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/ChangeIntegerToLongQuickFix.cs @@ -14,6 +14,33 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Changes 16-bit (max value 32,767) Integer declarations to use 32-bit (max value 2,147,483,647‬) Long integer type instead. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class ChangeIntegerToLongQuickFix : QuickFixBase { private readonly IDeclarationFinderProvider _declarationFinderProvider; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ChangeProcedureToFunctionQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/ChangeProcedureToFunctionQuickFix.cs index fa9995a668..0fb26b261c 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ChangeProcedureToFunctionQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/ChangeProcedureToFunctionQuickFix.cs @@ -10,6 +10,42 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Adjusts a Sub procedure to be a Function procedure, and updates all usages. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class ChangeProcedureToFunctionQuickFix : QuickFixBase { public ChangeProcedureToFunctionQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ConvertToProcedureQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/ConvertToProcedureQuickFix.cs index 10aa3461a0..74cf3c4dbb 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ConvertToProcedureQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/ConvertToProcedureQuickFix.cs @@ -11,6 +11,42 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Adjusts a Function procedure to be a Sub procedure. This operation may result in broken code. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class ConvertToProcedureQuickFix : QuickFixBase { public ConvertToProcedureQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/DeclareAsExplicitVariantQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/DeclareAsExplicitVariantQuickFix.cs index fa4beeaa94..6862004fae 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/DeclareAsExplicitVariantQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/DeclareAsExplicitVariantQuickFix.cs @@ -7,6 +7,33 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Adds an explicit Variant data type to an implicitly typed declaration. Note: a more specific data type might be more appropriate. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class DeclareAsExplicitVariantQuickFix : QuickFixBase { public DeclareAsExplicitVariantQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/EncapsulateFieldQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/EncapsulateFieldQuickFix.cs index 4c33d20531..cab501754d 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/EncapsulateFieldQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/EncapsulateFieldQuickFix.cs @@ -4,6 +4,35 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Runs the 'Encapsulate Field' refactoring, which prompts for identifier names for the new property and its value parameter. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class EncapsulateFieldQuickFix : RefactoringQuickFixBase { public EncapsulateFieldQuickFix(EncapsulateFieldRefactoring refactoring) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ExpandBangNotationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/ExpandBangNotationQuickFix.cs index 66249fdae8..69a89eb637 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ExpandBangNotationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/ExpandBangNotationQuickFix.cs @@ -13,6 +13,38 @@ namespace Rubberduck.CodeAnalysis.QuickFixes { + /// + /// Replaces bang operators ('dictionary access') with explicit default member calls. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public class ExpandBangNotationQuickFix : QuickFixBase { private readonly IDeclarationFinderProvider _declarationFinderProvider; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ExpandDefaultMemberQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/ExpandDefaultMemberQuickFix.cs index 91df6f170f..d7f95a949f 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ExpandDefaultMemberQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/ExpandDefaultMemberQuickFix.cs @@ -13,6 +13,42 @@ namespace Rubberduck.CodeAnalysis.QuickFixes { + /// + /// Makes default member calls explicit. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public class ExpandDefaultMemberQuickFix : QuickFixBase { private readonly IDeclarationFinderProvider _declarationFinderProvider; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/IgnoreOnceQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/IgnoreOnceQuickFix.cs index 38525a4a64..ddea996549 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/IgnoreOnceQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/IgnoreOnceQuickFix.cs @@ -1,21 +1,41 @@ -using System; using System.Collections.Generic; using System.Linq; -using Antlr4.Runtime.Misc; -using Antlr4.Runtime.Tree; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Annotations; -using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.VBA.Parsing; namespace Rubberduck.Inspections.QuickFixes { + /// + /// Adds an '@Ignore annotation to ignore a specific inspection result. Applicable to all inspections whose results can be annotated in a module. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class IgnoreOnceQuickFix : QuickFixBase { private readonly RubberduckParserState _state; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/IntroduceLocalVariableQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/IntroduceLocalVariableQuickFix.cs index d4aa0fecda..b02f03ba0c 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/IntroduceLocalVariableQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/IntroduceLocalVariableQuickFix.cs @@ -9,6 +9,32 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Introduces a local Variant variable for an otherwise undeclared identifier. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class IntroduceLocalVariableQuickFix : QuickFixBase { public IntroduceLocalVariableQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/IsMissingOnInappropriateArgumentQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/IsMissingOnInappropriateArgumentQuickFix.cs index 25c0fc0faa..319823205d 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/IsMissingOnInappropriateArgumentQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/IsMissingOnInappropriateArgumentQuickFix.cs @@ -12,6 +12,33 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Replaces misuses of the IsMissing function with the appropriate default value for the specified parameter type. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class IsMissingOnInappropriateArgumentQuickFix : QuickFixBase { private readonly IDeclarationFinderProvider _declarationFinderProvider; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/MakeSingleLineParameterQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/MakeSingleLineParameterQuickFix.cs index a3c79a807e..e5a5ac1890 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/MakeSingleLineParameterQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/MakeSingleLineParameterQuickFix.cs @@ -6,6 +6,28 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Rewrites a parameter declaration that is split across multiple lines. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class MakeSingleLineParameterQuickFix : QuickFixBase { public MakeSingleLineParameterQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/MoveFieldCloserToUsageQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/MoveFieldCloserToUsageQuickFix.cs index ebda66ebce..042f67f9e7 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/MoveFieldCloserToUsageQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/MoveFieldCloserToUsageQuickFix.cs @@ -5,6 +5,37 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Moves field declaration to the procedure scope it's used in. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class MoveFieldCloserToUsageQuickFix : RefactoringQuickFixBase { public MoveFieldCloserToUsageQuickFix(MoveCloserToUsageRefactoring refactoring) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/OptionExplicitQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/OptionExplicitQuickFix.cs index 6a86395f40..d7a7666a4e 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/OptionExplicitQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/OptionExplicitQuickFix.cs @@ -7,6 +7,32 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Adds 'Option Explicit' to the top of code modules. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class OptionExplicitQuickFix : QuickFixBase { public OptionExplicitQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/PassParameterByReferenceQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/PassParameterByReferenceQuickFix.cs index f4debba3f2..4d565ab77b 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/PassParameterByReferenceQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/PassParameterByReferenceQuickFix.cs @@ -6,6 +6,31 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Modifies a parameter to be passed by reference. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class PassParameterByReferenceQuickFix : QuickFixBase { public PassParameterByReferenceQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/PassParameterByValueQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/PassParameterByValueQuickFix.cs index f6aa61048c..da9c0ab594 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/PassParameterByValueQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/PassParameterByValueQuickFix.cs @@ -10,6 +10,29 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Modifies a parameter to be passed by value. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class PassParameterByValueQuickFix : QuickFixBase { //TODO: Change this to IDeclarationFinderProvider once the FIXME below is handled. From 8bdf90f3b310e4fda17c8f55fdd18ab86ac5bebf Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Sun, 22 Dec 2019 19:49:34 -0800 Subject: [PATCH 077/461] sizing the Preview textBox --- .../EncapsulateField/EncapsulateFieldPresenter.cs | 2 +- .../Refactorings/EncapsulateField/EncapsulateFieldView.xaml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldPresenter.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldPresenter.cs index 029518342c..0b2418c320 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldPresenter.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldPresenter.cs @@ -6,7 +6,7 @@ namespace Rubberduck.UI.Refactorings.EncapsulateField internal class EncapsulateFieldPresenter : RefactoringPresenterBase, IEncapsulateFieldPresenter { private static readonly DialogData DialogData = - DialogData.Create(RubberduckUI.EncapsulateField_Caption, 800, 1000); + DialogData.Create(RubberduckUI.EncapsulateField_Caption, 800, 900); public EncapsulateFieldPresenter(EncapsulateFieldModel model, IRefactoringDialogFactory dialogFactory) : base(DialogData, model, dialogFactory) { } diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml index ecacbff6b8..8a36d8795e 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml @@ -7,7 +7,7 @@ xmlns:converters="clr-namespace:Rubberduck.UI.Converters" mc:Ignorable="d" d:DesignHeight="800" - d:DesignWidth="1000"> + d:DesignWidth="900"> @@ -88,7 +88,7 @@ Margin="5,0,0,5"> - + @@ -212,7 +212,7 @@ ShowLineNumbers="False" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" - Height="400" + Height="300" IsReadOnly="True" IsTabStop="False" TabIndex="6" From 579149f2d7198d9abe6c52b05b63e1c75ea16a46 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Sun, 22 Dec 2019 19:52:07 -0800 Subject: [PATCH 078/461] Support adding fields to existing Private UDT This prepares the way to incrementally add fields to an ObjectStateUDT --- .../EncapsulateFieldElementFactory.cs | 6 +-- .../EncapsulateField/EncapsulateFieldModel.cs | 32 +++++++++++-- .../EncapsulateFieldRefactoring.cs | 39 +++++++++++++-- .../EncapsulateFieldValidator.cs | 14 +++--- .../FieldCandidates/ArrayCandidate.cs | 2 +- .../EncapsulateFieldCandidate.cs | 25 ++++++++-- .../ObjectStateUDT.cs} | 48 +++++++++++++++---- .../UserDefinedTypeCandidate.cs | 12 ++++- .../UserDefinedTypeMemberCandidate.cs | 11 ++++- .../EncapsulateUsingStateUDTTests.cs | 43 +++++++++++++++++ .../EncapsulateField/TestSupport.cs | 15 +++++- 11 files changed, 208 insertions(+), 39 deletions(-) rename Rubberduck.Refactorings/EncapsulateField/{StateUDT.cs => FieldCandidates/ObjectStateUDT.cs} (62%) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs index 95a493d79c..77a007707b 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs @@ -23,9 +23,9 @@ public EncapsulateFieldElementFactory(IDeclarationFinderProvider declarationFind _targetQMN = targetQMN; } - public IStateUDT CreateStateUDTField() + public IObjectStateUDT CreateStateUDTField() { - var stateUDT = new StateUDT(_targetQMN, _validator) as IStateUDT; + var stateUDT = new ObjectStateUDT(_targetQMN) as IObjectStateUDT; stateUDT = SetNonConflictIdentifier(stateUDT, c => { return _validator.IsConflictingStateUDTFieldIdentifier(stateUDT); }, (s) => { stateUDT.FieldIdentifier = s; }, () => stateUDT.FieldIdentifier, _validator); @@ -92,7 +92,7 @@ public IEnumerable CreateEncapsulationCandidates() return candidates; } - private IStateUDT SetNonConflictIdentifier(IStateUDT candidate, Predicate conflictDetector, Action setValue, Func getIdentifier, IEncapsulateFieldNamesValidator validator) + private IObjectStateUDT SetNonConflictIdentifier(IObjectStateUDT candidate, Predicate conflictDetector, Action setValue, Func getIdentifier, IEncapsulateFieldNamesValidator validator) { var isConflictingIdentifier = conflictDetector(candidate); for (var count = 1; count < 10 && isConflictingIdentifier; count++) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index 3b4bd08976..aa7275a1d7 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -10,16 +10,18 @@ public class EncapsulateFieldModel : IRefactoringModel { private readonly Func _previewDelegate; private QualifiedModuleName _targetQMN; + private IEncapsulateFieldNamesValidator _validator; private IDictionary)> _udtFieldToUdtDeclarationMap = new Dictionary)>(); - public EncapsulateFieldModel(Declaration target, IEnumerable candidates, IStateUDT stateUDTField, Func previewDelegate) + public EncapsulateFieldModel(Declaration target, IEnumerable candidates, IObjectStateUDT stateUDTField, Func previewDelegate, IEncapsulateFieldNamesValidator validator) { _previewDelegate = previewDelegate; _targetQMN = target.QualifiedModuleName; + _validator = validator; EncapsulationCandidates = candidates.ToList(); - StateUDTField = stateUDTField; + //StateUDTField = stateUDTField; } public List EncapsulationCandidates { set; get; } = new List(); @@ -45,7 +47,31 @@ public IEncapsulateFieldCandidate this[Declaration fieldDeclaration] public bool EncapsulateWithUDT { set; get; } - public IStateUDT StateUDTField { set; get; } + private IObjectStateUDT _stateUDTField; + public IObjectStateUDT StateUDTField + { + set + { + _stateUDTField = value; + } + get + { + if (_stateUDTField != null) + { + return _stateUDTField; + } + + if (!EncapsulateWithUDT) { return null; } + var stateUDT = EncapsulationCandidates.Where(sfc => sfc is IUserDefinedTypeCandidate udt + && udt.IsObjectStateUDT).Select(sfc => sfc as IUserDefinedTypeCandidate).FirstOrDefault(); + + _stateUDTField = stateUDT != null + ? new ObjectStateUDT(stateUDT) + : null; + + return _stateUDTField; + } + } public string PreviewRefactoring() => _previewDelegate(this); } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 171d13f109..5a3ef2acf1 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -96,7 +96,8 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) target, candidates, _encapsulationCandidateFactory.CreateStateUDTField(), - PreviewRewrite); + PreviewRewrite, + validator); _codeSectionStartIndex = _declarationFinderProvider.DeclarationFinder .Members(_targetQMN).Where(m => m.IsMember()) @@ -127,7 +128,7 @@ private string PreviewRewrite(EncapsulateFieldModel model) return previewRewriter.GetText(maxConsecutiveNewLines: 3); } - private IStateUDT StateUDTField + private IObjectStateUDT StateUDTField => Model.EncapsulateWithUDT ? Model.StateUDTField : null; @@ -179,12 +180,39 @@ private void ModifyFields(EncapsulateFieldModel model, IEncapsulateFieldRewriteS { if (model.EncapsulateWithUDT) { + IModuleRewriter rewriter; + foreach (var field in model.SelectedFieldCandidates) { - var rewriter = refactorRewriteSession.CheckOutModuleRewriter(_targetQMN); + rewriter = refactorRewriteSession.CheckOutModuleRewriter(_targetQMN); refactorRewriteSession.Remove(field.Declaration, rewriter); } + + if (model.StateUDTField is null) + { + model.StateUDTField = _encapsulationCandidateFactory.CreateStateUDTField(); + return; + } + var stateUDT = model.StateUDTField; + var stateUDTDeclaration = model.StateUDTField as IEncapsulateFieldDeclaration; + //if (stateUDT.WrappedUDT != null) + //{ + stateUDT.AddMembers(model.SelectedFieldCandidates); + //} + var content = stateUDT.TypeDeclarationBlock(_indenter); + rewriter = refactorRewriteSession.CheckOutModuleRewriter(_targetQMN); + + var udts = _declarationFinderProvider.DeclarationFinder.UserDeclarations(DeclarationType.UserDefinedType); + + var udtDeclaration = _declarationFinderProvider.DeclarationFinder.UserDeclarations(DeclarationType.UserDefinedType) + .Where(udt => udt.HasPrivateAccessibility() + && udt.QualifiedModuleName.Equals(stateUDTDeclaration.QualifiedModuleName) + && udt.IdentifierName.Equals(stateUDTDeclaration.AsTypeName)) + .Single(); + + rewriter.Replace(udtDeclaration, content); + return; } @@ -253,7 +281,10 @@ private void LoadNewDeclarationBlocks(EncapsulateFieldModel model) { if (model.EncapsulateWithUDT) { - var stateUDT = StateUDTField as IStateUDT; + //if (StateUDTField/*?.WrappedUDT*/ != null) { return; } + if (StateUDTField.IsExistingDeclaration) { return; } + + var stateUDT = StateUDTField; stateUDT.AddMembers(model.SelectedFieldCandidates); AddCodeBlock(NewContentTypes.TypeDeclarationBlock, stateUDT.TypeDeclarationBlock(_indenter)); diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs index 002c2cd57c..6d07c81cb6 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -16,8 +16,8 @@ public interface IEncapsulateFieldNamesValidator bool IsSelfConsistent(IEncapsulateFieldCandidate candidate, out string errorMessage); bool IsConflictingFieldIdentifier(string fieldName, IEncapsulateFieldCandidate candidate, DeclarationType declarationType); bool HasValidEncapsulationIdentifiers(IEncapsulateFieldCandidate candidate, out string errorMessage); - bool IsConflictingStateUDTTypeIdentifier(IStateUDT stateUDT); - bool IsConflictingStateUDTFieldIdentifier(IStateUDT stateUDT); + bool IsConflictingStateUDTTypeIdentifier(IObjectStateUDT stateUDT); + bool IsConflictingStateUDTFieldIdentifier(IObjectStateUDT stateUDT); IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType); } @@ -51,7 +51,6 @@ public void RegisterFieldCandidate(IEncapsulateFieldCandidate candidate) UDTMemberCandidates.Add(member); } } - } private DeclarationFinder DeclarationFinder => _declarationFinderProvider.DeclarationFinder; @@ -119,11 +118,12 @@ private List PotentialConflictIdentifiers(IEncapsulateFieldCandidate can return nameConflictCandidates.Select(c => c.IdentifierName).ToList(); } - private List PotentialConflictIdentifiers(IStateUDT stateUDT, DeclarationType declarationType) + private List PotentialConflictIdentifiers(IObjectStateUDT stateUDT, DeclarationType declarationType) { + var stateUDTDeclaration = stateUDT as IEncapsulateFieldDeclaration; var potentialDeclarationIdentifierConflicts = new List(); - var members = _declarationFinderProvider.DeclarationFinder.Members(stateUDT.QualifiedModuleName); + var members = _declarationFinderProvider.DeclarationFinder.Members(stateUDTDeclaration.QualifiedModuleName); var nameConflictCandidates = members .Where(d => !IsAlwaysIgnoreNameConflictType(d, declarationType)).ToList(); @@ -195,14 +195,14 @@ public bool IsConflictingFieldIdentifier(string fieldName, IEncapsulateFieldCand return members.Any(m => m.IsEquivalentVBAIdentifierTo(fieldName)); } - public bool IsConflictingStateUDTTypeIdentifier(IStateUDT stateUDT) + public bool IsConflictingStateUDTTypeIdentifier(IObjectStateUDT stateUDT) { var potentialConflictNames = PotentialConflictIdentifiers(stateUDT, DeclarationType.UserDefinedType); return potentialConflictNames.Any(m => m.IsEquivalentVBAIdentifierTo(stateUDT.TypeIdentifier)); } - public bool IsConflictingStateUDTFieldIdentifier(IStateUDT stateUDT) + public bool IsConflictingStateUDTFieldIdentifier(IObjectStateUDT stateUDT) { var potentialConflictNames = PotentialConflictIdentifiers(stateUDT, DeclarationType.Variable); diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs index 94543571eb..e449a923d1 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs @@ -29,7 +29,7 @@ public ArrayCandidate(Declaration declaration, IEncapsulateFieldNamesValidator v public override string AsUDTMemberDeclaration => $"{PropertyName}({_subscripts}) {Tokens.As} {AsTypeName_Field}"; - public override void StageFieldReferenceReplacements(IStateUDT stateUDT = null) + public override void StageFieldReferenceReplacements(IObjectStateUDT stateUDT = null) { PropertyAccessor = stateUDT is null ? AccessorTokens.Field : AccessorTokens.Property; ReferenceAccessor = AccessorTokens.Property; diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs index 89bc4828e8..6a6a3a0497 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs @@ -7,16 +7,25 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface IEncapsulateFieldCandidate + public interface IEncapsulateFieldDeclaration { - Declaration Declaration { get; } string IdentifierName { get; } + QualifiedModuleName QualifiedModuleName { get; } + string AsTypeName { get; } + Selection Selection { get; } + Accessibility Accessibility { get; } + } + + public interface IEncapsulateFieldCandidate : IEncapsulateFieldDeclaration + { + Declaration Declaration { get; } + //string IdentifierName { get; } string TargetID { get; } bool IsReadOnly { get; set; } bool EncapsulateFlag { get; set; } string FieldIdentifier { set; get; } bool CanBeReadWrite { set; get; } - QualifiedModuleName QualifiedModuleName { get; } + //QualifiedModuleName QualifiedModuleName { get; } string PropertyName { get; set; } string AsTypeName_Field { get; set; } string AsTypeName_Property { get; set; } @@ -29,7 +38,7 @@ public interface IEncapsulateFieldCandidate void SetReferenceRewriteContent(IdentifierReference idRef, string replacementText); string ReferenceQualifier { set; get; } string ReferenceWithinNewProperty { get; } - void StageFieldReferenceReplacements(IStateUDT stateUDT = null); + void StageFieldReferenceReplacements(IObjectStateUDT stateUDT = null); AccessorTokens PropertyAccessor { set; get; } AccessorTokens ReferenceAccessor { set; get; } bool TryValidateEncapsulationAttributes(out string errorMessage); @@ -81,7 +90,7 @@ public EncapsulateFieldCandidate(string identifier, string asTypeName, Qualified _hashCode = ($"{_qmn.Name}.{identifier}").GetHashCode(); } - public virtual void StageFieldReferenceReplacements(IStateUDT stateUDT = null) + public virtual void StageFieldReferenceReplacements(IObjectStateUDT stateUDT = null) { PropertyAccessor = stateUDT is null ? AccessorTokens.Field : AccessorTokens.Property; ReferenceAccessor = AccessorTokens.Property; @@ -93,6 +102,12 @@ public virtual void StageFieldReferenceReplacements(IStateUDT stateUDT = null) public Declaration Declaration => _target; + public Selection Selection => _target.Selection; + + public Accessibility Accessibility => _target.Accessibility; + + public string AsTypeName => _target.AsTypeName; + public bool HasConflictingPropertyIdentifier => _validator.HasConflictingIdentifier(this, DeclarationType.Property, out var errorMessage); diff --git a/Rubberduck.Refactorings/EncapsulateField/StateUDT.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs similarity index 62% rename from Rubberduck.Refactorings/EncapsulateField/StateUDT.cs rename to Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs index c28a8f4512..c69dbc42f4 100644 --- a/Rubberduck.Refactorings/EncapsulateField/StateUDT.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs @@ -11,50 +11,78 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface IStateUDT + public interface IObjectStateUDT : IEncapsulateFieldDeclaration { string TypeIdentifier { set; get; } string FieldIdentifier { set; get; } string TypeDeclarationBlock(IIndenter indenter = null); string FieldDeclarationBlock { get; } void AddMembers(IEnumerable fields); - QualifiedModuleName QualifiedModuleName { set; get; } + bool IsExistingDeclaration { get; } } /* * StateUDT is the UserDefinedType introduced by this refactoring * whose members represent object state in lieu of individually declared member variables/fields. */ - public class StateUDT : IStateUDT + public class ObjectStateUDT : IObjectStateUDT//, IEncapsulateFieldDeclaration { private static string _defaultNewFieldName = EncapsulateFieldResources.DefaultStateUDTFieldName; private List _members; - private readonly IEncapsulateFieldNamesValidator _validator; + private readonly IUserDefinedTypeCandidate _decoratedUDT; - public StateUDT(QualifiedModuleName qmn, IEncapsulateFieldNamesValidator validator) - :this($"{EncapsulateFieldResources.StateUserDefinedTypeIdentifierPrefix}{qmn.ComponentName.CapitalizeFirstLetter()}", validator) + public ObjectStateUDT(IUserDefinedTypeCandidate udt) + :this(udt.Declaration.AsTypeName) + { + if (!udt.Declaration.Accessibility.Equals(Accessibility.Private)) + { + throw new ArgumentException(); + } + + _decoratedUDT = udt; + QualifiedModuleName = udt.Declaration.QualifiedModuleName; + } + + public ObjectStateUDT(QualifiedModuleName qmn) + :this($"{EncapsulateFieldResources.StateUserDefinedTypeIdentifierPrefix}{qmn.ComponentName.CapitalizeFirstLetter()}") { QualifiedModuleName = qmn; } - public StateUDT(string typeIdentifier, IEncapsulateFieldNamesValidator validator) + public ObjectStateUDT(string typeIdentifier) { - _validator = validator; FieldIdentifier = _defaultNewFieldName; TypeIdentifier = typeIdentifier; _members = new List(); } + public string IdentifierName => _decoratedUDT?.IdentifierName ?? FieldIdentifier; + + public Selection Selection => _decoratedUDT?.Selection ?? new Selection(); + + public Accessibility Accessibility => Accessibility.Private; // _decoratedUDT.Accessibility; + + public string AsTypeName => _decoratedUDT?.AsTypeName ?? TypeIdentifier; + public QualifiedModuleName QualifiedModuleName { set; get; } public string TypeIdentifier { set; get; } + public bool IsExistingDeclaration => _decoratedUDT != null; + public string FieldIdentifier { set; get; } - public void AddMembers(IEnumerable fields) => _members = fields.ToList(); + public void AddMembers(IEnumerable fields) + { + if (IsExistingDeclaration) + { + _members = _decoratedUDT.Members.Select(m => m).Cast().ToList(); + } + _members.AddRange(fields); + } public string FieldDeclarationBlock - => $"{Accessibility.Private} {FieldIdentifier} {Tokens.As} {TypeIdentifier}"; + => $"{Accessibility.Private} {IdentifierName} {Tokens.As} {AsTypeName}"; public string TypeDeclarationBlock(IIndenter indenter = null) { diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs index 97c954919c..d1e32db824 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs @@ -14,6 +14,7 @@ public interface IUserDefinedTypeCandidate : IEncapsulateFieldCandidate IEnumerable Members { get; } void AddMember(IUserDefinedTypeMemberCandidate member); bool TypeDeclarationIsPrivate { set; get; } + bool IsObjectStateUDT { set; get; } } public class UserDefinedTypeCandidate : EncapsulateFieldCandidate, IUserDefinedTypeCandidate @@ -35,6 +36,13 @@ public void AddMember(IUserDefinedTypeMemberCandidate member) public bool TypeDeclarationIsPrivate { set; get; } + private bool _isObjectStateUDT; + public bool IsObjectStateUDT + { + set => _isObjectStateUDT = value; + get => _isObjectStateUDT; + } + public override string FieldIdentifier { get => TypeDeclarationIsPrivate ? _fieldAndProperty.TargetFieldName : _fieldAndProperty.Field; @@ -79,7 +87,7 @@ public override bool EncapsulateFlag } base.EncapsulateFlag = value; } - get => _encapsulateFlag; + get => _encapsulateFlag && !_isObjectStateUDT; } @@ -123,7 +131,7 @@ public override IEnumerable PropertyAttributeSets } } - public override void StageFieldReferenceReplacements(IStateUDT stateUDT = null) + public override void StageFieldReferenceReplacements(IObjectStateUDT stateUDT = null) { PropertyAccessor = stateUDT is null ? AccessorTokens.Field : AccessorTokens.Property; diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs index 3bfa59553e..3d65961e79 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs @@ -34,9 +34,15 @@ public UserDefinedTypeMemberCandidate(IEncapsulateFieldCandidate efd, IUserDefin private IEncapsulateFieldCandidate _decoratedField; + public Selection Selection => _decoratedField.Selection; + + public Accessibility Accessibility => _decoratedField.Accessibility; + + public string AsTypeName => _decoratedField.AsTypeName; + public IUserDefinedTypeCandidate Parent { private set; get; } - public void StageFieldReferenceReplacements(IStateUDT stateUDT = null) { } + public void StageFieldReferenceReplacements(IObjectStateUDT stateUDT = null) { } private string _referenceQualifier; public string ReferenceQualifier @@ -195,7 +201,8 @@ public bool ImplementSet get => _decoratedField.ImplementSet; } public IEnumerable PropertyAttributeSets => _decoratedField.PropertyAttributeSets; - public string AsUDTMemberDeclaration { get; } + public string AsUDTMemberDeclaration //{ get; } + => _decoratedField.AsUDTMemberDeclaration; // $"{_decoratedField.PropertyName} {Tokens.As} {_decoratedField.AsTypeName_Field}"; public IEnumerable> ReferenceReplacements => _decoratedField.ReferenceReplacements; public string ReferenceWithinNewProperty => $"{Parent.ReferenceWithinNewProperty}.{_decoratedField.IdentifierName}"; diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs index ddde11d01e..000e6a5c4b 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs @@ -118,6 +118,49 @@ Public Sub Foo(newValue As String) StringAssert.Contains(" First = newValue", actualCode); } + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void LoadsExistingUDT() + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +Private my|Bar As TBar + +Public foo As Long +Public bar As String +Public foobar As Byte +"; + + var userInput = new UserInputDataObject() + .UserSelectsField("foo") + .UserSelectsField("bar") + .UserSelectsField("foobar"); + + userInput.EncapsulateAsUDT = true; + userInput.ObjectStateUDTTargetID = "myBar"; + + var presenterAction = Support.SetParameters(userInput); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.DoesNotContain($"Private this As {Support.StateUDTDefaultType}", actualCode); + //StringAssert.Contains($"Private Type {Support.StateUDTDefaultType}", actualCode); + StringAssert.Contains("Foo As Long", actualCode); + StringAssert.DoesNotContain("Public foo As Long", actualCode); + StringAssert.Contains("Bar As String", actualCode); + StringAssert.DoesNotContain("Public bar As Long", actualCode); + StringAssert.Contains("Foobar As Byte", actualCode); + StringAssert.DoesNotContain("Public foobar As Long", actualCode); + StringAssert.DoesNotContain("MyBar As TBar", actualCode); + StringAssert.DoesNotContain("Private this As TBar", actualCode); + StringAssert.Contains("First As String", actualCode); + StringAssert.Contains("Second As Long", actualCode); + } + [Test] [Category("Refactorings")] [Category("Encapsulate Field")] diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index d026f8d66a..6e119f9593 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -65,8 +65,17 @@ public Func SetParameters(UserInpu return model => { model.EncapsulateWithUDT = userInput.EncapsulateAsUDT; - model.StateUDTField.TypeIdentifier = userInput.StateUDT_TypeName ?? model.StateUDTField.TypeIdentifier; - model.StateUDTField.FieldIdentifier = userInput.StateUDT_FieldName ?? model.StateUDTField.FieldIdentifier; + if (userInput.EncapsulateAsUDT) + { + var stateUDT = model.SelectedFieldCandidates.Where(sfc => sfc is IUserDefinedTypeCandidate udt && udt.TargetID == userInput.ObjectStateUDTTargetID) + .Select(sfc => sfc as IUserDefinedTypeCandidate).SingleOrDefault(); + if (stateUDT != null) + { + stateUDT.IsObjectStateUDT = userInput.ObjectStateUDTTargetID != null; + model.StateUDTField = new ObjectStateUDT(stateUDT); + } + } + foreach (var testModifiedAttribute in userInput.EncapsulateFieldAttributes) { var attrsInitializedByTheRefactoring = model[testModifiedAttribute.TargetFieldName]; //.EncapsulationAttributes; @@ -228,6 +237,8 @@ public UserInputDataObject AddUserInputSet(string fieldName, string propertyName public bool EncapsulateAsUDT { set; get; } + public string ObjectStateUDTTargetID { set; get; } + public string StateUDT_TypeName { set; get; } public string StateUDT_FieldName { set; get; } From 8c4325bd3d36b5ab7f25e7432bfd6f67fe09265c Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Mon, 23 Dec 2019 11:35:43 -0500 Subject: [PATCH 079/461] added quickfix xmldoc, R-W --- .../QuickFixes/RemoveAnnotationQuickFix.cs | 30 ++++++++++++++ .../QuickFixes/RemoveAttributeQuickFix.cs | 29 ++++++++++++++ .../QuickFixes/RemoveCommentQuickFix.cs | 29 +++++++++++++- .../RemoveDuplicatedAnnotationQuickFix.cs | 28 +++++++++++++ .../RemoveEmptyElseBlockQuickFix.cs | 32 +++++++++++++++ .../QuickFixes/RemoveEmptyIfBlockQuickFix.cs | 35 +++++++++++++++++ .../RemoveExplicitByRefModifierQuickFix.cs | 28 ++++++++++++- .../RemoveExplicitCallStatementQuickFix.cs | 35 +++++++++++++++++ .../RemoveExplicitLetStatementQuickFix.cs | 31 +++++++++++++++ .../QuickFixes/RemoveLocalErrorQuickFix.cs | 39 +++++++++++++++++++ .../RemoveOptionBaseStatementQuickFix.cs | 30 ++++++++++++++ .../QuickFixes/RemoveStepOneQuickFix.cs | 33 ++++++++++++++++ .../QuickFixes/RemoveStopKeywordQuickFix.cs | 29 ++++++++++++++ .../QuickFixes/RemoveTypeHintsQuickFix.cs | 31 +++++++++++++++ .../RemoveUnassignedIdentifierQuickFix.cs | 28 +++++++++++++ .../RemoveUnassignedVariableUsageQuickFix.cs | 29 ++++++++++++++ .../RemoveUnusedDeclarationQuickFix.cs | 36 ++++++++++++++++- .../RemoveUnusedParameterQuickFix.cs | 35 +++++++++++++++++ .../QuickFixes/RenameDeclarationQuickFix.cs | 39 +++++++++++++++++++ ...laceEmptyStringLiteralStatementQuickFix.cs | 31 +++++++++++++++ .../ReplaceGlobalModifierQuickFix.cs | 21 ++++++++++ ...eIfElseWithConditionalStatementQuickFix.cs | 35 +++++++++++++++++ .../ReplaceObsoleteCommentMarkerQuickFix.cs | 27 +++++++++++++ .../ReplaceObsoleteErrorStatementQuickFix.cs | 27 +++++++++++++ ...ReplaceWhileWendWithDoWhileLoopQuickFix.cs | 33 ++++++++++++++++ .../RestoreErrorHandlingQuickFix.cs | 35 +++++++++++++++++ .../SetExplicitVariantReturnTypeQuickFix.cs | 27 +++++++++++++ .../SpecifyExplicitByRefModifierQuickFix.cs | 28 ++++++++++++- .../SpecifyExplicitPublicModifierQuickFix.cs | 27 +++++++++++++ .../SplitMultipleDeclarationsQuickFix.cs | 30 ++++++++++++++ .../UntypedFunctionUsageQuickFix.cs | 29 +++++++++++++- ...seSetKeywordForObjectAssignmentQuickFix.cs | 36 ++++++++++++++++- .../QuickFixes/WriteOnlyPropertyQuickFix.cs | 32 +++++++++++++++ 33 files changed, 1016 insertions(+), 8 deletions(-) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveAnnotationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveAnnotationQuickFix.cs index 22fd29c744..f1659620d0 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveAnnotationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveAnnotationQuickFix.cs @@ -6,6 +6,36 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Removes an annotation comment representing a hidden module or member attribute, in order to maintain consistency between hidden attributes and annotation comments. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class RemoveAnnotationQuickFix : QuickFixBase { private readonly IAnnotationUpdater _annotationUpdater; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveAttributeQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveAttributeQuickFix.cs index 352964edc0..11a8e0da2d 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveAttributeQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveAttributeQuickFix.cs @@ -9,6 +9,35 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Removes a hidden attribute, in order to maintain consistency between hidden attributes and (missing) annotation comments. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public class RemoveAttributeQuickFix : QuickFixBase { private readonly IAttributesUpdater _attributesUpdater; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveCommentQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveCommentQuickFix.cs index e17409f5f0..982109d35c 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveCommentQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveCommentQuickFix.cs @@ -5,6 +5,33 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Removes a comment. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class RemoveCommentQuickFix : QuickFixBase { public RemoveCommentQuickFix() @@ -17,7 +44,7 @@ public override void Fix(IInspectionResult result, IRewriteSession rewriteSessio rewriter.Remove(result.Context); } - public override string Description(IInspectionResult result) => Resources.Inspections.QuickFixes.RemoveObsoleteStatementQuickFix; + public override string Description(IInspectionResult result) => Resources.Inspections.QuickFixes.RemoveCommentQuickFix; public override bool CanFixInProcedure => true; public override bool CanFixInModule => true; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveDuplicatedAnnotationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveDuplicatedAnnotationQuickFix.cs index 14552c1e47..a85e50cea5 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveDuplicatedAnnotationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveDuplicatedAnnotationQuickFix.cs @@ -7,6 +7,34 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Removes a duplicated annotation comment. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class RemoveDuplicatedAnnotationQuickFix : QuickFixBase { private readonly IAnnotationUpdater _annotationUpdater; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveEmptyElseBlockQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveEmptyElseBlockQuickFix.cs index 83ace83be6..201a322ef0 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveEmptyElseBlockQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveEmptyElseBlockQuickFix.cs @@ -6,6 +6,38 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Removes an empty Else block. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class RemoveEmptyElseBlockQuickFix : QuickFixBase { public RemoveEmptyElseBlockQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveEmptyIfBlockQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveEmptyIfBlockQuickFix.cs index 0a2f2fb065..92f04c8f91 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveEmptyIfBlockQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveEmptyIfBlockQuickFix.cs @@ -10,6 +10,41 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Removes an empty conditional block by inverting the condition expression. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// xlCalculationManual Then + /// + /// Application.Calculation = xlCalculationManual + /// End If + /// '... + /// End Sub + /// ]]> + /// + /// public sealed class RemoveEmptyIfBlockQuickFix : QuickFixBase { public RemoveEmptyIfBlockQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitByRefModifierQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitByRefModifierQuickFix.cs index d981f1b751..8e64fd7a87 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitByRefModifierQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitByRefModifierQuickFix.cs @@ -8,10 +8,36 @@ using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.VBA.Extensions; namespace Rubberduck.Inspections.QuickFixes { + /// + /// Removes an explicit ByRef modifier, making it implicit. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class RemoveExplicitByRefModifierQuickFix : QuickFixBase { private readonly IDeclarationFinderProvider _declarationFinderProvider; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitCallStatementQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitCallStatementQuickFix.cs index 88601e6c97..afd0d6e984 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitCallStatementQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitCallStatementQuickFix.cs @@ -6,6 +6,41 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Makes a call statement implicit by removing the 'Call' keyword, adjusting argument list parentheses accordingly. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class RemoveExplicitCallStatementQuickFix : QuickFixBase { public RemoveExplicitCallStatementQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitLetStatementQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitLetStatementQuickFix.cs index 286635fc54..264a975765 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitLetStatementQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitLetStatementQuickFix.cs @@ -7,6 +7,37 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Makes the 'Let' keyword of a value assignment implicit. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class RemoveExplicitLetStatementQuickFix : QuickFixBase { public RemoveExplicitLetStatementQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveLocalErrorQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveLocalErrorQuickFix.cs index aedb0bbbe4..10150baad3 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveLocalErrorQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveLocalErrorQuickFix.cs @@ -6,6 +6,45 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Makes the 'Local' keyword of an 'On Error' statement implicit. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class RemoveLocalErrorQuickFix : QuickFixBase { public RemoveLocalErrorQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveOptionBaseStatementQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveOptionBaseStatementQuickFix.cs index a980f9d34c..7cb1ef5510 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveOptionBaseStatementQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveOptionBaseStatementQuickFix.cs @@ -5,6 +5,36 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Removes 'Option Base 0' statement from a module, making it implicit (0 being the default implicit lower bound for implicitly-sized arrays). + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class RemoveOptionBaseStatementQuickFix : QuickFixBase { public RemoveOptionBaseStatementQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveStepOneQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveStepOneQuickFix.cs index 676f013f1e..08c68e529e 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveStepOneQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveStepOneQuickFix.cs @@ -5,6 +5,39 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Removes 'Step 1' specifier from 'For...Next' loop statement, 1 being the implicit default 'Step' increment. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class RemoveStepOneQuickFix : QuickFixBase { public RemoveStepOneQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveStopKeywordQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveStopKeywordQuickFix.cs index 18929a6c69..7dbc04151c 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveStopKeywordQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveStopKeywordQuickFix.cs @@ -5,6 +5,35 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Removes 'Stop' instruction. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class RemoveStopKeywordQuickFix : QuickFixBase { public RemoveStopKeywordQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveTypeHintsQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveTypeHintsQuickFix.cs index c1ab54b6cf..2336f9818a 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveTypeHintsQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveTypeHintsQuickFix.cs @@ -8,6 +8,37 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Removes type hint characters from identifier declarations and value literals. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class RemoveTypeHintsQuickFix : QuickFixBase { public RemoveTypeHintsQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveUnassignedIdentifierQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveUnassignedIdentifierQuickFix.cs index e2c0ab47fb..da3054fa59 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveUnassignedIdentifierQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveUnassignedIdentifierQuickFix.cs @@ -5,6 +5,34 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Removes the declaration for a variable that is never assigned. This operation may result in broken code if the unassigned variable is in use. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class RemoveUnassignedIdentifierQuickFix : QuickFixBase { public RemoveUnassignedIdentifierQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveUnassignedVariableUsageQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveUnassignedVariableUsageQuickFix.cs index 89655ca69f..bd7f5282d1 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveUnassignedVariableUsageQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveUnassignedVariableUsageQuickFix.cs @@ -11,6 +11,35 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Removes an instruction that references a variable that isn't assigned. This operation may break the code. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class RemoveUnassignedVariableUsageQuickFix : QuickFixBase { public RemoveUnassignedVariableUsageQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveUnusedDeclarationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveUnusedDeclarationQuickFix.cs index 515bf8d2ac..6aa169ee60 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveUnusedDeclarationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveUnusedDeclarationQuickFix.cs @@ -6,12 +6,44 @@ namespace Rubberduck.Inspections.QuickFixes { /// - /// A code inspection quickfix that removes an unused identifier declaration. + /// Removes the declaration for a constant, variable, procedure, or line label that isn't used. This operation can break the code if the declaration is actually in use but Rubberduck couldn't find where. /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class RemoveUnusedDeclarationQuickFix : QuickFixBase { public RemoveUnusedDeclarationQuickFix() - : base(typeof(ConstantNotUsedInspection), typeof(ProcedureNotUsedInspection), typeof(VariableNotUsedInspection), typeof(LineLabelNotUsedInspection)) + : base(typeof(ConstantNotUsedInspection), + typeof(ProcedureNotUsedInspection), + typeof(VariableNotUsedInspection), + typeof(LineLabelNotUsedInspection)) {} public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveUnusedParameterQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveUnusedParameterQuickFix.cs index b0d100ee07..b37b6e22c8 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveUnusedParameterQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveUnusedParameterQuickFix.cs @@ -4,6 +4,41 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Refactors a procedure's signature to remove a parameter that isn't used. Also updates usages. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class RemoveUnusedParameterQuickFix : RefactoringQuickFixBase { public RemoveUnusedParameterQuickFix(RemoveParametersRefactoring refactoring) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RenameDeclarationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RenameDeclarationQuickFix.cs index bd118aade5..d636607b5b 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RenameDeclarationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RenameDeclarationQuickFix.cs @@ -7,6 +7,45 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Prompts for a new name, renames a declaration accordingly, and updates all usages. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class RenameDeclarationQuickFix : RefactoringQuickFixBase { public RenameDeclarationQuickFix(RenameRefactoring refactoring) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ReplaceEmptyStringLiteralStatementQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/ReplaceEmptyStringLiteralStatementQuickFix.cs index 27bfec7e25..36127b53fd 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ReplaceEmptyStringLiteralStatementQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/ReplaceEmptyStringLiteralStatementQuickFix.cs @@ -5,6 +5,37 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Replaces empty string literals '""' with the 'vbNullString' constant. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class ReplaceEmptyStringLiteralStatementQuickFix : QuickFixBase { public ReplaceEmptyStringLiteralStatementQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ReplaceGlobalModifierQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/ReplaceGlobalModifierQuickFix.cs index 0c31e2fc91..f707c277a3 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ReplaceGlobalModifierQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/ReplaceGlobalModifierQuickFix.cs @@ -8,6 +8,27 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Replaces 'Global' access modifier with the equivalent 'Public' keyword. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class ReplaceGlobalModifierQuickFix : QuickFixBase { public ReplaceGlobalModifierQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ReplaceIfElseWithConditionalStatementQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/ReplaceIfElseWithConditionalStatementQuickFix.cs index 3020fc05bd..db6683e9ff 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ReplaceIfElseWithConditionalStatementQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/ReplaceIfElseWithConditionalStatementQuickFix.cs @@ -7,6 +7,41 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Simplifies conditional Boolean literal assignments with a direct assignment to the conditional expression. + /// + /// + /// + /// + /// + /// + /// + /// 10 Then + /// result = True + /// Else + /// result = False + /// End If + /// Debug.Print result + /// End Sub + /// ]]> + /// + /// + /// 10 + /// Debug.Print result + /// End Sub + /// ]]> + /// + /// public sealed class ReplaceIfElseWithConditionalStatementQuickFix : QuickFixBase { public ReplaceIfElseWithConditionalStatementQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ReplaceObsoleteCommentMarkerQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/ReplaceObsoleteCommentMarkerQuickFix.cs index cc9129aef3..b78e787c44 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ReplaceObsoleteCommentMarkerQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/ReplaceObsoleteCommentMarkerQuickFix.cs @@ -6,6 +6,33 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Replaces the obsolete 'Rem' comment marker token with a single quote character. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class ReplaceObsoleteCommentMarkerQuickFix : QuickFixBase { public ReplaceObsoleteCommentMarkerQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ReplaceObsoleteErrorStatementQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/ReplaceObsoleteErrorStatementQuickFix.cs index 35364228a8..8852366442 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ReplaceObsoleteErrorStatementQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/ReplaceObsoleteErrorStatementQuickFix.cs @@ -6,6 +6,33 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Replaces the obsolete 'Error' statement with an 'ErrObject.Raise' member call. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class ReplaceObsoleteErrorStatementQuickFix : QuickFixBase { public ReplaceObsoleteErrorStatementQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ReplaceWhileWendWithDoWhileLoopQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/ReplaceWhileWendWithDoWhileLoopQuickFix.cs index e01e366d1f..3df609b4c9 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ReplaceWhileWendWithDoWhileLoopQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/ReplaceWhileWendWithDoWhileLoopQuickFix.cs @@ -6,6 +6,39 @@ namespace Rubberduck.CodeAnalysis.QuickFixes { + /// + /// Replaces 'While...Wend' loop statement with equivalent 'Do While...Loop'. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class ReplaceWhileWendWithDoWhileLoopQuickFix : QuickFixBase { public ReplaceWhileWendWithDoWhileLoopQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs index b96dc94f0e..506285c1c7 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs @@ -9,6 +9,41 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Introduces an error-handling subroutine to ensure error state is properly handled on scope exit. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// 0 Then 'TODO: handle specific error + /// Err.Clear + /// Resume Next + /// End If + /// End Sub + /// ]]> + /// + /// public sealed class RestoreErrorHandlingQuickFix : QuickFixBase { private const string LabelPrefix = "ErrorHandler"; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/SetExplicitVariantReturnTypeQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/SetExplicitVariantReturnTypeQuickFix.cs index 06c5d27bed..b9baa96ace 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/SetExplicitVariantReturnTypeQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/SetExplicitVariantReturnTypeQuickFix.cs @@ -7,6 +7,33 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Declares an explicit Variant return type for a procedure that implicitly returns a Variant. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class SetExplicitVariantReturnTypeQuickFix : QuickFixBase { public SetExplicitVariantReturnTypeQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/SpecifyExplicitByRefModifierQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/SpecifyExplicitByRefModifierQuickFix.cs index c3f6196536..3c9d6a8887 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/SpecifyExplicitByRefModifierQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/SpecifyExplicitByRefModifierQuickFix.cs @@ -8,10 +8,36 @@ using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.VBA.Extensions; namespace Rubberduck.Inspections.QuickFixes { + /// + /// Introduces an explicit 'ByRef' modifier for a parameter that is implicitly passed by reference. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class SpecifyExplicitByRefModifierQuickFix : QuickFixBase { private readonly IDeclarationFinderProvider _declarationFinderProvider; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/SpecifyExplicitPublicModifierQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/SpecifyExplicitPublicModifierQuickFix.cs index 5c95e0e80b..e870757ef9 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/SpecifyExplicitPublicModifierQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/SpecifyExplicitPublicModifierQuickFix.cs @@ -5,6 +5,33 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Introduces an explicit 'Public' access modifier for a procedure that is implicitly public. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class SpecifyExplicitPublicModifierQuickFix : QuickFixBase { public SpecifyExplicitPublicModifierQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/SplitMultipleDeclarationsQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/SplitMultipleDeclarationsQuickFix.cs index fbd2796e6e..8b990ccebb 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/SplitMultipleDeclarationsQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/SplitMultipleDeclarationsQuickFix.cs @@ -9,6 +9,36 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Splits multiple declarations into separate statements. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class SplitMultipleDeclarationsQuickFix : QuickFixBase { public SplitMultipleDeclarationsQuickFix() diff --git a/Rubberduck.CodeAnalysis/QuickFixes/UntypedFunctionUsageQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/UntypedFunctionUsageQuickFix.cs index 5a2da9f884..3bf068293d 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/UntypedFunctionUsageQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/UntypedFunctionUsageQuickFix.cs @@ -9,6 +9,33 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Replaces the use of a Variant-returning standard library function with its String-returning equivalent. Using this when the argument can be 'Null' will break the code. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class UntypedFunctionUsageQuickFix : QuickFixBase { public UntypedFunctionUsageQuickFix() @@ -37,7 +64,7 @@ private static string GetNewSignature(ParserRuleContext context) }); } - public override bool CanFixInProcedure => false; + public override bool CanFixInProcedure => true; public override bool CanFixInModule => true; public override bool CanFixInProject => true; } diff --git a/Rubberduck.CodeAnalysis/QuickFixes/UseSetKeywordForObjectAssignmentQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/UseSetKeywordForObjectAssignmentQuickFix.cs index 8e4f4c602c..6fa9e08652 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/UseSetKeywordForObjectAssignmentQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/UseSetKeywordForObjectAssignmentQuickFix.cs @@ -7,6 +7,36 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Introduces a 'Set' keyword for what appears to be a suspicious or malformed object reference assignment. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class UseSetKeywordForObjectAssignmentQuickFix : QuickFixBase { public UseSetKeywordForObjectAssignmentQuickFix() @@ -18,13 +48,15 @@ public override void Fix(IInspectionResult result, IRewriteSession rewriteSessio var rewriter = rewriteSession.CheckOutModuleRewriter(result.QualifiedSelection.QualifiedName); var letStmt = result.Context.GetAncestor(); var letToken = letStmt.LET(); + var setToken = Tokens.Set; if (letToken != null) { - rewriter.Replace(letToken, "Set"); + rewriter.Replace(letToken, setToken); } else { - rewriter.InsertBefore(letStmt.Start.TokenIndex, "Set "); + setToken += " "; + rewriter.InsertBefore(letStmt.Start.TokenIndex, setToken); } } diff --git a/Rubberduck.CodeAnalysis/QuickFixes/WriteOnlyPropertyQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/WriteOnlyPropertyQuickFix.cs index 05bd4916c6..3ee1aa718a 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/WriteOnlyPropertyQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/WriteOnlyPropertyQuickFix.cs @@ -9,6 +9,38 @@ namespace Rubberduck.Inspections.QuickFixes { + /// + /// Introduces a 'Property Get' member to make a write-only property read/write; Rubberduck will not infer the property's backing field, the body of the new member must be implemented manually. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// public sealed class WriteOnlyPropertyQuickFix : QuickFixBase { public WriteOnlyPropertyQuickFix() From c015dfbf06b6868848add9d46520f2b280cfacf0 Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Mon, 23 Dec 2019 11:36:26 -0500 Subject: [PATCH 080/461] removed ExperimentalAttribute --- .../Inspections/Concrete/EmptyIfBlockInspection.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyIfBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyIfBlockInspection.cs index 838c04ebfb..d124bba6dc 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyIfBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyIfBlockInspection.cs @@ -3,15 +3,12 @@ using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Results; using Rubberduck.Parsing; -using Rubberduck.Parsing.Common; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; -using Rubberduck.Resources.Experimentals; using Rubberduck.Parsing.VBA; using System.Collections.Generic; using System.Linq; -using Rubberduck.Inspections.Inspections.Extensions; namespace Rubberduck.Inspections.Concrete { @@ -40,7 +37,6 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - [Experimental(nameof(ExperimentalNames.EmptyBlockInspections))] internal class EmptyIfBlockInspection : ParseTreeInspectionBase { public EmptyIfBlockInspection(RubberduckParserState state) From 827c154d38fef0ef9bbc2462b620d67e609f71de Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Mon, 23 Dec 2019 11:36:54 -0500 Subject: [PATCH 081/461] Fixed xmldoc to actually reflect what the inspection does --- .../BooleanAssignedInIfElseInspection.cs | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs index 3018f23f25..d3614c0116 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs @@ -14,26 +14,30 @@ namespace Rubberduck.Inspections.Concrete { /// - /// Identifies redundant Boolean expressions in conditionals. + /// Identifies conditional assignments to mutually exclusive Boolean literal values in conditional branches. /// /// - /// A Boolean expression never needs to be compared to a Boolean literal in a conditional expression. + /// The assignment could be made directly to the result of the conditional Boolean expression instead. /// /// /// 10 Then + /// result = True + /// Else + /// result = False /// End If + /// Debug.Print result /// End Sub /// ]]> /// /// /// 10 + /// Debug.Print result /// End Sub /// ]]> /// From cab87b8b1599a99c615e60377d64d1b5c06318d7 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Mon, 23 Dec 2019 12:15:40 -0800 Subject: [PATCH 082/461] Refactoring reduce interface width --- .../EncapsulateFieldElementFactory.cs | 51 +------ .../EncapsulateField/EncapsulateFieldModel.cs | 13 +- .../EncapsulateFieldRefactoring.cs | 47 +++---- .../FieldCandidates/ArrayCandidate.cs | 21 +-- .../EncapsulateFieldCandidate.cs | 123 ++++++++-------- .../FieldCandidates/ObjectStateUDT.cs | 29 ++-- .../UserDefinedTypeCandidate.cs | 78 ++++------ .../UserDefinedTypeMemberCandidate.cs | 133 +++++++++--------- 8 files changed, 196 insertions(+), 299 deletions(-) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs index 77a007707b..bcbfe7d8b4 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs @@ -40,7 +40,6 @@ public IEncapsulateFieldCandidate CreateEncapsulationCandidate(Declaration targe IEncapsulateFieldCandidate candidate = CreateCandidate(target); - candidate = ApplyTypeSpecificAttributes(candidate); if (candidate is IUserDefinedTypeCandidate udtVariable) { (Declaration udtDeclaration, IEnumerable udtMembers) = GetUDTAndMembersForField(udtVariable); @@ -51,8 +50,6 @@ public IEncapsulateFieldCandidate CreateEncapsulationCandidate(Declaration targe { var candidateUDTMember = new UserDefinedTypeMemberCandidate(CreateCandidate(udtMemberDeclaration), udtVariable, _validator) as IUserDefinedTypeMemberCandidate; - candidateUDTMember = ApplyTypeSpecificAttributes(candidateUDTMember); - udtVariable.AddMember(candidateUDTMember); } } @@ -103,55 +100,9 @@ private IObjectStateUDT SetNonConflictIdentifier(IObjectStateUDT candidate, Pred return candidate; } - private T ApplyTypeSpecificAttributes(T candidate) where T: IEncapsulateFieldCandidate - { - /* - * Default values are: - * candidate.ImplementLetSetterType = true; - * candidate.ImplementSetSetterType = false; - * candidate.CanBeReadWrite = true; - * candidate.IsReadOnly = false; - */ - - if (candidate.Declaration.IsEnumField()) - { - //5.3.1 The declared type of a function declaration may not be a private enum name. - if (candidate.Declaration.AsTypeDeclaration.HasPrivateAccessibility()) - { - candidate.AsTypeName_Property = Tokens.Long; - } - } - else if (candidate.Declaration.AsTypeName.Equals(Tokens.Variant) - && !candidate.Declaration.IsArray) - { - candidate.ImplementLet = true; - candidate.ImplementSet = true; - } - else if (candidate.Declaration.IsObject) - { - candidate.ImplementLet = false; - candidate.ImplementSet = true; - } - return candidate; - } - private (Declaration TypeDeclaration, IEnumerable Members) GetUDTAndMembersForField(IUserDefinedTypeCandidate udtField) { - var userDefinedTypeDeclaration = _declarationFinderProvider.DeclarationFinder - .UserDeclarations(DeclarationType.UserDefinedType) - .Where(ut => ut.IdentifierName.Equals(udtField.AsTypeName_Field) - && ut.QualifiedModuleName == udtField.QualifiedModuleName) - .SingleOrDefault(); - - if (userDefinedTypeDeclaration is null) - { - userDefinedTypeDeclaration = _declarationFinderProvider.DeclarationFinder - .UserDeclarations(DeclarationType.UserDefinedType) - .Where(ut => ut.IdentifierName.Equals(udtField.AsTypeName_Field) - && ut.ProjectId == udtField.Declaration.ProjectId - && ut.Accessibility != Accessibility.Private) - .SingleOrDefault(); - } + var userDefinedTypeDeclaration = udtField.Declaration.AsTypeDeclaration; var udtMembers = _declarationFinderProvider.DeclarationFinder .UserDeclarations(DeclarationType.UserDefinedTypeMember) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index aa7275a1d7..bd51f4edd6 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -11,6 +11,7 @@ public class EncapsulateFieldModel : IRefactoringModel private readonly Func _previewDelegate; private QualifiedModuleName _targetQMN; private IEncapsulateFieldNamesValidator _validator; + private IObjectStateUDT _newObjectStateUDT; private IDictionary)> _udtFieldToUdtDeclarationMap = new Dictionary)>(); @@ -19,6 +20,7 @@ public EncapsulateFieldModel(Declaration target, IEnumerable sfc is IUserDefinedTypeCandidate udt + var selectedStateUDT = EncapsulationCandidates.Where(sfc => sfc is IUserDefinedTypeCandidate udt && udt.IsObjectStateUDT).Select(sfc => sfc as IUserDefinedTypeCandidate).FirstOrDefault(); - _stateUDTField = stateUDT != null - ? new ObjectStateUDT(stateUDT) - : null; + _stateUDTField = selectedStateUDT != null + ? new ObjectStateUDT(selectedStateUDT) + : _newObjectStateUDT; return _stateUDTField; } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 5a3ef2acf1..c3cdb482ab 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -128,10 +128,6 @@ private string PreviewRewrite(EncapsulateFieldModel model) return previewRewriter.GetText(maxConsecutiveNewLines: 3); } - private IObjectStateUDT StateUDTField - => Model.EncapsulateWithUDT ? Model.StateUDTField : null; - - public IEncapsulateFieldRewriteSession GeneratePreview(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) { if (!model.SelectedFieldCandidates.Any()) { return refactorRewriteSession; } @@ -159,13 +155,13 @@ private IEncapsulateFieldRewriteSession RefactorRewrite(EncapsulateFieldModel mo private void ModifyReferences(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) { - var stateUDT = model.EncapsulateWithUDT - ? model.StateUDTField - : null; - foreach (var field in model.SelectedFieldCandidates) { - field.StageFieldReferenceReplacements(stateUDT); + field.ReferenceQualifier = model.EncapsulateWithUDT + ? model.StateUDTField.FieldIdentifier + : null; + + field.LoadFieldReferenceContextReplacements(); } foreach (var rewriteReplacement in model.SelectedFieldCandidates.SelectMany(field => field.ReferenceReplacements)) @@ -189,29 +185,18 @@ private void ModifyFields(EncapsulateFieldModel model, IEncapsulateFieldRewriteS refactorRewriteSession.Remove(field.Declaration, rewriter); } - if (model.StateUDTField is null) + if (!model.StateUDTField.IsExistingDeclaration) { - model.StateUDTField = _encapsulationCandidateFactory.CreateStateUDTField(); return; } + var stateUDT = model.StateUDTField; - var stateUDTDeclaration = model.StateUDTField as IEncapsulateFieldDeclaration; - //if (stateUDT.WrappedUDT != null) - //{ - stateUDT.AddMembers(model.SelectedFieldCandidates); - //} - var content = stateUDT.TypeDeclarationBlock(_indenter); - rewriter = refactorRewriteSession.CheckOutModuleRewriter(_targetQMN); - var udts = _declarationFinderProvider.DeclarationFinder.UserDeclarations(DeclarationType.UserDefinedType); + stateUDT.AddMembers(model.SelectedFieldCandidates); - var udtDeclaration = _declarationFinderProvider.DeclarationFinder.UserDeclarations(DeclarationType.UserDefinedType) - .Where(udt => udt.HasPrivateAccessibility() - && udt.QualifiedModuleName.Equals(stateUDTDeclaration.QualifiedModuleName) - && udt.IdentifierName.Equals(stateUDTDeclaration.AsTypeName)) - .Single(); + rewriter = refactorRewriteSession.CheckOutModuleRewriter(_targetQMN); - rewriter.Replace(udtDeclaration, content); + rewriter.Replace(stateUDT.AsTypeDeclaration, stateUDT.TypeDeclarationBlock(_indenter)); return; } @@ -281,14 +266,14 @@ private void LoadNewDeclarationBlocks(EncapsulateFieldModel model) { if (model.EncapsulateWithUDT) { - //if (StateUDTField/*?.WrappedUDT*/ != null) { return; } - if (StateUDTField.IsExistingDeclaration) { return; } + if (model.StateUDTField?.IsExistingDeclaration ?? false) { return; } - var stateUDT = StateUDTField; - stateUDT.AddMembers(model.SelectedFieldCandidates); + model.StateUDTField = _encapsulationCandidateFactory.CreateStateUDTField(); + + model.StateUDTField.AddMembers(model.SelectedFieldCandidates); - AddCodeBlock(NewContentTypes.TypeDeclarationBlock, stateUDT.TypeDeclarationBlock(_indenter)); - AddCodeBlock(NewContentTypes.DeclarationBlock, stateUDT.FieldDeclarationBlock); + AddCodeBlock(NewContentTypes.TypeDeclarationBlock, model.StateUDTField.TypeDeclarationBlock(_indenter)); + AddCodeBlock(NewContentTypes.DeclarationBlock, model.StateUDTField.FieldDeclarationBlock); return; } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs index e449a923d1..7ade824cce 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs @@ -29,28 +29,19 @@ public ArrayCandidate(Declaration declaration, IEncapsulateFieldNamesValidator v public override string AsUDTMemberDeclaration => $"{PropertyName}({_subscripts}) {Tokens.As} {AsTypeName_Field}"; - public override void StageFieldReferenceReplacements(IObjectStateUDT stateUDT = null) + public override void LoadFieldReferenceContextReplacements() { - PropertyAccessor = stateUDT is null ? AccessorTokens.Field : AccessorTokens.Property; - ReferenceAccessor = AccessorTokens.Property; - ReferenceQualifier = stateUDT?.FieldIdentifier ?? null; - LoadFieldReferenceContextReplacements(); - } - - protected override void LoadFieldReferenceContextReplacements() - { - var field = this; - foreach (var idRef in field.Declaration.References) + foreach (var idRef in Declaration.References) { var replacementText = RequiresAccessQualification(idRef) - ? $"{field.QualifiedModuleName.ComponentName}.{field.ReferenceForPreExistingReferences}" - : field.FieldIdentifier; + ? $"{QualifiedModuleName.ComponentName}.{ReferenceForPreExistingReferences}" + : FieldIdentifier; - field.SetReferenceRewriteContent(idRef, replacementText); + SetReferenceRewriteContent(idRef, replacementText); } } - public override void SetReferenceRewriteContent(IdentifierReference idRef, string replacementText) + protected override void SetReferenceRewriteContent(IdentifierReference idRef, string replacementText) { var context = idRef.Context; if (idRef.Context is VBAParser.IndexExprContext idxExpression) diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs index 6a6a3a0497..4f5a8470b0 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs @@ -12,40 +12,31 @@ public interface IEncapsulateFieldDeclaration string IdentifierName { get; } QualifiedModuleName QualifiedModuleName { get; } string AsTypeName { get; } - Selection Selection { get; } - Accessibility Accessibility { get; } } public interface IEncapsulateFieldCandidate : IEncapsulateFieldDeclaration { Declaration Declaration { get; } - //string IdentifierName { get; } string TargetID { get; } bool IsReadOnly { get; set; } bool EncapsulateFlag { get; set; } string FieldIdentifier { set; get; } bool CanBeReadWrite { set; get; } - //QualifiedModuleName QualifiedModuleName { get; } string PropertyName { get; set; } string AsTypeName_Field { get; set; } string AsTypeName_Property { get; set; } string ParameterName { get; } - bool ImplementLet { get; set; } - bool ImplementSet { get; set; } + bool ImplementLet { get; } + bool ImplementSet { get; } IEnumerable PropertyAttributeSets { get; } string AsUDTMemberDeclaration { get; } IEnumerable> ReferenceReplacements { get; } - void SetReferenceRewriteContent(IdentifierReference idRef, string replacementText); string ReferenceQualifier { set; get; } - string ReferenceWithinNewProperty { get; } - void StageFieldReferenceReplacements(IObjectStateUDT stateUDT = null); - AccessorTokens PropertyAccessor { set; get; } - AccessorTokens ReferenceAccessor { set; get; } + void LoadFieldReferenceContextReplacements(); bool TryValidateEncapsulationAttributes(out string errorMessage); - } - public enum AccessorTokens { Field, Property } + public enum AccessorMember { Field, Property } public interface IEncapsulateFieldCandidateValidations { @@ -67,45 +58,52 @@ public EncapsulateFieldCandidate(Declaration declaration, IEncapsulateFieldNames : this(declaration.IdentifierName, declaration.AsTypeName, declaration.QualifiedModuleName, validator) { _target = declaration; + + if (_target.IsEnumField()) + { + //5.3.1 The declared type of a function declaration may not be a private enum name. + if (_target.AsTypeDeclaration.HasPrivateAccessibility()) + { + AsTypeName_Property = Tokens.Long; + } + } + else if (_target.AsTypeName.Equals(Tokens.Variant) + && !_target.IsArray) + { + ImplementLet = true; + ImplementSet = true; + } + else if (Declaration.IsObject) + { + ImplementLet = false; + ImplementSet = true; + } } public EncapsulateFieldCandidate(string identifier, string asTypeName, QualifiedModuleName qmn, IEncapsulateFieldNamesValidator validator) { - _target = null; - _fieldAndProperty = new EncapsulationIdentifiers(identifier); IdentifierName = identifier; AsTypeName_Field = asTypeName; AsTypeName_Property = asTypeName; _qmn = qmn; - PropertyAccessor = AccessorTokens.Field; - ReferenceAccessor = AccessorTokens.Property; + NewPropertyAccessor = AccessorMember.Field; + ReferenceAccessor = AccessorMember.Property; _validator = validator; ImplementLet = true; ImplementSet = false; + CanBeReadWrite = true; _hashCode = ($"{_qmn.Name}.{identifier}").GetHashCode(); } - public virtual void StageFieldReferenceReplacements(IObjectStateUDT stateUDT = null) - { - PropertyAccessor = stateUDT is null ? AccessorTokens.Field : AccessorTokens.Property; - ReferenceAccessor = AccessorTokens.Property; - ReferenceQualifier = stateUDT?.FieldIdentifier ?? null; - LoadFieldReferenceContextReplacements(); - } - protected Dictionary IdentifierReplacements { get; } = new Dictionary(); public Declaration Declaration => _target; - public Selection Selection => _target.Selection; - - public Accessibility Accessibility => _target.Accessibility; - public string AsTypeName => _target.AsTypeName; public bool HasConflictingPropertyIdentifier @@ -156,7 +154,7 @@ public virtual bool TryValidateEncapsulationAttributes(out string errorMessage) } } - public virtual void SetReferenceRewriteContent(IdentifierReference idRef, string replacementText) + protected virtual void SetReferenceRewriteContent(IdentifierReference idRef, string replacementText) { if (IdentifierReplacements.ContainsKey(idRef)) { @@ -249,6 +247,8 @@ public string IdentifierName set => _identifierName = value; } + public virtual string ReferenceQualifier { set; get; } + public string ParameterName => _fieldAndProperty.SetLetParameter; private bool _implLet; @@ -257,39 +257,45 @@ public string IdentifierName private bool _implSet; public bool ImplementSet { get => !IsReadOnly && _implSet; set => _implSet = value; } - public AccessorTokens PropertyAccessor { set; get; } + public virtual string AsUDTMemberDeclaration + => $"{PropertyName} {Tokens.As} {AsTypeName_Field}"; - public AccessorTokens ReferenceAccessor { set; get; } + public virtual IEnumerable PropertyAttributeSets + => new List() { AsPropertyAttributeSet }; - protected string _referenceQualifier; - public virtual string ReferenceQualifier + public virtual void LoadFieldReferenceContextReplacements() { - set => _referenceQualifier = value; - get => _referenceQualifier; + foreach (var idRef in Declaration.References) + { + var replacementText = RequiresAccessQualification(idRef) + ? $"{QualifiedModuleName.ComponentName}.{ReferenceForPreExistingReferences}" + : ReferenceForPreExistingReferences; + + SetReferenceRewriteContent(idRef, replacementText); + } } - public virtual string ReferenceWithinNewProperty => AccessorTokenToContent(PropertyAccessor); + protected AccessorMember NewPropertyAccessor { set; get; } - protected virtual string ReferenceForPreExistingReferences => AccessorTokenToContent(ReferenceAccessor); + protected AccessorMember ReferenceAccessor { set; get; } - private string AccessorTokenToContent(AccessorTokens token) - { - var accessor = token == AccessorTokens.Field - ? FieldIdentifier - : PropertyName; + protected virtual string ReferenceWithinNewProperty + => AccessorMemberToContent(NewPropertyAccessor); + + protected virtual string ReferenceForPreExistingReferences + => AccessorMemberToContent(ReferenceAccessor); + private string AccessorMemberToContent(AccessorMember accessorMember) + { if ((ReferenceQualifier?.Length ?? 0) > 0) { - return $"{ReferenceQualifier}.{accessor}"; + return $"{ReferenceQualifier}.{PropertyName}"; } - return accessor; - } - public virtual string AsUDTMemberDeclaration - => $"{PropertyName} {Tokens.As} {AsTypeName_Field}"; - - public virtual IEnumerable PropertyAttributeSets - => new List() { AsPropertyAttributeSet }; + return accessorMember == AccessorMember.Field + ? FieldIdentifier + : PropertyName; + } protected virtual IPropertyGeneratorAttributes AsPropertyAttributeSet { @@ -308,20 +314,7 @@ protected virtual IPropertyGeneratorAttributes AsPropertyAttributeSet } } - protected virtual void LoadFieldReferenceContextReplacements() - { - var field = this; - foreach (var idRef in field.Declaration.References) - { - var replacementText = RequiresAccessQualification(idRef) - ? $"{field.QualifiedModuleName.ComponentName}.{field.ReferenceForPreExistingReferences}" - : field.ReferenceForPreExistingReferences; - - field.SetReferenceRewriteContent(idRef, replacementText); - } - } - - protected bool RequiresAccessQualification(IdentifierReference idRef) + protected virtual bool RequiresAccessQualification(IdentifierReference idRef) { var isLHSOfMemberAccess = (idRef.Context.Parent is VBAParser.MemberAccessExprContext diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs index c69dbc42f4..649b528c7d 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs @@ -19,17 +19,16 @@ public interface IObjectStateUDT : IEncapsulateFieldDeclaration string FieldDeclarationBlock { get; } void AddMembers(IEnumerable fields); bool IsExistingDeclaration { get; } + Declaration AsTypeDeclaration { get; } } - /* - * StateUDT is the UserDefinedType introduced by this refactoring - * whose members represent object state in lieu of individually declared member variables/fields. - */ - public class ObjectStateUDT : IObjectStateUDT//, IEncapsulateFieldDeclaration + //ObjectStateUDT can be an existing UDT (Private only) selected by the user, or a + //newly inserted declaration + public class ObjectStateUDT : IObjectStateUDT { private static string _defaultNewFieldName = EncapsulateFieldResources.DefaultStateUDTFieldName; private List _members; - private readonly IUserDefinedTypeCandidate _decoratedUDT; + private readonly IUserDefinedTypeCandidate _wrappedUDT; public ObjectStateUDT(IUserDefinedTypeCandidate udt) :this(udt.Declaration.AsTypeName) @@ -39,7 +38,7 @@ public ObjectStateUDT(IUserDefinedTypeCandidate udt) throw new ArgumentException(); } - _decoratedUDT = udt; + _wrappedUDT = udt; QualifiedModuleName = udt.Declaration.QualifiedModuleName; } @@ -49,26 +48,24 @@ public ObjectStateUDT(QualifiedModuleName qmn) QualifiedModuleName = qmn; } - public ObjectStateUDT(string typeIdentifier) + private ObjectStateUDT(string typeIdentifier) { FieldIdentifier = _defaultNewFieldName; TypeIdentifier = typeIdentifier; _members = new List(); } - public string IdentifierName => _decoratedUDT?.IdentifierName ?? FieldIdentifier; + public string IdentifierName => _wrappedUDT?.IdentifierName ?? FieldIdentifier; - public Selection Selection => _decoratedUDT?.Selection ?? new Selection(); - - public Accessibility Accessibility => Accessibility.Private; // _decoratedUDT.Accessibility; - - public string AsTypeName => _decoratedUDT?.AsTypeName ?? TypeIdentifier; + public string AsTypeName => _wrappedUDT?.AsTypeName ?? TypeIdentifier; public QualifiedModuleName QualifiedModuleName { set; get; } public string TypeIdentifier { set; get; } - public bool IsExistingDeclaration => _decoratedUDT != null; + public bool IsExistingDeclaration => _wrappedUDT != null; + + public Declaration AsTypeDeclaration => _wrappedUDT.Declaration.AsTypeDeclaration; public string FieldIdentifier { set; get; } @@ -76,7 +73,7 @@ public void AddMembers(IEnumerable fields) { if (IsExistingDeclaration) { - _members = _decoratedUDT.Members.Select(m => m).Cast().ToList(); + _members = _wrappedUDT.Members.Select(m => m).Cast().ToList(); } _members.AddRange(fields); } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs index d1e32db824..5e7662a7d2 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs @@ -22,8 +22,8 @@ public class UserDefinedTypeCandidate : EncapsulateFieldCandidate, IUserDefinedT public UserDefinedTypeCandidate(Declaration declaration, IEncapsulateFieldNamesValidator validator) : base(declaration, validator) { - PropertyAccessor = AccessorTokens.Field; - ReferenceAccessor = AccessorTokens.Field; + NewPropertyAccessor = AccessorMember.Field; + ReferenceAccessor = AccessorMember.Field; } public void AddMember(IUserDefinedTypeMemberCandidate member) @@ -49,6 +49,20 @@ public override string FieldIdentifier set => _fieldAndProperty.Field = value; } + private string _referenceQualifier; + public override string ReferenceQualifier + { + set + { + _referenceQualifier = value; + foreach( var member in Members) + { + member.ReferenceQualifier = ReferenceWithinNewProperty; + } + } + get => _referenceQualifier; + } + private bool _isReadOnly; public override bool IsReadOnly { @@ -90,28 +104,23 @@ public override bool EncapsulateFlag get => _encapsulateFlag && !_isObjectStateUDT; } - - public override string ReferenceQualifier - { - set - { - _referenceQualifier = value; - PropertyAccessor = (value?.Length ?? 0) == 0 - ? AccessorTokens.Field - : AccessorTokens.Property; - } - get => _referenceQualifier; - } - - protected override void LoadFieldReferenceContextReplacements() + public override void LoadFieldReferenceContextReplacements() { if (TypeDeclarationIsPrivate) { - LoadPrivateUDTFieldReferenceExpressions(); + LoadPrivateUDTFieldLocalReferenceExpressions(); LoadUDTMemberReferenceExpressions(); return; } - base.LoadFieldReferenceContextReplacements(); + + foreach (var idRef in Declaration.References) + { + var replacementText = RequiresAccessQualification(idRef) + ? $"{QualifiedModuleName.ComponentName}.{PropertyName}" + : PropertyName; + + SetReferenceRewriteContent(idRef, replacementText); + } } public override IEnumerable PropertyAttributeSets @@ -131,19 +140,6 @@ public override IEnumerable PropertyAttributeSets } } - public override void StageFieldReferenceReplacements(IObjectStateUDT stateUDT = null) - { - - PropertyAccessor = stateUDT is null ? AccessorTokens.Field : AccessorTokens.Property; - ReferenceAccessor = AccessorTokens.Property; - ReferenceQualifier = stateUDT?.FieldIdentifier ?? null; - LoadFieldReferenceContextReplacements(); - foreach (var member in Members) - { - member.StageFieldReferenceReplacements(stateUDT); - } - } - public override IEnumerable> ReferenceReplacements { get @@ -207,7 +203,7 @@ public override bool TryValidateEncapsulationAttributes(out string errorMessage) return true; } - private void LoadPrivateUDTFieldReferenceExpressions() + private void LoadPrivateUDTFieldLocalReferenceExpressions() { foreach (var idRef in Declaration.References) { @@ -223,23 +219,7 @@ private void LoadUDTMemberReferenceExpressions() { foreach (var member in Members) { - foreach (var rf in member.FieldRelatedReferences(this)) - { - if (rf.QualifiedModuleName == QualifiedModuleName - && !rf.Context.TryGetAncestor(out _)) - { - member.SetReferenceRewriteContent(rf, member.PropertyName); - } - else - { - var moduleQualifier = rf.Context.TryGetAncestor(out _) - || rf.QualifiedModuleName == QualifiedModuleName - ? string.Empty - : $"{QualifiedModuleName.ComponentName}"; - - member.SetReferenceRewriteContent(rf, $"{moduleQualifier}.{member.PropertyName}"); - } - } + member.LoadReferenceExpressions(); } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs index 3d65961e79..ab3f50f9c4 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs @@ -14,49 +14,61 @@ public interface IUserDefinedTypeMemberCandidate : IEncapsulateFieldCandidate IUserDefinedTypeCandidate Parent { get; } IPropertyGeneratorAttributes AsPropertyGeneratorSpec { get; } Dictionary IdentifierReplacements { get; } - IEnumerable FieldRelatedReferences(IUserDefinedTypeCandidate field); + IEnumerable ParentContextReferences { get; } + void LoadReferenceExpressions(); } public class UserDefinedTypeMemberCandidate : IUserDefinedTypeMemberCandidate { private readonly IEncapsulateFieldNamesValidator _validator; private int _hashCode; - public UserDefinedTypeMemberCandidate(IEncapsulateFieldCandidate efd, IUserDefinedTypeCandidate udtVariable, IEncapsulateFieldNamesValidator validator) + private readonly string _uniqueID; + public UserDefinedTypeMemberCandidate(IEncapsulateFieldCandidate candidate, IUserDefinedTypeCandidate udtVariable, IEncapsulateFieldNamesValidator validator) { - _decoratedField = efd; + _wrappedCandidate = candidate; Parent = udtVariable; _validator = validator; PropertyName = IdentifierName; - PropertyAccessor = AccessorTokens.Property; - ReferenceAccessor = AccessorTokens.Property; - _hashCode = ($"{efd.QualifiedModuleName.Name}.{efd.IdentifierName}").GetHashCode(); + _uniqueID = BuildUniqueID(candidate); + _hashCode = _uniqueID.GetHashCode(); } - private IEncapsulateFieldCandidate _decoratedField; + private IEncapsulateFieldCandidate _wrappedCandidate; - public Selection Selection => _decoratedField.Selection; + public string AsTypeName => _wrappedCandidate.AsTypeName; - public Accessibility Accessibility => _decoratedField.Accessibility; + public IUserDefinedTypeCandidate Parent { private set; get; } - public string AsTypeName => _decoratedField.AsTypeName; + public void LoadFieldReferenceContextReplacements() { } - public IUserDefinedTypeCandidate Parent { private set; get; } + public string ReferenceQualifier { set; get; } + + public string TargetID => $"{Parent.IdentifierName}.{IdentifierName}"; - public void StageFieldReferenceReplacements(IObjectStateUDT stateUDT = null) { } + public IEnumerable ParentContextReferences + => GetUDTMemberReferencesForField(this, Parent); - private string _referenceQualifier; - public string ReferenceQualifier + public void LoadReferenceExpressions() { - set => _referenceQualifier = value; - get => Parent.ReferenceWithinNewProperty; - } + foreach (var rf in ParentContextReferences) + { + if (rf.QualifiedModuleName == QualifiedModuleName + && !rf.Context.TryGetAncestor(out _)) + { + SetReferenceRewriteContent(rf, PropertyName); + continue; + } + var moduleQualifier = rf.Context.TryGetAncestor(out _) + || rf.QualifiedModuleName == QualifiedModuleName + ? string.Empty + : $"{QualifiedModuleName.ComponentName}"; - public string TargetID => $"{Parent.IdentifierName}.{IdentifierName}"; + SetReferenceRewriteContent(rf, $"{moduleQualifier}.{PropertyName}"); + } + } - public IEnumerable FieldRelatedReferences(IUserDefinedTypeCandidate field) - => GetUDTMemberReferencesForField(this, field); - public void SetReferenceRewriteContent(IdentifierReference idRef, string replacementText) + protected void SetReferenceRewriteContent(IdentifierReference idRef, string replacementText) { Debug.Assert(idRef.Context.Parent is ParserRuleContext, "idRef.Context.Parent is not convertable to ParserRuleContext"); @@ -87,17 +99,18 @@ public IPropertyGeneratorAttributes AsPropertyGeneratorSpec public Dictionary IdentifierReplacements { get; } = new Dictionary(); - public override bool Equals(object obj) { return obj != null - && obj is IUserDefinedTypeMemberCandidate - && obj.GetHashCode() == GetHashCode(); + && obj is IUserDefinedTypeMemberCandidate udtMember + && BuildUniqueID(udtMember) == _uniqueID; } public override int GetHashCode() => _hashCode; - private IEnumerable GetUDTMemberReferencesForField(IEncapsulateFieldCandidate udtMember, IUserDefinedTypeCandidate field) + private static string BuildUniqueID(IEncapsulateFieldCandidate candidate) => $"{candidate.QualifiedModuleName.Name}.{candidate.IdentifierName}"; + + private static IEnumerable GetUDTMemberReferencesForField(IEncapsulateFieldCandidate udtMember, IUserDefinedTypeCandidate field) { var refs = new List(); foreach (var idRef in udtMember.Declaration.References) @@ -140,8 +153,8 @@ private IEnumerable GetUDTMemberReferencesForField(IEncapsu return refs; } - public Declaration Declaration => _decoratedField.Declaration; - public string IdentifierName => _decoratedField.IdentifierName; + public Declaration Declaration => _wrappedCandidate.Declaration; + public string IdentifierName => _wrappedCandidate.IdentifierName; public bool TryValidateEncapsulationAttributes(out string errorMessage) { @@ -151,72 +164,56 @@ public bool TryValidateEncapsulationAttributes(out string errorMessage) public bool IsReadOnly { - set => _decoratedField.IsReadOnly = value; - get => _decoratedField.IsReadOnly; + set => _wrappedCandidate.IsReadOnly = value; + get => _wrappedCandidate.IsReadOnly; } public bool EncapsulateFlag { - set => _decoratedField.EncapsulateFlag = value; - get => _decoratedField.EncapsulateFlag; + set => _wrappedCandidate.EncapsulateFlag = value; + get => _wrappedCandidate.EncapsulateFlag; } public string FieldIdentifier { - set => _decoratedField.FieldIdentifier = value; - get => _decoratedField.FieldIdentifier; + set => _wrappedCandidate.FieldIdentifier = value; + get => _wrappedCandidate.FieldIdentifier; } public bool CanBeReadWrite { - set => _decoratedField.CanBeReadWrite = value; - get => _decoratedField.CanBeReadWrite; + set => _wrappedCandidate.CanBeReadWrite = value; + get => _wrappedCandidate.CanBeReadWrite; } public bool HasValidEncapsulationAttributes => true; public QualifiedModuleName QualifiedModuleName - => _decoratedField.QualifiedModuleName; + => _wrappedCandidate.QualifiedModuleName; public string PropertyName { - set => _decoratedField.PropertyName = value; - get => _decoratedField.PropertyName; + set => _wrappedCandidate.PropertyName = value; + get => _wrappedCandidate.PropertyName; } public string AsTypeName_Field { - set => _decoratedField.AsTypeName_Field = value; - get => _decoratedField.AsTypeName_Field; + set => _wrappedCandidate.AsTypeName_Field = value; + get => _wrappedCandidate.AsTypeName_Field; } public string AsTypeName_Property { - set => _decoratedField.AsTypeName_Property = value; - get => _decoratedField.AsTypeName_Property; - } - public string ParameterName => _decoratedField.ParameterName; - public bool ImplementLet - { - set => _decoratedField.ImplementLet = value; - get => _decoratedField.ImplementLet; + set => _wrappedCandidate.AsTypeName_Property = value; + get => _wrappedCandidate.AsTypeName_Property; } - public bool ImplementSet - { - set => _decoratedField.ImplementSet = value; - get => _decoratedField.ImplementSet; - } - public IEnumerable PropertyAttributeSets => _decoratedField.PropertyAttributeSets; - public string AsUDTMemberDeclaration //{ get; } - => _decoratedField.AsUDTMemberDeclaration; // $"{_decoratedField.PropertyName} {Tokens.As} {_decoratedField.AsTypeName_Field}"; + public string ParameterName => _wrappedCandidate.ParameterName; - public IEnumerable> ReferenceReplacements => _decoratedField.ReferenceReplacements; - public string ReferenceWithinNewProperty => $"{Parent.ReferenceWithinNewProperty}.{_decoratedField.IdentifierName}"; + public bool ImplementLet => _wrappedCandidate.ImplementLet; - public AccessorTokens PropertyAccessor - { - set => _decoratedField.PropertyAccessor = value; - get => _decoratedField.PropertyAccessor; - } + public bool ImplementSet => _wrappedCandidate.ImplementSet; - public AccessorTokens ReferenceAccessor - { - set => _decoratedField.ReferenceAccessor = value; - get => _decoratedField.ReferenceAccessor; - } + public IEnumerable PropertyAttributeSets => _wrappedCandidate.PropertyAttributeSets; + public string AsUDTMemberDeclaration + => _wrappedCandidate.AsUDTMemberDeclaration; + + public IEnumerable> ReferenceReplacements => _wrappedCandidate.ReferenceReplacements; + + private string ReferenceWithinNewProperty => $"{ReferenceQualifier}.{_wrappedCandidate.IdentifierName}"; } } From 36d51f64e41aacd970276fd37e30982d7c302f81 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Fri, 27 Dec 2019 11:56:15 -0800 Subject: [PATCH 083/461] Added ObjectStateType selector --- .../EncapsulateFieldView.xaml | 19 ++- .../EncapsulateFieldViewModel.cs | 122 ++++++++++++++---- 2 files changed, 110 insertions(+), 31 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml index 8a36d8795e..559286a72d 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml @@ -57,14 +57,27 @@ - + + Width="200" + HorizontalAlignment="Left" + Margin="20,5,0,5" /> + + + @@ -216,7 +229,7 @@ IsReadOnly="True" IsTabStop="False" TabIndex="6" - Text="{Binding PropertyPreview,Mode=OneWay}" /> + Text="{Binding PropertiesPreview,Mode=OneWay}" /> diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs index 4028ffbc7f..ed1d816974 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs @@ -14,10 +14,19 @@ public class EncapsulateFieldViewModel : RefactoringViewModelBase _detailField; } - public string SelectionTargetID { set; get; } + private string _selectionTargetID; + public string SelectionTargetID + { + set => _selectionTargetID = value; + get => _selectionTargetID ?? _neverATargetID; + } public bool DetailUpdateRequired { @@ -52,7 +66,7 @@ public bool DetailUpdateRequired _detailFieldIsFlagged = !_detailFieldIsFlagged; return true; } - return SelectionTargetID != (DetailField?.TargetID ?? _neverATargeID); + return SelectionTargetID != DetailField?.TargetID; } } } @@ -60,7 +74,7 @@ public bool DetailUpdateRequired private MasterDetailSelectionManager _masterDetail; public RubberduckParserState State { get; } - public EncapsulateFieldViewModel(EncapsulateFieldModel model, RubberduckParserState state/*, IIndenter indenter*/) : base(model) + public EncapsulateFieldViewModel(EncapsulateFieldModel model, RubberduckParserState state) : base(model) { State = state; @@ -73,15 +87,10 @@ public EncapsulateFieldViewModel(EncapsulateFieldModel model, RubberduckParserSt ReadOnlyChangeCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ChangeIsReadOnlyFlag); _lastCheckedBoxes = EncapsulationFields.Where(ef => ef.EncapsulateFlag).ToList(); - var selectedField = model.SelectedFieldCandidates.FirstOrDefault(); - _masterDetail = new MasterDetailSelectionManager(selectedField.TargetID); - if (selectedField != null) - { - _masterDetail.DetailField = EncapsulationFields.Where(ef => ef.EncapsulateFlag).Single(); - } + _masterDetail = new MasterDetailSelectionManager(model.SelectedFieldCandidates.SingleOrDefault()); - ManageEncapsulationFlagsAndSelectedItem(selectedField); + ManageEncapsulationFlagsAndSelectedItem(); RefreshValidationResults(); } @@ -92,8 +101,8 @@ public ObservableCollection EncapsulationFields { var viewableFields = new ObservableCollection(); - var orderedFields = Model.EncapsulationCandidates - .OrderBy(efd => efd.Declaration.Selection); + var orderedFields = Model.EncapsulationCandidates.Where(ec => !(_selectedObjectStateUDT?.IsEncapsulateFieldCandidate(ec) ?? false)) + .OrderBy(efd => efd.Declaration.Selection).ToList(); foreach (var efd in orderedFields) { @@ -104,6 +113,58 @@ public ObservableCollection EncapsulationFields } } + public ObservableCollection UDTFields + { + get + { + var viewableFields = new ObservableCollection(); + + foreach (var state in Model.ObjectStateUDTCandidates) + { + viewableFields.Add(state); + } + return viewableFields; + } + } + + public bool ShowStateUDTSelections + { + get + { + return Model.ObjectStateUDTCandidates.Count() > 1 + && EncapsulateAsUDT; + } + } + + private IObjectStateUDT _selectedObjectStateUDT; + public IObjectStateUDT SelectedObjectStateUDT + { + get + { + _selectedObjectStateUDT = UDTFields.Where(f => f.IsSelected) + .SingleOrDefault() ?? UDTFields.FirstOrDefault(); + return _selectedObjectStateUDT; + } + set + { + _selectedObjectStateUDT = value; + Model.StateUDTField = _selectedObjectStateUDT; + SetObjectStateUDT(); + } + } + + private void SetObjectStateUDT() + { + foreach (var field in UDTFields) + { + field.IsSelected = _selectedObjectStateUDT == field; + } + OnPropertyChanged(nameof(SelectedObjectStateUDT)); + OnPropertyChanged(nameof(EncapsulationFields)); + OnPropertyChanged(nameof(PropertiesPreview)); + } + + public IEncapsulatedFieldViewData SelectedField { set @@ -118,10 +179,10 @@ public IEncapsulatedFieldViewData SelectedField UpdateDetailForSelection(); } - OnPropertyChanged(nameof(PropertyPreview)); + OnPropertyChanged(nameof(PropertiesPreview)); } - get => EncapsulationFields.FirstOrDefault(f => f.TargetID.Equals(_masterDetail.SelectionTargetID)); // _selectedField; + get => EncapsulationFields.FirstOrDefault(f => f.TargetID.Equals(_masterDetail.SelectionTargetID)); } private void UpdateDetailForSelection() @@ -138,7 +199,7 @@ private void UpdateDetailForSelection() OnPropertyChanged(nameof(SelectedFieldIsPrivateUDT)); OnPropertyChanged(nameof(SelectedFieldHasEditablePropertyName)); OnPropertyChanged(nameof(SelectionHasValidEncapsulationAttributes)); - OnPropertyChanged(nameof(PropertyPreview)); + OnPropertyChanged(nameof(PropertiesPreview)); OnPropertyChanged(nameof(EncapsulationFields)); OnPropertyChanged(nameof(ValidationErrorMessage)); } @@ -153,7 +214,7 @@ public string PropertyName UpdateDetailForSelection(); } - get => _masterDetail.DetailField?.PropertyName ?? SelectedField?.PropertyName ?? string.Empty; // _propertyName; + get => _masterDetail.DetailField?.PropertyName ?? SelectedField?.PropertyName ?? string.Empty; } public bool SelectedFieldIsNotFlagged @@ -199,7 +260,6 @@ public bool IsReadOnly set { _masterDetail.DetailField.IsReadOnly = value; - OnPropertyChanged(nameof(IsReadOnly)); } get => _masterDetail.DetailField?.IsReadOnly ?? SelectedField?.IsReadOnly ?? false; } @@ -210,7 +270,9 @@ public bool EncapsulateAsUDT set { Model.EncapsulateWithUDT = value; - OnPropertyChanged(nameof(PropertyPreview)); + OnPropertyChanged(nameof(EncapsulationFields)); + OnPropertyChanged(nameof(ShowStateUDTSelections)); + OnPropertyChanged(nameof(PropertiesPreview)); } } @@ -244,7 +306,7 @@ private void RefreshValidationResults() } } - public string PropertyPreview => Model.PreviewRefactoring(); + public string PropertiesPreview => Model.PreviewRefactoring(); public CommandBase SelectAllCommand { get; } public CommandBase DeselectAllCommand { get; } @@ -290,18 +352,17 @@ public string TitleText public string PrivateUDTPropertyText => EncapsulateFieldResources.PrivateUDTPropertyText; - private void ChangeIsReadOnlyFlag(object param) { if (SelectedField is null) { return; } _masterDetail.DetailField.IsReadOnly = SelectedField.IsReadOnly; OnPropertyChanged(nameof(IsReadOnly)); - OnPropertyChanged(nameof(PropertyPreview)); + OnPropertyChanged(nameof(PropertiesPreview)); } private List _lastCheckedBoxes = new List(); - private void ManageEncapsulationFlagsAndSelectedItem(object param) + private void ManageEncapsulationFlagsAndSelectedItem(object param = null) { var selected = _lastCheckedBoxes.FirstOrDefault(); if (_lastCheckedBoxes.Count == EncapsulationFields.Where(f => f.EncapsulateFlag).Count()) @@ -313,7 +374,7 @@ private void ManageEncapsulationFlagsAndSelectedItem(object param) var beforeChecked = _lastCheckedBoxes.ToList(); nowChecked.RemoveAll(c => _lastCheckedBoxes.Contains(c)); - beforeChecked.RemoveAll(c => EncapsulationFields.Where(ec => ec.EncapsulateFlag).Select(nc => nc).Contains(c)); //.TargetID)); + beforeChecked.RemoveAll(c => EncapsulationFields.Where(ec => ec.EncapsulateFlag).Select(nc => nc).Contains(c)); if (nowChecked.Any()) { selected = nowChecked.First(); @@ -322,9 +383,14 @@ private void ManageEncapsulationFlagsAndSelectedItem(object param) { selected = beforeChecked.First(); } + else + { + selected = null; + } + _lastCheckedBoxes = EncapsulationFields.Where(ef => ef.EncapsulateFlag).ToList(); - _masterDetail.SelectionTargetID = selected.TargetID; + _masterDetail.SelectionTargetID = selected?.TargetID ?? null; OnPropertyChanged(nameof(SelectedField)); if (_masterDetail.DetailUpdateRequired) { @@ -334,12 +400,12 @@ private void ManageEncapsulationFlagsAndSelectedItem(object param) } private void UpdatePreview() - => OnPropertyChanged(nameof(PropertyPreview)); + => OnPropertyChanged(nameof(PropertiesPreview)); private void ReloadListAndPreview() { OnPropertyChanged(nameof(EncapsulationFields)); - OnPropertyChanged(nameof(PropertyPreview)); + OnPropertyChanged(nameof(PropertiesPreview)); } } } \ No newline at end of file From b55e23a2ff963f07f3d7531980f0cd31cb8907d6 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Fri, 27 Dec 2019 11:59:59 -0800 Subject: [PATCH 084/461] Improvements to ObjectStateUDT handling Supports selection of an existing UDT to wrap fields. Provide some logic to establish re-use of a previously created objectStateUDT if the user adds more fields after the initial encapsulation process. --- .../EncapsulateFieldElementFactory.cs | 5 + .../EncapsulateField/EncapsulateFieldModel.cs | 37 +++--- .../EncapsulateFieldRefactoring.cs | 38 +++++- .../FieldCandidates/ArrayCandidate.cs | 2 +- .../EncapsulateFieldCandidate.cs | 7 +- .../FieldCandidates/ObjectStateUDT.cs | 46 +++++++- .../UserDefinedTypeCandidate.cs | 30 ++++- .../EncapsulateField/PropertyGenerator.cs | 12 +- .../EncapsulateField/EncapsulateFieldTests.cs | 4 + .../EncapsulateFieldValidatorTests.cs | 5 +- .../EncapsulateUsingStateUDTTests.cs | 110 ++++++++++++++++-- .../EncapsulatedUDTFieldTests.cs | 1 + .../EncapsulateField/TestSupport.cs | 29 ++--- 13 files changed, 257 insertions(+), 69 deletions(-) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs index bcbfe7d8b4..84a4fc3d0d 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs @@ -52,6 +52,11 @@ public IEncapsulateFieldCandidate CreateEncapsulationCandidate(Declaration targe udtVariable.AddMember(candidateUDTMember); } + + var udtVariablesOfSameType = _declarationFinderProvider.DeclarationFinder.UserDeclarations(DeclarationType.Variable) + .Where(v => v.AsTypeDeclaration == udtDeclaration); + + udtVariable.CanBeObjectStateUDT = udtVariable.TypeDeclarationIsPrivate && udtVariablesOfSameType.Count() == 1; } _validator.RegisterFieldCandidate(candidate); diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index bd51f4edd6..b5d59320b6 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using Rubberduck.Parsing.Symbols; +using Rubberduck.Refactorings.EncapsulateField.Extensions; using Rubberduck.VBEditor; namespace Rubberduck.Refactorings.EncapsulateField @@ -23,7 +24,7 @@ public EncapsulateFieldModel(Declaration target, IEnumerable EncapsulationCandidates { set; get; } = new List(); @@ -49,33 +50,29 @@ public IEncapsulateFieldCandidate this[Declaration fieldDeclaration] public bool EncapsulateWithUDT { set; get; } - private IObjectStateUDT _stateUDTField; - public IObjectStateUDT StateUDTField + public IObjectStateUDT StateUDTField { set; get; } + + public string PreviewRefactoring() => _previewDelegate(this); + + private List _objStateCandidates; + public IEnumerable ObjectStateUDTCandidates { - set - { - _stateUDTField = value; - } get { - if (!EncapsulateWithUDT) { return null; } - - if (_stateUDTField != null) + if (_objStateCandidates != null) { - return _stateUDTField; + return _objStateCandidates; } - var selectedStateUDT = EncapsulationCandidates.Where(sfc => sfc is IUserDefinedTypeCandidate udt - && udt.IsObjectStateUDT).Select(sfc => sfc as IUserDefinedTypeCandidate).FirstOrDefault(); - - _stateUDTField = selectedStateUDT != null - ? new ObjectStateUDT(selectedStateUDT) - : _newObjectStateUDT; + _objStateCandidates = new List(); + foreach (var candidate in UDTFieldCandidates.Where(udt => udt.CanBeObjectStateUDT)) + { + _objStateCandidates.Add(new ObjectStateUDT(candidate)); + } - return _stateUDTField; + _objStateCandidates.Add(_newObjectStateUDT); + return _objStateCandidates; } } - - public string PreviewRefactoring() => _previewDelegate(this); } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index c3cdb482ab..3cd95efa27 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -92,10 +92,18 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) var selected = candidates.Single(c => c.Declaration == target); selected.EncapsulateFlag = true; + //var newObjectStateUDT = _encapsulationCandidateFactory.CreateStateUDTField(); + + if (!TryRetrieveExistingObjectStateUDT(target, candidates, out var objectStateUDT)) + { + objectStateUDT = _encapsulationCandidateFactory.CreateStateUDTField(); + objectStateUDT.IsSelected = true; + } + Model = new EncapsulateFieldModel( target, candidates, - _encapsulationCandidateFactory.CreateStateUDTField(), + objectStateUDT, PreviewRewrite, validator); @@ -107,6 +115,34 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) return Model; } + //Identify an existing objectStateUDT and make it unavailable for the user to select for encapsulation. + //This prevents the user from inadvertently nesting a stateUDT within a new stateUDT + private bool TryRetrieveExistingObjectStateUDT(Declaration target, IEnumerable candidates, out IObjectStateUDT objectStateUDT) + { + objectStateUDT = null; + //Determination relies on matching the refactoring-generated name and a couple other UDT attributes + //to determine if an objectStateUDT pre-exists the refactoring. + + //Question: would using an Annotations (like '@IsObjectStateUDT) be better? + //The logic would then be: if Annotated => it's the one. else => apply the matching criteria below + + //e.g., In cases where the user chooses an existing UDT for the initial encapsulation, the matching + //refactoring will not assign the name and the criteria below will fail => so applying an Annotation would + //make it possible to find again + var objectStateUDTIdentifier = $"{EncapsulateFieldResources.StateUserDefinedTypeIdentifierPrefix}{target.QualifiedModuleName.ComponentName}"; + + var objectStateUDTMatches = candidates.Where(c => c is IUserDefinedTypeCandidate udt + && udt.Declaration.HasPrivateAccessibility() + && udt.Declaration.AsTypeDeclaration.IdentifierName.StartsWith(objectStateUDTIdentifier, StringComparison.InvariantCultureIgnoreCase)) + .Select(pm => pm as IUserDefinedTypeCandidate); + + if (objectStateUDTMatches.Count() == 1) + { + objectStateUDT = new ObjectStateUDT(objectStateUDTMatches.First()) { IsSelected = true }; + } + return objectStateUDT != null; + } + protected override void RefactorImpl(EncapsulateFieldModel model) { var refactorRewriteSession = new EncapsulateFieldRewriteSession(RewritingManager.CheckOutCodePaneSession()) as IEncapsulateFieldRewriteSession; diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs index 7ade824cce..82bca5d805 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs @@ -35,7 +35,7 @@ public override void LoadFieldReferenceContextReplacements() { var replacementText = RequiresAccessQualification(idRef) ? $"{QualifiedModuleName.ComponentName}.{ReferenceForPreExistingReferences}" - : FieldIdentifier; + : ReferenceForPreExistingReferences; SetReferenceRewriteContent(idRef, replacementText); } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs index 4f5a8470b0..ae0ca97d46 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs @@ -205,8 +205,8 @@ public virtual string PropertyName public override bool Equals(object obj) { return obj != null - && obj is IEncapsulateFieldCandidate - && obj.GetHashCode() == GetHashCode(); + && obj is IEncapsulateFieldCandidate efc + && $"{efc.QualifiedModuleName.Name}.{efc.TargetID}" == $"{_qmn.Name}.{IdentifierName}"; } public override int GetHashCode() => _hashCode; @@ -309,7 +309,8 @@ protected virtual IPropertyGeneratorAttributes AsPropertyAttributeSet ParameterName = ParameterName, GenerateLetter = ImplementLet, GenerateSetter = ImplementSet, - UsesSetAssignment = Declaration.IsObject + UsesSetAssignment = Declaration.IsObject, + IsUDTProperty = false }; } } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs index 649b528c7d..317abdadfe 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs @@ -20,6 +20,8 @@ public interface IObjectStateUDT : IEncapsulateFieldDeclaration void AddMembers(IEnumerable fields); bool IsExistingDeclaration { get; } Declaration AsTypeDeclaration { get; } + bool IsSelected { set; get; } + bool IsEncapsulateFieldCandidate(IEncapsulateFieldCandidate efc); } //ObjectStateUDT can be an existing UDT (Private only) selected by the user, or a @@ -29,17 +31,20 @@ public class ObjectStateUDT : IObjectStateUDT private static string _defaultNewFieldName = EncapsulateFieldResources.DefaultStateUDTFieldName; private List _members; private readonly IUserDefinedTypeCandidate _wrappedUDT; + private int _hashCode; public ObjectStateUDT(IUserDefinedTypeCandidate udt) - :this(udt.Declaration.AsTypeName) + : this(udt.Declaration.AsTypeName) { - if (!udt.Declaration.Accessibility.Equals(Accessibility.Private)) + if (!udt.TypeDeclarationIsPrivate) { throw new ArgumentException(); } + FieldIdentifier = udt.IdentifierName; _wrappedUDT = udt; - QualifiedModuleName = udt.Declaration.QualifiedModuleName; + udt.EncapsulateFlag = false; + _hashCode = ($"{_qmn.Name}.{_wrappedUDT.IdentifierName}").GetHashCode(); } public ObjectStateUDT(QualifiedModuleName qmn) @@ -59,13 +64,20 @@ private ObjectStateUDT(string typeIdentifier) public string AsTypeName => _wrappedUDT?.AsTypeName ?? TypeIdentifier; - public QualifiedModuleName QualifiedModuleName { set; get; } + public bool IsSelected { set; get; } + + private QualifiedModuleName _qmn; + public QualifiedModuleName QualifiedModuleName + { + set => _qmn = value; + get => _wrappedUDT?.QualifiedModuleName ?? _qmn; + } public string TypeIdentifier { set; get; } public bool IsExistingDeclaration => _wrappedUDT != null; - public Declaration AsTypeDeclaration => _wrappedUDT.Declaration.AsTypeDeclaration; + public Declaration AsTypeDeclaration => _wrappedUDT?.Declaration.AsTypeDeclaration; public string FieldIdentifier { set; get; } @@ -90,6 +102,30 @@ public string TypeDeclarationBlock(IIndenter indenter = null) return string.Join(Environment.NewLine, BlockLines(Accessibility.Private)); } + public override bool Equals(object obj) + { + if (obj is IObjectStateUDT stateUDT && stateUDT.FieldIdentifier == FieldIdentifier) + { + return true; + } + if (obj is IEncapsulateFieldDeclaration fd && fd.IdentifierName == IdentifierName) + { + return true; + } + return false; + } + + public bool IsEncapsulateFieldCandidate(IEncapsulateFieldCandidate efc) + { + if (efc is IEncapsulateFieldDeclaration fd && fd.IdentifierName == IdentifierName) + { + return true; + } + return false; + } + + public override int GetHashCode() => _hashCode; + private IEnumerable BlockLines(Accessibility accessibility) { var blockLines = new List(); diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs index 5e7662a7d2..a8d358552a 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs @@ -14,7 +14,7 @@ public interface IUserDefinedTypeCandidate : IEncapsulateFieldCandidate IEnumerable Members { get; } void AddMember(IUserDefinedTypeMemberCandidate member); bool TypeDeclarationIsPrivate { set; get; } - bool IsObjectStateUDT { set; get; } + bool CanBeObjectStateUDT { set; get; } } public class UserDefinedTypeCandidate : EncapsulateFieldCandidate, IUserDefinedTypeCandidate @@ -36,11 +36,11 @@ public void AddMember(IUserDefinedTypeMemberCandidate member) public bool TypeDeclarationIsPrivate { set; get; } - private bool _isObjectStateUDT; - public bool IsObjectStateUDT + private bool _canBeObjectStateUDT; + public bool CanBeObjectStateUDT { - set => _isObjectStateUDT = value; - get => _isObjectStateUDT; + set => _canBeObjectStateUDT = value; + get => _canBeObjectStateUDT; } public override string FieldIdentifier @@ -101,7 +101,7 @@ public override bool EncapsulateFlag } base.EncapsulateFlag = value; } - get => _encapsulateFlag && !_isObjectStateUDT; + get => _encapsulateFlag; // && !_isObjectStateUDT; } public override void LoadFieldReferenceContextReplacements() @@ -203,6 +203,24 @@ public override bool TryValidateEncapsulationAttributes(out string errorMessage) return true; } + protected override IPropertyGeneratorAttributes AsPropertyAttributeSet + { + get + { + return new PropertyAttributeSet() + { + PropertyName = PropertyName, + BackingField = ReferenceWithinNewProperty, + AsTypeName = AsTypeName_Property, + ParameterName = ParameterName, + GenerateLetter = ImplementLet, + GenerateSetter = ImplementSet, + UsesSetAssignment = Declaration.IsObject, + IsUDTProperty = true + }; + } + } + private void LoadPrivateUDTFieldLocalReferenceExpressions() { foreach (var idRef in Declaration.References) diff --git a/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs b/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs index 115613b376..9ec76cf3d9 100644 --- a/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs @@ -1,4 +1,5 @@ -using Rubberduck.SmartIndenter; +using Rubberduck.Parsing.Grammar; +using Rubberduck.SmartIndenter; using System; using System.Collections.Generic; @@ -13,6 +14,7 @@ public interface IPropertyGeneratorAttributes bool GenerateLetter { get; } bool GenerateSetter { get; } bool UsesSetAssignment { get; } + bool IsUDTProperty { get; } } public class PropertyAttributeSet : IPropertyGeneratorAttributes @@ -24,6 +26,7 @@ public class PropertyAttributeSet : IPropertyGeneratorAttributes public bool GenerateLetter { get; set; } public bool GenerateSetter { get; set; } public bool UsesSetAssignment { get; set; } + public bool IsUDTProperty { get; set; } } public class PropertyGenerator @@ -37,6 +40,7 @@ public PropertyGenerator() { } public bool GenerateLetter { get; set; } public bool GenerateSetter { get; set; } public bool UsesSetAssignment { get; set; } + public bool IsUDTProperty { get; set; } public string AsPropertyBlock(IPropertyGeneratorAttributes spec, IIndenter indenter) { @@ -47,6 +51,7 @@ public string AsPropertyBlock(IPropertyGeneratorAttributes spec, IIndenter inden GenerateLetter = spec.GenerateLetter; GenerateSetter = spec.GenerateSetter; UsesSetAssignment = spec.UsesSetAssignment; + IsUDTProperty = spec.IsUDTProperty; return string.Join(Environment.NewLine, indenter.Indent(AsLines, true)); } @@ -104,8 +109,11 @@ private string LetterCode { return string.Empty; } + + var byVal_byRef = IsUDTProperty ? Tokens.ByRef : Tokens.ByVal; + return string.Join(Environment.NewLine, - $"Public Property Let {PropertyName}(ByVal {ParameterName} As {AsTypeName})", + $"Public Property Let {PropertyName}({byVal_byRef} {ParameterName} As {AsTypeName})", $" {BackingField} = {ParameterName}", "End Property", Environment.NewLine); diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs index d4c00e3c8f..eb63a13851 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs @@ -744,7 +744,11 @@ End Property Assert.AreEqual(expectedCode.Trim(), actualCode); } + //Consider... + //https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/can-t-redim-erase-or-assign-to-variant-that-contains-array-whose-element-is-with + //https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/constants-fixed-length-strings-arrays-user-defined-types-and-declare-statements [Test] + [Ignore("Resolve use of Redim locally and externally")] [Category("Refactorings")] [Category("Encapsulate Field")] public void EncapsulateArray_Redim() diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs index 1303135a30..c508e3452f 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs @@ -161,6 +161,7 @@ End Property Assert.IsFalse(model["fizz"].TryValidateEncapsulationAttributes(out _)); } + [TestCase("Number", "Bazzle", true, true)] [TestCase("Number", "Number", false, false)] [TestCase("Test", "Number", false, true)] @@ -438,7 +439,7 @@ End Type var userInput = new UserInputDataObject() .UserSelectsField(fieldUT); - userInput.EncapsulateAsUDT = true; + userInput.EncapsulateUsingUDTField(); var presenterAction = Support.SetParameters(userInput); @@ -481,7 +482,7 @@ Public mF|oo As Long var userInput = new UserInputDataObject() .UserSelectsField(fieldUT); - userInput.EncapsulateAsUDT = true; + userInput.EncapsulateUsingUDTField(); var presenterAction = Support.SetParameters(userInput); diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs index 000e6a5c4b..8725954304 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs @@ -1,5 +1,6 @@ using NUnit.Framework; using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings; using Rubberduck.Refactorings.EncapsulateField; @@ -75,7 +76,7 @@ End Type var userInput = new UserInputDataObject() .UserSelectsField("myBar"); - userInput.EncapsulateAsUDT = true; + userInput.EncapsulateUsingUDTField(); var presenterAction = Support.SetParameters(userInput); @@ -110,7 +111,7 @@ Public Sub Foo(newValue As String) var userInput = new UserInputDataObject() .UserSelectsField("myBar"); - userInput.EncapsulateAsUDT = true; + userInput.EncapsulateUsingUDTField(); var presenterAction = Support.SetParameters(userInput); @@ -142,8 +143,8 @@ Public foobar As Byte .UserSelectsField("bar") .UserSelectsField("foobar"); - userInput.EncapsulateAsUDT = true; - userInput.ObjectStateUDTTargetID = "myBar"; + userInput.EncapsulateUsingUDTField("myBar"); + //userInput.ObjectStateUDTTargetID = "myBar"; var presenterAction = Support.SetParameters(userInput); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); @@ -178,7 +179,7 @@ Public foobar As Byte .UserSelectsField("bar") .UserSelectsField("foobar"); - userInput.EncapsulateAsUDT = true; + userInput.EncapsulateUsingUDTField(); var presenterAction = Support.SetParameters(userInput); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); @@ -209,7 +210,7 @@ Public myBar As TBar var userInput = new UserInputDataObject() .UserSelectsField("myBar"); - userInput.EncapsulateAsUDT = true; + userInput.EncapsulateUsingUDTField(); var presenterAction = Support.SetParameters(userInput); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); @@ -222,6 +223,35 @@ Public myBar As TBar Assert.AreEqual(index, indexLast); } + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedType_MultipleFieldsOfSameUDT() + { + string inputCode = +$@" + +Private Type TBar + First As Long + Second As String +End Type + +Public fooBar As TBar +Public myBar As TBar +"; + + var userInput = new UserInputDataObject() + .UserSelectsField("myBar"); + + userInput.EncapsulateUsingUDTField(); + + var presenterAction = Support.SetParameters(userInput); + var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, "myBar", DeclarationType.Variable, presenterAction); + + Assert.AreEqual(1, model.ObjectStateUDTCandidates.Count()); + } + [Test] [Category("Refactorings")] [Category("Encapsulate Field")] @@ -242,7 +272,7 @@ Public numberT|ype As NumberTypes var userInput = new UserInputDataObject() .UserSelectsField("numberType"); - userInput.EncapsulateAsUDT = true; + userInput.EncapsulateUsingUDTField(); var presenterAction = Support.SetParameters(userInput); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); @@ -267,12 +297,43 @@ public void UserDefinedType_BoundedArrayField(string arrayIdentifier, string dim var userInput = new UserInputDataObject() .UserSelectsField(arrayIdentifier); - userInput.EncapsulateAsUDT = true; + userInput.EncapsulateUsingUDTField(); + + var presenterAction = Support.SetParameters(userInput); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.Contains("Property Get AnArray() As Variant", actualCode); + StringAssert.Contains("AnArray = this.AnArray", actualCode); + StringAssert.Contains($" AnArray({dimensions}) As String", actualCode); + } + + [TestCase("anArray", "5")] + [TestCase("anArray", "1 To 100")] + [TestCase("anArray", "")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserDefinedType_LocallyReferencedArray(string arrayIdentifier, string dimensions) + { + var selectedInput = arrayIdentifier.Replace("n", "n|"); + string inputCode = +$@" +Public {selectedInput}({dimensions}) As String + +Public Property Get AnArrayTest() As Variant + AnArrayTest = anArray +End Property + +"; + + var userInput = new UserInputDataObject() + .UserSelectsField(arrayIdentifier); + + userInput.EncapsulateUsingUDTField(); var presenterAction = Support.SetParameters(userInput); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.Contains("Property Get AnArray() As Variant", actualCode); StringAssert.Contains("AnArray = this.AnArray", actualCode); + StringAssert.Contains("AnArrayTest = this.AnArray", actualCode); StringAssert.Contains($" AnArray({dimensions}) As String", actualCode); } @@ -303,13 +364,44 @@ Public myBar As TBar .UserSelectsField("myBar"); - userInput.EncapsulateAsUDT = true; + userInput.EncapsulateUsingUDTField(); var presenterAction = Support.SetParameters(userInput); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.Contains($"Private Type {expectedIdentifier}", actualCode); } + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void StateObjectCandidatesContent() + { + string inputCode = +$@" +Private Type TBar + First As String + Second As Long +End Type + +Public mFoo As String +Public mBar As Long +Private mFizz + +Public myBar As TBar"; + + var userInput = new UserInputDataObject() + .UserSelectsField("mFizz"); + + userInput.EncapsulateUsingUDTField(); + + var presenterAction = Support.SetParameters(userInput); + + var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, "mFizz", DeclarationType.Variable, presenterAction); + var test = model.ObjectStateUDTCandidates; + + Assert.AreEqual(2, model.ObjectStateUDTCandidates.Count()); + } protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) { diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs index 4cb52eece0..bf03393ea2 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs @@ -472,6 +472,7 @@ End Type StringAssert.DoesNotContain($"this.First = value", actualCode); StringAssert.DoesNotContain($"this.Second = value", actualCode); StringAssert.DoesNotContain($"Second = Second", actualCode); + StringAssert.Contains($"Public Property Let MyType(ByRef value As TBar", actualCode); } } diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index 6e119f9593..5d00aea6a7 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -67,12 +67,13 @@ public Func SetParameters(UserInpu model.EncapsulateWithUDT = userInput.EncapsulateAsUDT; if (userInput.EncapsulateAsUDT) { - var stateUDT = model.SelectedFieldCandidates.Where(sfc => sfc is IUserDefinedTypeCandidate udt && udt.TargetID == userInput.ObjectStateUDTTargetID) + var stateUDT = model.EncapsulationCandidates.Where(sfc => sfc is IUserDefinedTypeCandidate udt && udt.TargetID == userInput.ObjectStateUDTTargetID) .Select(sfc => sfc as IUserDefinedTypeCandidate).SingleOrDefault(); if (stateUDT != null) { - stateUDT.IsObjectStateUDT = userInput.ObjectStateUDTTargetID != null; + stateUDT.EncapsulateFlag = false; model.StateUDTField = new ObjectStateUDT(stateUDT); + model.StateUDTField.IsSelected = true; } } @@ -206,21 +207,8 @@ public class UserInputDataObject public UserInputDataObject() { } - //public UserInputDataObject(string fieldName, string propertyName = null, /*bool encapsulationFlag = true,*/ bool isReadOnly = false) - // : this() - //{ - // UserSelectsField(fieldName, propertyName/*, encapsulationFlag*/, isReadOnly); - //} - public UserInputDataObject UserSelectsField(string fieldName, string propertyName = null/*, bool encapsulationFlag = true*/, bool isReadOnly = false) { - //var attrs = new TestEncapsulationAttributes(fieldName, true, isReadOnly); - //attrs.PropertyName = propertyName ?? attrs.PropertyName; - //attrs.EncapsulateFlag = true; - //attrs.IsReadOnly = isReadOnly; - - //_userInput.Add(attrs); - //return this; return AddUserInputSet(fieldName, propertyName, true, isReadOnly); } @@ -237,6 +225,12 @@ public UserInputDataObject AddUserInputSet(string fieldName, string propertyName public bool EncapsulateAsUDT { set; get; } + public void EncapsulateUsingUDTField(string targetID = null) + { + ObjectStateUDTTargetID = targetID; + EncapsulateAsUDT = true; + } + public string ObjectStateUDTTargetID { set; get; } public string StateUDT_TypeName { set; get; } @@ -247,10 +241,5 @@ public TestEncapsulationAttributes this[string fieldName] => EncapsulateFieldAttributes.Where(efa => efa.TargetFieldName == fieldName).Single(); public IEnumerable EncapsulateFieldAttributes => _userInput; - - //public void AddUDTMemberNameFlagPairs(params (string, string, bool)[] nameFlagPairs) - // => _udtNameFlagPairs.AddRange(nameFlagPairs); - - //public IEnumerable<(string, string, bool)> UDTMemberNameFlagPairs => _udtNameFlagPairs; } } From 42a7bab304cf5d61d0f6ad2777e97b8cea74a996 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Sun, 29 Dec 2019 11:35:09 -0800 Subject: [PATCH 085/461] Improved UDTMember validations --- .../EncapsulateFieldView.xaml | 40 ++++----- .../EncapsulateFieldViewModel.cs | 14 ++-- .../ViewableEncapsulatedField.cs | 9 +- .../Common/VBAIdentifierValidator.cs | 31 +++++-- .../EncapsulateFieldElementFactory.cs | 57 ++++++------- .../EncapsulateField/EncapsulateFieldModel.cs | 18 +++- .../EncapsulateFieldRefactoring.cs | 10 +-- .../EncapsulateFieldValidator.cs | 45 +++++----- .../FieldCandidates/ArrayCandidate.cs | 31 ++++++- .../EncapsulateFieldCandidate.cs | 82 +++++++++++++------ .../EncapsulationIdentifiers.cs | 31 ++++--- .../UserDefinedTypeCandidate.cs | 4 +- .../UserDefinedTypeMemberCandidate.cs | 6 +- .../EncapsulateField/EncapsulateFieldTests.cs | 2 +- .../EncapsulateFieldValidatorTests.cs | 20 +++++ .../EncapsulatedUDTFieldTests.cs | 4 +- .../EncapsulationIdentifiersTests.cs | 2 +- .../EncapsulateField/TestSupport.cs | 12 +-- .../VBAIdentifierValidatorTests.cs | 17 ++++ 19 files changed, 271 insertions(+), 164 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml index 559286a72d..2faec19ce8 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml @@ -58,26 +58,26 @@ - - - - + + + + diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs index ed1d816974..8c1de0b96e 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs @@ -132,7 +132,7 @@ public bool ShowStateUDTSelections get { return Model.ObjectStateUDTCandidates.Count() > 1 - && EncapsulateAsUDT; + && ConvertFieldsToUDTMembers; } } @@ -264,15 +264,15 @@ public bool IsReadOnly get => _masterDetail.DetailField?.IsReadOnly ?? SelectedField?.IsReadOnly ?? false; } - public bool EncapsulateAsUDT + public bool ConvertFieldsToUDTMembers { - get => Model.EncapsulateWithUDT; + get => Model.ConvertFieldsToUDTMembers; set { - Model.EncapsulateWithUDT = value; - OnPropertyChanged(nameof(EncapsulationFields)); - OnPropertyChanged(nameof(ShowStateUDTSelections)); - OnPropertyChanged(nameof(PropertiesPreview)); + Model.ConvertFieldsToUDTMembers = value; + ReloadListAndPreview(); + RefreshValidationResults(); + UpdateDetailForSelection(); } } diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs index fc4eee5825..4ba5ffda69 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs @@ -1,11 +1,4 @@ -using Rubberduck.Parsing.Symbols; -using Rubberduck.Refactorings.EncapsulateField; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; +using Rubberduck.Refactorings.EncapsulateField; namespace Rubberduck.UI.Refactorings.EncapsulateField { diff --git a/Rubberduck.Refactorings/Common/VBAIdentifierValidator.cs b/Rubberduck.Refactorings/Common/VBAIdentifierValidator.cs index d5c64a8c77..bb10db53f4 100644 --- a/Rubberduck.Refactorings/Common/VBAIdentifierValidator.cs +++ b/Rubberduck.Refactorings/Common/VBAIdentifierValidator.cs @@ -68,14 +68,14 @@ bool IsTooShort() /// /// Predicate function determining if an identifier string conforms to MS-VBAL naming requirements /// - public static bool IsValidIdentifier(string name, DeclarationType declarationType) - => !TryMatchInvalidIdentifierCriteria(name, declarationType, out _); + public static bool IsValidIdentifier(string name, DeclarationType declarationType, bool isArrayDeclaration = false) + => !TryMatchInvalidIdentifierCriteria(name, declarationType, out _, isArrayDeclaration); /// /// Evaluates an identifier string's conformance with MS-VBAL naming requirements. /// /// Message for first matching invalid identifier criteria. Or, an empty string if the identifier is valid - public static bool TryMatchInvalidIdentifierCriteria(string name, DeclarationType declarationType, out string criteriaMatchMessage) + public static bool TryMatchInvalidIdentifierCriteria(string name, DeclarationType declarationType, out string criteriaMatchMessage, bool isArrayDeclaration = false) { criteriaMatchMessage = string.Empty; @@ -103,11 +103,28 @@ public static bool TryMatchInvalidIdentifierCriteria(string name, DeclarationTyp } //Is a reserved identifier - if (!declarationType.HasFlag(DeclarationType.UserDefinedTypeMember) - && ReservedIdentifiers.Contains(name, StringComparer.InvariantCultureIgnoreCase)) + if (!declarationType.HasFlag(DeclarationType.UserDefinedTypeMember)) { - criteriaMatchMessage = string.Format(RubberduckUI.InvalidNameCriteria_IsReservedKeywordFormat, name); - return true; + if (ReservedIdentifiers.Contains(name, StringComparer.InvariantCultureIgnoreCase)) + { + criteriaMatchMessage = string.Format(RubberduckUI.InvalidNameCriteria_IsReservedKeywordFormat, name); + return true; + } + } + else if (isArrayDeclaration) //is a DeclarationType.UserDefinedTypeMember + { + //DeclarationType.UserDefinedTypeMember can have reserved identifier keywords + //...unless the declaration is an array. Adding the parentheses causes errors. + + //Name is not a reserved identifier, but when used as a UDTMember array declaration + //it collides with the 'Name' Statement (Renames a disk file, directory, or folder) + var invalidUDTArrayIdentifiers = ReservedIdentifiers.Concat(new List() { "Name" }); + + if (invalidUDTArrayIdentifiers.Contains(name, StringComparer.InvariantCultureIgnoreCase)) + { + criteriaMatchMessage = string.Format(RubberduckUI.InvalidNameCriteria_IsReservedKeywordFormat, name); + return true; + } } //"VBA" identifier not allowed for projects diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs index 84a4fc3d0d..024499ded2 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs @@ -13,13 +13,15 @@ namespace Rubberduck.Refactorings.EncapsulateField public class EncapsulateFieldElementFactory { private readonly IDeclarationFinderProvider _declarationFinderProvider; - private readonly IEncapsulateFieldNamesValidator _validator; + private readonly IEncapsulateFieldValidator _validator; + private readonly IValidateEncapsulateFieldNames _namesValidator; private QualifiedModuleName _targetQMN; - public EncapsulateFieldElementFactory(IDeclarationFinderProvider declarationFinderProvider, QualifiedModuleName targetQMN, IEncapsulateFieldNamesValidator validator) + public EncapsulateFieldElementFactory(IDeclarationFinderProvider declarationFinderProvider, QualifiedModuleName targetQMN, IEncapsulateFieldValidator validator ) { _declarationFinderProvider = declarationFinderProvider; _validator = validator; + _namesValidator = validator as IValidateEncapsulateFieldNames; _targetQMN = targetQMN; } @@ -27,54 +29,42 @@ public IObjectStateUDT CreateStateUDTField() { var stateUDT = new ObjectStateUDT(_targetQMN) as IObjectStateUDT; - stateUDT = SetNonConflictIdentifier(stateUDT, c => { return _validator.IsConflictingStateUDTFieldIdentifier(stateUDT); }, (s) => { stateUDT.FieldIdentifier = s; }, () => stateUDT.FieldIdentifier, _validator); + stateUDT = SetNonConflictIdentifier(stateUDT, c => { return _validator.IsConflictingStateUDTFieldIdentifier(stateUDT); }, (s) => { stateUDT.FieldIdentifier = s; }, () => stateUDT.FieldIdentifier, _namesValidator); - stateUDT = SetNonConflictIdentifier(stateUDT, c => { return _validator.IsConflictingStateUDTTypeIdentifier(stateUDT); }, (s) => { stateUDT.TypeIdentifier = s; }, () => stateUDT.TypeIdentifier, _validator); + stateUDT = SetNonConflictIdentifier(stateUDT, c => { return _validator.IsConflictingStateUDTTypeIdentifier(stateUDT); }, (s) => { stateUDT.TypeIdentifier = s; }, () => stateUDT.TypeIdentifier, _namesValidator); return stateUDT; } - public IEncapsulateFieldCandidate CreateEncapsulationCandidate(Declaration target) + private IEncapsulateFieldCandidate CreateCandidate(Declaration target) { - Debug.Assert(!target.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)); - - IEncapsulateFieldCandidate candidate = CreateCandidate(target); - - if (candidate is IUserDefinedTypeCandidate udtVariable) + if (target.IsUserDefinedTypeField()) { - (Declaration udtDeclaration, IEnumerable udtMembers) = GetUDTAndMembersForField(udtVariable); + var udtField = new UserDefinedTypeCandidate(target, _namesValidator) as IUserDefinedTypeCandidate; + + (Declaration udtDeclaration, IEnumerable udtMembers) = GetUDTAndMembersForField(udtField); - udtVariable.TypeDeclarationIsPrivate = udtDeclaration.HasPrivateAccessibility(); + udtField.TypeDeclarationIsPrivate = udtDeclaration.HasPrivateAccessibility(); foreach (var udtMemberDeclaration in udtMembers) { - var candidateUDTMember = new UserDefinedTypeMemberCandidate(CreateCandidate(udtMemberDeclaration), udtVariable, _validator) as IUserDefinedTypeMemberCandidate; + var candidateUDTMember = new UserDefinedTypeMemberCandidate(CreateCandidate(udtMemberDeclaration), udtField, _namesValidator) as IUserDefinedTypeMemberCandidate; - udtVariable.AddMember(candidateUDTMember); + udtField.AddMember(candidateUDTMember); } var udtVariablesOfSameType = _declarationFinderProvider.DeclarationFinder.UserDeclarations(DeclarationType.Variable) .Where(v => v.AsTypeDeclaration == udtDeclaration); - udtVariable.CanBeObjectStateUDT = udtVariable.TypeDeclarationIsPrivate && udtVariablesOfSameType.Count() == 1; - } - - _validator.RegisterFieldCandidate(candidate); + udtField.CanBeObjectStateUDT = udtField.TypeDeclarationIsPrivate && udtVariablesOfSameType.Count() == 1; - return candidate; - } - - private IEncapsulateFieldCandidate CreateCandidate(Declaration target) - { - if (target.IsUserDefinedTypeField()) - { - return new UserDefinedTypeCandidate(target, _validator); + return udtField; } else if (target.IsArray) { - return new ArrayCandidate(target, _validator); + return new ArrayCandidate(target, _namesValidator); } - return new EncapsulateFieldCandidate(target, _validator); + return new EncapsulateFieldCandidate(target, _namesValidator); } public IEnumerable CreateEncapsulationCandidates() @@ -84,9 +74,14 @@ public IEnumerable CreateEncapsulationCandidates() .Where(v => v.IsMemberVariable() && !v.IsWithEvents); var candidates = new List(); - foreach (var field in fieldDeclarations) + foreach (var fieldDeclaration in fieldDeclarations) { - var fieldEncapsulationCandidate = CreateEncapsulationCandidate(field); + Debug.Assert(!fieldDeclaration.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)); + + var fieldEncapsulationCandidate = CreateCandidate(fieldDeclaration); + + _validator.RegisterFieldCandidate(fieldEncapsulationCandidate); + candidates.Add(fieldEncapsulationCandidate); } @@ -94,7 +89,7 @@ public IEnumerable CreateEncapsulationCandidates() return candidates; } - private IObjectStateUDT SetNonConflictIdentifier(IObjectStateUDT candidate, Predicate conflictDetector, Action setValue, Func getIdentifier, IEncapsulateFieldNamesValidator validator) + private IObjectStateUDT SetNonConflictIdentifier(IObjectStateUDT candidate, Predicate conflictDetector, Action setValue, Func getIdentifier, IValidateEncapsulateFieldNames validator) { var isConflictingIdentifier = conflictDetector(candidate); for (var count = 1; count < 10 && isConflictingIdentifier; count++) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index b5d59320b6..dc17914354 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -11,12 +11,12 @@ public class EncapsulateFieldModel : IRefactoringModel { private readonly Func _previewDelegate; private QualifiedModuleName _targetQMN; - private IEncapsulateFieldNamesValidator _validator; + private IValidateEncapsulateFieldNames _validator; private IObjectStateUDT _newObjectStateUDT; private IDictionary)> _udtFieldToUdtDeclarationMap = new Dictionary)>(); - public EncapsulateFieldModel(Declaration target, IEnumerable candidates, IObjectStateUDT stateUDTField, Func previewDelegate, IEncapsulateFieldNamesValidator validator) + public EncapsulateFieldModel(Declaration target, IEnumerable candidates, IObjectStateUDT stateUDTField, Func previewDelegate, IValidateEncapsulateFieldNames validator) { _previewDelegate = previewDelegate; _targetQMN = target.QualifiedModuleName; @@ -48,7 +48,19 @@ public IEncapsulateFieldCandidate this[string encapsulatedFieldTargetID] public IEncapsulateFieldCandidate this[Declaration fieldDeclaration] => EncapsulationCandidates.Where(c => c.Declaration == fieldDeclaration).Single(); - public bool EncapsulateWithUDT { set; get; } + private bool _convertFieldsToUDTMembers; + public bool ConvertFieldsToUDTMembers + { + set + { + _convertFieldsToUDTMembers = value; + foreach (var candidate in EncapsulationCandidates) + { + candidate.ConvertFieldToUDTMember = value; + } + } + get => _convertFieldsToUDTMembers; + } public IObjectStateUDT StateUDTField { set; get; } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 3cd95efa27..71a584fc8d 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -85,15 +85,13 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) _targetQMN = target.QualifiedModuleName; - var validator = new EncapsulateFieldNamesValidator(_declarationFinderProvider); + var validator = new EncapsulateFieldValidator(_declarationFinderProvider) as IEncapsulateFieldValidator; _encapsulationCandidateFactory = new EncapsulateFieldElementFactory(_declarationFinderProvider, _targetQMN, validator); var candidates = _encapsulationCandidateFactory.CreateEncapsulationCandidates(); var selected = candidates.Single(c => c.Declaration == target); selected.EncapsulateFlag = true; - //var newObjectStateUDT = _encapsulationCandidateFactory.CreateStateUDTField(); - if (!TryRetrieveExistingObjectStateUDT(target, candidates, out var objectStateUDT)) { objectStateUDT = _encapsulationCandidateFactory.CreateStateUDTField(); @@ -193,7 +191,7 @@ private void ModifyReferences(EncapsulateFieldModel model, IEncapsulateFieldRewr { foreach (var field in model.SelectedFieldCandidates) { - field.ReferenceQualifier = model.EncapsulateWithUDT + field.ReferenceQualifier = model.ConvertFieldsToUDTMembers ? model.StateUDTField.FieldIdentifier : null; @@ -210,7 +208,7 @@ private void ModifyReferences(EncapsulateFieldModel model, IEncapsulateFieldRewr private void ModifyFields(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) { - if (model.EncapsulateWithUDT) + if (model.ConvertFieldsToUDTMembers) { IModuleRewriter rewriter; @@ -300,7 +298,7 @@ private void InsertNewContent(EncapsulateFieldModel model, IEncapsulateFieldRewr private void LoadNewDeclarationBlocks(EncapsulateFieldModel model) { - if (model.EncapsulateWithUDT) + if (model.ConvertFieldsToUDTMembers) { if (model.StateUDTField?.IsExistingDeclaration ?? false) { return; } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs index 6d07c81cb6..447bc366dd 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -8,20 +8,27 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface IEncapsulateFieldNamesValidator + public interface IObjectStateUDTNamesValidator { - void RegisterFieldCandidate(IEncapsulateFieldCandidate candidate); - bool IsValidVBAIdentifier(string identifier, DeclarationType declarationType, out string errorMessage); + bool IsConflictingStateUDTTypeIdentifier(IObjectStateUDT stateUDT); + bool IsConflictingStateUDTFieldIdentifier(IObjectStateUDT stateUDT); + } + + public interface IValidateEncapsulateFieldNames + { + bool IsValidVBAIdentifier(string identifier, DeclarationType declarationType, out string errorMessage, bool isArray = false); bool HasConflictingIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType, out string errorMessage); bool IsSelfConsistent(IEncapsulateFieldCandidate candidate, out string errorMessage); bool IsConflictingFieldIdentifier(string fieldName, IEncapsulateFieldCandidate candidate, DeclarationType declarationType); - bool HasValidEncapsulationIdentifiers(IEncapsulateFieldCandidate candidate, out string errorMessage); - bool IsConflictingStateUDTTypeIdentifier(IObjectStateUDT stateUDT); - bool IsConflictingStateUDTFieldIdentifier(IObjectStateUDT stateUDT); IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType); } - public class EncapsulateFieldNamesValidator : IEncapsulateFieldNamesValidator + public interface IEncapsulateFieldValidator : IObjectStateUDTNamesValidator, IValidateEncapsulateFieldNames + { + void RegisterFieldCandidate(IEncapsulateFieldCandidate candidate); + } + + public class EncapsulateFieldValidator : IEncapsulateFieldValidator { private readonly IDeclarationFinderProvider _declarationFinderProvider; @@ -31,7 +38,7 @@ public class EncapsulateFieldNamesValidator : IEncapsulateFieldNamesValidator private List FlaggedCandidates => FieldCandidates.Where(rc => rc.EncapsulateFlag).ToList(); - public EncapsulateFieldNamesValidator(IDeclarationFinderProvider declarationFinderProvider) + public EncapsulateFieldValidator(IDeclarationFinderProvider declarationFinderProvider) { _declarationFinderProvider = declarationFinderProvider; FieldCandidates = new List(); @@ -55,23 +62,9 @@ public void RegisterFieldCandidate(IEncapsulateFieldCandidate candidate) private DeclarationFinder DeclarationFinder => _declarationFinderProvider.DeclarationFinder; - - public bool HasValidEncapsulationIdentifiers(IEncapsulateFieldCandidate candidate, out string errorMessage) - { - if (VBAIdentifierValidator.TryMatchInvalidIdentifierCriteria(candidate.PropertyName, DeclarationType.Property, out errorMessage)) - { - return false; - } - if (!IsSelfConsistent(candidate, out errorMessage)) - { - return false; - } - return true; - } - - public bool IsValidVBAIdentifier(string identifier, DeclarationType declarationType, out string errorMessage) + public bool IsValidVBAIdentifier(string identifier, DeclarationType declarationType, out string errorMessage, bool isArray = false) { - return !VBAIdentifierValidator.TryMatchInvalidIdentifierCriteria(identifier, declarationType, out errorMessage); + return !VBAIdentifierValidator.TryMatchInvalidIdentifierCriteria(identifier, declarationType, out errorMessage, isArray); } public bool IsSelfConsistent(IEncapsulateFieldCandidate candidate, out string errorMessage) @@ -97,7 +90,7 @@ public bool IsSelfConsistent(IEncapsulateFieldCandidate candidate, out string er private List PotentialConflictIdentifiers(IEncapsulateFieldCandidate candidate, DeclarationType declarationType) { - var members = _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) + var members = DeclarationFinder.Members(candidate.QualifiedModuleName) .Where(d => d != candidate.Declaration); var nameConflictCandidates = members @@ -123,7 +116,7 @@ private List PotentialConflictIdentifiers(IObjectStateUDT stateUDT, Decl var stateUDTDeclaration = stateUDT as IEncapsulateFieldDeclaration; var potentialDeclarationIdentifierConflicts = new List(); - var members = _declarationFinderProvider.DeclarationFinder.Members(stateUDTDeclaration.QualifiedModuleName); + var members = DeclarationFinder.Members(stateUDTDeclaration.QualifiedModuleName); var nameConflictCandidates = members .Where(d => !IsAlwaysIgnoreNameConflictType(d, declarationType)).ToList(); diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs index 82bca5d805..82e44f1ae8 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs @@ -6,10 +6,15 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public class ArrayCandidate : EncapsulateFieldCandidate + public interface IArrayCandidate : IEncapsulateFieldCandidate + { + + } + + public class ArrayCandidate : EncapsulateFieldCandidate, IArrayCandidate { private string _subscripts; - public ArrayCandidate(Declaration declaration, IEncapsulateFieldNamesValidator validator) + public ArrayCandidate(Declaration declaration, IValidateEncapsulateFieldNames validator) :base(declaration, validator) { ImplementLet = false; @@ -29,6 +34,28 @@ public ArrayCandidate(Declaration declaration, IEncapsulateFieldNamesValidator v public override string AsUDTMemberDeclaration => $"{PropertyName}({_subscripts}) {Tokens.As} {AsTypeName_Field}"; + public override bool TryValidateEncapsulationAttributes(out string errorMessage) //, bool isArray = false) + { + errorMessage = string.Empty; + if (!EncapsulateFlag) { return true; } + + if (ConvertFieldToUDTMember) + { + return TryValidateAsUDTMemberEncapsulationAttributes(out errorMessage, true); + } + + if (!TryValidateEncapsulationAttributes(DeclarationType.Property, out errorMessage, true)) + { + return false; + } + + if (_validator.HasConflictingIdentifier(this, DeclarationType.Variable, out errorMessage)) + { + return false; + } + return true; + } + public override void LoadFieldReferenceContextReplacements() { foreach (var idRef in Declaration.References) diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs index ae0ca97d46..efbdf464df 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs @@ -34,6 +34,7 @@ public interface IEncapsulateFieldCandidate : IEncapsulateFieldDeclaration string ReferenceQualifier { set; get; } void LoadFieldReferenceContextReplacements(); bool TryValidateEncapsulationAttributes(out string errorMessage); + bool ConvertFieldToUDTMember { set; get; } } public enum AccessorMember { Field, Property } @@ -51,13 +52,28 @@ public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate, IEncapsulat protected QualifiedModuleName _qmn; protected int _hashCode; private string _identifierName; - protected IEncapsulateFieldNamesValidator _validator; + protected IValidateEncapsulateFieldNames _validator; protected EncapsulationIdentifiers _fieldAndProperty; - public EncapsulateFieldCandidate(Declaration declaration, IEncapsulateFieldNamesValidator validator) - : this(declaration.IdentifierName, declaration.AsTypeName, declaration.QualifiedModuleName, validator) + public EncapsulateFieldCandidate(Declaration declaration, IValidateEncapsulateFieldNames validator) { _target = declaration; + _validator = validator; + _fieldAndProperty = new EncapsulationIdentifiers(declaration.IdentifierName, (string name) => _validator.IsValidVBAIdentifier(name, DeclarationType.Property, out _)); + IdentifierName = declaration.IdentifierName; + AsTypeName_Field = declaration.AsTypeName; + AsTypeName_Property = declaration.AsTypeName; + _qmn = declaration.QualifiedModuleName; + NewPropertyAccessor = AccessorMember.Field; + ReferenceAccessor = AccessorMember.Property; + + + ImplementLet = true; + ImplementSet = false; + + CanBeReadWrite = true; + + _hashCode = ($"{_qmn.Name}.{declaration.IdentifierName}").GetHashCode(); if (_target.IsEnumField()) { @@ -80,26 +96,6 @@ public EncapsulateFieldCandidate(Declaration declaration, IEncapsulateFieldNames } } - public EncapsulateFieldCandidate(string identifier, string asTypeName, QualifiedModuleName qmn, IEncapsulateFieldNamesValidator validator) - { - _fieldAndProperty = new EncapsulationIdentifiers(identifier); - IdentifierName = identifier; - AsTypeName_Field = asTypeName; - AsTypeName_Property = asTypeName; - _qmn = qmn; - NewPropertyAccessor = AccessorMember.Field; - ReferenceAccessor = AccessorMember.Property; - - _validator = validator; - - ImplementLet = true; - ImplementSet = false; - - CanBeReadWrite = true; - - _hashCode = ($"{_qmn.Name}.{identifier}").GetHashCode(); - } - protected Dictionary IdentifierReplacements { get; } = new Dictionary(); public Declaration Declaration => _target; @@ -117,28 +113,58 @@ public virtual bool TryValidateEncapsulationAttributes(out string errorMessage) errorMessage = string.Empty; if (!EncapsulateFlag) { return true; } - if (!_validator.IsValidVBAIdentifier(PropertyName, DeclarationType.Property, out errorMessage)) + if (ConvertFieldToUDTMember) + { + return TryValidateAsUDTMemberEncapsulationAttributes(out errorMessage); + } + + if (!TryValidateEncapsulationAttributes(DeclarationType.Property, out errorMessage)) { return false; } - if (!_validator.IsSelfConsistent(this, out errorMessage)) + if (_validator.HasConflictingIdentifier(this, DeclarationType.Variable, out errorMessage)) { return false; } + return true; + } - if (_validator.HasConflictingIdentifier(this, DeclarationType.Property, out errorMessage)) + protected virtual bool TryValidateAsUDTMemberEncapsulationAttributes(out string errorMessage, bool isArray = false) + { + errorMessage = string.Empty; + if (!EncapsulateFlag) { return true; } + + if (!TryValidateEncapsulationAttributes(DeclarationType.UserDefinedTypeMember, out errorMessage, isArray)) { return false; } + return TryValidateEncapsulationAttributes(Declaration.DeclarationType, out errorMessage, isArray); + } - if (_validator.HasConflictingIdentifier(this, DeclarationType.Variable, out errorMessage)) + protected bool TryValidateEncapsulationAttributes(DeclarationType declarationType, out string errorMessage, bool isArray = false) + { + errorMessage = string.Empty; + if (!EncapsulateFlag) { return true; } + + if (!_validator.IsValidVBAIdentifier(PropertyName, declarationType, out errorMessage, isArray)) + { + return false; + } + + if (!_validator.IsSelfConsistent(this, out errorMessage)) + { + return false; + } + + if (_validator.HasConflictingIdentifier(this, declarationType, out errorMessage)) { return false; } return true; } + public virtual IEnumerable> ReferenceReplacements { get @@ -257,6 +283,8 @@ public string IdentifierName private bool _implSet; public bool ImplementSet { get => !IsReadOnly && _implSet; set => _implSet = value; } + public bool ConvertFieldToUDTMember { set; get; } + public virtual string AsUDTMemberDeclaration => $"{PropertyName} {Tokens.As} {AsTypeName_Field}"; diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs index e21881c6df..2ace273214 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs @@ -3,6 +3,7 @@ using Rubberduck.Common; using System.Collections.Generic; using Rubberduck.Refactorings.EncapsulateField.Extensions; +using System; namespace Rubberduck.Refactorings.EncapsulateField { @@ -14,27 +15,31 @@ public class EncapsulationIdentifiers private string _targetIdentifier; private string _setLetParameter; - public EncapsulationIdentifiers(Declaration target) - : this(target.IdentifierName) { } - - public EncapsulationIdentifiers(string field) + public EncapsulationIdentifiers(string field, Predicate IsValidPropertyName) { _targetIdentifier = field; + + DefaultPropertyName = field.CapitalizeFirstLetter(); + DefaultNewFieldName = (field.ToLowerCaseFirstLetter()).IncrementEncapsulationIdentifier(); + if (field.TryMatchHungarianNotationCriteria(out var nonHungarianName)) { - DefaultPropertyName = nonHungarianName; - DefaultNewFieldName = field; + if (IsValidPropertyName(nonHungarianName)) + { + DefaultPropertyName = nonHungarianName; + DefaultNewFieldName = field; + } } else if (field.StartsWith("m_")) { - DefaultPropertyName = field.Substring(2).CapitalizeFirstLetter(); - DefaultNewFieldName = field; - } - else - { - DefaultPropertyName = field.CapitalizeFirstLetter(); - DefaultNewFieldName = (field.ToLowerCaseFirstLetter()).IncrementEncapsulationIdentifier(); + var propertyName = field.Substring(2).CapitalizeFirstLetter(); + if (IsValidPropertyName(propertyName)) + { + DefaultPropertyName = propertyName; + DefaultNewFieldName = field; + } } + _fieldAndProperty = new KeyValuePair(DefaultNewFieldName, DefaultPropertyName); _setLetParameter = DEFAULT_WRITE_PARAMETER; } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs index a8d358552a..fcef6b1eaf 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs @@ -19,7 +19,7 @@ public interface IUserDefinedTypeCandidate : IEncapsulateFieldCandidate public class UserDefinedTypeCandidate : EncapsulateFieldCandidate, IUserDefinedTypeCandidate { - public UserDefinedTypeCandidate(Declaration declaration, IEncapsulateFieldNamesValidator validator) + public UserDefinedTypeCandidate(Declaration declaration, IValidateEncapsulateFieldNames validator) : base(declaration, validator) { NewPropertyAccessor = AccessorMember.Field; @@ -101,7 +101,7 @@ public override bool EncapsulateFlag } base.EncapsulateFlag = value; } - get => _encapsulateFlag; // && !_isObjectStateUDT; + get => _encapsulateFlag; } public override void LoadFieldReferenceContextReplacements() diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs index ab3f50f9c4..3ea6c677c0 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs @@ -20,10 +20,10 @@ public interface IUserDefinedTypeMemberCandidate : IEncapsulateFieldCandidate public class UserDefinedTypeMemberCandidate : IUserDefinedTypeMemberCandidate { - private readonly IEncapsulateFieldNamesValidator _validator; + private readonly IValidateEncapsulateFieldNames _validator; private int _hashCode; private readonly string _uniqueID; - public UserDefinedTypeMemberCandidate(IEncapsulateFieldCandidate candidate, IUserDefinedTypeCandidate udtVariable, IEncapsulateFieldNamesValidator validator) + public UserDefinedTypeMemberCandidate(IEncapsulateFieldCandidate candidate, IUserDefinedTypeCandidate udtVariable, IValidateEncapsulateFieldNames validator) { _wrappedCandidate = candidate; Parent = udtVariable; @@ -208,6 +208,8 @@ public string AsTypeName_Property public bool ImplementSet => _wrappedCandidate.ImplementSet; + public bool ConvertFieldToUDTMember { set; get; } + public IEnumerable PropertyAttributeSets => _wrappedCandidate.PropertyAttributeSets; public string AsUDTMemberDeclaration => _wrappedCandidate.AsUDTMemberDeclaration; diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs index eb63a13851..dd6a408cf3 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs @@ -495,7 +495,7 @@ Sub Bar(ByVal name As Integer) var presenterAction = Support.SetParametersForSingleTarget("fizz", "Name"); - var enapsulationIdentifiers = new EncapsulationIdentifiers("fizz") { Property = "Name" }; + var enapsulationIdentifiers = new EncapsulationIdentifiers("fizz", (string name) => true) { Property = "Name" }; var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.AreEqualIgnoringCase(enapsulationIdentifiers.TargetFieldName, "fizz"); diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs index c508e3452f..c4219ce096 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs @@ -500,6 +500,26 @@ Public mF|oo As Long StringAssert.Contains($"Private Type TModuleOne_1", actualCode); } + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UDTReservedMemberArrayIdentifier() + { + var fieldName = "Name"; + var userInput = new UserInputDataObject() + .UserSelectsField(fieldName); + + userInput.EncapsulateAsUDT = true; + + var presenterAction = Support.SetParameters(userInput); + + var vbe = MockVbeBuilder.BuildFromModules( + (MockVbeBuilder.TestModuleName, $"Private {fieldName}(5) As String", ComponentType.StandardModule)).Object; + + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, fieldName, DeclarationType.Variable, presenterAction); + + Assert.AreEqual(false, model[fieldName].TryValidateEncapsulationAttributes(out var message), message); + } protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) { diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs index bf03393ea2..50ae67c0fc 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs @@ -64,8 +64,8 @@ End Type Public th|is As TBar Public that As TBar"; - var expectedThis = new EncapsulationIdentifiers("this"); - var expectedThat = new EncapsulationIdentifiers("that"); + var expectedThis = new EncapsulationIdentifiers("this", (string name) => true); + var expectedThat = new EncapsulationIdentifiers("that", (string name) => true); var userInput = new UserInputDataObject() .AddUserInputSet(expectedThis.TargetFieldName, encapsulationFlag: encapsulateThis) diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs index 30640927cb..2751c37264 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs @@ -85,7 +85,7 @@ public void PropertyNameChange_UniqueParamName() [Category("Encapsulate Field")] public void AccountsForHungarianNamesAndMemberPrefix(string inputName, string expectedPropertyName, string expectedFieldName) { - var sut = new EncapsulationIdentifiers(inputName); + var sut = new EncapsulationIdentifiers(inputName, (string name) => true); Assert.AreEqual(expectedPropertyName, sut.DefaultPropertyName); Assert.AreEqual(expectedFieldName, sut.DefaultNewFieldName); diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index 5d00aea6a7..46acf74430 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -36,7 +36,7 @@ public Func UserAcceptsDefaults(bo { return model => { - model.EncapsulateWithUDT = asUDT; + model.ConvertFieldsToUDTMembers = asUDT; return model; }; } @@ -64,7 +64,7 @@ public Func SetParameters(UserInpu { return model => { - model.EncapsulateWithUDT = userInput.EncapsulateAsUDT; + model.ConvertFieldsToUDTMembers = userInput.EncapsulateAsUDT; if (userInput.EncapsulateAsUDT) { var stateUDT = model.EncapsulationCandidates.Where(sfc => sfc is IUserDefinedTypeCandidate udt && udt.TargetID == userInput.ObjectStateUDTTargetID) @@ -98,7 +98,7 @@ public Func SetParameters(string o encapsulatedField.IsReadOnly = attrs.IsReadOnly; encapsulatedField.EncapsulateFlag = attrs.EncapsulateFlag; - model.EncapsulateWithUDT = asUDT; + model.ConvertFieldsToUDTMembers = asUDT; return model; }; } @@ -127,7 +127,7 @@ public IEncapsulateFieldCandidate RetrieveEncapsulatedField(string inputCode, st using (state) { var match = state.DeclarationFinder.MatchName(fieldName).Single(); - return new EncapsulateFieldCandidate(match, new EncapsulateFieldNamesValidator(state)) as IEncapsulateFieldCandidate; + return new EncapsulateFieldCandidate(match, new EncapsulateFieldValidator(state)) as IEncapsulateFieldCandidate; } } @@ -141,7 +141,7 @@ public IEncapsulateFieldCandidate RetrieveEncapsulatedField(string inputCode, st using (state) { var match = state.DeclarationFinder.MatchName(fieldName).Where(m => m.DeclarationType.Equals(declarationType)).Single(); - return new EncapsulateFieldCandidate(match, new EncapsulateFieldNamesValidator(state)) as IEncapsulateFieldCandidate; + return new EncapsulateFieldCandidate(match, new EncapsulateFieldValidator(state)) as IEncapsulateFieldCandidate; } } @@ -178,7 +178,7 @@ public class TestEncapsulationAttributes { public TestEncapsulationAttributes(string fieldName, bool encapsulationFlag = true, bool isReadOnly = false) { - _identifiers = new EncapsulationIdentifiers(fieldName); + _identifiers = new EncapsulationIdentifiers(fieldName, (string name) => true); EncapsulateFlag = encapsulationFlag; IsReadOnly = isReadOnly; } diff --git a/RubberduckTests/VBAIdentifierValidatorTests.cs b/RubberduckTests/VBAIdentifierValidatorTests.cs index db2da0dc9b..954c52f04d 100644 --- a/RubberduckTests/VBAIdentifierValidatorTests.cs +++ b/RubberduckTests/VBAIdentifierValidatorTests.cs @@ -20,6 +20,7 @@ public class VBAIdentifierValidatorTests [TestCase("O123456789O123456789O123456789O1", DeclarationType.Variable, true)] //32 chars OK for variables [TestCase("O123456789O123456789O123456789O1", DeclarationType.Project, true)] //32 chars OK for projects [Category("Rename")] + [Category("Refactorings")] public void VBAIdentifierValidator_IsValidName(string identifier, DeclarationType declarationType, bool expected) { Assert.AreEqual(expected, VBAIdentifierValidator.IsValidIdentifier(identifier, declarationType)); @@ -30,10 +31,26 @@ public void VBAIdentifierValidator_IsValidName(string identifier, DeclarationTyp [TestCase("b1", false)] //too short [TestCase("bbbbbbb", false)] //repeated letter [Category("Rename")] + [Category("Refactorings")] public void VBAIdentifierValidator_IsMeaningfulName(string identifier, bool expected) { Assert.AreEqual(expected, VBAIdentifierValidator.IsMeaningfulIdentifier(identifier)); } + [TestCase("CStr", DeclarationType.UserDefinedTypeMember, false, false)] + [TestCase("CStr", DeclarationType.UserDefinedTypeMember, true, true)] + [TestCase("CStr", DeclarationType.Property, false, true)] + [TestCase("CStr", DeclarationType.Property, true, true)] + [TestCase("Name", DeclarationType.UserDefinedTypeMember, false, false)] + [TestCase("Name", DeclarationType.UserDefinedTypeMember, true, true)] + [TestCase("Name", DeclarationType.Property, false, false)] + [TestCase("Name", DeclarationType.Property, true, false)] + [Category("Rename")] + [Category("Refactorings")] + public void UDTMemberIdentifierValidations(string identifier, DeclarationType declarationType, bool isArray, bool expectedResult) + { + var result = VBAIdentifierValidator.TryMatchInvalidIdentifierCriteria(identifier, declarationType, out var errorMessage, isArray); + Assert.AreEqual(expectedResult, result, errorMessage); + } } } From 091b637008baeb6cfd94844e72b98d0d76f23e29 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Mon, 30 Dec 2019 06:32:00 -0800 Subject: [PATCH 086/461] Recognize pre-existing ObjectStateUDT If an existing ObjectStateUDT (from a prior encapuslate field operation) can be found, then setup the refactoring to add to the ObjectStateUDT. --- .../EncapsulateField/EncapsulateFieldViewModel.cs | 13 +++++++++++++ .../EncapsulateField/EncapsulateFIeldResources.cs | 4 +++- .../EncapsulateField/EncapsulateFieldModel.cs | 4 ++-- .../EncapsulateField/EncapsulateFieldRefactoring.cs | 9 ++++++++- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs index 8c1de0b96e..587417436b 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs @@ -367,6 +367,14 @@ private void ManageEncapsulationFlagsAndSelectedItem(object param = null) var selected = _lastCheckedBoxes.FirstOrDefault(); if (_lastCheckedBoxes.Count == EncapsulationFields.Where(f => f.EncapsulateFlag).Count()) { + _lastCheckedBoxes = EncapsulationFields.Where(f => f.EncapsulateFlag).ToList(); + if (EncapsulationFields.Where(f => f.EncapsulateFlag).Count() == 0 + && EncapsulationFields.Count() > 0) + { + SetSelectedField(EncapsulationFields.First()); + return; + } + SetSelectedField(_lastCheckedBoxes.First()); return; } @@ -390,6 +398,11 @@ private void ManageEncapsulationFlagsAndSelectedItem(object param = null) _lastCheckedBoxes = EncapsulationFields.Where(ef => ef.EncapsulateFlag).ToList(); + SetSelectedField(selected); + } + + private void SetSelectedField(IEncapsulatedFieldViewData selected) + { _masterDetail.SelectionTargetID = selected?.TargetID ?? null; OnPropertyChanged(nameof(SelectedField)); if (_masterDetail.DetailUpdateRequired) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs index de06f08096..6baae26f91 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs @@ -12,12 +12,14 @@ namespace Rubberduck.Refactorings.EncapsulateField public class EncapsulateFieldResources { public static string PreviewEndOfChangesMarker - => "'<===== No Changes below this line =====>"; + => "'<===== Property and Declaration changes above this line =====>"; public static string DefaultPropertyParameter => "value"; public static string DefaultStateUDTFieldName => "this"; + //TODO: Is it meaningful to change the Type prefix for different cultures? + //If not, remove this declaration public static string StateUserDefinedTypeIdentifierPrefix => "T"; public static string GroupBoxHeaderSuffix = "Encapsulation Property Name:"; diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index dc17914354..126def7513 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -66,7 +66,7 @@ public bool ConvertFieldsToUDTMembers public string PreviewRefactoring() => _previewDelegate(this); - private List _objStateCandidates; + private HashSet _objStateCandidates; public IEnumerable ObjectStateUDTCandidates { get @@ -76,7 +76,7 @@ public IEnumerable ObjectStateUDTCandidates return _objStateCandidates; } - _objStateCandidates = new List(); + _objStateCandidates = new HashSet(); foreach (var candidate in UDTFieldCandidates.Where(udt => udt.CanBeObjectStateUDT)) { _objStateCandidates.Add(new ObjectStateUDT(candidate)); diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 71a584fc8d..9644c52e15 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -92,7 +92,13 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) var selected = candidates.Single(c => c.Declaration == target); selected.EncapsulateFlag = true; - if (!TryRetrieveExistingObjectStateUDT(target, candidates, out var objectStateUDT)) + var forceUseOfObjectStateUDT = false; + if (TryRetrieveExistingObjectStateUDT(target, candidates, out var objectStateUDT)) + { + objectStateUDT.IsSelected = true; + forceUseOfObjectStateUDT = true; + } + else { objectStateUDT = _encapsulationCandidateFactory.CreateStateUDTField(); objectStateUDT.IsSelected = true; @@ -110,6 +116,7 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) .OrderBy(c => c.Selection) .FirstOrDefault()?.Context.Start.TokenIndex ?? null; + Model.ConvertFieldsToUDTMembers = forceUseOfObjectStateUDT; return Model; } From 917861fc02a5a531ed6b68e5ff95c23b8c5ad53b Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Mon, 30 Dec 2019 10:01:53 -0800 Subject: [PATCH 087/461] Handle array redim external to declaring module Separated Array related tests into dedicated test class/file. Some enum tests consolidation. --- .../EncapsulateFIeldResources.cs | 2 + .../FieldCandidates/ArrayCandidate.cs | 25 +- .../EncapsulateArrayFieldTests.cs | 215 ++++++++++++++++++ .../EncapsulateField/EncapsulateFieldTests.cs | 174 +------------- .../EncapsulateFieldValidatorTests.cs | 8 +- .../EncapsulateUsingStateUDTTests.cs | 2 +- .../EncapsulationIdentifiersTests.cs | 6 +- .../EncapsulateField/TestSupport.cs | 24 +- 8 files changed, 267 insertions(+), 189 deletions(-) create mode 100644 RubberduckTests/Refactoring/EncapsulateField/EncapsulateArrayFieldTests.cs diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs index 6baae26f91..c7076c0c38 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs @@ -48,5 +48,7 @@ public static string PrivateUDTPropertyText public static string Parameter => "Parameter"; public static string NameConflictDetected => "Name Conflict Detected"; + + public static string ArrayHasExternalRedimFormat => "Storage space for {0} is reallocated external to module '{1}'"; } } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs index 82e44f1ae8..48282c377c 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs @@ -8,7 +8,6 @@ namespace Rubberduck.Refactorings.EncapsulateField { public interface IArrayCandidate : IEncapsulateFieldCandidate { - } public class ArrayCandidate : EncapsulateFieldCandidate, IArrayCandidate @@ -31,14 +30,25 @@ public ArrayCandidate(Declaration declaration, IValidateEncapsulateFieldNames va } } + private bool HasExternalRedimOperation + => Declaration.References.Any(rf => rf.QualifiedModuleName != QualifiedModuleName + && rf.Context.TryGetAncestor(out _)); + + public override string AsUDTMemberDeclaration => $"{PropertyName}({_subscripts}) {Tokens.As} {AsTypeName_Field}"; - public override bool TryValidateEncapsulationAttributes(out string errorMessage) //, bool isArray = false) + public override bool TryValidateEncapsulationAttributes(out string errorMessage) { errorMessage = string.Empty; if (!EncapsulateFlag) { return true; } + if (HasExternalRedimOperation) + { + errorMessage = string.Format(EncapsulateFieldResources.ArrayHasExternalRedimFormat, Declaration.IdentifierName, Declaration.QualifiedModuleName.ComponentName); + return false; + } + if (ConvertFieldToUDTMember) { return TryValidateAsUDTMemberEncapsulationAttributes(out errorMessage, true); @@ -60,6 +70,17 @@ public override void LoadFieldReferenceContextReplacements() { foreach (var idRef in Declaration.References) { + //Locally, we do all operations using the backing field + if (idRef.QualifiedModuleName == QualifiedModuleName) + { + var accessor = ConvertFieldToUDTMember + ? ReferenceForPreExistingReferences + : FieldIdentifier; + + SetReferenceRewriteContent(idRef, accessor); + continue; + } + var replacementText = RequiresAccessQualification(idRef) ? $"{QualifiedModuleName.ComponentName}.{ReferenceForPreExistingReferences}" : ReferenceForPreExistingReferences; diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateArrayFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateArrayFieldTests.cs new file mode 100644 index 0000000000..93aa8b1c5d --- /dev/null +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateArrayFieldTests.cs @@ -0,0 +1,215 @@ +using NUnit.Framework; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.Refactorings; +using Rubberduck.Refactorings.EncapsulateField; +using Rubberduck.VBEditor; +using Rubberduck.VBEditor.Utility; +using RubberduckTests.Mocks; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RubberduckTests.Refactoring.EncapsulateField +{ + [TestFixture] + public class EncapsulateArrayFieldTests : InteractiveRefactoringTestBase + { + private EncapsulateFieldTestSupport Support { get; } = new EncapsulateFieldTestSupport(); + + [TestCase("Private", "mArray(5) As String", "mArray(5) As String")] + [TestCase("Public", "mArray(5) As String", "mArray(5) As String")] + [TestCase("Private", "mArray(5,2,3) As String", "mArray(5,2,3) As String")] + [TestCase("Public", "mArray(5,2,3) As String", "mArray(5,2,3) As String")] + [TestCase("Private", "mArray(1 to 10) As String", "mArray(1 to 10) As String")] + [TestCase("Public", "mArray(1 to 10) As String", "mArray(1 to 10) As String")] + [TestCase("Private", "mArray() As String", "mArray() As String")] + [TestCase("Public", "mArray() As String", "mArray() As String")] + [TestCase("Private", "mArray(5)", "mArray(5) As Variant")] + [TestCase("Public", "mArray(5)", "mArray(5) As Variant")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulateArray(string visibility, string arrayDeclaration, string expectedArrayDeclaration) + { + string inputCode = + $@"Option Explicit + +{visibility} {arrayDeclaration}"; + + var selection = new Selection(3, 8, 3, 11); + + string expectedCode = + $@"Option Explicit + +Private {expectedArrayDeclaration} + +Public Property Get MyArray() As Variant + MyArray = mArray +End Property +"; + var userInput = new UserInputDataObject() + .UserSelectsField("mArray", "MyArray"); + + var presenterAction = Support.SetParameters(userInput); + var actualCode = RefactoredCode(inputCode, selection, presenterAction); + Assert.AreEqual(expectedCode.Trim(), actualCode); + } + + [TestCase("5")] + [TestCase("5,2,3")] + [TestCase("1 to 100")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulateArray_DeclaredInList(string dimensions) + { + string inputCode = + $@"Option Explicit + +Public mArray({dimensions}) As String, anotherVar As Long, andOneMore As Variant"; + + var selection = new Selection(3, 8, 3, 11); + + string expectedCode = + $@"Option Explicit + +Public anotherVar As Long, andOneMore As Variant +Private mArray({dimensions}) As String + +Public Property Get MyArray() As Variant + MyArray = mArray +End Property +"; + var presenterAction = Support.SetParametersForSingleTarget("mArray", "MyArray"); + var actualCode = RefactoredCode(inputCode, selection, presenterAction); + StringAssert.Contains("Public anotherVar As Long, andOneMore As Variant", actualCode); + StringAssert.Contains($"Private mArray({dimensions}) As String", actualCode); + StringAssert.Contains("Get MyArray() As Variant", actualCode); + StringAssert.Contains("MyArray = mArray", actualCode); + StringAssert.DoesNotContain("Let MyArray", actualCode); + StringAssert.DoesNotContain("Set MyArray", actualCode); + } + + [TestCase("mArr|ay(5) As String, mNextVar As Long", "Private mArray(5) As String")] + [TestCase("mNextVar As Long, mArr|ay(5) As String", "Private mArray(5) As String")] + [TestCase("mArr|ay(5), mNextVar As Long", "Private mArray(5) As Variant")] + [TestCase("mNextVar As Long, mAr|ray(5)", "Private mArray(5) As Variant")] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void EncapsulateArray_newFieldNameForFieldInList(string declarationList, string expectedDeclaration) + { + string inputCode = + $@"Option Explicit + +Public {declarationList}"; + + string expectedCode = + $@"Option Explicit + +Public mNextVar As Long + +{expectedDeclaration} + +Public Property Get MyArray() As Variant + MyArray = mArray +End Property +"; + var presenterAction = Support.SetParametersForSingleTarget("mArray", "MyArray"); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + Assert.AreEqual(expectedCode.Trim(), actualCode); + } + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void RedimsBackingVariable() + { + string inputCode = + $@"Option Explicit + +Public myA|rray() As Integer + +Private Sub InitializeArray(size As Long) + Redim myArray(size) + Dim idx As Long + For idx = 1 To size + myArray(idx) = idx + Next idx +End Sub +"; + + var presenterAction = Support.UserAcceptsDefaults(); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.Contains("Public Property Get MyArray() As Variant", actualCode); + StringAssert.DoesNotContain("Public Property Let MyArray(", actualCode); + StringAssert.Contains("Redim myArray_1(size)", actualCode); + StringAssert.Contains("myArray_1(idx) = idx", actualCode); + } + + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void RedimsBackingVariableAsUDT() + { + string inputCode = + $@"Option Explicit + +Public myA|rray() As Integer + +Private Sub InitializeArray(size As Long) + Redim myArray(size) + Dim idx As Long + For idx = 1 To size + myArray(idx) = idx + Next idx +End Sub +"; + + var presenterAction = Support.UserAcceptsDefaults(convertFieldToUDTMember: true); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.Contains("Public Property Get MyArray() As Variant", actualCode); + StringAssert.DoesNotContain("Public Property Let MyArray(", actualCode); + StringAssert.Contains("Redim this.MyArray(size)", actualCode); + StringAssert.Contains("this.MyArray(idx) = idx", actualCode); + } + + [TestCase(false)] + [TestCase(true)] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void RedimsBackingVariableExternally(bool convertField) + { + var fieldUT = "myArray"; + string inputCode = + $@"Option Explicit + +Public myArray() As Long +"; + var redimCode = + $@"Option Explicit + +Private Sub InitializeArray(size As Long) + Redim myArray(size) + Dim idx As Long + For idx = 1 To size + myArray(idx) = idx + Next idx +End Sub +"; + var presenterAction = Support.UserAcceptsDefaults(convertFieldToUDTMember: convertField); + + var vbe = MockVbeBuilder.BuildFromStdModules(("SourceModule", inputCode), ("ClientModule", redimCode)); + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe.Object, fieldUT, DeclarationType.Variable, presenterAction); + + model[fieldUT].TryValidateEncapsulationAttributes(out var errorMessage); + + StringAssert.AreNotEqualIgnoringCase(EncapsulateFieldResources.ArrayHasExternalRedimFormat, errorMessage); + } + + protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) + => Support.SupportTestRefactoring(rewritingManager, state, factory, selectionService); + } +} diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs index dd6a408cf3..fb4c875805 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs @@ -362,54 +362,31 @@ End Enum } //5.3.1 The declared type of a function declaration may not be a private enum name. - [TestCase("Public")] - [TestCase("Private")] + [TestCase("Public", null)] + [TestCase("Private", null)] + [TestCase("Public", ", foo As Long, bar As String")] + [TestCase("Private", ", foo As Long, bar As String")] [Category("Refactorings")] [Category("Encapsulate Field")] - public void EncapsulateEnumField_PrivateEnum(string fieldAccessibility) + public void EncapsulateEnumField(string enumTypeAccessibility, string declarationList) { string inputCode = $@" -Private Enum NumberTypes - Whole = -1 - Integral = 0 - Rational = 1 -End Enum - -{fieldAccessibility} numberT|ype As NumberTypes -"; - - var presenterAction = Support.UserAcceptsDefaults(); - var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - StringAssert.Contains("Private numberType_1 As NumberTypes", actualCode); - StringAssert.Contains("Public Property Get NumberType() As Long", actualCode); - StringAssert.Contains("NumberType = numberType_1", actualCode); - } - - //5.3.1 The declared type of a function declaration may not be a private enum name. - [Test] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void EncapsulatePrivateEnumFieldInList_PrivateEnum() - { - const string inputCode = - @" - -Private Enum NumberTypes +{enumTypeAccessibility} Enum NumberTypes Whole = -1 Integral = 0 Rational = 1 End Enum -Public foo As Long, bar As String, numberT|ype As NumberTypes, fooBar As Variant +Private numberT|ype As NumberTypes{declarationList ?? string.Empty} "; var presenterAction = Support.UserAcceptsDefaults(); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - StringAssert.Contains("Public foo As Long", actualCode); + var expectedPropertyType = enumTypeAccessibility == "Public" ? "NumberTypes" : "Long"; StringAssert.Contains("Private numberType_1 As NumberTypes", actualCode); - StringAssert.Contains("Public Property Get NumberType() As Long", actualCode); + StringAssert.Contains($"Public Property Get NumberType() As {expectedPropertyType}", actualCode); StringAssert.Contains("NumberType = numberType_1", actualCode); } @@ -470,7 +447,7 @@ public void EncapsulatePrivateField_DefaultsAsUDT() const string inputCode = @"|Private fizz As Integer"; - var presenterAction = Support.UserAcceptsDefaults(asUDT: true); + var presenterAction = Support.UserAcceptsDefaults(convertFieldToUDTMember: true); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.Contains("Fizz As Integer", actualCode); StringAssert.Contains($"this As {Support.StateUDTDefaultType}", actualCode); @@ -643,137 +620,6 @@ End Property Assert.AreEqual(expectedCode.Trim(), actualCode); } - [TestCase("Private", "mArray(5) As String", "mArray(5) As String")] - [TestCase("Public", "mArray(5) As String", "mArray(5) As String")] - [TestCase("Private", "mArray(5,2,3) As String", "mArray(5,2,3) As String")] - [TestCase("Public", "mArray(5,2,3) As String", "mArray(5,2,3) As String")] - [TestCase("Private", "mArray(1 to 10) As String", "mArray(1 to 10) As String")] - [TestCase("Public", "mArray(1 to 10) As String", "mArray(1 to 10) As String")] - [TestCase("Private", "mArray() As String", "mArray() As String")] - [TestCase("Public", "mArray() As String", "mArray() As String")] - [TestCase("Private", "mArray(5)", "mArray(5) As Variant")] - [TestCase("Public", "mArray(5)", "mArray(5) As Variant")] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void EncapsulateArray(string visibility, string arrayDeclaration, string expectedArrayDeclaration) - { - string inputCode = - $@"Option Explicit - -{visibility} {arrayDeclaration}"; - - var selection = new Selection(3, 8, 3, 11); - - string expectedCode = - $@"Option Explicit - -Private {expectedArrayDeclaration} - -Public Property Get MyArray() As Variant - MyArray = mArray -End Property -"; - var userInput = new UserInputDataObject() - .UserSelectsField("mArray", "MyArray"); - - var presenterAction = Support.SetParameters(userInput); - var actualCode = RefactoredCode(inputCode, selection, presenterAction); - Assert.AreEqual(expectedCode.Trim(), actualCode); - } - - [TestCase("5")] - [TestCase("5,2,3")] - [TestCase("1 to 100")] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void EncapsulateArray_DeclaredInList(string dimensions) - { - string inputCode = - $@"Option Explicit - -Public mArray({dimensions}) As String, anotherVar As Long, andOneMore As Variant"; - - var selection = new Selection(3, 8, 3, 11); - - string expectedCode = - $@"Option Explicit - -Public anotherVar As Long, andOneMore As Variant -Private mArray({dimensions}) As String - -Public Property Get MyArray() As Variant - MyArray = mArray -End Property -"; - var presenterAction = Support.SetParametersForSingleTarget("mArray", "MyArray"); - var actualCode = RefactoredCode(inputCode, selection, presenterAction); - StringAssert.Contains("Public anotherVar As Long, andOneMore As Variant", actualCode); - StringAssert.Contains($"Private mArray({dimensions}) As String", actualCode); - StringAssert.Contains("Get MyArray() As Variant", actualCode); - StringAssert.Contains("MyArray = mArray", actualCode); - StringAssert.DoesNotContain("Let MyArray", actualCode); - StringAssert.DoesNotContain("Set MyArray", actualCode); - } - - [TestCase("mArr|ay(5) As String, mNextVar As Long", "Private mArray(5) As String")] - [TestCase("mNextVar As Long, mArr|ay(5) As String", "Private mArray(5) As String")] - [TestCase("mArr|ay(5), mNextVar As Long", "Private mArray(5) As Variant")] - [TestCase("mNextVar As Long, mAr|ray(5)", "Private mArray(5) As Variant")] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void EncapsulateArray_newFieldNameForFieldInList(string declarationList, string expectedDeclaration) - { - string inputCode = - $@"Option Explicit - -Public {declarationList}"; - - string expectedCode = - $@"Option Explicit - -Public mNextVar As Long - -{expectedDeclaration} - -Public Property Get MyArray() As Variant - MyArray = mArray -End Property -"; - var presenterAction = Support.SetParametersForSingleTarget("mArray", "MyArray"); - var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - Assert.AreEqual(expectedCode.Trim(), actualCode); - } - - //Consider... - //https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/can-t-redim-erase-or-assign-to-variant-that-contains-array-whose-element-is-with - //https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/constants-fixed-length-strings-arrays-user-defined-types-and-declare-statements - [Test] - [Ignore("Resolve use of Redim locally and externally")] - [Category("Refactorings")] - [Category("Encapsulate Field")] - public void EncapsulateArray_Redim() - { - string inputCode = - $@"Option Explicit - -Private myA|rray() As Integer - -Private Sub InitializeArray(size As Long) - Redim myArray(size) - For idx = 1 To size - myArray(idx) = idx - Next idx -End Sub -"; - - var presenterAction = Support.UserAcceptsDefaults(); - var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - StringAssert.Contains("Public Property Get MyArray() As Variant", actualCode); - StringAssert.DoesNotContain("Public Property Let MyArray(", actualCode); - StringAssert.Contains("Redim myArray_1(size)", actualCode); - StringAssert.Contains("myArray_1(idx) = idx", actualCode); - } - [TestCase(false)] [TestCase(true)] [Category("Refactorings")] diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs index c4219ce096..e38eff9856 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs @@ -31,7 +31,7 @@ public void VBAIdentifier_Property(string originalFieldName, string newPropertyN string inputCode = $@"Public {originalFieldName} As String"; - var encapsulatedField = Support.RetrieveEncapsulatedField(inputCode, originalFieldName); + var encapsulatedField = Support.RetrieveEncapsulateFieldCandidate(inputCode, originalFieldName); encapsulatedField.PropertyName = newPropertyName; encapsulatedField.EncapsulateFlag = true; @@ -100,8 +100,8 @@ Private Function First() As String First = myBar.First End Function"; - var encapsulatedField = Support.RetrieveEncapsulatedField(inputCode, "First", DeclarationType.UserDefinedTypeMember); - var validation = encapsulatedField as IEncapsulateFieldCandidateValidations; + var candidate = Support.RetrieveEncapsulateFieldCandidate(inputCode, "First", DeclarationType.UserDefinedTypeMember); + var validation = candidate as IEncapsulateFieldCandidateValidations; var result = validation.HasConflictingPropertyIdentifier; Assert.AreEqual(true, validation.HasConflictingPropertyIdentifier); } @@ -125,7 +125,7 @@ Public Property Let Fizz_1(ByVal value As String) fizzle = value End Property "; - var encapsulatedField = Support.RetrieveEncapsulatedField(inputCode, "fizz"); + var encapsulatedField = Support.RetrieveEncapsulateFieldCandidate(inputCode, "fizz"); Assert.IsTrue(encapsulatedField.TryValidateEncapsulationAttributes(out _)); } diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs index 8725954304..1208d18dc0 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs @@ -52,7 +52,7 @@ End Type Private this As Long"; - var presenterAction = Support.UserAcceptsDefaults(asUDT: true); + var presenterAction = Support.UserAcceptsDefaults(convertFieldToUDTMember: true); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.Contains("Private this As Long", actualCode); StringAssert.Contains($"Private this_1 As {Support.StateUDTDefaultType}", actualCode); diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs index 2751c37264..9b09e8d17a 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs @@ -35,7 +35,7 @@ Public Property Let Name(ByVal value As String) fizz1 = value End Property "; - var encapsulatedField = Support.RetrieveEncapsulatedField(inputCode, "fizz"); + var encapsulatedField = Support.RetrieveEncapsulateFieldCandidate(inputCode, "fizz"); Assert.IsTrue(encapsulatedField.TryValidateEncapsulationAttributes(out _)); } @@ -46,7 +46,7 @@ public void FieldNameValuesPerSequenceOfPropertyNameChanges() { string inputCode = "Public fizz As String"; - var encapsulatedField = Support.RetrieveEncapsulatedField(inputCode, "fizz"); + var encapsulatedField = Support.RetrieveEncapsulateFieldCandidate(inputCode, "fizz"); StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.FieldIdentifier); encapsulatedField.PropertyName = "Test"; @@ -69,7 +69,7 @@ public void PropertyNameChange_UniqueParamName() { string inputCode = "Public value As String"; - var encapsulatedField = Support.RetrieveEncapsulatedField(inputCode, "value"); + var encapsulatedField = Support.RetrieveEncapsulateFieldCandidate(inputCode, "value"); encapsulatedField.PropertyName = "Test"; StringAssert.AreEqualIgnoringCase("value_value", encapsulatedField.ParameterName); diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index 46acf74430..6572694a31 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -32,11 +32,11 @@ private TestEncapsulationAttributes UserModifiedEncapsulationAttributes(string f return testAttrs; } - public Func UserAcceptsDefaults(bool asUDT = false) + public Func UserAcceptsDefaults(bool convertFieldToUDTMember = false) { return model => { - model.ConvertFieldsToUDTMembers = asUDT; + model.ConvertFieldsToUDTMembers = convertFieldToUDTMember; return model; }; } @@ -117,26 +117,20 @@ public IRefactoring SupportTestRefactoring(IRewritingManager rewritingManager, R return new EncapsulateFieldRefactoring(state, indenter, factory, rewritingManager, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); } - public IEncapsulateFieldCandidate RetrieveEncapsulatedField(string inputCode, string fieldName) + public IEncapsulateFieldCandidate RetrieveEncapsulateFieldCandidate(string inputCode, string fieldName) { var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; - - var selectedComponentName = vbe.SelectedVBComponent.Name; - - var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); - using (state) - { - var match = state.DeclarationFinder.MatchName(fieldName).Single(); - return new EncapsulateFieldCandidate(match, new EncapsulateFieldValidator(state)) as IEncapsulateFieldCandidate; - } + return RetrieveEncapsulateFieldCandidate(vbe, fieldName); } - public IEncapsulateFieldCandidate RetrieveEncapsulatedField(string inputCode, string fieldName, DeclarationType declarationType) + public IEncapsulateFieldCandidate RetrieveEncapsulateFieldCandidate(string inputCode, string fieldName, DeclarationType declarationType) { var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; + return RetrieveEncapsulateFieldCandidate(vbe, fieldName, declarationType); + } - var selectedComponentName = vbe.SelectedVBComponent.Name; - + public IEncapsulateFieldCandidate RetrieveEncapsulateFieldCandidate(IVBE vbe, string fieldName, DeclarationType declarationType = DeclarationType.Variable) + { var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); using (state) { From 9d0fcb27093d4e227e72bfde0737ab531aec1e27 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Tue, 31 Dec 2019 06:40:01 -0800 Subject: [PATCH 088/461] Fixed preexisting UDTMembers name change bug When converting fields to UDTMembers, UDTMember identifiers that pre-existed the refactoring where being updated to non-conflict names...but they should remain constant. --- .../EncapsulateFieldViewModel.cs | 1 + .../EncapsulateField/EncapsulateFieldModel.cs | 22 ++++++++--- .../EncapsulateFieldRefactoring.cs | 17 ++++---- .../FieldCandidates/ObjectStateUDT.cs | 14 +++++++ .../UserDefinedTypeCandidate.cs | 4 +- .../UserDefinedTypeMemberCandidate.cs | 25 ++++++++++-- .../EncapsulateFieldValidatorTests.cs | 2 +- .../EncapsulateUsingStateUDTTests.cs | 39 ++++++++++++++++++- .../EncapsulateField/TestSupport.cs | 16 ++++---- 9 files changed, 111 insertions(+), 29 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs index 587417436b..223afc17b3 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs @@ -273,6 +273,7 @@ public bool ConvertFieldsToUDTMembers ReloadListAndPreview(); RefreshValidationResults(); UpdateDetailForSelection(); + OnPropertyChanged(nameof(ShowStateUDTSelections)); } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index 126def7513..f08152cd6b 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -24,7 +24,7 @@ public EncapsulateFieldModel(Declaration target, IEnumerable EncapsulationCandidates { set; get; } = new List(); @@ -54,15 +54,25 @@ public bool ConvertFieldsToUDTMembers set { _convertFieldsToUDTMembers = value; - foreach (var candidate in EncapsulationCandidates) - { - candidate.ConvertFieldToUDTMember = value; - } + SetFieldsToUDTMemberFlags(value); } get => _convertFieldsToUDTMembers; } - public IObjectStateUDT StateUDTField { set; get; } + private IObjectStateUDT _activeObjectStateUDT; + public IObjectStateUDT StateUDTField + { + set => _activeObjectStateUDT = value; + get => _activeObjectStateUDT ?? _newObjectStateUDT; + } + + private void SetFieldsToUDTMemberFlags(bool value) + { + foreach (var candidate in EncapsulationCandidates) + { + candidate.ConvertFieldToUDTMember = value; + } + } public string PreviewRefactoring() => _previewDelegate(this); diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 9644c52e15..39dcb0ac82 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -98,25 +98,28 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) objectStateUDT.IsSelected = true; forceUseOfObjectStateUDT = true; } - else - { - objectStateUDT = _encapsulationCandidateFactory.CreateStateUDTField(); - objectStateUDT.IsSelected = true; - } + + var defaultStateUDT = _encapsulationCandidateFactory.CreateStateUDTField(); + defaultStateUDT.IsSelected = objectStateUDT is null; Model = new EncapsulateFieldModel( target, candidates, - objectStateUDT, + defaultStateUDT, PreviewRewrite, validator); + if (forceUseOfObjectStateUDT) + { + Model.ConvertFieldsToUDTMembers = true; + Model.StateUDTField = objectStateUDT; + } + _codeSectionStartIndex = _declarationFinderProvider.DeclarationFinder .Members(_targetQMN).Where(m => m.IsMember()) .OrderBy(c => c.Selection) .FirstOrDefault()?.Context.Start.TokenIndex ?? null; - Model.ConvertFieldsToUDTMembers = forceUseOfObjectStateUDT; return Model; } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs index 317abdadfe..c0074837da 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs @@ -22,6 +22,7 @@ public interface IObjectStateUDT : IEncapsulateFieldDeclaration Declaration AsTypeDeclaration { get; } bool IsSelected { set; get; } bool IsEncapsulateFieldCandidate(IEncapsulateFieldCandidate efc); + IEnumerable ExistingMembers { get; } } //ObjectStateUDT can be an existing UDT (Private only) selected by the user, or a @@ -66,6 +67,19 @@ private ObjectStateUDT(string typeIdentifier) public bool IsSelected { set; get; } + public IEnumerable ExistingMembers + { + get + { + if (IsExistingDeclaration) + { + return _wrappedUDT.Members; + } + return Enumerable.Empty(); + } + } + + private QualifiedModuleName _qmn; public QualifiedModuleName QualifiedModuleName { diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs index fcef6b1eaf..bd07a20545 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs @@ -83,10 +83,10 @@ public override bool EncapsulateFlag { if (TypeDeclarationIsPrivate) { - foreach (var member in Members) + foreach (var member in Members.Where(m => !m.ConvertFieldToUDTMember && m.IsExistingMember)) { member.EncapsulateFlag = value; - if (!_validator.HasConflictingIdentifier(member, DeclarationType.Property, out _)) + if (!member.EncapsulateFlag || !_validator.HasConflictingIdentifier(member, DeclarationType.Property, out _)) { continue; } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs index 3ea6c677c0..563e0fdd40 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs @@ -16,6 +16,7 @@ public interface IUserDefinedTypeMemberCandidate : IEncapsulateFieldCandidate Dictionary IdentifierReplacements { get; } IEnumerable ParentContextReferences { get; } void LoadReferenceExpressions(); + bool IsExistingMember { get; } } public class UserDefinedTypeMemberCandidate : IUserDefinedTypeMemberCandidate @@ -167,11 +168,24 @@ public bool IsReadOnly set => _wrappedCandidate.IsReadOnly = value; get => _wrappedCandidate.IsReadOnly; } + + private bool _encapsulateFlag; public bool EncapsulateFlag { - set => _wrappedCandidate.EncapsulateFlag = value; - get => _wrappedCandidate.EncapsulateFlag; + set + { + _encapsulateFlag = value; + if (!IsExistingMember) + { + _wrappedCandidate.EncapsulateFlag = value; + } + } + + get => _encapsulateFlag; //=> _wrappedCandidate.EncapsulateFlag; } + + public bool IsExistingMember => _wrappedCandidate.Declaration.ParentDeclaration.DeclarationType is DeclarationType.UserDefinedType; + public string FieldIdentifier { set => _wrappedCandidate.FieldIdentifier = value; @@ -208,7 +222,12 @@ public string AsTypeName_Property public bool ImplementSet => _wrappedCandidate.ImplementSet; - public bool ConvertFieldToUDTMember { set; get; } + private bool _convertFieldToUDTMember; + public bool ConvertFieldToUDTMember + { + set => _convertFieldToUDTMember = value; + get => false; + } public IEnumerable PropertyAttributeSets => _wrappedCandidate.PropertyAttributeSets; public string AsUDTMemberDeclaration diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs index e38eff9856..7c495c5337 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs @@ -509,7 +509,7 @@ public void UDTReservedMemberArrayIdentifier() var userInput = new UserInputDataObject() .UserSelectsField(fieldName); - userInput.EncapsulateAsUDT = true; + userInput.ConvertFieldsToUDTMembers = true; var presenterAction = Support.SetParameters(userInput); diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs index 1208d18dc0..cf7cea80ef 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs @@ -144,12 +144,10 @@ Public foobar As Byte .UserSelectsField("foobar"); userInput.EncapsulateUsingUDTField("myBar"); - //userInput.ObjectStateUDTTargetID = "myBar"; var presenterAction = Support.SetParameters(userInput); var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.DoesNotContain($"Private this As {Support.StateUDTDefaultType}", actualCode); - //StringAssert.Contains($"Private Type {Support.StateUDTDefaultType}", actualCode); StringAssert.Contains("Foo As Long", actualCode); StringAssert.DoesNotContain("Public foo As Long", actualCode); StringAssert.Contains("Bar As String", actualCode); @@ -162,6 +160,43 @@ Public foobar As Byte StringAssert.Contains("Second As Long", actualCode); } + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void DoesNotChangeExistingUDTMembers() + { + string inputCode = +$@" +Private Type T{MockVbeBuilder.TestModuleName} + Name As String +End Type + +Private this As T{MockVbeBuilder.TestModuleName} + +Public foo As Long +Public bar As String +Public foo|bar As Byte + +Public Property Let Name(value As String) + this.Name = value +End Property + +Public Property Get Name() As String + Name = this.Name +End Property +"; + + var userInput = new UserInputDataObject() + .UserSelectsField("foobar"); + + userInput.EncapsulateUsingUDTField($"T{MockVbeBuilder.TestModuleName}"); + + var presenterAction = Support.SetParameters(userInput); + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + StringAssert.DoesNotContain($"Name_1 As String", actualCode); + StringAssert.DoesNotContain($"ThisName As String", actualCode); + } + [Test] [Category("Refactorings")] [Category("Encapsulate Field")] diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index 6572694a31..c54572273d 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -64,8 +64,8 @@ public Func SetParameters(UserInpu { return model => { - model.ConvertFieldsToUDTMembers = userInput.EncapsulateAsUDT; - if (userInput.EncapsulateAsUDT) + model.ConvertFieldsToUDTMembers = userInput.ConvertFieldsToUDTMembers; + if (userInput.ConvertFieldsToUDTMembers) { var stateUDT = model.EncapsulationCandidates.Where(sfc => sfc is IUserDefinedTypeCandidate udt && udt.TargetID == userInput.ObjectStateUDTTargetID) .Select(sfc => sfc as IUserDefinedTypeCandidate).SingleOrDefault(); @@ -79,7 +79,7 @@ public Func SetParameters(UserInpu foreach (var testModifiedAttribute in userInput.EncapsulateFieldAttributes) { - var attrsInitializedByTheRefactoring = model[testModifiedAttribute.TargetFieldName]; //.EncapsulationAttributes; + var attrsInitializedByTheRefactoring = model[testModifiedAttribute.TargetFieldName]; attrsInitializedByTheRefactoring.PropertyName = testModifiedAttribute.PropertyName; attrsInitializedByTheRefactoring.EncapsulateFlag = testModifiedAttribute.EncapsulateFlag; @@ -89,7 +89,7 @@ public Func SetParameters(UserInpu }; } - public Func SetParameters(string originalField, TestEncapsulationAttributes attrs, bool asUDT = false) + public Func SetParameters(string originalField, TestEncapsulationAttributes attrs, bool convertFieldsToUDTMembers = false) { return model => { @@ -98,7 +98,7 @@ public Func SetParameters(string o encapsulatedField.IsReadOnly = attrs.IsReadOnly; encapsulatedField.EncapsulateFlag = attrs.EncapsulateFlag; - model.ConvertFieldsToUDTMembers = asUDT; + model.ConvertFieldsToUDTMembers = convertFieldsToUDTMembers; return model; }; } @@ -139,7 +139,7 @@ public IEncapsulateFieldCandidate RetrieveEncapsulateFieldCandidate(IVBE vbe, st } } - public EncapsulateFieldModel RetrieveUserModifiedModelPriorToRefactoring(IVBE vbe, string declarationName, DeclarationType declarationType, Func presenterAdjustment) //, params string[] fieldIdentifiers) + public EncapsulateFieldModel RetrieveUserModifiedModelPriorToRefactoring(IVBE vbe, string declarationName, DeclarationType declarationType, Func presenterAdjustment) { var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); using (state) @@ -217,12 +217,12 @@ public UserInputDataObject AddUserInputSet(string fieldName, string propertyName return this; } - public bool EncapsulateAsUDT { set; get; } + public bool ConvertFieldsToUDTMembers { set; get; } public void EncapsulateUsingUDTField(string targetID = null) { ObjectStateUDTTargetID = targetID; - EncapsulateAsUDT = true; + ConvertFieldsToUDTMembers = true; } public string ObjectStateUDTTargetID { set; get; } From 30afa7e086ac9144a0762890b2bbea1a82befcb6 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Tue, 31 Dec 2019 08:28:43 -0800 Subject: [PATCH 089/461] Added two failing tests and resolutions --- .../EncapsulateFieldValidator.cs | 8 ++ .../EncapsulateFieldCandidate.cs | 7 ++ .../FieldCandidates/ObjectStateUDT.cs | 15 +++- .../EncapsulateFieldValidatorTests.cs | 83 ++++++++++++++++--- .../EncapsulateUsingStateUDTTests.cs | 6 +- .../EncapsulateField/TestSupport.cs | 8 ++ 6 files changed, 109 insertions(+), 18 deletions(-) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs index 447bc366dd..ebeeda5d19 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -93,6 +93,14 @@ private List PotentialConflictIdentifiers(IEncapsulateFieldCandidate can var members = DeclarationFinder.Members(candidate.QualifiedModuleName) .Where(d => d != candidate.Declaration); + if (candidate.ConvertFieldToUDTMember) + { + var membersToRemove = FieldCandidates.Where(fc => fc.EncapsulateFlag && fc.Declaration.DeclarationType.HasFlag(DeclarationType.Variable)) + .Select(fc => fc.Declaration); + + members = members.Except(membersToRemove); + } + var nameConflictCandidates = members .Where(d => !IsAlwaysIgnoreNameConflictType(d, declarationType)).ToList(); diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs index efbdf464df..79ed7ee857 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs @@ -139,6 +139,12 @@ protected virtual bool TryValidateAsUDTMemberEncapsulationAttributes(out string { return false; } + + if (!TryValidateEncapsulationAttributes(DeclarationType.Property, out errorMessage, isArray)) + { + return false; + } + return TryValidateEncapsulationAttributes(Declaration.DeclarationType, out errorMessage, isArray); } @@ -161,6 +167,7 @@ protected bool TryValidateEncapsulationAttributes(DeclarationType declarationTyp { return false; } + return true; } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs index c0074837da..a8064c0d2b 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs @@ -44,7 +44,6 @@ public ObjectStateUDT(IUserDefinedTypeCandidate udt) FieldIdentifier = udt.IdentifierName; _wrappedUDT = udt; - udt.EncapsulateFlag = false; _hashCode = ($"{_qmn.Name}.{_wrappedUDT.IdentifierName}").GetHashCode(); } @@ -65,7 +64,19 @@ private ObjectStateUDT(string typeIdentifier) public string AsTypeName => _wrappedUDT?.AsTypeName ?? TypeIdentifier; - public bool IsSelected { set; get; } + private bool _isSelected; + public bool IsSelected + { + set + { + _isSelected = value; + if (_isSelected && IsExistingDeclaration) + { + _wrappedUDT.EncapsulateFlag = false; + } + } + get => _isSelected; + } public IEnumerable ExistingMembers { diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs index 7c495c5337..f1dadd5778 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs @@ -155,8 +155,7 @@ End Property var presenterAction = Support.SetParameters(userInput); - var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; - var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, fieldUT, DeclarationType.Variable, presenterAction); + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(inputCode, fieldUT, DeclarationType.Variable, presenterAction); Assert.IsFalse(model["fizz"].TryValidateEncapsulationAttributes(out _)); } @@ -188,8 +187,7 @@ Public Property Get Test() As Integer var presenterAction = Support.SetParameters(userInput); - var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; - var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, fieldUT, DeclarationType.Variable, presenterAction); + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(inputCode, fieldUT, DeclarationType.Variable, presenterAction); Assert.AreEqual(fizz_expectedResult, model["fizz"].TryValidateEncapsulationAttributes(out _), "fizz failed"); Assert.AreEqual(bazz_expectedResult, model["bazz"].TryValidateEncapsulationAttributes(out _), "bazz failed"); @@ -221,8 +219,7 @@ End Type var presenterAction = Support.SetParameters(userInput); - var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; - var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, fieldUT, DeclarationType.Variable, presenterAction); + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(inputCode, fieldUT, DeclarationType.Variable, presenterAction); Assert.AreEqual(true, model[fieldUT].TryValidateEncapsulationAttributes(out var message), message); } @@ -244,8 +241,7 @@ Public wholeNumber As String var presenterAction = Support.SetParameters(userInput); - var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; - var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, fieldUT, DeclarationType.Variable, presenterAction); + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(inputCode, fieldUT, DeclarationType.Variable, presenterAction); Assert.AreEqual(false, model[fieldUT].TryValidateEncapsulationAttributes(out _)); } @@ -310,8 +306,7 @@ public void DefaultPropertyNameConflictsResolved() var presenterAction = Support.UserAcceptsDefaults(fieldUT, "strTest"); - var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; - var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, fieldUT, DeclarationType.Variable, presenterAction); + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(inputCode, fieldUT, DeclarationType.Variable, presenterAction); Assert.AreEqual(true, model[fieldUT].TryValidateEncapsulationAttributes(out var errorMsg), errorMsg); } @@ -363,8 +358,7 @@ End Function var presenterAction = Support.SetParameters(userInput); - var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; - var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, fieldUT, DeclarationType.Variable, presenterAction); + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(inputCode, fieldUT, DeclarationType.Variable, presenterAction); Assert.AreEqual(false, model[fieldUT].TryValidateEncapsulationAttributes(out _)); } @@ -521,6 +515,71 @@ public void UDTReservedMemberArrayIdentifier() Assert.AreEqual(false, model[fieldName].TryValidateEncapsulationAttributes(out var message), message); } + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserEntersUDTMemberPropertyNameInConflictWithExistingField() + { + const string inputCode = + @" + +Private Type TVehicle + Wheels As Integer + MPG As Double +End Type + +Private vehicle As TVehicle + +Private seats As Integer + +Private foo As String +"; + var userInput = new UserInputDataObject() + .UserSelectsField("seats", "Foo"); + + userInput.ConvertFieldsToUDTMembers = true; + userInput.ObjectStateUDTTargetID = "TVehicle"; + + var presenterAction = Support.SetParameters(userInput); + + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(inputCode, "seats", DeclarationType.Variable, presenterAction); + Assert.AreEqual(false, model["seats"].TryValidateEncapsulationAttributes(out var errorMessage), errorMessage); + } + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UserClearsConflictingNameByEncapsulatingConflictingVariable() + { + const string inputCode = + @" + +Private Type TVehicle + Wheels As Integer + MPG As Double +End Type + +Private mVehicle As TVehicle + +Private seats As Integer + +Private foo As String +"; + //By encapsulating variable mVehicle, the variable disappears and + //is converted to UDTMember name "Vehicle" and "Vehicle" properties + // - thus removing the conflict created by the user editing the "seats" property + var userInput = new UserInputDataObject() + .UserSelectsField("seats", "MVehicle") + .UserSelectsField("mVehicle"); + + userInput.ConvertFieldsToUDTMembers = true; + + var presenterAction = Support.SetParameters(userInput); + + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(inputCode, "seats", DeclarationType.Variable, presenterAction); + Assert.AreEqual(true, model["seats"].TryValidateEncapsulationAttributes(out var errorMessage), errorMessage); + } + protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) { return Support.SupportTestRefactoring(rewritingManager, state, factory, selectionService); diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs index cf7cea80ef..e486286be9 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs @@ -281,8 +281,7 @@ Public myBar As TBar userInput.EncapsulateUsingUDTField(); var presenterAction = Support.SetParameters(userInput); - var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; - var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, "myBar", DeclarationType.Variable, presenterAction); + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(inputCode, "myBar", DeclarationType.Variable, presenterAction); Assert.AreEqual(1, model.ObjectStateUDTCandidates.Count()); } @@ -431,8 +430,7 @@ Private mFizz var presenterAction = Support.SetParameters(userInput); - var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; - var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe, "mFizz", DeclarationType.Variable, presenterAction); + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(inputCode, "mFizz", DeclarationType.Variable, presenterAction); var test = model.ObjectStateUDTCandidates; Assert.AreEqual(2, model.ObjectStateUDTCandidates.Count()); diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index c54572273d..e86968431f 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -139,6 +139,14 @@ public IEncapsulateFieldCandidate RetrieveEncapsulateFieldCandidate(IVBE vbe, st } } + + + public EncapsulateFieldModel RetrieveUserModifiedModelPriorToRefactoring(string inputCode, string declarationName, DeclarationType declarationType, Func presenterAdjustment) + { + var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; + return RetrieveUserModifiedModelPriorToRefactoring(vbe, declarationName, declarationType, presenterAdjustment); + } + public EncapsulateFieldModel RetrieveUserModifiedModelPriorToRefactoring(IVBE vbe, string declarationName, DeclarationType declarationType, Func presenterAdjustment) { var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); From aefff96629942a4a2285e6d9f94317b38c6a22a8 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Tue, 31 Dec 2019 16:57:25 -0800 Subject: [PATCH 090/461] Refactoring - WIP Returned to strategy pattern for the two methods of encapsulation supported by the refactoring. More files...but clearer code. --- .../EncapsulateFieldElementFactory.cs | 34 +-- .../EncapsulateField/EncapsulateFieldModel.cs | 8 +- .../EncapsulateFieldRefactoring.cs | 258 +++--------------- .../EncapsulateFieldValidator.cs | 69 +---- .../ConvertFieldsToUDTMembers.cs | 58 ++++ .../EncapsulateFieldStrategyBase.cs | 121 ++++++++ .../UseBackingFields.cs | 73 +++++ .../FieldCandidates/ArrayCandidate.cs | 5 +- .../EncapsulateFieldCandidate.cs | 83 ++++-- .../EncapsulationIdentifiers.cs | 17 +- .../UserDefinedTypeCandidate.cs | 19 +- .../UserDefinedTypeMemberCandidate.cs | 5 +- .../EncapsulationIdentifiersTests.cs | 4 +- .../EncapsulateField/TestSupport.cs | 4 +- 14 files changed, 404 insertions(+), 354 deletions(-) create mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs create mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs create mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/UseBackingFields.cs diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs index 024499ded2..abfb868228 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs @@ -13,34 +13,34 @@ namespace Rubberduck.Refactorings.EncapsulateField public class EncapsulateFieldElementFactory { private readonly IDeclarationFinderProvider _declarationFinderProvider; - private readonly IEncapsulateFieldValidator _validator; - private readonly IValidateEncapsulateFieldNames _namesValidator; + //private readonly IEncapsulateFieldValidator _validator; + //private readonly IValidateEncapsulateFieldNames _namesValidator; private QualifiedModuleName _targetQMN; - public EncapsulateFieldElementFactory(IDeclarationFinderProvider declarationFinderProvider, QualifiedModuleName targetQMN, IEncapsulateFieldValidator validator ) + public EncapsulateFieldElementFactory(IDeclarationFinderProvider declarationFinderProvider, QualifiedModuleName targetQMN)//, IEncapsulateFieldValidator validator ) { _declarationFinderProvider = declarationFinderProvider; - _validator = validator; - _namesValidator = validator as IValidateEncapsulateFieldNames; + //_validator = validator; + //_namesValidator = validator as IValidateEncapsulateFieldNames; _targetQMN = targetQMN; } - public IObjectStateUDT CreateStateUDTField() + public IObjectStateUDT CreateStateUDTField(IEncapsulateFieldValidator validator) { var stateUDT = new ObjectStateUDT(_targetQMN) as IObjectStateUDT; - stateUDT = SetNonConflictIdentifier(stateUDT, c => { return _validator.IsConflictingStateUDTFieldIdentifier(stateUDT); }, (s) => { stateUDT.FieldIdentifier = s; }, () => stateUDT.FieldIdentifier, _namesValidator); + stateUDT = SetNonConflictIdentifier(stateUDT, c => { return validator.IsConflictingStateUDTFieldIdentifier(stateUDT); }, (s) => { stateUDT.FieldIdentifier = s; }, () => stateUDT.FieldIdentifier, validator as IValidateEncapsulateFieldNames); // _namesValidator); - stateUDT = SetNonConflictIdentifier(stateUDT, c => { return _validator.IsConflictingStateUDTTypeIdentifier(stateUDT); }, (s) => { stateUDT.TypeIdentifier = s; }, () => stateUDT.TypeIdentifier, _namesValidator); + stateUDT = SetNonConflictIdentifier(stateUDT, c => { return validator.IsConflictingStateUDTTypeIdentifier(stateUDT); }, (s) => { stateUDT.TypeIdentifier = s; }, () => stateUDT.TypeIdentifier, validator as IValidateEncapsulateFieldNames); // _namesValidator); return stateUDT; } - private IEncapsulateFieldCandidate CreateCandidate(Declaration target) + private IEncapsulateFieldCandidate CreateCandidate(Declaration target, IValidateEncapsulateFieldNames validator) { if (target.IsUserDefinedTypeField()) { - var udtField = new UserDefinedTypeCandidate(target, _namesValidator) as IUserDefinedTypeCandidate; + var udtField = new UserDefinedTypeCandidate(target, validator) as IUserDefinedTypeCandidate; (Declaration udtDeclaration, IEnumerable udtMembers) = GetUDTAndMembersForField(udtField); @@ -48,7 +48,7 @@ private IEncapsulateFieldCandidate CreateCandidate(Declaration target) foreach (var udtMemberDeclaration in udtMembers) { - var candidateUDTMember = new UserDefinedTypeMemberCandidate(CreateCandidate(udtMemberDeclaration), udtField, _namesValidator) as IUserDefinedTypeMemberCandidate; + var candidateUDTMember = new UserDefinedTypeMemberCandidate(CreateCandidate(udtMemberDeclaration, validator), udtField, validator) as IUserDefinedTypeMemberCandidate; udtField.AddMember(candidateUDTMember); } @@ -62,12 +62,12 @@ private IEncapsulateFieldCandidate CreateCandidate(Declaration target) } else if (target.IsArray) { - return new ArrayCandidate(target, _namesValidator); + return new ArrayCandidate(target, validator); } - return new EncapsulateFieldCandidate(target, _namesValidator); + return new EncapsulateFieldCandidate(target, validator); } - public IEnumerable CreateEncapsulationCandidates() + public IEnumerable CreateEncapsulationCandidates(IValidateEncapsulateFieldNames validator) { var fieldDeclarations = _declarationFinderProvider.DeclarationFinder .Members(_targetQMN) @@ -78,10 +78,12 @@ public IEnumerable CreateEncapsulationCandidates() { Debug.Assert(!fieldDeclaration.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)); - var fieldEncapsulationCandidate = CreateCandidate(fieldDeclaration); + var fieldEncapsulationCandidate = CreateCandidate(fieldDeclaration, validator); - _validator.RegisterFieldCandidate(fieldEncapsulationCandidate); + //_namesValidator.AssignNoConflictIdentifier(fieldEncapsulationCandidate, DeclarationType.Property); + //_namesValidator.AssignNoConflictIdentifier(fieldEncapsulationCandidate, DeclarationType.Variable); + //_validator.RegisterFieldCandidate(fieldEncapsulationCandidate); candidates.Add(fieldEncapsulationCandidate); } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index f08152cd6b..525add385f 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -11,22 +11,24 @@ public class EncapsulateFieldModel : IRefactoringModel { private readonly Func _previewDelegate; private QualifiedModuleName _targetQMN; - private IValidateEncapsulateFieldNames _validator; + //private IValidateEncapsulateFieldNames _validator; private IObjectStateUDT _newObjectStateUDT; private IDictionary)> _udtFieldToUdtDeclarationMap = new Dictionary)>(); - public EncapsulateFieldModel(Declaration target, IEnumerable candidates, IObjectStateUDT stateUDTField, Func previewDelegate, IValidateEncapsulateFieldNames validator) + public EncapsulateFieldModel(Declaration target, IEnumerable candidates, IObjectStateUDT stateUDTField, Func previewDelegate, IEncapsulateFieldValidator validator) { _previewDelegate = previewDelegate; _targetQMN = target.QualifiedModuleName; - _validator = validator; _newObjectStateUDT = stateUDTField; + Validator = validator; EncapsulationCandidates = candidates.ToList(); ConvertFieldsToUDTMembers = false; } + public IEncapsulateFieldValidator Validator {set; get;} + public List EncapsulationCandidates { set; get; } = new List(); public IEnumerable SelectedFieldCandidates diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 39dcb0ac82..12dacacba3 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -10,7 +10,6 @@ using Rubberduck.VBEditor.Utility; using System.Collections.Generic; using System; -using Antlr4.Runtime; using Rubberduck.Refactorings.EncapsulateField.Extensions; namespace Rubberduck.Refactorings.EncapsulateField @@ -26,14 +25,6 @@ public class EncapsulateFieldRefactoring : InteractiveRefactoringBase> _newContent { set; get; } - - private int? _codeSectionStartIndex; - - private static string DoubleSpace => $"{Environment.NewLine}{Environment.NewLine}"; public EncapsulateFieldRefactoring( IDeclarationFinderProvider declarationFinderProvider, @@ -50,7 +41,11 @@ public EncapsulateFieldRefactoring( _indenter = indenter; } - public EncapsulateFieldModel Model { set; get; } + public EncapsulateFieldModel TestUserInteractionOnly(Declaration target, Func userInteraction) + { + var model = InitializeModel(target); + return userInteraction(model); + } protected override Declaration FindTargetDeclaration(QualifiedSelection targetSelection) { @@ -65,62 +60,56 @@ protected override Declaration FindTargetDeclaration(QualifiedSelection targetSe return selectedDeclaration; } - public EncapsulateFieldModel TestUserInteractionOnly(Declaration target, Func userInteraction) - { - var model = InitializeModel(target); - return userInteraction(model); - } - protected override EncapsulateFieldModel InitializeModel(Declaration target) { - if (target == null) - { - throw new TargetDeclarationIsNullException(); - } + if (target == null) { throw new TargetDeclarationIsNullException(); } - if (!target.DeclarationType.Equals(DeclarationType.Variable)) - { - throw new InvalidDeclarationTypeException(target); - } + if (!target.DeclarationType.Equals(DeclarationType.Variable)) { throw new InvalidDeclarationTypeException(target); } _targetQMN = target.QualifiedModuleName; - var validator = new EncapsulateFieldValidator(_declarationFinderProvider) as IEncapsulateFieldValidator; - _encapsulationCandidateFactory = new EncapsulateFieldElementFactory(_declarationFinderProvider, _targetQMN, validator); + var validator = new EncapsulateFieldValidator(_declarationFinderProvider); + + var encapsulationCandidateFactory = new EncapsulateFieldElementFactory(_declarationFinderProvider, _targetQMN); + + var candidates = encapsulationCandidateFactory.CreateEncapsulationCandidates(validator as IValidateEncapsulateFieldNames); + + validator.RegisterFieldCandidates(candidates); + + foreach (var candidate in candidates) + { + if (candidate is IAssignNoConflictNames namer) + { + namer.AssignIdentifiers(validator); + } + } - var candidates = _encapsulationCandidateFactory.CreateEncapsulationCandidates(); var selected = candidates.Single(c => c.Declaration == target); selected.EncapsulateFlag = true; - var forceUseOfObjectStateUDT = false; + var defaultObjectStateUDT = encapsulationCandidateFactory.CreateStateUDTField(validator); + defaultObjectStateUDT.IsSelected = true; + if (TryRetrieveExistingObjectStateUDT(target, candidates, out var objectStateUDT)) { objectStateUDT.IsSelected = true; - forceUseOfObjectStateUDT = true; + defaultObjectStateUDT.IsSelected = false; } - var defaultStateUDT = _encapsulationCandidateFactory.CreateStateUDTField(); - defaultStateUDT.IsSelected = objectStateUDT is null; - - Model = new EncapsulateFieldModel( + var model = new EncapsulateFieldModel( target, candidates, - defaultStateUDT, + defaultObjectStateUDT, PreviewRewrite, validator); - if (forceUseOfObjectStateUDT) + if (objectStateUDT != null) { - Model.ConvertFieldsToUDTMembers = true; - Model.StateUDTField = objectStateUDT; + model.StateUDTField = objectStateUDT; + model.ConvertFieldsToUDTMembers = true; } - _codeSectionStartIndex = _declarationFinderProvider.DeclarationFinder - .Members(_targetQMN).Where(m => m.IsMember()) - .OrderBy(c => c.Selection) - .FirstOrDefault()?.Context.Start.TokenIndex ?? null; - - return Model; + return model; } //Identify an existing objectStateUDT and make it unavailable for the user to select for encapsulation. @@ -154,6 +143,7 @@ private bool TryRetrieveExistingObjectStateUDT(Declaration target, IEnumerable field.ReferenceReplacements)) - { - (ParserRuleContext Context, string Text) = rewriteReplacement.Value; - var rewriter = refactorRewriteSession.CheckOutModuleRewriter(rewriteReplacement.Key.QualifiedModuleName); - rewriter.Replace(Context, Text); - } - } - - private void ModifyFields(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) - { - if (model.ConvertFieldsToUDTMembers) - { - IModuleRewriter rewriter; - - foreach (var field in model.SelectedFieldCandidates) - { - rewriter = refactorRewriteSession.CheckOutModuleRewriter(_targetQMN); - - refactorRewriteSession.Remove(field.Declaration, rewriter); - } - - if (!model.StateUDTField.IsExistingDeclaration) - { - return; - } - - var stateUDT = model.StateUDTField; - - stateUDT.AddMembers(model.SelectedFieldCandidates); - - rewriter = refactorRewriteSession.CheckOutModuleRewriter(_targetQMN); + var strategy = model.ConvertFieldsToUDTMembers + ? new ConvertFieldsToUDTMembers(_declarationFinderProvider, _targetQMN, _indenter) as IEncapsulateStrategy + : new UseBackingFields(_declarationFinderProvider, _targetQMN, _indenter) as IEncapsulateStrategy; - rewriter.Replace(stateUDT.AsTypeDeclaration, stateUDT.TypeDeclarationBlock(_indenter)); - - return; - } - - foreach (var field in model.SelectedFieldCandidates) - { - var rewriter = refactorRewriteSession.CheckOutModuleRewriter(_targetQMN); - - if (field.Declaration.HasPrivateAccessibility() && field.FieldIdentifier.Equals(field.Declaration.IdentifierName)) - { - rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); - continue; - } - - if (field.Declaration.IsDeclaredInList() && !field.Declaration.HasPrivateAccessibility()) - { - refactorRewriteSession.Remove(field.Declaration, rewriter); - continue; - } - - rewriter.Rename(field.Declaration, field.FieldIdentifier); - rewriter.SetVariableVisiblity(field.Declaration, Accessibility.Private.TokenString()); - rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); - } + return strategy.RefactorRewrite(model, refactorRewriteSession, asPreview); } - - private void InsertNewContent(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession, bool postPendPreviewMessage = false) - { - _newContent = new Dictionary> - { - { NewContentTypes.PostContentMessage, new List() }, - { NewContentTypes.DeclarationBlock, new List() }, - { NewContentTypes.MethodBlock, new List() }, - { NewContentTypes.TypeDeclarationBlock, new List() } - }; - - var rewriter = refactorRewriteSession.CheckOutModuleRewriter(_targetQMN); - - LoadNewDeclarationBlocks(model); - - LoadNewPropertyBlocks(model); - - if (postPendPreviewMessage) - { - _newContent[NewContentTypes.PostContentMessage].Add(EncapsulateFieldResources.PreviewEndOfChangesMarker); - } - - var newContentBlock = string.Join(DoubleSpace, - (_newContent[NewContentTypes.TypeDeclarationBlock]) - .Concat(_newContent[NewContentTypes.DeclarationBlock]) - .Concat(_newContent[NewContentTypes.MethodBlock]) - .Concat(_newContent[NewContentTypes.PostContentMessage])) - .Trim(); - - - if (_codeSectionStartIndex.HasValue) - { - rewriter.InsertBefore(_codeSectionStartIndex.Value, $"{newContentBlock}{DoubleSpace}"); - } - else - { - rewriter.InsertAtEndOfFile($"{DoubleSpace}{newContentBlock}"); - } - } - - private void LoadNewDeclarationBlocks(EncapsulateFieldModel model) - { - if (model.ConvertFieldsToUDTMembers) - { - if (model.StateUDTField?.IsExistingDeclaration ?? false) { return; } - - model.StateUDTField = _encapsulationCandidateFactory.CreateStateUDTField(); - - model.StateUDTField.AddMembers(model.SelectedFieldCandidates); - - AddCodeBlock(NewContentTypes.TypeDeclarationBlock, model.StateUDTField.TypeDeclarationBlock(_indenter)); - AddCodeBlock(NewContentTypes.DeclarationBlock, model.StateUDTField.FieldDeclarationBlock); - return; - } - - //New field declarations created here were removed from their list within ModifyFields(...) - var fieldsRequiringNewDeclaration = model.SelectedFieldCandidates - .Where(field => field.Declaration.IsDeclaredInList() - && field.Declaration.Accessibility != Accessibility.Private); - - foreach (var field in fieldsRequiringNewDeclaration) - { - var targetIdentifier = field.Declaration.Context.GetText().Replace(field.IdentifierName, field.FieldIdentifier); - var newField = field.Declaration.IsTypeSpecified - ? $"{Tokens.Private} {targetIdentifier}" - : $"{Tokens.Private} {targetIdentifier} {Tokens.As} {field.Declaration.AsTypeName}"; - - AddCodeBlock(NewContentTypes.DeclarationBlock, newField); - } - } - - private void LoadNewPropertyBlocks(EncapsulateFieldModel model) - { - var propertyGenerationSpecs = model.SelectedFieldCandidates - .SelectMany(f => f.PropertyAttributeSets); - - var generator = new PropertyGenerator(); - foreach (var spec in propertyGenerationSpecs) - { - AddCodeBlock(NewContentTypes.MethodBlock, generator.AsPropertyBlock(spec, _indenter)); - } - } - - private void AddCodeBlock(NewContentTypes contentType, string block) - => _newContent[contentType].Add(block); } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs index ebeeda5d19..3c9db3ec39 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs @@ -18,14 +18,13 @@ public interface IValidateEncapsulateFieldNames { bool IsValidVBAIdentifier(string identifier, DeclarationType declarationType, out string errorMessage, bool isArray = false); bool HasConflictingIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType, out string errorMessage); - bool IsSelfConsistent(IEncapsulateFieldCandidate candidate, out string errorMessage); - bool IsConflictingFieldIdentifier(string fieldName, IEncapsulateFieldCandidate candidate, DeclarationType declarationType); - IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType); + bool HasConflictingIdentifierIgnoreEncapsulationFlag(IEncapsulateFieldCandidate field, DeclarationType declarationType, out string errorMessage); + bool IsConflictingProposedIdentifier(string fieldName, IEncapsulateFieldCandidate candidate, DeclarationType declarationType); } public interface IEncapsulateFieldValidator : IObjectStateUDTNamesValidator, IValidateEncapsulateFieldNames { - void RegisterFieldCandidate(IEncapsulateFieldCandidate candidate); + void RegisterFieldCandidates(IEnumerable candidates); } public class EncapsulateFieldValidator : IEncapsulateFieldValidator @@ -45,15 +44,12 @@ public EncapsulateFieldValidator(IDeclarationFinderProvider declarationFinderPro UDTMemberCandidates = new List(); } - public void RegisterFieldCandidate(IEncapsulateFieldCandidate candidate) + public void RegisterFieldCandidates(IEnumerable candidates) { - FieldCandidates.Add(candidate); - AssignNoConflictIdentifier(candidate, DeclarationType.Property); - AssignNoConflictIdentifier(candidate, DeclarationType.Variable); - - if (candidate is IUserDefinedTypeCandidate udt) + FieldCandidates.AddRange(candidates); + foreach (var udtCandidate in candidates.Where(c => c is IUserDefinedTypeCandidate).Cast()) { - foreach (var member in udt.Members) + foreach (var member in udtCandidate.Members) { UDTMemberCandidates.Add(member); } @@ -67,27 +63,6 @@ public bool IsValidVBAIdentifier(string identifier, DeclarationType declarationT return !VBAIdentifierValidator.TryMatchInvalidIdentifierCriteria(identifier, declarationType, out errorMessage, isArray); } - public bool IsSelfConsistent(IEncapsulateFieldCandidate candidate, out string errorMessage) - { - errorMessage = string.Empty; - if (candidate.PropertyName.IsEquivalentVBAIdentifierTo(candidate.FieldIdentifier)) - { - errorMessage = $"{EncapsulateFieldResources.Conflict}: {EncapsulateFieldResources.Property}({candidate.PropertyName}) => {EncapsulateFieldResources.Field}({candidate.FieldIdentifier})"; - return false; - } - if (candidate.PropertyName.IsEquivalentVBAIdentifierTo(candidate.ParameterName)) - { - errorMessage = $"{EncapsulateFieldResources.Conflict}: {EncapsulateFieldResources.Property}({candidate.PropertyName}) => {EncapsulateFieldResources.Parameter}({candidate.ParameterName})"; - return false; - } - if (candidate.FieldIdentifier.IsEquivalentVBAIdentifierTo(candidate.ParameterName)) - { - errorMessage = $"{EncapsulateFieldResources.Conflict}: {EncapsulateFieldResources.Field}({candidate.FieldIdentifier}) => {EncapsulateFieldResources.Parameter}({candidate.ParameterName})"; - return false; - } - return true; - } - private List PotentialConflictIdentifiers(IEncapsulateFieldCandidate candidate, DeclarationType declarationType) { var members = DeclarationFinder.Members(candidate.QualifiedModuleName) @@ -134,7 +109,10 @@ private List PotentialConflictIdentifiers(IObjectStateUDT stateUDT, Decl return potentialDeclarationIdentifierConflicts.ToList(); } - public bool HasConflictingIdentifier(IEncapsulateFieldCandidate field, DeclarationType declarationType, out string errorMessage) + public bool HasConflictingIdentifierIgnoreEncapsulationFlag(IEncapsulateFieldCandidate field, DeclarationType declarationType, out string errorMessage) + => InternalHasConflictingIdentifier(field, declarationType, true, out errorMessage); + + public bool HasConflictingIdentifier(IEncapsulateFieldCandidate field, DeclarationType declarationType, out string errorMessage) => InternalHasConflictingIdentifier(field, declarationType, false, out errorMessage); private bool InternalHasConflictingIdentifier(IEncapsulateFieldCandidate field, DeclarationType declarationType, bool ignoreEncapsulationFlags, out string errorMessage) @@ -166,30 +144,7 @@ private bool InternalHasConflictingIdentifier(IEncapsulateFieldCandidate field, return false; } - public IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType) - { - var isConflictingIdentifier = InternalHasConflictingIdentifier(candidate, declarationType, true, out _); - for (var count = 1; count < 10 && isConflictingIdentifier; count++) - { - var identifier = declarationType.HasFlag(DeclarationType.Property) - ? candidate.PropertyName - : candidate.FieldIdentifier; - - if (declarationType.HasFlag(DeclarationType.Property)) - { - candidate.PropertyName = identifier.IncrementEncapsulationIdentifier(); - } - else - { - candidate.FieldIdentifier = identifier.IncrementEncapsulationIdentifier(); - } - isConflictingIdentifier = InternalHasConflictingIdentifier(candidate, declarationType, true, out _); - } - return candidate; - } - - - public bool IsConflictingFieldIdentifier(string fieldName, IEncapsulateFieldCandidate candidate, DeclarationType declarationType) + public bool IsConflictingProposedIdentifier(string fieldName, IEncapsulateFieldCandidate candidate, DeclarationType declarationType) { var members = PotentialConflictIdentifiers(candidate, declarationType); diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs new file mode 100644 index 0000000000..8973cd1fd1 --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs @@ -0,0 +1,58 @@ +using Antlr4.Runtime; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.VBA; +using Rubberduck.SmartIndenter; +using Rubberduck.VBEditor; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + public class ConvertFieldsToUDTMembers : EncapsulateFieldStrategyBase + { + public ConvertFieldsToUDTMembers(IDeclarationFinderProvider declarationFinderProvider, QualifiedModuleName qmn, IIndenter indenter) + : base(declarationFinderProvider, qmn, indenter) { } + + protected override void ModifyFields(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) + { + var rewriter = refactorRewriteSession.CheckOutModuleRewriter(_targetQMN); + + foreach (var field in model.SelectedFieldCandidates) + { + refactorRewriteSession.Remove(field.Declaration, rewriter); + } + + if (model.StateUDTField.IsExistingDeclaration) + { + model.StateUDTField.AddMembers(model.SelectedFieldCandidates); + + rewriter.Replace(model.StateUDTField.AsTypeDeclaration, model.StateUDTField.TypeDeclarationBlock(_indenter)); + } + } + + protected override void ModifyReferences(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) + { + foreach (var field in model.SelectedFieldCandidates) + { + field.LoadFieldReferenceContextReplacements(model.StateUDTField.FieldIdentifier); + } + + RewriteReferences(model, refactorRewriteSession); + } + + protected override void LoadNewDeclarationBlocks(EncapsulateFieldModel model) + { + if (model.StateUDTField.IsExistingDeclaration) { return; } + + model.StateUDTField.AddMembers(model.SelectedFieldCandidates); + + AddContentBlock(NewContentTypes.TypeDeclarationBlock, model.StateUDTField.TypeDeclarationBlock(_indenter)); + + AddContentBlock(NewContentTypes.DeclarationBlock, model.StateUDTField.FieldDeclarationBlock); + return; + } + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs new file mode 100644 index 0000000000..5858ee8165 --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs @@ -0,0 +1,121 @@ +using Antlr4.Runtime; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.Refactorings.EncapsulateField.Extensions; +using Rubberduck.SmartIndenter; +using Rubberduck.VBEditor; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + public interface IEncapsulateStrategy + { + IEncapsulateFieldRewriteSession RefactorRewrite(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession, bool asPreview); + } + + public abstract class EncapsulateFieldStrategyBase : IEncapsulateStrategy + { + protected readonly IIndenter _indenter; + protected QualifiedModuleName _targetQMN; + private readonly int? _codeSectionStartIndex; + + protected enum NewContentTypes { TypeDeclarationBlock, DeclarationBlock, MethodBlock, PostContentMessage }; + protected Dictionary> _newContent { set; get; } + private static string DoubleSpace => $"{Environment.NewLine}{Environment.NewLine}"; + + public EncapsulateFieldStrategyBase(IDeclarationFinderProvider declarationFinderProvider, QualifiedModuleName qmn, IIndenter indenter) + { + _targetQMN = qmn; + _indenter = indenter; + + _codeSectionStartIndex = declarationFinderProvider.DeclarationFinder + .Members(_targetQMN).Where(m => m.IsMember()) + .OrderBy(c => c.Selection) + .FirstOrDefault()?.Context.Start.TokenIndex ?? null; + } + + public IEncapsulateFieldRewriteSession RefactorRewrite(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession, bool asPreview) + { + ModifyFields(model, refactorRewriteSession); + + ModifyReferences(model, refactorRewriteSession); + + InsertNewContent(model, refactorRewriteSession, asPreview); + + return refactorRewriteSession; + } + + protected abstract void ModifyFields(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession rewriteSession); + + protected abstract void ModifyReferences(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession); + + protected abstract void LoadNewDeclarationBlocks(EncapsulateFieldModel model); + + protected void RewriteReferences(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) + { + foreach (var rewriteReplacement in model.SelectedFieldCandidates.SelectMany(field => field.ReferenceReplacements)) + { + (ParserRuleContext Context, string Text) = rewriteReplacement.Value; + var rewriter = refactorRewriteSession.CheckOutModuleRewriter(rewriteReplacement.Key.QualifiedModuleName); + rewriter.Replace(Context, Text); + } + } + + protected void AddContentBlock(NewContentTypes contentType, string block) + => _newContent[contentType].Add(block); + + private void InsertNewContent(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession, bool isPreview = false) + { + _newContent = new Dictionary> + { + { NewContentTypes.PostContentMessage, new List() }, + { NewContentTypes.DeclarationBlock, new List() }, + { NewContentTypes.MethodBlock, new List() }, + { NewContentTypes.TypeDeclarationBlock, new List() } + }; + + LoadNewDeclarationBlocks(model); + + LoadNewPropertyBlocks(model); + + if (isPreview) + { + AddContentBlock(NewContentTypes.PostContentMessage, EncapsulateFieldResources.PreviewEndOfChangesMarker); + } + + var newContentBlock = string.Join(DoubleSpace, + (_newContent[NewContentTypes.TypeDeclarationBlock]) + .Concat(_newContent[NewContentTypes.DeclarationBlock]) + .Concat(_newContent[NewContentTypes.MethodBlock]) + .Concat(_newContent[NewContentTypes.PostContentMessage])) + .Trim(); + + var rewriter = refactorRewriteSession.CheckOutModuleRewriter(_targetQMN); + if (_codeSectionStartIndex.HasValue) + { + rewriter.InsertBefore(_codeSectionStartIndex.Value, $"{newContentBlock}{DoubleSpace}"); + } + else + { + rewriter.InsertAtEndOfFile($"{DoubleSpace}{newContentBlock}"); + } + } + + private void LoadNewPropertyBlocks(EncapsulateFieldModel model) + { + var propertyGenerationSpecs = model.SelectedFieldCandidates + .SelectMany(f => f.PropertyAttributeSets); + + var generator = new PropertyGenerator(); + foreach (var spec in propertyGenerationSpecs) + { + AddContentBlock(NewContentTypes.MethodBlock, generator.AsPropertyBlock(spec, _indenter)); + } + } + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/UseBackingFields.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/UseBackingFields.cs new file mode 100644 index 0000000000..c91f9d5941 --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/UseBackingFields.cs @@ -0,0 +1,73 @@ +using Antlr4.Runtime; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.Refactorings.EncapsulateField.Extensions; +using Rubberduck.SmartIndenter; +using Rubberduck.VBEditor; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + public class UseBackingFields : EncapsulateFieldStrategyBase + { + public UseBackingFields(IDeclarationFinderProvider declarationFinderProvider, QualifiedModuleName qmn, IIndenter indenter) + : base(declarationFinderProvider, qmn, indenter) { } + + protected override void ModifyFields(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) + { + var rewriter = refactorRewriteSession.CheckOutModuleRewriter(_targetQMN); + + foreach (var field in model.SelectedFieldCandidates) + { + if (field.Declaration.HasPrivateAccessibility() && field.FieldIdentifier.Equals(field.Declaration.IdentifierName)) + { + rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); + continue; + } + + if (field.Declaration.IsDeclaredInList() && !field.Declaration.HasPrivateAccessibility()) + { + refactorRewriteSession.Remove(field.Declaration, rewriter); + continue; + } + + rewriter.Rename(field.Declaration, field.FieldIdentifier); + rewriter.SetVariableVisiblity(field.Declaration, Accessibility.Private.TokenString()); + rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); + } + } + + protected override void ModifyReferences(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) + { + foreach (var field in model.SelectedFieldCandidates) + { + field.LoadFieldReferenceContextReplacements(); + } + + RewriteReferences(model, refactorRewriteSession); + } + + protected override void LoadNewDeclarationBlocks(EncapsulateFieldModel model) + { + //New field declarations created here were removed from their list within ModifyFields(...) + var fieldsRequiringNewDeclaration = model.SelectedFieldCandidates + .Where(field => field.Declaration.IsDeclaredInList() + && field.Declaration.Accessibility != Accessibility.Private); + + foreach (var field in fieldsRequiringNewDeclaration) + { + var targetIdentifier = field.Declaration.Context.GetText().Replace(field.IdentifierName, field.FieldIdentifier); + var newField = field.Declaration.IsTypeSpecified + ? $"{Tokens.Private} {targetIdentifier}" + : $"{Tokens.Private} {targetIdentifier} {Tokens.As} {field.Declaration.AsTypeName}"; + + AddContentBlock(NewContentTypes.DeclarationBlock, newField); + } + } + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs index 48282c377c..7c0070eed4 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs @@ -59,15 +59,16 @@ public override bool TryValidateEncapsulationAttributes(out string errorMessage) return false; } - if (_validator.HasConflictingIdentifier(this, DeclarationType.Variable, out errorMessage)) + if (NamesValidator.HasConflictingIdentifier(this, DeclarationType.Variable, out errorMessage)) { return false; } return true; } - public override void LoadFieldReferenceContextReplacements() + public override void LoadFieldReferenceContextReplacements(string referenceQualifier = null) { + ReferenceQualifier = referenceQualifier; foreach (var idRef in Declaration.References) { //Locally, we do all operations using the backing field diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs index 79ed7ee857..67131d98cf 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs @@ -14,6 +14,12 @@ public interface IEncapsulateFieldDeclaration string AsTypeName { get; } } + public interface IAssignNoConflictNames + { + void AssignIdentifiers(IValidateEncapsulateFieldNames validator); + IValidateEncapsulateFieldNames NamesValidator { set; get; } + } + public interface IEncapsulateFieldCandidate : IEncapsulateFieldDeclaration { Declaration Declaration { get; } @@ -32,7 +38,7 @@ public interface IEncapsulateFieldCandidate : IEncapsulateFieldDeclaration string AsUDTMemberDeclaration { get; } IEnumerable> ReferenceReplacements { get; } string ReferenceQualifier { set; get; } - void LoadFieldReferenceContextReplacements(); + void LoadFieldReferenceContextReplacements(string referenceQualifier = null); bool TryValidateEncapsulationAttributes(out string errorMessage); bool ConvertFieldToUDTMember { set; get; } } @@ -45,21 +51,19 @@ public interface IEncapsulateFieldCandidateValidations bool HasConflictingFieldIdentifier { get; } } - - public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate, IEncapsulateFieldCandidateValidations + public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate, IEncapsulateFieldCandidateValidations, IAssignNoConflictNames { protected Declaration _target; protected QualifiedModuleName _qmn; protected int _hashCode; private string _identifierName; - protected IValidateEncapsulateFieldNames _validator; protected EncapsulationIdentifiers _fieldAndProperty; public EncapsulateFieldCandidate(Declaration declaration, IValidateEncapsulateFieldNames validator) { _target = declaration; - _validator = validator; - _fieldAndProperty = new EncapsulationIdentifiers(declaration.IdentifierName, (string name) => _validator.IsValidVBAIdentifier(name, DeclarationType.Property, out _)); + NamesValidator = validator; + _fieldAndProperty = new EncapsulationIdentifiers(declaration.IdentifierName, (string name) => NamesValidator.IsValidVBAIdentifier(name, DeclarationType.Property, out _)); IdentifierName = declaration.IdentifierName; AsTypeName_Field = declaration.AsTypeName; AsTypeName_Property = declaration.AsTypeName; @@ -67,14 +71,12 @@ public EncapsulateFieldCandidate(Declaration declaration, IValidateEncapsulateFi NewPropertyAccessor = AccessorMember.Field; ReferenceAccessor = AccessorMember.Property; - - ImplementLet = true; - ImplementSet = false; - CanBeReadWrite = true; _hashCode = ($"{_qmn.Name}.{declaration.IdentifierName}").GetHashCode(); + ImplementLet = true; + ImplementSet = false; if (_target.IsEnumField()) { //5.3.1 The declared type of a function declaration may not be a private enum name. @@ -86,7 +88,6 @@ public EncapsulateFieldCandidate(Declaration declaration, IValidateEncapsulateFi else if (_target.AsTypeName.Equals(Tokens.Variant) && !_target.IsArray) { - ImplementLet = true; ImplementSet = true; } else if (Declaration.IsObject) @@ -102,11 +103,13 @@ public EncapsulateFieldCandidate(Declaration declaration, IValidateEncapsulateFi public string AsTypeName => _target.AsTypeName; + public IValidateEncapsulateFieldNames NamesValidator { set; get; } + public bool HasConflictingPropertyIdentifier - => _validator.HasConflictingIdentifier(this, DeclarationType.Property, out var errorMessage); + => NamesValidator.HasConflictingIdentifier(this, DeclarationType.Property, out var errorMessage); public bool HasConflictingFieldIdentifier - => _validator.HasConflictingIdentifier(this, DeclarationType.Variable, out var errorMessage); + => NamesValidator.HasConflictingIdentifier(this, DeclarationType.Variable, out var errorMessage); public virtual bool TryValidateEncapsulationAttributes(out string errorMessage) { @@ -123,7 +126,7 @@ public virtual bool TryValidateEncapsulationAttributes(out string errorMessage) return false; } - if (_validator.HasConflictingIdentifier(this, DeclarationType.Variable, out errorMessage)) + if (NamesValidator.HasConflictingIdentifier(this, DeclarationType.Variable, out errorMessage)) { return false; } @@ -153,17 +156,12 @@ protected bool TryValidateEncapsulationAttributes(DeclarationType declarationTyp errorMessage = string.Empty; if (!EncapsulateFlag) { return true; } - if (!_validator.IsValidVBAIdentifier(PropertyName, declarationType, out errorMessage, isArray)) - { - return false; - } - - if (!_validator.IsSelfConsistent(this, out errorMessage)) + if (!NamesValidator.IsValidVBAIdentifier(PropertyName, declarationType, out errorMessage, isArray)) { return false; } - if (_validator.HasConflictingIdentifier(this, declarationType, out errorMessage)) + if (NamesValidator.HasConflictingIdentifier(this, declarationType, out errorMessage)) { return false; } @@ -171,7 +169,6 @@ protected bool TryValidateEncapsulationAttributes(DeclarationType declarationTyp return true; } - public virtual IEnumerable> ReferenceReplacements { get @@ -208,8 +205,8 @@ public virtual bool EncapsulateFlag if (!_encapsulateFlag) { PropertyName = _fieldAndProperty.DefaultPropertyName; - _validator.AssignNoConflictIdentifier(this, DeclarationType.Property); - _validator.AssignNoConflictIdentifier(this, DeclarationType.Variable); + AssignNoConflictIdentifier(this, DeclarationType.Property, NamesValidator); + AssignNoConflictIdentifier(this, DeclarationType.Variable, NamesValidator); } } get => _encapsulateFlag; @@ -244,11 +241,40 @@ public override bool Equals(object obj) public override int GetHashCode() => _hashCode; + public void AssignIdentifiers(IValidateEncapsulateFieldNames validator) + { + AssignNoConflictIdentifier(this, DeclarationType.Property, validator); + AssignNoConflictIdentifier(this, DeclarationType.Variable, validator); + } + + protected static IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType, IValidateEncapsulateFieldNames validator) + { + var isConflictingIdentifier = validator.HasConflictingIdentifierIgnoreEncapsulationFlag(candidate, declarationType, out _); + for (var count = 1; count < 10 && isConflictingIdentifier; count++) + { + var identifier = declarationType.HasFlag(DeclarationType.Property) + ? candidate.PropertyName + : candidate.FieldIdentifier; + + if (declarationType.HasFlag(DeclarationType.Property)) + { + candidate.PropertyName = identifier.IncrementEncapsulationIdentifier(); + } + else + { + candidate.FieldIdentifier = identifier.IncrementEncapsulationIdentifier(); + } + isConflictingIdentifier = validator.HasConflictingIdentifierIgnoreEncapsulationFlag(candidate, declarationType, out _); + } + return candidate; + } + + //The preferred NewFieldName is the original Identifier private void TryRestoreNewFieldNameAsOriginalFieldIdentifierName() { var canNowUseOriginalFieldName = !_fieldAndProperty.TargetFieldName.IsEquivalentVBAIdentifierTo(_fieldAndProperty.Property) - && !_validator.IsConflictingFieldIdentifier(_fieldAndProperty.TargetFieldName, this, DeclarationType.Variable); + && !NamesValidator.IsConflictingProposedIdentifier(_fieldAndProperty.TargetFieldName, this, DeclarationType.Variable); if (canNowUseOriginalFieldName) { @@ -259,11 +285,11 @@ private void TryRestoreNewFieldNameAsOriginalFieldIdentifierName() if (_fieldAndProperty.Field.IsEquivalentVBAIdentifierTo(_fieldAndProperty.TargetFieldName)) { _fieldAndProperty.Field = _fieldAndProperty.DefaultNewFieldName; - var isConflictingFieldIdentifier = _validator.HasConflictingIdentifier(this, DeclarationType.Variable, out _); + var isConflictingFieldIdentifier = NamesValidator.HasConflictingIdentifier(this, DeclarationType.Variable, out _); for (var count = 1; count < 10 && isConflictingFieldIdentifier; count++) { FieldIdentifier = FieldIdentifier.IncrementEncapsulationIdentifier(); - isConflictingFieldIdentifier = _validator.HasConflictingIdentifier(this, DeclarationType.Variable, out _); + isConflictingFieldIdentifier = NamesValidator.HasConflictingIdentifier(this, DeclarationType.Variable, out _); } } } @@ -298,8 +324,9 @@ public virtual string AsUDTMemberDeclaration public virtual IEnumerable PropertyAttributeSets => new List() { AsPropertyAttributeSet }; - public virtual void LoadFieldReferenceContextReplacements() + public virtual void LoadFieldReferenceContextReplacements(string referenceQualifier = null) { + ReferenceQualifier = referenceQualifier; foreach (var idRef in Declaration.References) { var replacementText = RequiresAccessQualification(idRef) diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs index 2ace273214..7b04f5e621 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs @@ -77,20 +77,11 @@ private void SetNonConflictParameterName() { _setLetParameter = DEFAULT_WRITE_PARAMETER; - if (!(Field.IsEquivalentVBAIdentifierTo(DEFAULT_WRITE_PARAMETER) - || Property.IsEquivalentVBAIdentifierTo(DEFAULT_WRITE_PARAMETER))) + var guard = 0; + while ( guard++ < 10 && (Field.IsEquivalentVBAIdentifierTo(_setLetParameter) + || Property.IsEquivalentVBAIdentifierTo(_setLetParameter))) { - return; - } - - if (Field.IsEquivalentVBAIdentifierTo(SetLetParameter)) - { - _setLetParameter = $"{Field}_{DEFAULT_WRITE_PARAMETER}"; - } - - if (Property.IsEquivalentVBAIdentifierTo(SetLetParameter)) - { - _setLetParameter = $"{Property}_{Field}_{DEFAULT_WRITE_PARAMETER}"; + _setLetParameter = _setLetParameter.IncrementEncapsulationIdentifier(); } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs index bd07a20545..b6b90b0e79 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs @@ -86,7 +86,7 @@ public override bool EncapsulateFlag foreach (var member in Members.Where(m => !m.ConvertFieldToUDTMember && m.IsExistingMember)) { member.EncapsulateFlag = value; - if (!member.EncapsulateFlag || !_validator.HasConflictingIdentifier(member, DeclarationType.Property, out _)) + if (!member.EncapsulateFlag || !NamesValidator.HasConflictingIdentifier(member, DeclarationType.Property, out _)) { continue; } @@ -96,7 +96,8 @@ public override bool EncapsulateFlag //Try to use a name involving the parent's identifier to make it unique/meaningful //before giving up and creating incremented value(s). member.PropertyName = $"{FieldIdentifier.CapitalizeFirstLetter()}{member.PropertyName.CapitalizeFirstLetter()}"; - _validator.AssignNoConflictIdentifier(member, DeclarationType.Property); + //_validator.AssignNoConflictIdentifier(member, DeclarationType.Property); + AssignNoConflictIdentifier(member, DeclarationType.Property, NamesValidator); } } base.EncapsulateFlag = value; @@ -104,8 +105,9 @@ public override bool EncapsulateFlag get => _encapsulateFlag; } - public override void LoadFieldReferenceContextReplacements() + public override void LoadFieldReferenceContextReplacements(string referenceQualifier = null) { + ReferenceQualifier = referenceQualifier; if (TypeDeclarationIsPrivate) { LoadPrivateUDTFieldLocalReferenceExpressions(); @@ -181,22 +183,17 @@ public override bool TryValidateEncapsulationAttributes(out string errorMessage) errorMessage = string.Empty; if (!EncapsulateFlag) { return true; } - if (!_validator.IsValidVBAIdentifier(PropertyName, DeclarationType.Property, out errorMessage)) + if (!NamesValidator.IsValidVBAIdentifier(PropertyName, DeclarationType.Property, out errorMessage)) { return false; } - if (!TypeDeclarationIsPrivate && !_validator.IsSelfConsistent(this, out errorMessage)) + if (NamesValidator.HasConflictingIdentifier(this, DeclarationType.Property, out errorMessage)) { return false; } - if (_validator.HasConflictingIdentifier(this, DeclarationType.Property, out errorMessage)) - { - return false; - } - - if (_validator.HasConflictingIdentifier(this, DeclarationType.Variable, out errorMessage)) + if (NamesValidator.HasConflictingIdentifier(this, DeclarationType.Variable, out errorMessage)) { return false; } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs index 563e0fdd40..5bd0e66d06 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs @@ -40,7 +40,10 @@ public UserDefinedTypeMemberCandidate(IEncapsulateFieldCandidate candidate, IUse public IUserDefinedTypeCandidate Parent { private set; get; } - public void LoadFieldReferenceContextReplacements() { } + public void LoadFieldReferenceContextReplacements(string referenceQualifier = null) + { + ReferenceQualifier = referenceQualifier; + } public string ReferenceQualifier { set; get; } diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs index 9b09e8d17a..69bb49b116 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs @@ -72,10 +72,10 @@ public void PropertyNameChange_UniqueParamName() var encapsulatedField = Support.RetrieveEncapsulateFieldCandidate(inputCode, "value"); encapsulatedField.PropertyName = "Test"; - StringAssert.AreEqualIgnoringCase("value_value", encapsulatedField.ParameterName); + StringAssert.AreEqualIgnoringCase("value_1", encapsulatedField.ParameterName); encapsulatedField.PropertyName = "Value"; - StringAssert.AreEqualIgnoringCase("Value_value_1_value", encapsulatedField.ParameterName); + StringAssert.AreEqualIgnoringCase("value_2", encapsulatedField.ParameterName); } [TestCase("strValue", "Value", "strValue")] diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index e86968431f..101a883650 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -131,7 +131,7 @@ public IEncapsulateFieldCandidate RetrieveEncapsulateFieldCandidate(string input public IEncapsulateFieldCandidate RetrieveEncapsulateFieldCandidate(IVBE vbe, string fieldName, DeclarationType declarationType = DeclarationType.Variable) { - var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); + var state = MockParser.CreateAndParse(vbe); using (state) { var match = state.DeclarationFinder.MatchName(fieldName).Where(m => m.DeclarationType.Equals(declarationType)).Single(); @@ -139,8 +139,6 @@ public IEncapsulateFieldCandidate RetrieveEncapsulateFieldCandidate(IVBE vbe, st } } - - public EncapsulateFieldModel RetrieveUserModifiedModelPriorToRefactoring(string inputCode, string declarationName, DeclarationType declarationType, Func presenterAdjustment) { var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; From 1589ddc4859346c31d48b216c1dad996166f112f Mon Sep 17 00:00:00 2001 From: IvenBach Date: Fri, 3 Jan 2020 12:02:15 -0800 Subject: [PATCH 091/461] Add ignore/unignore test group Need to correct for multiple ignore group commands so that only a single @IgonoreTest annotation is added. Unignore isn't working and need to figure out the logic. --- .../UI/UnitTesting/TestExplorerViewModel.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs b/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs index 338b95403e..97aa75abd1 100644 --- a/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs +++ b/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs @@ -424,12 +424,14 @@ private void ExecuteIgnoreGroupCommand (object parameter) { var rewriteSession = RewritingManager.CheckOutCodePaneSession(); var testGroup = GroupContainingSelectedTest(MouseOverTest); + var ignoreTestAnnotation = new IgnoreTestAnnotation(); + foreach (TestMethodViewModel test in testGroup.Items) { // var testMethod = parameter == null // ? _mousedOverTestMethod - // : (parameter as TestMethodViewModel).Method; - AnnotationUpdater.AddAnnotation(rewriteSession, test.Method.Declaration, Parsing.Annotations.AnnotationType.IgnoreTest); + // : (parameter as TestMethodViewModel).Method; + AnnotationUpdater.AddAnnotation(rewriteSession, test.Method.Declaration, ignoreTestAnnotation); } rewriteSession.TryRewrite(); @@ -442,8 +444,12 @@ private void ExecuteUnignoreGroupCommand(object parameter) foreach (TestMethodViewModel test in testGroup.Items) { //ExecuteUnignoreTestCommand(test); + //var ignoreTestAnnotations = test.Method.Declaration.Annotations + // .Where(iannotations => iannotations.AnnotationType == Parsing.Annotations.AnnotationType.IgnoreTest); + var ignoreTestAnnotations = test.Method.Declaration.Annotations - .Where(iannotations => iannotations.AnnotationType == Parsing.Annotations.AnnotationType.IgnoreTest); + .Where(pta => pta.Annotation.Target == AnnotationTarget.Member + && pta.AnnotationArguments.Contains("'@IgnoreTest")); foreach (var ignoreTestAnnotation in ignoreTestAnnotations) { From b22821ef02ff2db65846ad89152a5d0087791bb4 Mon Sep 17 00:00:00 2001 From: IvenBach Date: Fri, 3 Jan 2020 14:52:11 -0800 Subject: [PATCH 092/461] Add ignore/unignore group command Respective command displays when mouse is over group header, when applicable. --- .../UI/UnitTesting/TestExplorerControl.xaml | 10 ++-- .../UI/UnitTesting/TestExplorerViewModel.cs | 57 +++++++++++++++---- .../UnitTesting/TestExplorer.Designer.cs | 4 +- .../UnitTesting/TestExplorer.resx | 4 +- 4 files changed, 57 insertions(+), 18 deletions(-) diff --git a/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml b/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml index 38d9aa18cb..95dd941485 100644 --- a/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml +++ b/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml @@ -454,14 +454,16 @@ - - + + + Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_ContextMenuUnignoreGroup}" + Visibility="{Binding DisplayUnignoreGroupLabel, Converter={StaticResource BoolToVisibility}}"> diff --git a/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs b/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs index 97aa75abd1..0195a58b00 100644 --- a/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs +++ b/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs @@ -140,6 +140,8 @@ private void RefreshContextMenu() { OnPropertyChanged(nameof(DisplayUnignoreTestLabel)); OnPropertyChanged(nameof(DisplayIgnoreTestLabel)); + OnPropertyChanged(nameof(DisplayUnignoreGroupLabel)); + OnPropertyChanged(nameof(DisplayIgnoreGroupLabel)); } private static readonly Dictionary GroupDescriptions = new Dictionary @@ -245,6 +247,36 @@ private void HandleTestCompletion(object sender, TestCompletedEventArgs e) private TestMethod _mousedOverTestMethod => ((TestMethodViewModel)SelectedItem).Method; public bool DisplayUnignoreTestLabel => SelectedItem != null && _mousedOverTestMethod.IsIgnored; public bool DisplayIgnoreTestLabel => SelectedItem != null && !_mousedOverTestMethod.IsIgnored; + + public bool DisplayUnignoreGroupLabel + { + get + { + if (MouseOverGroup?.Items == null) + { + return false; + } + + var testsInGroup = MouseOverGroup.Items.Cast(); + + return testsInGroup.Where(test => test.Method.IsIgnored).Any(); ; + } + } + + public bool DisplayIgnoreGroupLabel + { + get + { + if (MouseOverGroup?.Items == null) + { + return false; + } + + var testsInGroup = MouseOverGroup.Items.Cast(); + + return testsInGroup.Where(test => test.Method.IsIgnored).Count() != MouseOverGroup.Items.Count; + } + } #region Commands @@ -428,10 +460,19 @@ private void ExecuteIgnoreGroupCommand (object parameter) foreach (TestMethodViewModel test in testGroup.Items) { - // var testMethod = parameter == null - // ? _mousedOverTestMethod - // : (parameter as TestMethodViewModel).Method; - AnnotationUpdater.AddAnnotation(rewriteSession, test.Method.Declaration, ignoreTestAnnotation); + var needsIgnoreAnnotationAdded = true; + foreach (var annotation in test.Method.Declaration.Annotations) + { + if (annotation.Annotation is IgnoreTestAnnotation) + { + needsIgnoreAnnotationAdded = false; + }; + } + + if (needsIgnoreAnnotationAdded) + { + AnnotationUpdater.AddAnnotation(rewriteSession, test.Method.Declaration, ignoreTestAnnotation); + } } rewriteSession.TryRewrite(); @@ -441,15 +482,11 @@ private void ExecuteUnignoreGroupCommand(object parameter) { var rewriteSession = RewritingManager.CheckOutCodePaneSession(); var testGroup = GroupContainingSelectedTest(MouseOverTest); + foreach (TestMethodViewModel test in testGroup.Items) { - //ExecuteUnignoreTestCommand(test); - //var ignoreTestAnnotations = test.Method.Declaration.Annotations - // .Where(iannotations => iannotations.AnnotationType == Parsing.Annotations.AnnotationType.IgnoreTest); - var ignoreTestAnnotations = test.Method.Declaration.Annotations - .Where(pta => pta.Annotation.Target == AnnotationTarget.Member - && pta.AnnotationArguments.Contains("'@IgnoreTest")); + .Where(pta => pta.Annotation is IgnoreTestAnnotation); foreach (var ignoreTestAnnotation in ignoreTestAnnotations) { diff --git a/Rubberduck.Resources/UnitTesting/TestExplorer.Designer.cs b/Rubberduck.Resources/UnitTesting/TestExplorer.Designer.cs index ab492f53e1..3065abc50a 100644 --- a/Rubberduck.Resources/UnitTesting/TestExplorer.Designer.cs +++ b/Rubberduck.Resources/UnitTesting/TestExplorer.Designer.cs @@ -124,7 +124,7 @@ public static string TestExplorer_CategoryName { } /// - /// Looks up a localized string similar to Ignore all tests in group. + /// Looks up a localized string similar to Ignore group tests. /// public static string TestExplorer_ContextMenuIgnoreGroup { get { @@ -169,7 +169,7 @@ public static string TestExplorer_ContextMenuRunSingle { } /// - /// Looks up a localized string similar to Unignore all tests in group. + /// Looks up a localized string similar to Unignore group tests. /// public static string TestExplorer_ContextMenuUnignoreGroup { get { diff --git a/Rubberduck.Resources/UnitTesting/TestExplorer.resx b/Rubberduck.Resources/UnitTesting/TestExplorer.resx index 4b7e80f173..983b721f86 100644 --- a/Rubberduck.Resources/UnitTesting/TestExplorer.resx +++ b/Rubberduck.Resources/UnitTesting/TestExplorer.resx @@ -352,9 +352,9 @@ Unignore test - Ignore all tests in group + Ignore group tests - Unignore all tests in group + Unignore group tests \ No newline at end of file From 01bd9805416a3e355be3ad18e4e2c9a763b9a8ed Mon Sep 17 00:00:00 2001 From: IvenBach Date: Fri, 3 Jan 2020 15:13:02 -0800 Subject: [PATCH 093/461] Rename and clarify ignore/unignore commands --- .../UI/UnitTesting/TestExplorerControl.xaml | 5 ++- .../UI/UnitTesting/TestExplorerViewModel.cs | 45 ++++++++++--------- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml b/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml index 95dd941485..e5cabf315b 100644 --- a/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml +++ b/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml @@ -454,14 +454,15 @@ - - diff --git a/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs b/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs index 0195a58b00..47d420b051 100644 --- a/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs +++ b/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs @@ -67,7 +67,7 @@ public TestExplorerViewModel(ISelectionService selectionService, NavigateCommand = new NavigateCommand(selectionService); RunSingleTestCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteSingleTestCommand, CanExecuteSingleTest); RunSelectedTestsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteSelectedTestsCommand, CanExecuteSelectedTestsCommand); - RunSelectedGroupCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteRunSelectedGroupCommand, CanExecuteSelectedGroupCommand); + RunSelectedGroupCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteRunSelectedGroupCommand, CanExecuteGroupCommand); CancelTestRunCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteCancelTestRunCommand, CanExecuteCancelTestRunCommand); ResetResultsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteResetResultsCommand, CanExecuteResetResultsCommand); CopyResultsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteCopyResultsCommand); @@ -76,8 +76,8 @@ public TestExplorerViewModel(ISelectionService selectionService, ExpandAllCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteExpandAll); IgnoreTestCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteIgnoreTestCommand); UnignoreTestCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteUnignoreTestCommand); - IgnoreSelectedGroupCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteIgnoreGroupCommand, CanIgnoreSelectedGroupCommand); - UnignoreSelectedGroupCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteUnignoreGroupCommand, CanUnignoreSelectedGroupCommand); + IgnoreGroupCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteIgnoreGroupCommand, CanIgnoreGroupCommand); + UnignoreGroupCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteUnignoreGroupCommand, CanUnignoreGroupCommand); RewritingManager = rewritingManager; AnnotationUpdater = annotationUpdater; @@ -312,8 +312,8 @@ public bool DisplayIgnoreGroupLabel public CommandBase IgnoreTestCommand { get; } public CommandBase UnignoreTestCommand { get; } - public CommandBase IgnoreSelectedGroupCommand { get; } - public CommandBase UnignoreSelectedGroupCommand { get; } + public CommandBase IgnoreGroupCommand { get; } + public CommandBase UnignoreGroupCommand { get; } #endregion @@ -329,19 +329,19 @@ private bool CanExecuteSelectedTestsCommand(object obj) return !Model.IsBusy && obj is IList viewModels && viewModels.Count > 0; } - private bool CanExecuteSelectedGroupCommand(object obj) + private bool CanExecuteGroupCommand(object obj) { return !Model.IsBusy && (MouseOverTest != null || MouseOverGroup != null); } - private bool CanIgnoreSelectedGroupCommand(object obj) + private bool CanIgnoreGroupCommand(object obj) { - return CanExecuteSelectedGroupCommand(obj); + return CanExecuteGroupCommand(obj); } - private bool CanUnignoreSelectedGroupCommand(object obj) + private bool CanUnignoreGroupCommand(object obj) { - return CanExecuteSelectedGroupCommand(obj); + return CanExecuteGroupCommand(obj); } private bool CanExecuteResetResultsCommand(object obj) @@ -460,16 +460,21 @@ private void ExecuteIgnoreGroupCommand (object parameter) foreach (TestMethodViewModel test in testGroup.Items) { - var needsIgnoreAnnotationAdded = true; - foreach (var annotation in test.Method.Declaration.Annotations) - { - if (annotation.Annotation is IgnoreTestAnnotation) - { - needsIgnoreAnnotationAdded = false; - }; - } - - if (needsIgnoreAnnotationAdded) + //var needsIgnoreAnnotationAdded = true; + //foreach (var annotation in test.Method.Declaration.Annotations) + //{ + // if (annotation.Annotation is IgnoreTestAnnotation) + // { + // needsIgnoreAnnotationAdded = false; + // }; + //} + + //if (needsIgnoreAnnotationAdded) + //{ + // AnnotationUpdater.AddAnnotation(rewriteSession, test.Method.Declaration, ignoreTestAnnotation); + //} + + if (!test.Method.IsIgnored) { AnnotationUpdater.AddAnnotation(rewriteSession, test.Method.Declaration, ignoreTestAnnotation); } From 7f414d11ccf95e69e95f3812612bb26502eca656 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sat, 4 Jan 2020 16:26:42 +0100 Subject: [PATCH 094/461] Make FunctionReturnValueNotUsedInspection report references Previously, it reported on declarations, which does not help in finding the offending call sites. An inspection with the old intended behaviour will be added again in the next commits. --- .../FunctionReturnValueNotUsedInspection.cs | 166 ++++-------------- .../QuickFixes/ConvertToProcedureQuickFix.cs | 2 +- .../Inspections/InspectionInfo.Designer.cs | 9 + .../Inspections/InspectionInfo.cs.resx | 2 +- .../Inspections/InspectionInfo.de.resx | 7 +- .../Inspections/InspectionInfo.es.resx | 2 +- .../Inspections/InspectionInfo.fr.resx | 2 +- .../Inspections/InspectionInfo.resx | 5 +- .../Inspections/InspectionNames.Designer.cs | 9 + .../Inspections/InspectionNames.cs.resx | 2 +- .../Inspections/InspectionNames.de.resx | 7 +- .../Inspections/InspectionNames.es.resx | 2 +- .../Inspections/InspectionNames.fr.resx | 2 +- .../Inspections/InspectionNames.resx | 5 +- .../Inspections/InspectionResults.Designer.cs | 9 + .../Inspections/InspectionResults.cs.resx | 2 +- .../Inspections/InspectionResults.de.resx | 7 +- .../Inspections/InspectionResults.es.resx | 2 +- .../Inspections/InspectionResults.fr.resx | 2 +- .../Inspections/InspectionResults.resx | 7 +- ...nctionReturnValueNotUsedInspectionTests.cs | 81 ++++++++- 21 files changed, 175 insertions(+), 157 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueNotUsedInspection.cs index 2ae078393c..80fdb7fc2d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueNotUsedInspection.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Results; using Rubberduck.Parsing; @@ -11,17 +12,14 @@ using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor; -using Rubberduck.Inspections.Inspections.Extensions; namespace Rubberduck.Inspections.Concrete { /// - /// Warns when a user function's return value is never used, at any of its call sites. + /// Warns when a user function's return value is not used at a call site. /// /// /// A 'Function' procedure normally means its return value to be captured and consumed by the calling code. - /// It's possible that not all call sites need the return value, but if the value is systematically discarded then this - /// means the function is side-effecting, and thus should probably be a 'Sub' procedure instead. /// /// /// /// - public sealed class FunctionReturnValueNotUsedInspection : InspectionBase + public sealed class FunctionReturnValueNotUsedInspection : IdentifierReferenceInspectionBase { public FunctionReturnValueNotUsedInspection(RubberduckParserState state) : base(state) { } - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultReference(IdentifierReference reference) { - var interfaceMembers = State.DeclarationFinder.FindAllInterfaceMembers().ToList(); - var interfaceImplementationMembers = State.DeclarationFinder.FindAllInterfaceImplementingMembers(); - var functions = State.DeclarationFinder - .UserDeclarations(DeclarationType.Function) - .Where(item => item.References.Any(r => !IsReturnStatement(item, r) && !r.IsAssignment)) - .ToList(); - var interfaceMemberIssues = GetInterfaceMemberIssues(interfaceMembers); - var nonInterfaceFunctions = functions.Except(interfaceMembers.Union(interfaceImplementationMembers)); - var nonInterfaceIssues = GetNonInterfaceIssues(nonInterfaceFunctions); - return interfaceMemberIssues.Union(nonInterfaceIssues); + return reference?.Declaration != null + && !reference.IsAssignment + && !reference.IsArrayAccess + && !reference.IsInnerRecursiveDefaultMemberAccess + && reference.Declaration.DeclarationType == DeclarationType.Function + && IsCalledAsProcedure(reference.Context); } - private IEnumerable GetInterfaceMemberIssues(IEnumerable interfaceMembers) + private static bool IsCalledAsProcedure(ParserRuleContext context) { - return from interfaceMember in interfaceMembers - let implementationMembers = - State.DeclarationFinder.FindInterfaceImplementationMembers(interfaceMember).ToList() - where interfaceMember.DeclarationType == DeclarationType.Function && - !IsReturnValueUsed(interfaceMember) && - implementationMembers.All(member => !IsReturnValueUsed(member)) - let implementationMemberIssues = - implementationMembers.Select( - implementationMember => - Tuple.Create(implementationMember.Context, - new QualifiedSelection(implementationMember.QualifiedName.QualifiedModuleName, - implementationMember.Selection), implementationMember)) - select CreateInspectionResult(this, interfaceMember); - - } - - private IEnumerable GetNonInterfaceIssues(IEnumerable nonInterfaceFunctions) - { - var returnValueNotUsedFunctions = nonInterfaceFunctions.Where(function => function.DeclarationType == DeclarationType.Function && !IsReturnValueUsed(function)); - var nonInterfaceIssues = returnValueNotUsedFunctions - .Where(function => !IsRecursive(function)) - .Select(function => - new DeclarationInspectionResult( - this, - string.Format(InspectionResults.FunctionReturnValueNotUsedInspection, function.IdentifierName), - function)); - return nonInterfaceIssues; - } - - private bool IsRecursive(Declaration function) - { - return function.References.Any(usage => usage.ParentScoping.Equals(function) && IsIndexExprOrCallStmt(usage)); - } - - private bool IsReturnValueUsed(Declaration function) - { - // TODO: This is O(MG) at work here. Need to refactor the whole shebang. - return (from usage in function.References - where !IsLet(usage) - where !IsSet(usage) - where !IsCallStmt(usage) - where !IsTypeOfExpression(usage) - where !IsAddressOfCall(usage) - select usage).Any(usage => !IsReturnStatement(function, usage)); - } - - private bool IsAddressOfCall(IdentifierReference usage) - { - return usage.Context.IsDescendentOf(); - } - - private bool IsTypeOfExpression(IdentifierReference usage) - { - return usage.Context.IsDescendentOf(); - } - - private bool IsReturnStatement(Declaration function, IdentifierReference assignment) - { - return assignment.ParentScoping.Equals(function) && assignment.Declaration.Equals(function); - } - - private bool IsIndexExprOrCallStmt(IdentifierReference usage) - { - return IsCallStmt(usage) || IsIndexExprContext(usage); - } - - private bool IsCallStmt(IdentifierReference usage) - { - var callStmt = usage.Context.GetAncestor(); + var callStmt = context.GetAncestor(); if (callStmt == null) { return false; } - var indexExpr = usage.Context.GetAncestor(); - if (indexExpr != null) - { - var memberAccessStmt = usage.Context.GetAncestor(); - if (memberAccessStmt != null && - callStmt.SourceInterval.ProperlyContains(memberAccessStmt.SourceInterval) && - memberAccessStmt.SourceInterval.ProperlyContains(indexExpr.SourceInterval)) - { - return false; - } - } - - var argumentList = CallStatement.GetArgumentList(callStmt); - if (argumentList == null) + //If we are in an argument list, the value is used somewhere in defining the argument. + var argumentListParent = context.GetAncestor(); + if (argumentListParent != null) { - return true; + return false; } - return !usage.Context.IsDescendentOf(argumentList); - } - private bool IsIndexExprContext(IdentifierReference usage) - { - var indexExpr = usage.Context.GetAncestor(); - if (indexExpr == null) + //Member accesses are parsed right-to-left, e.g. 'foo.Bar' is the parent of 'foo'. + //Thus, having a member access parent means that the return value is used somehow. + var ownFunctionCallExpression = context.Parent is VBAParser.MemberAccessExprContext methodCall + ? methodCall + : context; + var memberAccessParent = ownFunctionCallExpression.GetAncestor(); + if (memberAccessParent != null) { return false; } - var argumentList = indexExpr.argumentList(); - if (argumentList == null) - { - return true; - } - return !usage.Context.IsDescendentOf(argumentList); - } - private bool IsLet(IdentifierReference usage) - { - var letStmt = usage.Context.GetAncestor(); + ////AddressOf statements are ignored because they are supposed to not use the return value. + //var addressOfParent = context.GetAncestor(); + //if (addressOfParent != null) + //{ + // return false; + //} - return letStmt != null && letStmt == usage.Context; + return true; } - private bool IsSet(IdentifierReference usage) + protected override string ResultDescription(IdentifierReference reference) { - var setStmt = usage.Context.GetAncestor(); - - return setStmt != null && setStmt == usage.Context; - } - - private DeclarationInspectionResult CreateInspectionResult(IInspection inspection, Declaration interfaceMember) - { - dynamic properties = new PropertyBag(); - properties.DisableFixes = nameof(QuickFixes.ConvertToProcedureQuickFix); - - return new DeclarationInspectionResult(inspection, - string.Format(InspectionResults.FunctionReturnValueNotUsedInspection, - interfaceMember.IdentifierName), - interfaceMember, properties: properties); + var functionName = reference.Declaration.QualifiedName.ToString(); + return string.Format(InspectionResults.FunctionReturnValueNotUsedInspection, functionName); } } } diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ConvertToProcedureQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/ConvertToProcedureQuickFix.cs index 74cf3c4dbb..683d7e1971 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ConvertToProcedureQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/ConvertToProcedureQuickFix.cs @@ -50,7 +50,7 @@ namespace Rubberduck.Inspections.QuickFixes public sealed class ConvertToProcedureQuickFix : QuickFixBase { public ConvertToProcedureQuickFix() - : base(typeof(NonReturningFunctionInspection), typeof(FunctionReturnValueNotUsedInspection)) + : base(typeof(NonReturningFunctionInspection), typeof(FunctionReturnValueNeverUsedInspection)) {} public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) diff --git a/Rubberduck.Resources/Inspections/InspectionInfo.Designer.cs b/Rubberduck.Resources/Inspections/InspectionInfo.Designer.cs index 1a9408dac8..03ef56de47 100644 --- a/Rubberduck.Resources/Inspections/InspectionInfo.Designer.cs +++ b/Rubberduck.Resources/Inspections/InspectionInfo.Designer.cs @@ -279,6 +279,15 @@ public static string ExcelUdfNameIsValidCellReferenceInspection { /// /// Looks up a localized string similar to A member is written as a function, but used as a procedure. Unless the function is recursive, consider converting the 'Function' into a 'Sub'. If the function is recursive, none of its external callers are using the returned value.. /// + public static string FunctionReturnValueNeverUsedInspection { + get { + return ResourceManager.GetString("FunctionReturnValueNeverUsedInspection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The return value of a function is not used, i.e. it is used like a procedure. This is either an oversight or the function is used for its side-effects, whose existence would also be a code smell.. + /// public static string FunctionReturnValueNotUsedInspection { get { return ResourceManager.GetString("FunctionReturnValueNotUsedInspection", resourceCulture); diff --git a/Rubberduck.Resources/Inspections/InspectionInfo.cs.resx b/Rubberduck.Resources/Inspections/InspectionInfo.cs.resx index c6423592bf..675311048a 100644 --- a/Rubberduck.Resources/Inspections/InspectionInfo.cs.resx +++ b/Rubberduck.Resources/Inspections/InspectionInfo.cs.resx @@ -247,7 +247,7 @@ Jestliže může být parametr prázdný, ignorujte výsledek této inspekce; p Deklarace proměnné objektu s automatickým instancí v rozsahu procedur mění, jak funguje nulling reference, což může vést k neočekávanému chování. - + Člen je definován jako funkce, ale používá se jako procedura. Pokud nejde o rekurzivní funkci, zvažte zapsání 'Function' jako 'Sub'. Pokud je funkce rekurzivní, žádný z jejich externích voláních nepoužívá její návratnou hodnotu. diff --git a/Rubberduck.Resources/Inspections/InspectionInfo.de.resx b/Rubberduck.Resources/Inspections/InspectionInfo.de.resx index 4b8a1f0e1c..91ef02eb7f 100644 --- a/Rubberduck.Resources/Inspections/InspectionInfo.de.resx +++ b/Rubberduck.Resources/Inspections/InspectionInfo.de.resx @@ -226,8 +226,8 @@ Falls der Parameter 'null' sein kann, bitte dieses Auftreten ignorieren. 'null' Das Schlüsselwort 'Public' kann nur auf Modulebene verwendet werden; Sein Konterpart 'Private' kann auch nur auf Modulebene verwendet werden. 'Dim' jedoch kann verwendet werden, um sowohl modulweite als auch prozedurweite Variablen zu deklarieren. Um der Konsistenz Willen ist es besser, 'Dim' nur für lokale Variablen zu verwenden, also 'Private' statt 'Dim' auf Modulebene zu verwenden. - - Ein Member ist als Funktion geschrieben, aber wird wie eine Prozedur verwendet. Falls die Funktion nicht rekursiv ist, sollten Sie in Erwägung ziehen, die 'Function' in ein 'Sub' zu konvertieren. Falls die Funktion rekursiv ist, verwendet keiner der externen Aufrufer den Rückgabewert. + + Ein Member ist als Funktion geschrieben, wird aber wie eine Prozedur verwendet. Falls die Funktion nicht rekursiv ist, sollten Sie in Erwägung ziehen, die 'Function' in ein 'Sub' zu konvertieren. Falls die Funktion rekursiv ist, verwendet keiner der externen Aufrufer den Rückgabewert. Es wird ein Memberzugriff verwendet, der vom Interface des Objektes nicht deklariert wird. Dies ist höchstwahrscheinlich ein Fehler. Falls der Memberzugriff das erweiterbare Interface des Objektes verwendet, erwägen Sie ein nicht erweiterbares Äquivalent zu verwenden um Prüfungen zur Kompilierzeit zu ermöglichen und das Auftreten von Laufzeitfehler 438 zu verhindern. @@ -433,4 +433,7 @@ Falls der Parameter 'null' sein kann, bitte dieses Auftreten ignorieren. 'null' Eine Bedingung in einem Case-Ausdruck ist entweder nie erfüllt, verursacht einen Laufzeitfehler oder kann nicht erfüllt werden, da die vorherigen Case-Ausdrücke bereits alle zulässigen Werte abdecken. Infolgedessen wird der Code in dem Case-Zweig nie ausgeführt und stellt "toten Code" dar oder der Case-Ausdruck stellt sogar einen Laufzeitfehler dar, der nur darauf wartet irgendwann aufzutreten. Der Case-Zweig sollte entweder gelöscht, verändert oder an eine andere Stelle verschoben werden. + + Der Rückgabewert einer Funktion wird nicht verwendet, d.h. die wird wie eine Prozedur verwendet. Dies ist entweder ein Versäumnis oder die Funktion wird wegen ihrer Nebenwirkungen verwendet, deren Existenz in der Regel selber problematisch wäre. + \ No newline at end of file diff --git a/Rubberduck.Resources/Inspections/InspectionInfo.es.resx b/Rubberduck.Resources/Inspections/InspectionInfo.es.resx index f62faf1ebe..e0886eea32 100644 --- a/Rubberduck.Resources/Inspections/InspectionInfo.es.resx +++ b/Rubberduck.Resources/Inspections/InspectionInfo.es.resx @@ -217,7 +217,7 @@ Si el parámetro puede ser nulo, ignore el resultado de esta inspección; pasar Una declaración de variable de objeto auto-instanciada en el ámbito del procedimiento cambia cómo funciona la anulación de la referencia, lo que puede llevar a un comportamiento inesperado. - + Un miembro se escribe como una función, pero se usa como un procedimiento. A menos que la función sea recursiva, considere convertir la 'Función' en un 'Sub'. Si la función es recursiva, ninguno de sus llamadores externos está utilizando el valor devuelto. diff --git a/Rubberduck.Resources/Inspections/InspectionInfo.fr.resx b/Rubberduck.Resources/Inspections/InspectionInfo.fr.resx index 1455f5955a..005726c001 100644 --- a/Rubberduck.Resources/Inspections/InspectionInfo.fr.resx +++ b/Rubberduck.Resources/Inspections/InspectionInfo.fr.resx @@ -210,7 +210,7 @@ Une variable objet assignée lors de sa déclaration dans une procédure, modifie comment VBA gère cet objet, ce qui peut mener à un comportement inattendu. - + Un membre est implémenté comme une fonction, mais utilisé comme une procédure. À moins que la fonction soit récursive, considérez la convertir en procédure. Si la fonction est récursive, aucun appelant externe n'utilise sa valeur de retour. diff --git a/Rubberduck.Resources/Inspections/InspectionInfo.resx b/Rubberduck.Resources/Inspections/InspectionInfo.resx index e825f2951b..6863b2338e 100644 --- a/Rubberduck.Resources/Inspections/InspectionInfo.resx +++ b/Rubberduck.Resources/Inspections/InspectionInfo.resx @@ -217,7 +217,7 @@ If the parameter can be null, ignore this inspection result; passing a null valu An auto-instantiated object variable declaration at procedure scope changes how nulling the reference works, which can lead to unexpected behavior. - + A member is written as a function, but used as a procedure. Unless the function is recursive, consider converting the 'Function' into a 'Sub'. If the function is recursive, none of its external callers are using the returned value. @@ -433,4 +433,7 @@ If the parameter can be null, ignore this inspection result; passing a null valu Whenever both sides of an assignment without Set are objects, there is an assignment from the default member of the RHS to the one on the LHS. Although this might be intentional, in many situations it will just mask an erroneously forgotten Set. + + The return value of a function is not used, i.e. it is used like a procedure. This is either an oversight or the function is used for its side-effects, whose existence would also be a code smell. + \ No newline at end of file diff --git a/Rubberduck.Resources/Inspections/InspectionNames.Designer.cs b/Rubberduck.Resources/Inspections/InspectionNames.Designer.cs index 2b41b34db8..8ccc5e21d3 100644 --- a/Rubberduck.Resources/Inspections/InspectionNames.Designer.cs +++ b/Rubberduck.Resources/Inspections/InspectionNames.Designer.cs @@ -279,6 +279,15 @@ public static string ExcelUdfNameIsValidCellReferenceInspection { /// /// Looks up a localized string similar to Function return value is never used. /// + public static string FunctionReturnValueNeverUsedInspection { + get { + return ResourceManager.GetString("FunctionReturnValueNeverUsedInspection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Function return value is not used. + /// public static string FunctionReturnValueNotUsedInspection { get { return ResourceManager.GetString("FunctionReturnValueNotUsedInspection", resourceCulture); diff --git a/Rubberduck.Resources/Inspections/InspectionNames.cs.resx b/Rubberduck.Resources/Inspections/InspectionNames.cs.resx index 13d4a0ea7d..652990593b 100644 --- a/Rubberduck.Resources/Inspections/InspectionNames.cs.resx +++ b/Rubberduck.Resources/Inspections/InspectionNames.cs.resx @@ -213,7 +213,7 @@ Reference k objektu proměnné je automaticky instancovaná - + Vratná hodnota funkce není nikdy použita diff --git a/Rubberduck.Resources/Inspections/InspectionNames.de.resx b/Rubberduck.Resources/Inspections/InspectionNames.de.resx index 594214b562..7a959a9ba9 100644 --- a/Rubberduck.Resources/Inspections/InspectionNames.de.resx +++ b/Rubberduck.Resources/Inspections/InspectionNames.de.resx @@ -213,8 +213,8 @@ Objektvariable ist selbstzugewiesen. - - Der Rückgabewert der Funktion wird nicht genutzt. + + Der Rückgabewert der Funktion wird nie genutzt. Zuweisung in eine Objektvariable benötigt das 'Set'-Schlüsselwort. @@ -417,4 +417,7 @@ Verdächtige Let-Zuweisung + + Der Rückgabewert der Funktion wird nicht genutzt. + \ No newline at end of file diff --git a/Rubberduck.Resources/Inspections/InspectionNames.es.resx b/Rubberduck.Resources/Inspections/InspectionNames.es.resx index a8a1cf32a1..415cf8f326 100644 --- a/Rubberduck.Resources/Inspections/InspectionNames.es.resx +++ b/Rubberduck.Resources/Inspections/InspectionNames.es.resx @@ -216,7 +216,7 @@ La referencia de la variable de objeto es una instancia automática - + El valor de retorno de la función nunca se usa diff --git a/Rubberduck.Resources/Inspections/InspectionNames.fr.resx b/Rubberduck.Resources/Inspections/InspectionNames.fr.resx index a0f27da9fc..325202f775 100644 --- a/Rubberduck.Resources/Inspections/InspectionNames.fr.resx +++ b/Rubberduck.Resources/Inspections/InspectionNames.fr.resx @@ -213,7 +213,7 @@ La variable objet est assignée lors de sa déclaration - + La valeur de retour de la fonction n'est jamais utilisée. diff --git a/Rubberduck.Resources/Inspections/InspectionNames.resx b/Rubberduck.Resources/Inspections/InspectionNames.resx index 4dde116c1a..1324f267a6 100644 --- a/Rubberduck.Resources/Inspections/InspectionNames.resx +++ b/Rubberduck.Resources/Inspections/InspectionNames.resx @@ -216,7 +216,7 @@ Object variable reference is auto-instantiated - + Function return value is never used @@ -437,4 +437,7 @@ Suspicious Let assignment + + Function return value is not used + \ No newline at end of file diff --git a/Rubberduck.Resources/Inspections/InspectionResults.Designer.cs b/Rubberduck.Resources/Inspections/InspectionResults.Designer.cs index 0de5757f9f..1df0fe53d2 100644 --- a/Rubberduck.Resources/Inspections/InspectionResults.Designer.cs +++ b/Rubberduck.Resources/Inspections/InspectionResults.Designer.cs @@ -279,6 +279,15 @@ public static string ExcelUdfNameIsValidCellReferenceInspection { /// /// Looks up a localized string similar to Return value of function '{0}' is never used.. /// + public static string FunctionReturnValueNeverUsedInspection { + get { + return ResourceManager.GetString("FunctionReturnValueNeverUsedInspection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Return value of function '{0}' is not used.. + /// public static string FunctionReturnValueNotUsedInspection { get { return ResourceManager.GetString("FunctionReturnValueNotUsedInspection", resourceCulture); diff --git a/Rubberduck.Resources/Inspections/InspectionResults.cs.resx b/Rubberduck.Resources/Inspections/InspectionResults.cs.resx index 814640a737..61927a1c6c 100644 --- a/Rubberduck.Resources/Inspections/InspectionResults.cs.resx +++ b/Rubberduck.Resources/Inspections/InspectionResults.cs.resx @@ -195,7 +195,7 @@ Reference '{0}' objektu je automaticky instancovaná - + Návratná hodnota funkce '{0}' není nikdy použita. diff --git a/Rubberduck.Resources/Inspections/InspectionResults.de.resx b/Rubberduck.Resources/Inspections/InspectionResults.de.resx index a8acad1e5e..2817e62f0f 100644 --- a/Rubberduck.Resources/Inspections/InspectionResults.de.resx +++ b/Rubberduck.Resources/Inspections/InspectionResults.de.resx @@ -137,8 +137,8 @@ Objekt-Referenz '{0}' ist sebstzugewiesen. - - Der Rückgabewert der Funktion '{0}' wird nicht verwendet. + + Der Rückgabewert der Funktion '{0}' wird nie verwendet. Der Parameter '{0}' wird als byVal übergeben und bekommt ienen Wert zugesiesen. @@ -458,4 +458,7 @@ In Memoriam, 1972-2018 Bereichsbedingungen in Case-Ausdrücken müssen von der Form '[x] T [y]' sein, wobei [x] kleiner oder gleich [y] ist. + + Der Rückgabewert der Funktion '{0}' wird nicht verwendet. + \ No newline at end of file diff --git a/Rubberduck.Resources/Inspections/InspectionResults.es.resx b/Rubberduck.Resources/Inspections/InspectionResults.es.resx index 229164188d..93daaa7ad7 100644 --- a/Rubberduck.Resources/Inspections/InspectionResults.es.resx +++ b/Rubberduck.Resources/Inspections/InspectionResults.es.resx @@ -138,7 +138,7 @@ La referencia de objeto '{0}' se crea automáticamente. - + El valor de retorno de la función '{0}' nunca se usa. diff --git a/Rubberduck.Resources/Inspections/InspectionResults.fr.resx b/Rubberduck.Resources/Inspections/InspectionResults.fr.resx index bc9d29034f..b988fa43e6 100644 --- a/Rubberduck.Resources/Inspections/InspectionResults.fr.resx +++ b/Rubberduck.Resources/Inspections/InspectionResults.fr.resx @@ -137,7 +137,7 @@ La variable '{0}' est assignée lors de sa déclaration - + La valeur de retour de la fonction '{0}' n'est jamais utilisée. diff --git a/Rubberduck.Resources/Inspections/InspectionResults.resx b/Rubberduck.Resources/Inspections/InspectionResults.resx index 7fc185cf90..7990692d3f 100644 --- a/Rubberduck.Resources/Inspections/InspectionResults.resx +++ b/Rubberduck.Resources/Inspections/InspectionResults.resx @@ -141,7 +141,7 @@ Object reference '{0}' is auto-instantiated. - + Return value of function '{0}' is never used. @@ -498,4 +498,7 @@ In memoriam, 1972-2018 There is an assignment from the default member of the result of expression '{1}' to that of the expression '{0}'. {0} lhsExpression; {1} rhsExpression - + + Return value of function '{0}' is not used. + + \ No newline at end of file diff --git a/RubberduckTests/Inspections/FunctionReturnValueNotUsedInspectionTests.cs b/RubberduckTests/Inspections/FunctionReturnValueNotUsedInspectionTests.cs index 5c27e997d7..0d37e3faf5 100644 --- a/RubberduckTests/Inspections/FunctionReturnValueNotUsedInspectionTests.cs +++ b/RubberduckTests/Inspections/FunctionReturnValueNotUsedInspectionTests.cs @@ -60,7 +60,28 @@ End Sub [Test] [Category("Inspections")] [Category("Unused Value")] - public void FunctionReturnValueNotUsed_ReturnsResult_AddressOf() + public void FunctionReturnValueNotUsed_TwoUses_TwoResults() + { + const string code = @" +Public Function Foo(ByVal bar As String) As Integer + Foo = 42 +End Function + +Public Sub Bar() + Foo ""Test"" +End Sub + +Public Sub Baz() + Foo ""Test"" +End Sub +"; + Assert.AreEqual(2, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void AddressOf_NoResult() { const string code = @" Public Function Foo(ByVal bar As String) As Integer @@ -71,7 +92,7 @@ Public Sub Bar() Bar AddressOf Foo End Sub "; - Assert.AreEqual(1, InspectionResultsForStandardModule(code).Count()); + Assert.AreEqual(0, InspectionResultsForStandardModule(code).Count()); } [Test] @@ -111,7 +132,7 @@ End Sub [Test] [Category("Inspections")] [Category("Unused Value")] - public void FunctionReturnValueNotUsed_DoesNotReturnResult_MultipleConsecutiveCalls() + public void FunctionReturnValueNotUsed_MultipleConsecutiveCalls_returnsOneResult() { const string code = @" Public Function Foo(ByVal bar As String) As Integer @@ -122,7 +143,7 @@ Public Sub Baz() Foo Foo(Foo(""Bar"")) End Sub "; - Assert.AreEqual(0, InspectionResultsForStandardModule(code).Count()); + Assert.AreEqual(1, InspectionResultsForStandardModule(code).Count()); } [Test] @@ -355,6 +376,58 @@ End Sub Assert.AreEqual(1, InspectionResultsForModules(modules).Count()); } + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void MemberCallOnReturnValue_NoResult() + { + const string classCode = @" +Public Function Test() As Bar +End Function + +Public Sub FooBar() +End Sub +"; + const string callSiteCode = @" +Public Sub Baz() + Dim testObj As Bar + Set testObj = new Bar + testObj.Test.FooBar +End Sub +"; + var modules = new (string, string, ComponentType)[] + { + ("Bar", classCode, ComponentType.ClassModule), + ("TestModule", callSiteCode, ComponentType.StandardModule), + }; + + Assert.AreEqual(0, InspectionResultsForModules(modules).Count()); + } + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void InterfaceMemberNotUsed_NoResult() + { + const string interfaceCode = @" +Public Function Test() As Integer +End Function +"; + const string implementationCode = + @"Implements IFoo +Public Function IFoo_Test() As Integer + IFoo_Test = 42 +End Function +"; + var modules = new (string, string, ComponentType)[] + { + ("IFoo", interfaceCode, ComponentType.ClassModule), + ("Bar", implementationCode, ComponentType.ClassModule) + }; + + Assert.AreEqual(0, InspectionResultsForModules(modules).Count()); + } + [Test] [Category("Inspections")] [Category("Unused Value")] From 9a51872443cb5884aa638330db2b7a15fcffd491 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sat, 4 Jan 2020 18:05:35 +0100 Subject: [PATCH 095/461] Make DeclarationFinder store members by declarationType --- .../QuickFixes/ConvertToProcedureQuickFix.cs | 2 +- .../DeclarationCaching/DeclarationFinder.cs | 31 ++++++++++++++----- .../Extensions/DictionaryExtensions.cs | 13 +++++++- .../QuickFixes/IgnoreOnceQuickFixTests.cs | 4 +-- 4 files changed, 39 insertions(+), 11 deletions(-) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ConvertToProcedureQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/ConvertToProcedureQuickFix.cs index 683d7e1971..bcf0d01768 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ConvertToProcedureQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/ConvertToProcedureQuickFix.cs @@ -50,7 +50,7 @@ namespace Rubberduck.Inspections.QuickFixes public sealed class ConvertToProcedureQuickFix : QuickFixBase { public ConvertToProcedureQuickFix() - : base(typeof(NonReturningFunctionInspection), typeof(FunctionReturnValueNeverUsedInspection)) + : base(typeof(NonReturningFunctionInspection)) {} public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) diff --git a/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs b/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs index 018572cea8..0d198a3fab 100644 --- a/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs +++ b/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs @@ -26,7 +26,7 @@ public class DeclarationFinder private readonly IHostApplication _hostApp; private IDictionary> _declarationsByName; - private IDictionary> _declarations; + private IDictionary>> _declarations; private readonly IReadOnlyDictionary _failedResolutionStores; private readonly ConcurrentDictionary _newFailedResolutionStores; @@ -104,6 +104,8 @@ private List CollectionConstructionActions(IReadOnlyList de () => _declarations = declarations .GroupBy(item => item.QualifiedName.QualifiedModuleName) + .SelectMany(grp1 => grp1.GroupBy(declaration => declaration.DeclarationType), (grp1, grp2) => (grp1, grp2)) + .GroupBy(tpl => tpl.grp1.Key, tpl => tpl.grp2) .ToDictionary(), () => _declarationsByName = declarations @@ -282,16 +284,33 @@ public IEnumerable Members(Declaration module) return Members(module.QualifiedName.QualifiedModuleName); } + public IEnumerable Members(Declaration module, DeclarationType declarationType) + { + return Members(module.QualifiedName.QualifiedModuleName, declarationType); + } + public IEnumerable Members(QualifiedModuleName module) { return _declarations.TryGetValue(module, out var members) - ? members + ? members.AllValues() : Enumerable.Empty(); } + public IEnumerable Members(QualifiedModuleName module, DeclarationType declarationType) + { + if (!_declarations.TryGetValue(module, out var membersByType)) + { + return Enumerable.Empty(); + } + + return membersByType + .Where(item => item.Key.HasFlag(declarationType)) + .SelectMany(item => item.Value); + } + public Declaration ModuleDeclaration(QualifiedModuleName module) { - return Members(module).SingleOrDefault(member => member.DeclarationType.HasFlag(DeclarationType.Module)); + return Members(module, DeclarationType.Module).SingleOrDefault(); } public IReadOnlyCollection AllModules => _declarations.Keys.AsReadOnly(); @@ -494,10 +513,8 @@ public IEnumerable Parameters(Declaration parameterizedMem public IEnumerable FindMemberMatches(Declaration parent, string memberName) { - return _declarations.TryGetValue(parent.QualifiedName.QualifiedModuleName, out var children) - ? children.Where(item => item.DeclarationType.HasFlag(DeclarationType.Member) - && item.IdentifierName == memberName) - : Enumerable.Empty(); + return Members(parent.QualifiedName.QualifiedModuleName, DeclarationType.Member) + .Where(member => member.IdentifierName.Equals(memberName)); } public IEnumerable FindAnnotations(QualifiedModuleName module, int annotatedLine) diff --git a/Rubberduck.VBEEditor/Extensions/DictionaryExtensions.cs b/Rubberduck.VBEEditor/Extensions/DictionaryExtensions.cs index eaee313aae..c23d8a7e91 100644 --- a/Rubberduck.VBEEditor/Extensions/DictionaryExtensions.cs +++ b/Rubberduck.VBEEditor/Extensions/DictionaryExtensions.cs @@ -24,16 +24,27 @@ public static IEnumerable AllValues( return source.SelectMany(item => item.Value); } + public static IEnumerable AllValues( + this IDictionary>> source) + { + return source.SelectMany(item => item.Value.AllValues()); + } + public static ConcurrentDictionary> ToConcurrentDictionary(this IEnumerable> source) { return new ConcurrentDictionary>(source.Select(x => new KeyValuePair>(x.Key, new ConcurrentBag(x)))); } - public static Dictionary> ToDictionary(this IEnumerable> source) + public static IDictionary> ToDictionary(this IEnumerable> source) { return source.ToDictionary(group => group.Key, group => group.ToList()); } + public static IDictionary>> ToDictionary(this IEnumerable>> source) + { + return source.ToDictionary(group => group.Key, group => group.ToDictionary()); + } + public static IReadOnlyDictionary> ToReadonlyDictionary(this IEnumerable> source) { return source.ToDictionary(group => group.Key, group => (IReadOnlyList)group.ToList()); diff --git a/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs b/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs index b987e56f88..d931082361 100644 --- a/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs @@ -125,11 +125,11 @@ Public Sub Goo() End Sub"; const string expectedCode = - @"'@Ignore FunctionReturnValueNotUsed -Public Function Foo(ByVal bar As String) As Boolean + @"Public Function Foo(ByVal bar As String) As Boolean End Function Public Sub Goo() + '@Ignore FunctionReturnValueNotUsed Foo ""test"" End Sub"; From 761a2fdebaf7affbc1a6c526a7c5ea41827ab6e1 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sat, 4 Jan 2020 22:22:02 +0100 Subject: [PATCH 096/461] Reintroduce FunctionReturnValueNeverUsedInspection This is basically what the old FunctionReturnValueNotUsedInspection was supposed to be. --- .../Abstract/DeclarationInspectionBase.cs | 68 +++ .../IdentifierReferenceInspectionBase.cs | 3 +- .../Inspections/Abstract/QuickFixBase.cs | 1 - .../FunctionReturnValueNeverUsedInspection.cs | 311 +++++++++++ .../FunctionReturnValueNotUsedInspection.cs | 7 - .../Concrete/ProcedureNotUsedInspection.cs | 3 - .../QuickFixes/ConvertToProcedureQuickFix.cs | 60 ++- ...tionReturnValueNeverUsedInspectionTests.cs | 488 ++++++++++++++++++ .../ConvertToProcedureQuickFixTests.cs | 42 +- .../QuickFixes/IgnoreOnceQuickFixTests.cs | 26 + 10 files changed, 968 insertions(+), 41 deletions(-) create mode 100644 Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs create mode 100644 Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueNeverUsedInspection.cs create mode 100644 RubberduckTests/Inspections/FunctionReturnValueNeverUsedInspectionTests.cs diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs new file mode 100644 index 0000000000..bf40b0a025 --- /dev/null +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using System.Linq; +using Rubberduck.Inspections.Results; +using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.VBEditor; + +namespace Rubberduck.Inspections.Abstract +{ + public abstract class DeclarationInspectionBase : InspectionBase + { + protected readonly IDeclarationFinderProvider DeclarationFinderProvider; + protected readonly DeclarationType[] RelevantDeclarationTypes; + + protected DeclarationInspectionBase(RubberduckParserState state, params DeclarationType[] relevantDeclarationTypes) + : base(state) + { + DeclarationFinderProvider = state; + RelevantDeclarationTypes = relevantDeclarationTypes; + } + + protected abstract bool IsResultDeclaration(Declaration declaration); + protected abstract string ResultDescription(Declaration declaration); + + protected override IEnumerable DoGetInspectionResults() + { + var results = new List(); + foreach (var moduleDeclaration in State.DeclarationFinder.UserDeclarations(DeclarationType.Module)) + { + if (moduleDeclaration == null) + { + continue; + } + + var module = moduleDeclaration.QualifiedModuleName; + results.AddRange(DoGetInspectionResults(module)); + } + + return results; + } + + private IEnumerable DoGetInspectionResults(QualifiedModuleName module) + { + var objectionableDeclarations = RelevantDeclarationsInModule(module) + .Where(IsResultDeclaration); + + return objectionableDeclarations + .Select(InspectionResult) + .ToList(); + } + + protected virtual IEnumerable RelevantDeclarationsInModule(QualifiedModuleName module) + { + return RelevantDeclarationTypes + .SelectMany(declarationType => DeclarationFinderProvider.DeclarationFinder.Members(module, declarationType)) + .Distinct(); + } + + protected virtual IInspectionResult InspectionResult(Declaration declaration) + { + return new DeclarationInspectionResult( + this, + ResultDescription(declaration), + declaration); + } + } +} \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs index 24362fa2b5..1067dca057 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; @@ -13,7 +12,7 @@ public abstract class IdentifierReferenceInspectionBase : InspectionBase { protected readonly IDeclarationFinderProvider DeclarationFinderProvider; - public IdentifierReferenceInspectionBase(RubberduckParserState state) + protected IdentifierReferenceInspectionBase(RubberduckParserState state) : base(state) { DeclarationFinderProvider = state; diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/QuickFixBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/QuickFixBase.cs index 4569cf28ca..f8c246b357 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/QuickFixBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/QuickFixBase.cs @@ -6,7 +6,6 @@ using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; -using Rubberduck.Parsing.VBA.Extensions; using Rubberduck.Parsing.VBA.Parsing; namespace Rubberduck.Inspections.Abstract diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueNeverUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueNeverUsedInspection.cs new file mode 100644 index 0000000000..36218fa548 --- /dev/null +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueNeverUsedInspection.cs @@ -0,0 +1,311 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Antlr4.Runtime; +using Rubberduck.Inspections.Abstract; +using Rubberduck.Inspections.Results; +using Rubberduck.JunkDrawer.Extensions; +using Rubberduck.Parsing; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Inspections; +using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Resources.Inspections; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.VBEditor; + +namespace Rubberduck.Inspections.Concrete +{ + /// + /// Warns when a user function's return value is never used, at any of its call sites. + /// + /// + /// A 'Function' procedure normally means its return value to be captured and consumed by the calling code. + /// It's possible that not all call sites need the return value, but if the value is systematically discarded then this + /// means the function is side-effecting, and thus should probably be a 'Sub' procedure instead. + /// + /// + /// + /// + /// + /// + /// + public sealed class FunctionReturnValueNeverUsedInspection : DeclarationInspectionBase + { + public FunctionReturnValueNeverUsedInspection(RubberduckParserState state) + :base(state, DeclarationType.Function) + {} + + protected override bool IsResultDeclaration(Declaration declaration) + { + if (!(declaration is ModuleBodyElementDeclaration moduleBodyElementDeclaration)) + { + return false; + } + + //We only report the interface itself. + if (moduleBodyElementDeclaration.IsInterfaceImplementation) + { + return false; + } + + var finder = DeclarationFinderProvider.DeclarationFinder; + + if (moduleBodyElementDeclaration.IsInterfaceMember) + { + return IsInterfaceIssue(moduleBodyElementDeclaration, finder); + } + + return IsIssueItself(moduleBodyElementDeclaration); + } + + private bool IsIssueItself(ModuleBodyElementDeclaration declaration) + { + var procedureCallReferences = ProcedureCallReferences(declaration).ToHashSet(); + if (!procedureCallReferences.Any()) + { + return false; + } + + return declaration.References + .All(reference => procedureCallReferences.Contains(reference) + || reference.IsAssignment && IsReturnStatement(declaration, reference)); + } + + private bool IsReturnStatement(Declaration function, IdentifierReference assignment) + { + return assignment.ParentScoping.Equals(function) && assignment.Declaration.Equals(function); + } + + private bool IsInterfaceIssue(ModuleBodyElementDeclaration declaration, DeclarationFinder finder) + { + if (!IsIssueItself(declaration)) + { + return false; + } + + var implementations = finder.FindInterfaceImplementationMembers(declaration); + return implementations.All(implementation => IsIssueItself(implementation) + || implementation.References.All(reference => + reference.IsAssignment + && IsReturnStatement(implementation, reference))); + } + + private static IEnumerable ProcedureCallReferences(Declaration declaration) + { + return declaration.References + .Where(IsProcedureCallReference); + } + + private static bool IsProcedureCallReference(IdentifierReference reference) + { + return reference?.Declaration != null + && !reference.IsAssignment + && !reference.IsArrayAccess + && !reference.IsInnerRecursiveDefaultMemberAccess + && IsCalledAsProcedure(reference.Context); + } + + private static bool IsCalledAsProcedure(ParserRuleContext context) + { + var callStmt = context.GetAncestor(); + if (callStmt == null) + { + return false; + } + + //If we are in an argument list, the value is used somewhere in defining the argument. + var argumentListParent = context.GetAncestor(); + if (argumentListParent != null) + { + return false; + } + + //Member accesses are parsed right-to-left, e.g. 'foo.Bar' is the parent of 'foo'. + //Thus, having a member access parent means that the return value is used somehow. + var ownFunctionCallExpression = context.Parent is VBAParser.MemberAccessExprContext methodCall + ? methodCall + : context; + var memberAccessParent = ownFunctionCallExpression.GetAncestor(); + if (memberAccessParent != null) + { + return false; + } + + return true; + } + + protected override string ResultDescription(Declaration declaration) + { + var functionName = declaration.QualifiedName.ToString(); + return string.Format(InspectionResults.FunctionReturnValueNeverUsedInspection, functionName); + } + + //protected override IEnumerable DoGetInspectionResults() + //{ + // var interfaceMembers = State.DeclarationFinder.FindAllInterfaceMembers().ToList(); + // var interfaceImplementationMembers = State.DeclarationFinder.FindAllInterfaceImplementingMembers(); + // var functions = State.DeclarationFinder + // .UserDeclarations(DeclarationType.Function) + // .Where(item => item.References.Any(r => !IsReturnStatement(item, r) && !r.IsAssignment)) + // .ToList(); + // var interfaceMemberIssues = GetInterfaceMemberIssues(interfaceMembers); + // var nonInterfaceFunctions = functions.Except(interfaceMembers.Union(interfaceImplementationMembers)); + // var nonInterfaceIssues = GetNonInterfaceIssues(nonInterfaceFunctions); + // return interfaceMemberIssues.Union(nonInterfaceIssues); + //} + + private IEnumerable GetInterfaceMemberIssues(IEnumerable interfaceMembers) + { + return from interfaceMember in interfaceMembers + let implementationMembers = + State.DeclarationFinder.FindInterfaceImplementationMembers(interfaceMember).ToList() + where interfaceMember.DeclarationType == DeclarationType.Function && + !IsReturnValueUsed(interfaceMember) && + implementationMembers.All(member => !IsReturnValueUsed(member)) + let implementationMemberIssues = + implementationMembers.Select( + implementationMember => + Tuple.Create(implementationMember.Context, + new QualifiedSelection(implementationMember.QualifiedName.QualifiedModuleName, + implementationMember.Selection), implementationMember)) + select CreateInspectionResult(this, interfaceMember); + + } + + private IEnumerable GetNonInterfaceIssues(IEnumerable nonInterfaceFunctions) + { + var returnValueNotUsedFunctions = nonInterfaceFunctions.Where(function => function.DeclarationType == DeclarationType.Function && !IsReturnValueUsed(function)); + var nonInterfaceIssues = returnValueNotUsedFunctions + .Where(function => !IsRecursive(function)) + .Select(function => + new DeclarationInspectionResult( + this, + string.Format(InspectionResults.FunctionReturnValueNeverUsedInspection, function.IdentifierName), + function)); + return nonInterfaceIssues; + } + + private bool IsRecursive(Declaration function) + { + return function.References.Any(usage => usage.ParentScoping.Equals(function) && IsIndexExprOrCallStmt(usage)); + } + + private bool IsReturnValueUsed(Declaration function) + { + // TODO: This is O(MG) at work here. Need to refactor the whole shebang. + return (from usage in function.References + where !IsLet(usage) + where !IsSet(usage) + where !IsCallStmt(usage) + where !IsTypeOfExpression(usage) + where !IsAddressOfCall(usage) + select usage).Any(usage => !IsReturnStatement(function, usage)); + } + + private bool IsAddressOfCall(IdentifierReference usage) + { + return usage.Context.IsDescendentOf(); + } + + private bool IsTypeOfExpression(IdentifierReference usage) + { + return usage.Context.IsDescendentOf(); + } + + private bool IsIndexExprOrCallStmt(IdentifierReference usage) + { + return IsCallStmt(usage) || IsIndexExprContext(usage); + } + + private bool IsCallStmt(IdentifierReference usage) + { + var callStmt = usage.Context.GetAncestor(); + if (callStmt == null) + { + return false; + } + + var indexExpr = usage.Context.GetAncestor(); + if (indexExpr != null) + { + var memberAccessStmt = usage.Context.GetAncestor(); + if (memberAccessStmt != null && + callStmt.SourceInterval.ProperlyContains(memberAccessStmt.SourceInterval) && + memberAccessStmt.SourceInterval.ProperlyContains(indexExpr.SourceInterval)) + { + return false; + } + } + + var argumentList = CallStatement.GetArgumentList(callStmt); + if (argumentList == null) + { + return true; + } + return !usage.Context.IsDescendentOf(argumentList); + } + + private bool IsIndexExprContext(IdentifierReference usage) + { + var indexExpr = usage.Context.GetAncestor(); + if (indexExpr == null) + { + return false; + } + var argumentList = indexExpr.argumentList(); + if (argumentList == null) + { + return true; + } + return !usage.Context.IsDescendentOf(argumentList); + } + + private bool IsLet(IdentifierReference usage) + { + var letStmt = usage.Context.GetAncestor(); + + return letStmt != null && letStmt == usage.Context; + } + + private bool IsSet(IdentifierReference usage) + { + var setStmt = usage.Context.GetAncestor(); + + return setStmt != null && setStmt == usage.Context; + } + + private DeclarationInspectionResult CreateInspectionResult(IInspection inspection, Declaration interfaceMember) + { + dynamic properties = new PropertyBag(); + properties.DisableFixes = nameof(QuickFixes.ConvertToProcedureQuickFix); + + return new DeclarationInspectionResult(inspection, + string.Format(InspectionResults.FunctionReturnValueNeverUsedInspection, + interfaceMember.IdentifierName), + interfaceMember, properties: properties); + } + } +} diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueNotUsedInspection.cs index 80fdb7fc2d..7de41640f0 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueNotUsedInspection.cs @@ -85,13 +85,6 @@ private static bool IsCalledAsProcedure(ParserRuleContext context) return false; } - ////AddressOf statements are ignored because they are supposed to not use the return value. - //var addressOfParent = context.GetAncestor(); - //if (addressOfParent != null) - //{ - // return false; - //} - return true; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs index ec364a9593..797586b4e0 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.Common; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Inspections.Results; @@ -9,8 +8,6 @@ using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.VBA.Extensions; -using Rubberduck.VBEditor.SafeComWrappers; namespace Rubberduck.Inspections.Concrete { diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ConvertToProcedureQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/ConvertToProcedureQuickFix.cs index bcf0d01768..572854f0c5 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ConvertToProcedureQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/ConvertToProcedureQuickFix.cs @@ -8,6 +8,7 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; namespace Rubberduck.Inspections.QuickFixes { @@ -49,34 +50,59 @@ namespace Rubberduck.Inspections.QuickFixes /// public sealed class ConvertToProcedureQuickFix : QuickFixBase { - public ConvertToProcedureQuickFix() - : base(typeof(NonReturningFunctionInspection)) - {} + private readonly IDeclarationFinderProvider _declarationFinderProvider; + + public ConvertToProcedureQuickFix(IDeclarationFinderProvider declarationFinderProvider) + : base(typeof(NonReturningFunctionInspection), typeof(FunctionReturnValueNeverUsedInspection)) + { + _declarationFinderProvider = declarationFinderProvider; + } public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) { - var rewriter = rewriteSession.CheckOutModuleRewriter(result.Target.QualifiedModuleName); + if (!(result.Target is ModuleBodyElementDeclaration moduleBodyElementDeclaration)) + { + return; + } + + if (moduleBodyElementDeclaration.IsInterfaceMember) + { + var implementations = _declarationFinderProvider + .DeclarationFinder + .FindInterfaceImplementationMembers(moduleBodyElementDeclaration); + foreach (var implementation in implementations) + { + ConvertMember(implementation, rewriteSession); + } + } + + ConvertMember(moduleBodyElementDeclaration, rewriteSession); + } + + private void ConvertMember(ModuleBodyElementDeclaration member, IRewriteSession rewriteSession) + { + var rewriter = rewriteSession.CheckOutModuleRewriter(member.QualifiedModuleName); - switch (result.Context) + switch (member.Context) { case VBAParser.FunctionStmtContext functionContext: - ConvertFunction(result, functionContext, rewriter); + ConvertFunction(member, functionContext, rewriter); break; case VBAParser.PropertyGetStmtContext propertyGetContext: - ConvertPropertyGet(result, propertyGetContext, rewriter); + ConvertPropertyGet(member, propertyGetContext, rewriter); break; } } - private void ConvertFunction(IInspectionResult result, VBAParser.FunctionStmtContext functionContext, IModuleRewriter rewriter) + private void ConvertFunction(ModuleBodyElementDeclaration member, VBAParser.FunctionStmtContext functionContext, IModuleRewriter rewriter) { RemoveAsTypeDeclaration(functionContext, rewriter); - RemoveTypeHint(result, functionContext, rewriter); + RemoveTypeHint(member, functionContext, rewriter); ConvertFunctionDeclaration(functionContext, rewriter); ConvertExitFunctionStatements(functionContext, rewriter); - RemoveReturnStatements(result, rewriter); + RemoveReturnStatements(member, rewriter); } private static void RemoveAsTypeDeclaration(ParserRuleContext functionContext, IModuleRewriter rewriter) @@ -91,17 +117,17 @@ private static void RemoveAsTypeDeclaration(ParserRuleContext functionContext, I } } - private static void RemoveTypeHint(IInspectionResult result, ParserRuleContext functionContext, IModuleRewriter rewriter) + private static void RemoveTypeHint(ModuleBodyElementDeclaration member, ParserRuleContext functionContext, IModuleRewriter rewriter) { - if (result.Target.TypeHint != null) + if (member.TypeHint != null) { rewriter.Remove(functionContext.GetDescendent()); } } - private void RemoveReturnStatements(IInspectionResult result, IModuleRewriter rewriter) + private void RemoveReturnStatements(ModuleBodyElementDeclaration member, IModuleRewriter rewriter) { - foreach (var returnStatement in GetReturnStatements(result.Target)) + foreach (var returnStatement in GetReturnStatements(member)) { rewriter.Remove(returnStatement); } @@ -125,15 +151,15 @@ private static void ConvertExitFunctionStatements(VBAParser.FunctionStmtContext } } - private void ConvertPropertyGet(IInspectionResult result, VBAParser.PropertyGetStmtContext propertyGetContext, IModuleRewriter rewriter) + private void ConvertPropertyGet(ModuleBodyElementDeclaration member, VBAParser.PropertyGetStmtContext propertyGetContext, IModuleRewriter rewriter) { RemoveAsTypeDeclaration(propertyGetContext, rewriter); - RemoveTypeHint(result, propertyGetContext, rewriter); + RemoveTypeHint(member, propertyGetContext, rewriter); ConvertPropertyGetDeclaration(propertyGetContext, rewriter); ConvertExitPropertyStatements(propertyGetContext, rewriter); - RemoveReturnStatements(result, rewriter); + RemoveReturnStatements(member, rewriter); } private static void ConvertPropertyGetDeclaration(VBAParser.PropertyGetStmtContext propertyGetContext, IModuleRewriter rewriter) diff --git a/RubberduckTests/Inspections/FunctionReturnValueNeverUsedInspectionTests.cs b/RubberduckTests/Inspections/FunctionReturnValueNeverUsedInspectionTests.cs new file mode 100644 index 0000000000..8890af5594 --- /dev/null +++ b/RubberduckTests/Inspections/FunctionReturnValueNeverUsedInspectionTests.cs @@ -0,0 +1,488 @@ +using System.Linq; +using NUnit.Framework; +using Rubberduck.Inspections.Concrete; +using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Parsing.VBA; +using Rubberduck.VBEditor.SafeComWrappers; + +namespace RubberduckTests.Inspections +{ + [TestFixture] + public class FunctionReturnValueNeverUsedInspectionTests : InspectionTestsBase + { + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void IgnoresUnusedFunction() + { + const string code = @" +Public Function Foo() As Long + Foo = 42 +End Function +"; + Assert.AreEqual(0, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void ExplicitCallWithoutAssignment_ReturnsResult() + { + const string code = @" +Public Function Foo(ByVal bar As String) As Integer + Foo = 42 +End Function + +Public Sub Bar() + Call Foo(""Test"") +End Sub +"; + Assert.AreEqual(1, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void CallWithoutAssignment_ReturnsResult() + { + const string code = @" +Public Function Foo(ByVal bar As String) As Integer + Foo = 42 +End Function + +Public Sub Bar() + Foo ""Test"" +End Sub +"; + Assert.AreEqual(1, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void ReturnValueAssignment_DoesNotReturnResult() + { + const string code = @" +Public Function Foo(ByVal bar As String) As Integer + Foo = 42 +End Function + +Public Sub Baz() + TestVal = Foo(""Test"") +End Sub +"; + Assert.AreEqual(0, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void CallWithoutAssignmentAndUseOfReturnValue_NoResult() + { + const string code = @" +Public Function Foo(ByVal bar As String) As Integer + Foo = 42 +End Function + +Public Sub Bar() + Foo ""Test"" +End Sub + +Public Sub Baz() + Dim var As Integer + var = Foo(""Test"") +End Sub +"; + Assert.AreEqual(0, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void TwoUses_OneResult() + { + const string code = @" +Public Function Foo(ByVal bar As String) As Integer + Foo = 42 +End Function + +Public Sub Bar() + Foo ""Test"" +End Sub + +Public Sub Baz() + Foo ""Test"" +End Sub +"; + Assert.AreEqual(1, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void AdressOfAndCallWithoutAssignment_NoResult() + { + const string code = @" +Public Function Foo(ByVal bar As String) As Integer + Foo = 42 +End Function + +Public Sub Bar() + Foo ""Test"" +End Sub + +Public Sub Baz() + Bar AddressOf Foo +End Sub +"; + Assert.AreEqual(0, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void AddressOfAlone_NoResult() + { + const string code = @" +Public Function Foo(ByVal bar As String) As Integer + Foo = 42 +End Function + +Public Sub Bar() + Bar AddressOf Foo +End Sub +"; + Assert.AreEqual(0, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void NoReturnValueAssignment_ReturnsResult() + { + const string code = @" +Public Function Foo() As Integer +End Function + +Public Sub Bar() + Foo +End Sub +"; + Assert.AreEqual(1, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void Ignored_DoesNotReturnResult() + { + const string code = @" +'@Ignore FunctionReturnValueNeverUsed +Public Function Foo() As Integer +End Function + +Public Sub Bar() + Foo +End Sub +"; + Assert.AreEqual(0, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void DoesNotReturnResult_MultipleConsecutiveCalls() + { + const string code = @" +Public Function Foo(ByVal bar As String) As Integer + Foo = 42 +End Function + +Public Sub Baz() + Foo Foo(Foo(""Bar"")) +End Sub +"; + Assert.AreEqual(0, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void IfStatement_DoesNotReturnResult() + { + const string code = @" +Public Function Foo(ByVal bar As String) As Integer + Foo = 42 +End Function + +Public Sub Baz() + If Foo(""Test"") Then + End If +End Sub +"; + Assert.AreEqual(0, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void ForEachStatement_DoesNotReturnResult() + { + const string code = @" +Public Function Foo(ByVal bar As String) As Integer + Foo = 42 +End Function + +Sub Bar(ByVal fizz As Boolean) +End Sub + +Public Sub Baz() + For Each Bar In Foo + Next Bar +End Sub +"; + Assert.AreEqual(0, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void WhileStatement_DoesNotReturnResult() + { + const string code = @" +Public Function Foo(ByVal bar As String) As Integer + Foo = 42 +End Function + +Sub Bar(ByVal fizz As Boolean) +End Sub + +Public Sub Baz() + While Foo + Wend +End Sub +"; + Assert.AreEqual(0, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void DoUntilStatement_DoesNotReturnResult() + { + const string code = @" +Public Function Foo(ByVal bar As String) As Integer + Foo = 42 +End Function + +Sub Bar(ByVal fizz As Boolean) +End Sub + +Public Sub Baz() + Do Until Foo + Loop +End Sub +"; + Assert.AreEqual(0, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void RecursiveFunction_DoesNotReturnResult() + { + const string code = @" +Public Function Factorial(ByVal n As Long) As Long + If n <= 1 Then + Factorial = 1 + Else + Factorial = Factorial(n - 1) * n + End If +End Function +"; + Assert.AreEqual(0, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void ArgumentFunctionCall_DoesNotReturnResult() + { + const string code = @" +Public Function Foo(ByVal bar As String) As Integer + Foo = 42 +End Function + +Sub Bar(ByVal fizz As Boolean) +End Sub + +Public Sub Baz() + Bar Foo(""Test"") +End Sub +"; + Assert.AreEqual(0, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void IgnoresBuiltInFunctions_DoesNotReturnResult() + { + const string code = @" +Public Sub Dummy() + MsgBox ""Test"" + Workbooks.Add +End Sub +"; + Assert.AreEqual(0, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void GivenInterfaceImplementationMember_ReturnsNoResult() + { + const string interfaceCode = @" +Public Function Test() As Integer +End Function +"; + const string implementationCode = @" +Implements IFoo +Public Function IFoo_Test() As Integer + IFoo_Test = 42 +End Function +"; + const string callSiteCode = @" +Public Sub Baz() + Dim testObj As IFoo + Set testObj = new Bar + Dim result As Integer + result = testObj.Test +End Sub +"; + var modules = new (string, string, ComponentType)[] + { + ("IFoo", interfaceCode, ComponentType.ClassModule), + ("Bar", implementationCode, ComponentType.ClassModule), + ("TestModule", callSiteCode, ComponentType.StandardModule), + }; + + Assert.AreEqual(0, InspectionResultsForModules(modules).Count()); + } + + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void ChainedMemberAccess_ReturnsNoResult() + { + const string inputCode = @" +Public Function GetIt(x As Long) As Object +End Function + +Public Sub Baz() + GetIt(1).Select +End Sub"; + Assert.AreEqual(0, InspectionResultsForStandardModule(inputCode).Count()); + } + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void InterfaceMember_ReturnsResult() + { + const string interfaceCode = @" +Public Function Test() As Integer +End Function +"; + const string implementationCode = + @"Implements IFoo +Public Function IFoo_Test() As Integer + IFoo_Test = 42 +End Function +"; + const string callSiteCode = @" +Public Sub Baz() + Dim testObj As IFoo + Set testObj = new Bar + testObj.Test +End Sub +"; + var modules = new (string, string, ComponentType)[] + { + ("IFoo", interfaceCode, ComponentType.ClassModule), + ("Bar", implementationCode, ComponentType.ClassModule), + ("TestModule", callSiteCode, ComponentType.StandardModule), + }; + + Assert.AreEqual(1, InspectionResultsForModules(modules).Count()); + } + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void MemberCallOnReturnValue_NoResult() + { + const string classCode = @" +Public Function Test() As Bar +End Function + +Public Sub FooBar() +End Sub +"; + const string callSiteCode = @" +Public Sub Baz() + Dim testObj As Bar + Set testObj = new Bar + testObj.Test.FooBar +End Sub +"; + var modules = new (string, string, ComponentType)[] + { + ("Bar", classCode, ComponentType.ClassModule), + ("TestModule", callSiteCode, ComponentType.StandardModule), + }; + + Assert.AreEqual(0, InspectionResultsForModules(modules).Count()); + } + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void InterfaceMemberNotUsed_NoResult() + { + const string interfaceCode = @" +Public Function Test() As Integer +End Function +"; + const string implementationCode = + @"Implements IFoo +Public Function IFoo_Test() As Integer + IFoo_Test = 42 +End Function +"; + var modules = new (string, string, ComponentType)[] + { + ("IFoo", interfaceCode, ComponentType.ClassModule), + ("Bar", implementationCode, ComponentType.ClassModule) + }; + + Assert.AreEqual(0, InspectionResultsForModules(modules).Count()); + } + + [Test] + [Category("Inspections")] + [Category("Unused Value")] + public void InspectionName() + { + var inspection = InspectionUnderTest(null); + + Assert.AreEqual(nameof(FunctionReturnValueNeverUsedInspection), inspection.Name); + } + + protected override IInspection InspectionUnderTest(RubberduckParserState state) + { + return new FunctionReturnValueNeverUsedInspection(state); + } + } +} diff --git a/RubberduckTests/QuickFixes/ConvertToProcedureQuickFixTests.cs b/RubberduckTests/QuickFixes/ConvertToProcedureQuickFixTests.cs index d9466af5a2..cadc1d1d55 100644 --- a/RubberduckTests/QuickFixes/ConvertToProcedureQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ConvertToProcedureQuickFixTests.cs @@ -15,7 +15,7 @@ public class ConvertToProcedureQuickFixTests : QuickFixTestBase { [Test] [Category("QuickFixes")] - public void FunctionReturnValueNotUsed_QuickFixWorks_NoInterface() + public void FunctionReturnValueNeverUsedInspection_QuickFixWorks_NoInterface() { const string inputCode = @"Public Function Foo(ByVal bar As String) As Boolean @@ -46,13 +46,13 @@ Public Sub Test() End Sub "; - var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new FunctionReturnValueNotUsedInspection(state)); + var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new FunctionReturnValueNeverUsedInspection(state)); Assert.AreEqual(expectedCode, actualCode); } [Test] [Category("QuickFixes")] - public void FunctionReturnValueNotUsed_QuickFixWorks_NoInterface_ManyBodyStatements() + public void FunctionReturnValueNeverUsedInspection_QuickFixWorks_NoInterface_ManyBodyStatements() { const string inputCode = @"Function foo(ByRef fizz As Boolean) As Boolean @@ -86,13 +86,13 @@ Public Sub Test() End Sub "; - var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new FunctionReturnValueNotUsedInspection(state)); + var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new FunctionReturnValueNeverUsedInspection(state)); Assert.AreEqual(expectedCode, actualCode); } [Test] [Category("QuickFixes")] - public void FunctionReturnValueNotUsed_QuickFixWorks_Interface() + public void FunctionReturnValueNeverUsed_QuickFixWorks_Interface() { const string inputInterfaceCode = @"Public Function Test() As Integer @@ -108,12 +108,24 @@ Public Function IFoo_Test() As Integer IFoo_Test = 42 End Function"; + const string expectedImplementationCode1 = + @"Implements IFoo +Public Sub IFoo_Test() + +End Sub"; + const string inputImplementationCode2 = @"Implements IFoo Public Function IFoo_Test() As Integer IFoo_Test = 42 End Function"; + const string expectedImplementationCode2 = + @"Implements IFoo +Public Sub IFoo_Test() + +End Sub"; + const string callSiteCode = @" Public Function Baz() @@ -134,15 +146,23 @@ Dim testObj As IFoo using (state) { - var inspection = new FunctionReturnValueNotUsedInspection(state); + var inspection = new FunctionReturnValueNeverUsedInspection(state); var inspectionResults = inspection.GetInspectionResults(CancellationToken.None); var rewriteSession = rewritingManager.CheckOutCodePaneSession(); - new ConvertToProcedureQuickFix().Fix(inspectionResults.First(), rewriteSession); + new ConvertToProcedureQuickFix(state).Fix(inspectionResults.First(), rewriteSession); + + var interfaceModule = state.DeclarationFinder.AllModules.Single(module => module.ComponentName.Equals("IFoo")); + var implementationModule1 = state.DeclarationFinder.AllModules.Single(module => module.ComponentName.Equals("Bar")); + var implementationModule2 = state.DeclarationFinder.AllModules.Single(module => module.ComponentName.Equals("Bar2")); + + var actualInterfaceCode = rewriteSession.CheckOutModuleRewriter(interfaceModule).GetText(); + var actualImplementationModule1Code = rewriteSession.CheckOutModuleRewriter(implementationModule1).GetText(); + var actualImplementationModule2Code = rewriteSession.CheckOutModuleRewriter(implementationModule2).GetText(); - var component = vbe.Object.VBProjects[0].VBComponents[0]; - var actualCode = rewriteSession.CheckOutModuleRewriter(component.QualifiedModuleName).GetText(); - Assert.AreEqual(expectedInterfaceCode, actualCode); + Assert.AreEqual(expectedInterfaceCode, actualInterfaceCode); + Assert.AreEqual(expectedImplementationCode1, actualImplementationModule1Code); + Assert.AreEqual(expectedImplementationCode2, actualImplementationModule2Code); } } @@ -335,7 +355,7 @@ public void GivenParameterizedPropertyGetter_QuickFixKeepsParameter() protected override IQuickFix QuickFix(RubberduckParserState state) { - return new ConvertToProcedureQuickFix(); + return new ConvertToProcedureQuickFix(state); } } } diff --git a/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs b/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs index d931082361..278f77e779 100644 --- a/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs @@ -137,6 +137,32 @@ Public Sub Goo() Assert.AreEqual(expectedCode, actualCode); } + [Test] + [Category("QuickFixes")] + [Category("Unused Value")] + public void FunctionReturnValueNeverUsed_IgnoreQuickFixWorks() + { + const string inputCode = + @"Public Function Foo(ByVal bar As String) As Boolean +End Function + +Public Sub Goo() + Foo ""test"" +End Sub"; + + const string expectedCode = + @"'@Ignore FunctionReturnValueNeverUsed +Public Function Foo(ByVal bar As String) As Boolean +End Function + +Public Sub Goo() + Foo ""test"" +End Sub"; + + var actualCode = ApplyIgnoreOnceToFirstResult(inputCode, state => new FunctionReturnValueNeverUsedInspection(state), TestStandardModuleVbeSetup); + Assert.AreEqual(expectedCode, actualCode); + } + [Test] [Category("QuickFixes")] public void AnnotationListFollowedByCommentAddsAnnotationCorrectly() From f3040a19ecc9ae26dff9bd9dcb6bdd6c2875e8e1 Mon Sep 17 00:00:00 2001 From: IvenBach Date: Sat, 4 Jan 2020 10:07:12 -0800 Subject: [PATCH 097/461] Add ignore/unignore selection commands --- .../UI/UnitTesting/TestExplorerControl.xaml | 28 +++-- .../UI/UnitTesting/TestExplorerViewModel.cs | 103 ++++++++++++++---- .../UnitTesting/TestExplorer.Designer.cs | 18 +++ .../UnitTesting/TestExplorer.resx | 6 + 4 files changed, 123 insertions(+), 32 deletions(-) diff --git a/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml b/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml index e5cabf315b..12499f699e 100644 --- a/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml +++ b/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml @@ -55,12 +55,9 @@ - + - - - - + @@ -459,17 +456,32 @@ Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_ContextMenuIgnoreGroup}" Visibility="{Binding DisplayIgnoreGroupLabel, Converter={StaticResource BoolToVisibility}}"> - + - + - + + + + + + + + + + + + diff --git a/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs b/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs index 47d420b051..8ff07657e8 100644 --- a/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs +++ b/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs @@ -78,6 +78,8 @@ public TestExplorerViewModel(ISelectionService selectionService, UnignoreTestCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteUnignoreTestCommand); IgnoreGroupCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteIgnoreGroupCommand, CanIgnoreGroupCommand); UnignoreGroupCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteUnignoreGroupCommand, CanUnignoreGroupCommand); + IgnoreSelectedTestsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteIgnoreSelectedTestsCommand, CanExecuteSelectedTestsCommand); + UnignoreSelectedTestsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteUnignoreSelectedTestsCommand, CanUnignoreSelectedTestsCommand); RewritingManager = rewritingManager; AnnotationUpdater = annotationUpdater; @@ -259,7 +261,7 @@ public bool DisplayUnignoreGroupLabel var testsInGroup = MouseOverGroup.Items.Cast(); - return testsInGroup.Where(test => test.Method.IsIgnored).Any(); ; + return testsInGroup.Any(test => test.Method.IsIgnored); } } @@ -274,7 +276,7 @@ public bool DisplayIgnoreGroupLabel var testsInGroup = MouseOverGroup.Items.Cast(); - return testsInGroup.Where(test => test.Method.IsIgnored).Count() != MouseOverGroup.Items.Count; + return testsInGroup.Count(test => test.Method.IsIgnored) != MouseOverGroup.ItemCount; } } @@ -315,6 +317,9 @@ public bool DisplayIgnoreGroupLabel public CommandBase IgnoreGroupCommand { get; } public CommandBase UnignoreGroupCommand { get; } + public CommandBase IgnoreSelectedTestsCommand { get; } + public CommandBase UnignoreSelectedTestsCommand { get; } + #endregion #region Delegates @@ -329,6 +334,11 @@ private bool CanExecuteSelectedTestsCommand(object obj) return !Model.IsBusy && obj is IList viewModels && viewModels.Count > 0; } + private bool CanUnignoreSelectedTestsCommand(object obj) + { + return true; + } + private bool CanExecuteGroupCommand(object obj) { return !Model.IsBusy && (MouseOverTest != null || MouseOverGroup != null); @@ -432,22 +442,27 @@ private void ExecuteIgnoreTestCommand(object parameter) { var rewriteSession = RewritingManager.CheckOutCodePaneSession(); - AnnotationUpdater.AddAnnotation(rewriteSession, _mousedOverTestMethod.Declaration, new IgnoreTestAnnotation()); + var testMethod = parameter is null + ? _mousedOverTestMethod + : (TestMethod)parameter; + + AnnotationUpdater.AddAnnotation(rewriteSession, testMethod.Declaration, new IgnoreTestAnnotation()); rewriteSession.TryRewrite(); } private void ExecuteUnignoreTestCommand(object parameter) { - var rewriteSession = RewritingManager.CheckOutCodePaneSession(); - - var ignoreTestAnnotations = _mousedOverTestMethod.Declaration.Annotations + var testMethod = parameter is null + ? _mousedOverTestMethod + : (TestMethod)parameter; + + var ignoreTestAnnotations = testMethod.Declaration.Annotations .Where(pta => pta.Annotation is IgnoreTestAnnotation); - foreach (var ignoreTestAnnotation in ignoreTestAnnotations) - { - AnnotationUpdater.RemoveAnnotation(rewriteSession, ignoreTestAnnotation); - } + var rewriteSession = RewritingManager.CheckOutCodePaneSession(); + + AnnotationUpdater.RemoveAnnotations(rewriteSession, ignoreTestAnnotations); rewriteSession.TryRewrite(); } @@ -460,20 +475,6 @@ private void ExecuteIgnoreGroupCommand (object parameter) foreach (TestMethodViewModel test in testGroup.Items) { - //var needsIgnoreAnnotationAdded = true; - //foreach (var annotation in test.Method.Declaration.Annotations) - //{ - // if (annotation.Annotation is IgnoreTestAnnotation) - // { - // needsIgnoreAnnotationAdded = false; - // }; - //} - - //if (needsIgnoreAnnotationAdded) - //{ - // AnnotationUpdater.AddAnnotation(rewriteSession, test.Method.Declaration, ignoreTestAnnotation); - //} - if (!test.Method.IsIgnored) { AnnotationUpdater.AddAnnotation(rewriteSession, test.Method.Declaration, ignoreTestAnnotation); @@ -502,6 +503,60 @@ private void ExecuteUnignoreGroupCommand(object parameter) rewriteSession.TryRewrite(); } + private void ExecuteUnignoreSelectedTestsCommand(object parameter) + { + if (Model.IsBusy || !(parameter is IList viewModels && viewModels.Count > 0)) + { + return; + } + + var ignoredModels = viewModels.OfType() + .Where(model => model.Method.IsIgnored); + + if (!ignoredModels.Any()) + { + return; + } + + var rewriteSession = RewritingManager.CheckOutCodePaneSession(); + + foreach (var test in ignoredModels) + { + var ignoreTestAnnotations = test.Method.Declaration.Annotations + .Where(pta => pta.Annotation is IgnoreTestAnnotation); + + AnnotationUpdater.RemoveAnnotations(rewriteSession, ignoreTestAnnotations); + } + + rewriteSession.TryRewrite(); + } + + private void ExecuteIgnoreSelectedTestsCommand(object parameter) + { + if (Model.IsBusy || !(parameter is IList viewModels && viewModels.Count > 0)) + { + return; + } + + var unignoredModels = viewModels.OfType() + .Where(model => !model.Method.IsIgnored); + + if (!unignoredModels.Any()) + { + return; + } + + var rewriteSession = RewritingManager.CheckOutCodePaneSession(); + var ignoreTestAnnotation = new IgnoreTestAnnotation(); + + foreach (var test in unignoredModels) + { + AnnotationUpdater.AddAnnotation(rewriteSession, test.Method.Declaration, ignoreTestAnnotation); + } + + rewriteSession.TryRewrite(); + } + private void ExecuteCopyResultsCommand(object parameter) { const string XML_SPREADSHEET_DATA_FORMAT = "XML Spreadsheet"; diff --git a/Rubberduck.Resources/UnitTesting/TestExplorer.Designer.cs b/Rubberduck.Resources/UnitTesting/TestExplorer.Designer.cs index 3065abc50a..8f972fb85f 100644 --- a/Rubberduck.Resources/UnitTesting/TestExplorer.Designer.cs +++ b/Rubberduck.Resources/UnitTesting/TestExplorer.Designer.cs @@ -132,6 +132,15 @@ public static string TestExplorer_ContextMenuIgnoreGroup { } } + /// + /// Looks up a localized string similar to Ignore selected tests. + /// + public static string TestExplorer_ContextMenuIgnoreSelectedTests { + get { + return ResourceManager.GetString("TestExplorer_ContextMenuIgnoreSelectedTests", resourceCulture); + } + } + /// /// Looks up a localized string similar to Run all tests. /// @@ -177,6 +186,15 @@ public static string TestExplorer_ContextMenuUnignoreGroup { } } + /// + /// Looks up a localized string similar to Unignore selected tests. + /// + public static string TestExplorer_ContextMenuUnignoreSelectedTests { + get { + return ResourceManager.GetString("TestExplorer_ContextMenuUnignoreSelectedTests", resourceCulture); + } + } + /// /// Looks up a localized string similar to Duration. /// diff --git a/Rubberduck.Resources/UnitTesting/TestExplorer.resx b/Rubberduck.Resources/UnitTesting/TestExplorer.resx index 983b721f86..7bebb7c57f 100644 --- a/Rubberduck.Resources/UnitTesting/TestExplorer.resx +++ b/Rubberduck.Resources/UnitTesting/TestExplorer.resx @@ -357,4 +357,10 @@ Unignore group tests + + Unignore selected tests + + + Ignore selected tests + \ No newline at end of file From c899e688dd12f5323edff1793dd6456e39f70c1f Mon Sep 17 00:00:00 2001 From: IvenBach Date: Sat, 4 Jan 2020 22:15:29 -0800 Subject: [PATCH 098/461] Update resource strings --- Rubberduck.Resources/UnitTesting/TestExplorer.Designer.cs | 4 ++-- Rubberduck.Resources/UnitTesting/TestExplorer.resx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Rubberduck.Resources/UnitTesting/TestExplorer.Designer.cs b/Rubberduck.Resources/UnitTesting/TestExplorer.Designer.cs index 8f972fb85f..cfb2a476dd 100644 --- a/Rubberduck.Resources/UnitTesting/TestExplorer.Designer.cs +++ b/Rubberduck.Resources/UnitTesting/TestExplorer.Designer.cs @@ -124,7 +124,7 @@ public static string TestExplorer_CategoryName { } /// - /// Looks up a localized string similar to Ignore group tests. + /// Looks up a localized string similar to Ignore all tests in group. /// public static string TestExplorer_ContextMenuIgnoreGroup { get { @@ -178,7 +178,7 @@ public static string TestExplorer_ContextMenuRunSingle { } /// - /// Looks up a localized string similar to Unignore group tests. + /// Looks up a localized string similar to Unignore all tests in group. /// public static string TestExplorer_ContextMenuUnignoreGroup { get { diff --git a/Rubberduck.Resources/UnitTesting/TestExplorer.resx b/Rubberduck.Resources/UnitTesting/TestExplorer.resx index 7bebb7c57f..07acee92df 100644 --- a/Rubberduck.Resources/UnitTesting/TestExplorer.resx +++ b/Rubberduck.Resources/UnitTesting/TestExplorer.resx @@ -352,10 +352,10 @@ Unignore test - Ignore group tests + Ignore all tests in group - Unignore group tests + Unignore all tests in group Unignore selected tests From 332b963d343de3ee8ae695a818b74f778147d910 Mon Sep 17 00:00:00 2001 From: IvenBach Date: Sat, 4 Jan 2020 22:17:21 -0800 Subject: [PATCH 099/461] Make generic command execution check --- .../UI/UnitTesting/TestExplorerViewModel.cs | 27 +++++-------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs b/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs index 8ff07657e8..e940e2bd1a 100644 --- a/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs +++ b/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs @@ -66,7 +66,7 @@ public TestExplorerViewModel(ISelectionService selectionService, NavigateCommand = new NavigateCommand(selectionService); RunSingleTestCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteSingleTestCommand, CanExecuteSingleTest); - RunSelectedTestsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteSelectedTestsCommand, CanExecuteSelectedTestsCommand); + RunSelectedTestsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteSelectedTestsCommand, CanExecuteSelectionCommand); RunSelectedGroupCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteRunSelectedGroupCommand, CanExecuteGroupCommand); CancelTestRunCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteCancelTestRunCommand, CanExecuteCancelTestRunCommand); ResetResultsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteResetResultsCommand, CanExecuteResetResultsCommand); @@ -76,10 +76,10 @@ public TestExplorerViewModel(ISelectionService selectionService, ExpandAllCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteExpandAll); IgnoreTestCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteIgnoreTestCommand); UnignoreTestCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteUnignoreTestCommand); - IgnoreGroupCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteIgnoreGroupCommand, CanIgnoreGroupCommand); - UnignoreGroupCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteUnignoreGroupCommand, CanUnignoreGroupCommand); - IgnoreSelectedTestsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteIgnoreSelectedTestsCommand, CanExecuteSelectedTestsCommand); - UnignoreSelectedTestsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteUnignoreSelectedTestsCommand, CanUnignoreSelectedTestsCommand); + IgnoreGroupCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteIgnoreGroupCommand, CanExecuteGroupCommand); + UnignoreGroupCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteUnignoreGroupCommand, CanExecuteGroupCommand); + IgnoreSelectedTestsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteIgnoreSelectedTestsCommand, CanExecuteSelectionCommand); + UnignoreSelectedTestsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteUnignoreSelectedTestsCommand, CanExecuteSelectionCommand); RewritingManager = rewritingManager; AnnotationUpdater = annotationUpdater; @@ -329,31 +329,16 @@ private bool CanExecuteSingleTest(object obj) return !Model.IsBusy && MouseOverTest != null; } - private bool CanExecuteSelectedTestsCommand(object obj) + private bool CanExecuteSelectionCommand(object obj) { return !Model.IsBusy && obj is IList viewModels && viewModels.Count > 0; } - private bool CanUnignoreSelectedTestsCommand(object obj) - { - return true; - } - private bool CanExecuteGroupCommand(object obj) { return !Model.IsBusy && (MouseOverTest != null || MouseOverGroup != null); } - private bool CanIgnoreGroupCommand(object obj) - { - return CanExecuteGroupCommand(obj); - } - - private bool CanUnignoreGroupCommand(object obj) - { - return CanExecuteGroupCommand(obj); - } - private bool CanExecuteResetResultsCommand(object obj) { return !Model.IsBusy && Tests.OfType().Any(test => test.Result.Outcome != TestOutcome.Unknown); From b1a8ca7aa04d61a2ec228461fd725da6dcabe18d Mon Sep 17 00:00:00 2001 From: IvenBach Date: Sun, 5 Jan 2020 00:11:19 -0800 Subject: [PATCH 100/461] Update CanExecute logic for (i|uni)gnore commands --- -multiinst | 0 .../UI/UnitTesting/TestExplorerControl.xaml | 49 ++++++------- .../UI/UnitTesting/TestExplorerViewModel.cs | 73 ++++++++++--------- 3 files changed, 63 insertions(+), 59 deletions(-) create mode 100644 -multiinst diff --git a/-multiinst b/-multiinst new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml b/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml index 12499f699e..256ddc83a4 100644 --- a/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml +++ b/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml @@ -437,46 +437,45 @@ + + + + Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_TestToggle_Ignore}" > + Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_TestToggle_Unignore}" > - + + + + + + + + + + + + + Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_ContextMenuIgnoreGroup}" > - - - - - - - - - - - - + diff --git a/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs b/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs index e940e2bd1a..48041c68d9 100644 --- a/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs +++ b/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.ComponentModel; using System.Globalization; using System.Linq; @@ -66,7 +67,7 @@ public TestExplorerViewModel(ISelectionService selectionService, NavigateCommand = new NavigateCommand(selectionService); RunSingleTestCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteSingleTestCommand, CanExecuteSingleTest); - RunSelectedTestsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteSelectedTestsCommand, CanExecuteSelectionCommand); + RunSelectedTestsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteSelectedTestsCommand, CanExecuteSelectedCommands); RunSelectedGroupCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteRunSelectedGroupCommand, CanExecuteGroupCommand); CancelTestRunCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteCancelTestRunCommand, CanExecuteCancelTestRunCommand); ResetResultsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteResetResultsCommand, CanExecuteResetResultsCommand); @@ -74,12 +75,12 @@ public TestExplorerViewModel(ISelectionService selectionService, OpenTestSettingsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), OpenSettings); CollapseAllCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteCollapseAll); ExpandAllCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteExpandAll); - IgnoreTestCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteIgnoreTestCommand); - UnignoreTestCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteUnignoreTestCommand); - IgnoreGroupCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteIgnoreGroupCommand, CanExecuteGroupCommand); - UnignoreGroupCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteUnignoreGroupCommand, CanExecuteGroupCommand); - IgnoreSelectedTestsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteIgnoreSelectedTestsCommand, CanExecuteSelectionCommand); - UnignoreSelectedTestsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteUnignoreSelectedTestsCommand, CanExecuteSelectionCommand); + IgnoreTestCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteIgnoreTestCommand, CanExecuteIgnoreTestCommand); + UnignoreTestCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteUnignoreTestCommand, CanExecuteUnignoreTestCommand); + IgnoreSelectedTestsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteIgnoreSelectedTestsCommand, CanExecuteIgnoreSelectedTests); + UnignoreSelectedTestsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteUnignoreSelectedTestsCommand, CanExecuteUnignoreSelectedTests); + IgnoreGroupCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteIgnoreGroupCommand, CanExecuteIgnoreGroupCommand); + UnignoreGroupCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteUnignoreGroupCommand, CanExecuteUnignoreGroupCommand); RewritingManager = rewritingManager; AnnotationUpdater = annotationUpdater; @@ -140,10 +141,10 @@ public CollectionViewGroup MouseOverGroup private void RefreshContextMenu() { - OnPropertyChanged(nameof(DisplayUnignoreTestLabel)); - OnPropertyChanged(nameof(DisplayIgnoreTestLabel)); - OnPropertyChanged(nameof(DisplayUnignoreGroupLabel)); - OnPropertyChanged(nameof(DisplayIgnoreGroupLabel)); + OnPropertyChanged(nameof(CanExecuteUnignoreTestCommand)); + OnPropertyChanged(nameof(CanExecuteIgnoreTestCommand)); + OnPropertyChanged(nameof(CanExecuteUnignoreGroupCommand)); + OnPropertyChanged(nameof(CanExecuteIgnoreGroupCommand)); } private static readonly Dictionary GroupDescriptions = new Dictionary @@ -247,37 +248,41 @@ private void HandleTestCompletion(object sender, TestCompletedEventArgs e) public IAnnotationUpdater AnnotationUpdater { get; } private TestMethod _mousedOverTestMethod => ((TestMethodViewModel)SelectedItem).Method; - public bool DisplayUnignoreTestLabel => SelectedItem != null && _mousedOverTestMethod.IsIgnored; - public bool DisplayIgnoreTestLabel => SelectedItem != null && !_mousedOverTestMethod.IsIgnored; + public bool CanExecuteUnignoreTestCommand(object obj) => SelectedItem != null && _mousedOverTestMethod.IsIgnored; + public bool CanExecuteIgnoreTestCommand(object obj) => SelectedItem != null && !_mousedOverTestMethod.IsIgnored; - public bool DisplayUnignoreGroupLabel + public bool CanExecuteIgnoreSelectedTests(object obj) { - get + if (!Model.IsBusy && obj is IList viewModels && viewModels.Count > 0) { - if (MouseOverGroup?.Items == null) - { - return false; - } - - var testsInGroup = MouseOverGroup.Items.Cast(); + return viewModels.Cast().Count(test => test.Method.IsIgnored) != viewModels.Count; + } - return testsInGroup.Any(test => test.Method.IsIgnored); + return false; + } + public bool CanExecuteUnignoreSelectedTests(object obj) + { + if (!Model.IsBusy && obj is IList viewModels && viewModels.Count > 0) + { + return viewModels.Cast().Any(test => test.Method.IsIgnored); } + + return false; } - public bool DisplayIgnoreGroupLabel + public bool CanExecuteIgnoreGroupCommand(object obj) { - get - { - if (MouseOverGroup?.Items == null) - { - return false; - } + var groupItems = MouseOverGroup?.Items + ?? GroupContainingSelectedTest(MouseOverTest).Items; - var testsInGroup = MouseOverGroup.Items.Cast(); + return groupItems.Cast().Count(test => test.Method.IsIgnored) != groupItems.Count; + } + public bool CanExecuteUnignoreGroupCommand(object obj) + { + var groupItems = MouseOverGroup?.Items + ?? GroupContainingSelectedTest(MouseOverTest).Items; - return testsInGroup.Count(test => test.Method.IsIgnored) != MouseOverGroup.ItemCount; - } + return groupItems.Cast().Any(test => test.Method.IsIgnored); } #region Commands @@ -329,7 +334,7 @@ private bool CanExecuteSingleTest(object obj) return !Model.IsBusy && MouseOverTest != null; } - private bool CanExecuteSelectionCommand(object obj) + private bool CanExecuteSelectedCommands(object obj) { return !Model.IsBusy && obj is IList viewModels && viewModels.Count > 0; } @@ -452,7 +457,7 @@ private void ExecuteUnignoreTestCommand(object parameter) rewriteSession.TryRewrite(); } - private void ExecuteIgnoreGroupCommand (object parameter) + private void ExecuteIgnoreGroupCommand(object parameter) { var rewriteSession = RewritingManager.CheckOutCodePaneSession(); var testGroup = GroupContainingSelectedTest(MouseOverTest); From 78084fdbf788e2929b2a97bf1c941e89cadc5770 Mon Sep 17 00:00:00 2001 From: IvenBach Date: Sun, 5 Jan 2020 00:13:48 -0800 Subject: [PATCH 101/461] Remove unused using directives --- Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs | 4 ---- Rubberduck.Parsing/VBA/IAnnotationUpdater.cs | 1 - 2 files changed, 5 deletions(-) diff --git a/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs b/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs index 48041c68d9..066e0139de 100644 --- a/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs +++ b/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs @@ -1,12 +1,10 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.ComponentModel; using System.Globalization; using System.Linq; using System.Windows; -using System.Windows.Annotations; using System.Windows.Data; using NLog; using Rubberduck.Common; @@ -14,7 +12,6 @@ using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.VBA; -using Rubberduck.Resources; using Rubberduck.Settings; using Rubberduck.SettingsProvider; using Rubberduck.UI.Command; @@ -25,7 +22,6 @@ using Rubberduck.UI.UnitTesting.ViewModels; using Rubberduck.UnitTesting; using Rubberduck.VBEditor.Utility; -using Rubberduck.Formatters; namespace Rubberduck.UI.UnitTesting { diff --git a/Rubberduck.Parsing/VBA/IAnnotationUpdater.cs b/Rubberduck.Parsing/VBA/IAnnotationUpdater.cs index cd15aff747..8640c465d5 100644 --- a/Rubberduck.Parsing/VBA/IAnnotationUpdater.cs +++ b/Rubberduck.Parsing/VBA/IAnnotationUpdater.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using Antlr4.Runtime; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; From 482ec4cde1a2f76b751fb9e8d29e63f0badf1102 Mon Sep 17 00:00:00 2001 From: IvenBach Date: Sun, 5 Jan 2020 00:27:56 -0800 Subject: [PATCH 102/461] Remove commented out code --- Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs b/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs index 066e0139de..b8b14f5d63 100644 --- a/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs +++ b/Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs @@ -389,9 +389,6 @@ private void ExecuteSelectedTestsCommand(object obj) private void ExecuteRunSelectedGroupCommand(object obj) { - //var tests = MouseOverTest is null - // ? MouseOverGroup - // : Tests.Groups.OfType().FirstOrDefault(group => group.Items.Contains(MouseOverTest)); var tests = GroupContainingSelectedTest(MouseOverTest); if (tests is null) From 12e00fb5956b2ede020c0ab2cae9c06b427abec5 Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Sun, 5 Jan 2020 10:14:00 -0500 Subject: [PATCH 103/461] honor SCP settings; closes #5341 --- .../AutoComplete/SelfClosingPairs/SelfClosingPairHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rubberduck.Core/AutoComplete/SelfClosingPairs/SelfClosingPairHandler.cs b/Rubberduck.Core/AutoComplete/SelfClosingPairs/SelfClosingPairHandler.cs index 3ba10a12d6..8d39efa259 100644 --- a/Rubberduck.Core/AutoComplete/SelfClosingPairs/SelfClosingPairHandler.cs +++ b/Rubberduck.Core/AutoComplete/SelfClosingPairs/SelfClosingPairHandler.cs @@ -40,7 +40,7 @@ public SelfClosingPairHandler(ICodePaneHandler pane, SelfClosingPairCompletionSe public override bool Handle(AutoCompleteEventArgs e, AutoCompleteSettings settings, out CodeString result) { result = null; - if (!_scpInputLookup.TryGetValue(e.Character, out var pair) && e.Character != '\b') + if (!settings.SelfClosingPairs.IsEnabled || !_scpInputLookup.TryGetValue(e.Character, out var pair) && e.Character != '\b') { // not an interesting keypress. return false; From a182a8b004d54446bacea405d172374c59b8d5d7 Mon Sep 17 00:00:00 2001 From: Clemens Lieb Date: Tue, 31 Dec 2019 16:19:20 +0100 Subject: [PATCH 104/461] Coax codecov into cooperating, fixes #5332 Additionally make codecoverage status work on informational level. See necessity for fix described at https://github.com/OpenCover/opencover/issues/914 --- appveyor.yml | 21 +++++++++++++++------ codecov.yml | 18 ++++++++++++------ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 451b8279d0..515215d1af 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -50,11 +50,15 @@ dotnet_csproj: version: '{version}' assembly_version: '{version}' +# set up the environment variables used later in the build process +environment: + installer_dir: Rubberduck.Deployment\InnoSetup\Installers\ + codecov_token: + secure: WXzsqA7du+xTCQN0p06UFYOe94bKkB1ZtyCWS0Xlsu7OwIwKIa/OPaHj8Yev1JGl before_build: - development/java/Rubberduck.Parsing/Grammar/gradlew.bat -p development/java/Rubberduck.Parsing/Grammar clean build - cinst innosetup -version 5.6.1 - - cinst codecov - cinst opencover.portable - nuget restore RubberduckMeta.sln - nuget restore Rubberduck.sln @@ -66,14 +70,15 @@ build: # Otherwise we might run tests against artifacts that do not exist test_script: # we use -returntargetcode to fail the build if tests fail - - cmd: OpenCover.Console.exe -register:user -returntargetcode -target:"nunit3-console.exe" -targetargs:".\RubberduckTests\bin\RubberduckTests.dll" -output:".\Rubberduck_Coverage.xml" - - cmd: OpenCover.Console.exe -register:user -returntargetcode -target:"nunit3-console.exe" -targetargs:".\RubberduckTestsCodeAnalysis\bin\RubberduckTestsCodeAnalysis.dll" -output:".\RubberduckCodeAnalysis_Coverage.xml" # when using test_script, after_test seems to not be executed - - cmd: codecov -f "Rubberduck_Coverage.xml RubberduckCodeAnalysis_Coverage.xml" + # Manually select coverage instrumentation using "-register:Path64" to fix coverage generation + - | + OpenCover.Console.exe -register:Path64 -returntargetcode -target:"nunit3-console.exe" -targetargs:".\RubberduckTests\bin\RubberduckTests.dll" -output:".\Rubberduck_Coverage.xml" + OpenCover.Console.exe -register:Path64 -returntargetcode -target:"nunit3-console.exe" -targetargs:".\RubberduckTestsCodeAnalysis\bin\RubberduckTestsCodeAnalysis.dll" -output:".\RubberduckCodeAnalysis_Coverage.xml" + curl --silent https://codecov.io/bash --output codecov + bash codecov -f Rubberduck_Coverage.xml -f RubberduckCodeAnalysis_Coverage.xml # Define the installer-name depending on what branch we're building on -environment: - installer_dir: Rubberduck.Deployment\InnoSetup\Installers\ for: - branches: @@ -116,6 +121,10 @@ artifacts: name: InspectionDocs - path: Rubberduck.Deployment\InnoSetup\Installers\*.hash name: InstallerHashes + - path: Rubberduck_Coverage.xml + name: MainCoverage + - path: RubberduckCodeAnalysis_Coverage.xml + name: AnalysisCoverage deploy: - provider: GitHub tag: RETAGMEWITHAMESSAGE diff --git a/codecov.yml b/codecov.yml index 4763723202..da8dd5a659 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,7 +1,4 @@ codecov: - branch: next - ci: - - appveyor max_report_age: off ignore: @@ -19,8 +16,15 @@ coverage: precision: 2 range: 40..80 status: - # don't check patch coverage - patch: off + # don't block mindlessly on coverage failures + informational: true + # status information for PRs only + only_pulls: true + patch: + default: + # strongly suggest more than 60% of changes be covered + target: 60 + threshold: 10 project: default: target: 0 # don't force a minimum coverage @@ -31,4 +35,6 @@ coverage: comment: layout: "flags, diff, files" behavior: once - require_changes: yes + require_head: no + require_base: no + From c0c0afc3bff85338b25efc6cfd92c24f3d7d6ac3 Mon Sep 17 00:00:00 2001 From: Clemens Lieb Date: Sun, 5 Jan 2020 22:27:25 +0100 Subject: [PATCH 105/461] Limit coverage messages for performance gains --- appveyor.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 515215d1af..fcd6e1a763 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -72,9 +72,10 @@ test_script: # we use -returntargetcode to fail the build if tests fail # when using test_script, after_test seems to not be executed # Manually select coverage instrumentation using "-register:Path64" to fix coverage generation + # Limit number of visits recorded with threshold to improve performance - | - OpenCover.Console.exe -register:Path64 -returntargetcode -target:"nunit3-console.exe" -targetargs:".\RubberduckTests\bin\RubberduckTests.dll" -output:".\Rubberduck_Coverage.xml" - OpenCover.Console.exe -register:Path64 -returntargetcode -target:"nunit3-console.exe" -targetargs:".\RubberduckTestsCodeAnalysis\bin\RubberduckTestsCodeAnalysis.dll" -output:".\RubberduckCodeAnalysis_Coverage.xml" + OpenCover.Console.exe -register:Path64 -returntargetcode -target:"nunit3-console.exe" -threshold:10 -targetargs:".\RubberduckTests\bin\RubberduckTests.dll" -output:".\Rubberduck_Coverage.xml" + OpenCover.Console.exe -register:Path64 -returntargetcode -target:"nunit3-console.exe" -threshold:10 -targetargs:".\RubberduckTestsCodeAnalysis\bin\RubberduckTestsCodeAnalysis.dll" -output:".\RubberduckCodeAnalysis_Coverage.xml" curl --silent https://codecov.io/bash --output codecov bash codecov -f Rubberduck_Coverage.xml -f RubberduckCodeAnalysis_Coverage.xml From de90e516cd70df17c750fa12fad769a520297e61 Mon Sep 17 00:00:00 2001 From: IvenBach Date: Sun, 5 Jan 2020 18:22:16 -0800 Subject: [PATCH 106/461] Restore removed Scrollviewer --- .../UI/UnitTesting/TestExplorerControl.xaml | 285 +++++++++--------- 1 file changed, 146 insertions(+), 139 deletions(-) diff --git a/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml b/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml index 256ddc83a4..93d99d0b2e 100644 --- a/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml +++ b/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml @@ -349,145 +349,152 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 963486ad4823398c8fbbced67676711304835200 Mon Sep 17 00:00:00 2001 From: IvenBach Date: Sun, 5 Jan 2020 18:48:29 -0800 Subject: [PATCH 107/461] Replace tabs with spaces --- Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml b/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml index 93d99d0b2e..aa639eff0e 100644 --- a/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml +++ b/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml @@ -57,7 +57,7 @@ - + From 8692b667b17ad11405432bdc1b1c8fcf9b7f7e1d Mon Sep 17 00:00:00 2001 From: IvenBach Date: Mon, 6 Jan 2020 07:37:28 -0800 Subject: [PATCH 108/461] Replace tabs with spaces --- Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml b/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml index aa639eff0e..6f4637c216 100644 --- a/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml +++ b/Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml @@ -349,7 +349,7 @@ - + Date: Mon, 6 Jan 2020 08:55:14 -0800 Subject: [PATCH 109/461] WIP - reworking interfaces. All tests pass --- .../EncapsulateFieldViewModel.cs | 12 +- .../ViewableEncapsulatedField.cs | 3 +- .../EncapsulateField/ConflictDetectors.cs | 362 ++++++++++++++++++ .../EncapsulateFieldElementFactory.cs | 108 +++--- .../EncapsulateField/EncapsulateFieldModel.cs | 93 ++++- .../EncapsulateFieldRefactoring.cs | 36 +- .../EncapsulateFieldValidationsProvider.cs | 116 ++++++ .../EncapsulateFieldValidator.cs | 217 ----------- .../ConvertFieldsToUDTMembers.cs | 62 ++- .../EncapsulateFieldStrategyBase.cs | 14 +- .../UseBackingFields.cs | 33 +- .../FieldCandidates/ArrayCandidate.cs | 48 +-- .../ConvertToUDTMemberCandidate.cs | 162 ++++++++ .../FieldCandidates/EncapsulateField.cs | 81 ++++ .../EncapsulateFieldCandidate.cs | 212 ++++------ .../EncapsulationIdentifiers.cs | 6 +- .../FieldCandidates/ObjectStateUDT.cs | 87 ++++- .../UserDefinedTypeCandidate.cs | 85 ++-- .../UserDefinedTypeMemberCandidate.cs | 78 ++-- .../EncapsulateField/EncapsulateFieldTests.cs | 3 +- .../EncapsulateFieldValidatorTests.cs | 12 +- .../EncapsulatedUDTFieldTests.cs | 5 +- .../EncapsulationIdentifiersTests.cs | 26 +- .../EncapsulateField/TestSupport.cs | 33 +- 24 files changed, 1306 insertions(+), 588 deletions(-) create mode 100644 Rubberduck.Refactorings/EncapsulateField/ConflictDetectors.cs create mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidationsProvider.cs delete mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs create mode 100644 Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs create mode 100644 Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateField.cs diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs index 223afc17b3..7295a10c97 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs @@ -101,7 +101,10 @@ public ObservableCollection EncapsulationFields { var viewableFields = new ObservableCollection(); - var orderedFields = Model.EncapsulationCandidates.Where(ec => !(_selectedObjectStateUDT?.IsEncapsulateFieldCandidate(ec) ?? false)) + //var orderedFields = Model.EncapsulationCandidates.Where(ec => !(_selectedObjectStateUDT?.IsEncapsulateFieldCandidate(ec) ?? false)) + // .OrderBy(efd => efd.Declaration.Selection).ToList(); + + var orderedFields = Model.EncapsulationCandidates.Where(ec => !(_selectedObjectStateUDT?.IsExistingDeclaration ?? false)) .OrderBy(efd => efd.Declaration.Selection).ToList(); foreach (var efd in orderedFields) @@ -266,10 +269,13 @@ public bool IsReadOnly public bool ConvertFieldsToUDTMembers { - get => Model.ConvertFieldsToUDTMembers; + get => Model.EncapsulateFieldStrategy == EncapsulateFieldStrategy.ConvertFieldsToUDTMembers; // Model.ConvertFieldsToUDTMembers; set { - Model.ConvertFieldsToUDTMembers = value; + //Model.ConvertFieldsToUDTMembers = value; + Model.EncapsulateFieldStrategy = value + ? EncapsulateFieldStrategy.ConvertFieldsToUDTMembers + : EncapsulateFieldStrategy.UseBackingFields; ReloadListAndPreview(); RefreshValidationResults(); UpdateDetailForSelection(); diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs index 4ba5ffda69..03ed544bb4 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs @@ -73,7 +73,8 @@ public bool TryValidateEncapsulationAttributes(out string errorMessage) public bool CanBeReadWrite => _efd.CanBeReadWrite; - public string PropertyName { get => _efd.PropertyName; set => _efd.PropertyName = value; } + public string PropertyName { get => _efd.PropertyIdentifier; set => _efd.PropertyIdentifier = value; } + //public string PropertyIdentifier { get => _efd.PropertyIdentifier; set => _efd.PropertyIdentifier = value; } public bool EncapsulateFlag { get => _efd.EncapsulateFlag; set => _efd.EncapsulateFlag = value; } diff --git a/Rubberduck.Refactorings/EncapsulateField/ConflictDetectors.cs b/Rubberduck.Refactorings/EncapsulateField/ConflictDetectors.cs new file mode 100644 index 0000000000..e4d815a445 --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/ConflictDetectors.cs @@ -0,0 +1,362 @@ +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.Refactorings.EncapsulateField.Extensions; +using Rubberduck.VBEditor; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + public interface IEncapsulateFieldConflictFinder + { + //bool HasConflictingIdentifier(IEncapsulateFieldCandidate candidate, out string errorMessage); + //bool HasConflictingIdentifier(IEncapsulateFieldCandidate field, DeclarationType declarationType, out string errorMessage); + bool HasConflictingIdentifier(IEncapsulatableField candidate, out string errorMessage); + bool HasConflictingIdentifier(IEncapsulatableField field, DeclarationType declarationType, out string errorMessage); + IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType); + string CreateNonConflictIdentifierForProposedType(string identifier, QualifiedModuleName qmn, DeclarationType declarationType); + bool IsConflictingProposedIdentifier(string fieldName, IEncapsulateFieldCandidate candidate, DeclarationType declarationType); + bool TryValidateEncapsulationAttributes(IEncapsulatableField field, out string errorMessage); + } + + public class ConflictDetectorUseBackingFields : ConflictDetectorBase + { + public ConflictDetectorUseBackingFields(IDeclarationFinderProvider declarationFinderProvider, IEnumerable candidates, IEnumerable udtCandidates) + : base(declarationFinderProvider, candidates, udtCandidates) { } + + public override bool TryValidateEncapsulationAttributes(IEncapsulatableField field, out string errorMessage) + { + errorMessage = string.Empty; + if (!field.EncapsulateFlag) { return true; } + + if (!field.NameValidator.IsValidVBAIdentifier(field.PropertyIdentifier, out errorMessage)) + { + return false; + } + + if (HasConflictingIdentifier(field, DeclarationType.Property, out errorMessage)) + { + return false; + } + return true; + } + + protected override string IdentifierToCompare(IEncapsulatableField field, DeclarationType declarationType) + { + if (field is IUsingBackingField useBackingField) + { + return declarationType.HasFlag(DeclarationType.Property) + ? useBackingField.PropertyIdentifier + : useBackingField.FieldIdentifier; + } + return field.PropertyIdentifier; + } + + } + + public class ConflictDetectorConvertFieldsToUDTMembers : ConflictDetectorBase + { + public ConflictDetectorConvertFieldsToUDTMembers(IDeclarationFinderProvider declarationFinderProvider, IEnumerable candidates, IEnumerable udtCandidates) + : base(declarationFinderProvider, candidates, udtCandidates) { } + + public override bool TryValidateEncapsulationAttributes(IEncapsulatableField field, out string errorMessage) + { + errorMessage = string.Empty; + if (!field.EncapsulateFlag) { return true; } + + if (!field.NameValidator.IsValidVBAIdentifier(field.PropertyIdentifier, out errorMessage)) + { + return false; + } + + if (HasConflictingIdentifier(field, DeclarationType.Property, out errorMessage)) + { + return false; + } + + return true; + } + + protected override string IdentifierToCompare(IEncapsulatableField field, DeclarationType declarationType) + { + if (field is IConvertToUDTMember convertedField) + { + return declarationType.HasFlag(DeclarationType.Property) + ? convertedField.PropertyIdentifier + : convertedField.UDTMemberIdentifier; + } + return field.PropertyIdentifier; + } + + //protected override IEnumerable FindRelevantMembers(IEncapsulateFieldCandidate candidate) + //{ + // var members = _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) + // .Where(d => d != candidate.Declaration); + + // var membersToRemove = _fieldCandidates.Where(fc => fc.EncapsulateFlag && fc.Declaration.DeclarationType.HasFlag(DeclarationType.Variable)) + // .Select(fc => fc.Declaration); + + // return members.Except(membersToRemove); + //} + + protected override IEnumerable FindRelevantMembers(IEncapsulatableField candidate) + { + var members = _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) + .Where(d => d != candidate.Declaration); + + var membersToRemove = _fieldCandidates.Where(fc => fc.EncapsulateFlag && fc.Declaration.DeclarationType.HasFlag(DeclarationType.Variable)) + .Select(fc => fc.Declaration); + + return members.Except(membersToRemove); + } + } + + public abstract class ConflictDetectorBase : IEncapsulateFieldConflictFinder + { + protected readonly IDeclarationFinderProvider _declarationFinderProvider; + protected List _fieldCandidates { set; get; } = new List(); + protected List _udtMemberCandidates { set; get; } = new List(); + + public ConflictDetectorBase(IDeclarationFinderProvider declarationFinderProvider, IEnumerable candidates, IEnumerable udtCandidates)//, IValidateVBAIdentifiers nameValidator) + { + _declarationFinderProvider = declarationFinderProvider; + _fieldCandidates.AddRange(candidates); + _udtMemberCandidates.AddRange(udtCandidates); + } + + public abstract bool TryValidateEncapsulationAttributes(IEncapsulatableField field, out string errorMessage); + + //public bool HasConflictingIdentifier(IEncapsulateFieldCandidate candidate, out string errorMessage) + // => InternalHasConflictingIdentifier(candidate, DeclarationType.Property, false, out errorMessage); + + public bool HasConflictingIdentifier(IEncapsulatableField candidate, out string errorMessage) + => InternalHasConflictingIdentifier(candidate, DeclarationType.Property, false, out errorMessage); + + //public bool HasConflictingIdentifier(IEncapsulateFieldCandidate field, DeclarationType declarationType, out string errorMessage) + // => InternalHasConflictingIdentifier(field, declarationType, false, out errorMessage); + + public bool HasConflictingIdentifier(IEncapsulatableField field, DeclarationType declarationType, out string errorMessage) + => InternalHasConflictingIdentifier(field, declarationType, false, out errorMessage); + + public IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType) //, IValidateEncapsulateFieldNames validator) + { + var isConflictingIdentifier = HasConflictingIdentifierIgnoreEncapsulationFlag(candidate, declarationType, out _); + var guard = 0; + while (guard++ < 10 && isConflictingIdentifier) + { + var identifier = declarationType.HasFlag(DeclarationType.Property) + ? candidate.PropertyIdentifier + : candidate.FieldIdentifier; + + if (declarationType.HasFlag(DeclarationType.Property)) + { + candidate.PropertyIdentifier = identifier.IncrementEncapsulationIdentifier(); + } + else + { + candidate.FieldIdentifier = identifier.IncrementEncapsulationIdentifier(); + } + isConflictingIdentifier = HasConflictingIdentifierIgnoreEncapsulationFlag(candidate, declarationType, out _); + } + return candidate; + } + + public string CreateNonConflictIdentifierForProposedType(string identifier, QualifiedModuleName qmn, DeclarationType declarationType) + { + var guard = 0; + while (guard++ < 10 && IsConflictIdentifier(identifier, qmn, declarationType)) + { + identifier = identifier.IncrementEncapsulationIdentifier(); + } + return identifier; + } + + public bool IsConflictingProposedIdentifier(string fieldName, IEncapsulateFieldCandidate candidate, DeclarationType declarationType) + { + var members = PotentialConflictIdentifiers(candidate, declarationType); + + return members.Any(m => m.IsEquivalentVBAIdentifierTo(fieldName)); + } + + //protected virtual IEnumerable FindRelevantMembers(IEncapsulateFieldCandidate candidate) + // => _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) + // .Where(d => d != candidate.Declaration); + + protected virtual IEnumerable FindRelevantMembers(IEncapsulatableField candidate) + => _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) + .Where(d => d != candidate.Declaration); + + private bool InternalHasConflictingIdentifier(IEncapsulateFieldCandidate field, DeclarationType declarationType, bool ignoreEncapsulationFlags, out string errorMessage) + { + errorMessage = string.Empty; + + var potentialDeclarationIdentifierConflicts = new List(); + potentialDeclarationIdentifierConflicts.AddRange(PotentialConflictIdentifiers(field, declarationType)); + + if (ignoreEncapsulationFlags) + { + potentialDeclarationIdentifierConflicts.AddRange(_fieldCandidates.Where(fc => fc != field).Select(fc => fc.PropertyIdentifier)); + } + else + { + potentialDeclarationIdentifierConflicts.AddRange(FlaggedCandidates.Where(fc => fc != field).Select(fc => fc.PropertyIdentifier)); + } + + potentialDeclarationIdentifierConflicts.AddRange(_udtMemberCandidates.Where(udtm => udtm != field && udtm.EncapsulateFlag).Select(udtm => udtm.PropertyIdentifier)); + + var identifierToCompare = declarationType.HasFlag(DeclarationType.Property) + ? field.PropertyIdentifier + : field.FieldIdentifier; + + if (potentialDeclarationIdentifierConflicts.Any(m => m.IsEquivalentVBAIdentifierTo(identifierToCompare))) + { + errorMessage = EncapsulateFieldResources.NameConflictDetected; + return true; + } + return false; + } + + protected virtual bool InternalHasConflictingIdentifier(IEncapsulatableField field, DeclarationType declarationType, bool ignoreEncapsulationFlags, out string errorMessage) + { + errorMessage = string.Empty; + + var potentialDeclarationIdentifierConflicts = new List(); + potentialDeclarationIdentifierConflicts.AddRange(PotentialConflictIdentifiers(field, declarationType)); + + if (ignoreEncapsulationFlags) + { + potentialDeclarationIdentifierConflicts.AddRange(_fieldCandidates.Where(fc => fc != field).Select(fc => fc.PropertyIdentifier)); + } + else + { + potentialDeclarationIdentifierConflicts.AddRange(FlaggedCandidates.Where(fc => fc != field).Select(fc => fc.PropertyIdentifier)); + } + + potentialDeclarationIdentifierConflicts.AddRange(_udtMemberCandidates.Where(udtm => udtm != field && udtm.EncapsulateFlag).Select(udtm => udtm.PropertyIdentifier)); + + //var identifierToCompare = declarationType.HasFlag(DeclarationType.Property) + // ? field.PropertyIdentifier + // //: field.FieldIdentifier; + // : field.Declaration.IdentifierName; //TODO: Temporary + var identifierToCompare = IdentifierToCompare(field, DeclarationType.Property); + + if (potentialDeclarationIdentifierConflicts.Any(m => m.IsEquivalentVBAIdentifierTo(identifierToCompare))) + { + errorMessage = EncapsulateFieldResources.NameConflictDetected; + return true; + } + return false; + } + + protected abstract string IdentifierToCompare(IEncapsulatableField field, DeclarationType declarationType); + + //The refactoring only inserts new code elements with the following Accessibilities: + //Variables => Private + //Properties => Public + //UDT => Private + private bool IsAlwaysIgnoreNameConflictType(Declaration d, DeclarationType toEnapsulateDeclarationType) + { + var NeverCauseNameConflictTypes = new List() + { + DeclarationType.Project, + DeclarationType.ProceduralModule, + DeclarationType.ClassModule, + DeclarationType.Parameter, + DeclarationType.EnumerationMember, + DeclarationType.Enumeration, + DeclarationType.UserDefinedType, + DeclarationType.UserDefinedTypeMember + }; + + if (toEnapsulateDeclarationType.HasFlag(DeclarationType.Variable)) + { + //5.2.3.4: An enum member name may not be the same as any variable name + //or constant name that is defined within the same module + NeverCauseNameConflictTypes.Remove(DeclarationType.EnumerationMember); + } + else if (toEnapsulateDeclarationType.HasFlag(DeclarationType.UserDefinedType)) + { + //5.2.3.3 If an is an element of a its + //UDT name cannot be the same as the enum name of any + //or the UDT name of any other within the same + NeverCauseNameConflictTypes.Remove(DeclarationType.UserDefinedType); + + //5.2.3.4 The enum name of a cannot be the same as the enum name of any other + // or as the UDT name of a within the same . + NeverCauseNameConflictTypes.Remove(DeclarationType.Enumeration); + } + else if (toEnapsulateDeclarationType.HasFlag(DeclarationType.Property)) + { + //Each < subroutine - declaration > and < function - declaration > must have a + //procedure name that is different from any other module variable name, + //module constant name, enum member name, or procedure name that is defined + //within the same module. + + NeverCauseNameConflictTypes.Remove(DeclarationType.EnumerationMember); + } + return d.IsLocalVariable() + || d.IsLocalConstant() + || NeverCauseNameConflictTypes.Contains(d.DeclarationType); + } + + private List PotentialConflictIdentifiers(IEncapsulateFieldCandidate candidate, DeclarationType declarationType) + { + var members = FindRelevantMembers(candidate); + + var nameConflictCandidates = members + .Where(d => !IsAlwaysIgnoreNameConflictType(d, declarationType)).ToList(); + + var localReferences = candidate.Declaration.References.Where(rf => rf.QualifiedModuleName == candidate.QualifiedModuleName); + + if (localReferences.Any()) + { + foreach (var idRef in localReferences) + { + var locals = members.Except(nameConflictCandidates) + .Where(localDec => localDec.ParentScopeDeclaration.Equals(idRef.ParentScoping)); + + nameConflictCandidates.AddRange(locals); + } + } + return nameConflictCandidates.Select(c => c.IdentifierName).ToList(); + } + + private List PotentialConflictIdentifiers(IEncapsulatableField candidate, DeclarationType declarationType) + { + var members = FindRelevantMembers(candidate); + + var nameConflictCandidates = members + .Where(d => !IsAlwaysIgnoreNameConflictType(d, declarationType)).ToList(); + + var localReferences = candidate.Declaration.References.Where(rf => rf.QualifiedModuleName == candidate.QualifiedModuleName); + + if (localReferences.Any()) + { + foreach (var idRef in localReferences) + { + var locals = members.Except(nameConflictCandidates) + .Where(localDec => localDec.ParentScopeDeclaration.Equals(idRef.ParentScoping)); + + nameConflictCandidates.AddRange(locals); + } + } + return nameConflictCandidates.Select(c => c.IdentifierName).ToList(); + } + + private List FlaggedCandidates => _fieldCandidates.Where(f => f.EncapsulateFlag).ToList(); + + private bool HasConflictingIdentifierIgnoreEncapsulationFlag(IEncapsulateFieldCandidate field, DeclarationType declarationType, out string errorMessage) + => InternalHasConflictingIdentifier(field, declarationType, true, out errorMessage); + + private bool IsConflictIdentifier(string fieldName, QualifiedModuleName qmn, DeclarationType declarationType) + { + var nameConflictCandidates = _declarationFinderProvider.DeclarationFinder.Members(qmn) + .Where(d => !IsAlwaysIgnoreNameConflictType(d, declarationType)).ToList(); + + return nameConflictCandidates.Any(m => m.IdentifierName.IsEquivalentVBAIdentifierTo(fieldName)); + } + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs index abfb868228..bbfc7f8afa 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs @@ -1,6 +1,7 @@ using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Refactorings.Common; using Rubberduck.Refactorings.EncapsulateField.Extensions; using Rubberduck.VBEditor; using System; @@ -13,42 +14,94 @@ namespace Rubberduck.Refactorings.EncapsulateField public class EncapsulateFieldElementFactory { private readonly IDeclarationFinderProvider _declarationFinderProvider; - //private readonly IEncapsulateFieldValidator _validator; - //private readonly IValidateEncapsulateFieldNames _namesValidator; private QualifiedModuleName _targetQMN; public EncapsulateFieldElementFactory(IDeclarationFinderProvider declarationFinderProvider, QualifiedModuleName targetQMN)//, IEncapsulateFieldValidator validator ) { _declarationFinderProvider = declarationFinderProvider; - //_validator = validator; - //_namesValidator = validator as IValidateEncapsulateFieldNames; _targetQMN = targetQMN; + CreateRefactoringElements(); } - public IObjectStateUDT CreateStateUDTField(IEncapsulateFieldValidator validator) + public IObjectStateUDT ObjectStateUDT { private set; get; } + + public IEncapsulateFieldValidationsProvider ValidatorProvider { private set; get; } + + public IEnumerable Candidates { private set; get; } + + private void CreateRefactoringElements() + { + var fieldDeclarations = _declarationFinderProvider.DeclarationFinder + .Members(_targetQMN) + .Where(v => v.IsMemberVariable() && !v.IsWithEvents); + + ValidatorProvider = new EncapsulateFieldValidationsProvider(); + + var nameValidator = ValidatorProvider.NameOnlyValidator(Validators.Default); + + var candidates = new List(); + foreach (var fieldDeclaration in fieldDeclarations) + { + Debug.Assert(!fieldDeclaration.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)); + + var fieldEncapsulationCandidate = CreateCandidate(fieldDeclaration, nameValidator); + + + candidates.Add(fieldEncapsulationCandidate); + } + + ValidatorProvider.RegisterCandidates(candidates); + + var conflictsValidator = ValidatorProvider.ConflictDetector(EncapsulateFieldStrategy.UseBackingFields, _declarationFinderProvider); + + ObjectStateUDT = CreateStateUDTField(conflictsValidator); + foreach (var candidate in candidates) + { + candidate.ConflictFinder = conflictsValidator; + conflictsValidator.AssignNoConflictIdentifier(candidate, DeclarationType.Property); + conflictsValidator.AssignNoConflictIdentifier(candidate, DeclarationType.Variable); + + var converted = candidate as IConvertToUDTMember; + converted.ObjectStateUDT = ObjectStateUDT; + } + + Candidates = candidates; + } + + private IObjectStateUDT CreateStateUDTField(IEncapsulateFieldConflictFinder validator) { var stateUDT = new ObjectStateUDT(_targetQMN) as IObjectStateUDT; - stateUDT = SetNonConflictIdentifier(stateUDT, c => { return validator.IsConflictingStateUDTFieldIdentifier(stateUDT); }, (s) => { stateUDT.FieldIdentifier = s; }, () => stateUDT.FieldIdentifier, validator as IValidateEncapsulateFieldNames); // _namesValidator); + stateUDT.FieldIdentifier = validator.CreateNonConflictIdentifierForProposedType(stateUDT.FieldIdentifier, _targetQMN, DeclarationType.Variable); - stateUDT = SetNonConflictIdentifier(stateUDT, c => { return validator.IsConflictingStateUDTTypeIdentifier(stateUDT); }, (s) => { stateUDT.TypeIdentifier = s; }, () => stateUDT.TypeIdentifier, validator as IValidateEncapsulateFieldNames); // _namesValidator); + stateUDT.TypeIdentifier = validator.CreateNonConflictIdentifierForProposedType(stateUDT.TypeIdentifier, _targetQMN, DeclarationType.UserDefinedType); + + stateUDT.IsSelected = true; return stateUDT; } - private IEncapsulateFieldCandidate CreateCandidate(Declaration target, IValidateEncapsulateFieldNames validator) + private IEncapsulateFieldCandidate CreateCandidate(Declaration target, IValidateVBAIdentifiers validator)// Predicate nameValidator) { if (target.IsUserDefinedTypeField()) { - var udtField = new UserDefinedTypeCandidate(target, validator) as IUserDefinedTypeCandidate; + var udtValidator = ValidatorProvider.NameOnlyValidator(Validators.UserDefinedType); + var udtField = new UserDefinedTypeCandidate(target, udtValidator) as IUserDefinedTypeCandidate; (Declaration udtDeclaration, IEnumerable udtMembers) = GetUDTAndMembersForField(udtField); udtField.TypeDeclarationIsPrivate = udtDeclaration.HasPrivateAccessibility(); + udtField.NameValidator = udtValidator; + foreach (var udtMemberDeclaration in udtMembers) { - var candidateUDTMember = new UserDefinedTypeMemberCandidate(CreateCandidate(udtMemberDeclaration, validator), udtField, validator) as IUserDefinedTypeMemberCandidate; + var udtMemberValidator = ValidatorProvider.NameOnlyValidator(Validators.UserDefinedTypeMember); + if (udtMemberDeclaration.IsArray) + { + udtMemberValidator = ValidatorProvider.NameOnlyValidator(Validators.UserDefinedTypeMemberArray); + } + var candidateUDTMember = new UserDefinedTypeMemberCandidate(CreateCandidate(udtMemberDeclaration, udtMemberValidator), udtField) as IUserDefinedTypeMemberCandidate; udtField.AddMember(candidateUDTMember); } @@ -64,41 +117,8 @@ private IEncapsulateFieldCandidate CreateCandidate(Declaration target, IValidate { return new ArrayCandidate(target, validator); } - return new EncapsulateFieldCandidate(target, validator); - } - - public IEnumerable CreateEncapsulationCandidates(IValidateEncapsulateFieldNames validator) - { - var fieldDeclarations = _declarationFinderProvider.DeclarationFinder - .Members(_targetQMN) - .Where(v => v.IsMemberVariable() && !v.IsWithEvents); - - var candidates = new List(); - foreach (var fieldDeclaration in fieldDeclarations) - { - Debug.Assert(!fieldDeclaration.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)); - - var fieldEncapsulationCandidate = CreateCandidate(fieldDeclaration, validator); - - //_namesValidator.AssignNoConflictIdentifier(fieldEncapsulationCandidate, DeclarationType.Property); - //_namesValidator.AssignNoConflictIdentifier(fieldEncapsulationCandidate, DeclarationType.Variable); - - //_validator.RegisterFieldCandidate(fieldEncapsulationCandidate); - - candidates.Add(fieldEncapsulationCandidate); - } - - return candidates; - } - private IObjectStateUDT SetNonConflictIdentifier(IObjectStateUDT candidate, Predicate conflictDetector, Action setValue, Func getIdentifier, IValidateEncapsulateFieldNames validator) - { - var isConflictingIdentifier = conflictDetector(candidate); - for (var count = 1; count < 10 && isConflictingIdentifier; count++) - { - setValue(getIdentifier().IncrementEncapsulationIdentifier()); - isConflictingIdentifier = conflictDetector(candidate); - } + var candidate = new EncapsulateFieldCandidate(target, validator); return candidate; } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index 525add385f..d34a60b602 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings.EncapsulateField.Extensions; using Rubberduck.VBEditor; @@ -12,22 +13,41 @@ public class EncapsulateFieldModel : IRefactoringModel private readonly Func _previewDelegate; private QualifiedModuleName _targetQMN; //private IValidateEncapsulateFieldNames _validator; + private IDeclarationFinderProvider _declarationFinderProvider; + private IEncapsulateFieldValidationsProvider _validatorProvider; private IObjectStateUDT _newObjectStateUDT; private IDictionary)> _udtFieldToUdtDeclarationMap = new Dictionary)>(); - public EncapsulateFieldModel(Declaration target, IEnumerable candidates, IObjectStateUDT stateUDTField, Func previewDelegate, IEncapsulateFieldValidator validator) + public EncapsulateFieldModel(Declaration target, IEnumerable candidates, IObjectStateUDT stateUDTField, Func previewDelegate, IDeclarationFinderProvider declarationFinderProvider, IEncapsulateFieldValidationsProvider validatorProvider) // IEncapsulateFieldValidator validator) { _previewDelegate = previewDelegate; _targetQMN = target.QualifiedModuleName; _newObjectStateUDT = stateUDTField; + _declarationFinderProvider = declarationFinderProvider; + _validatorProvider = validatorProvider; - Validator = validator; EncapsulationCandidates = candidates.ToList(); - ConvertFieldsToUDTMembers = false; + EncapsulateFieldStrategy = EncapsulateFieldStrategy.UseBackingFields; } - public IEncapsulateFieldValidator Validator {set; get;} + public QualifiedModuleName QualifiedModuleName => _targetQMN; + + private EncapsulateFieldStrategy _encapsulationFieldStategy; + public EncapsulateFieldStrategy EncapsulateFieldStrategy + { + set + { + _encapsulationFieldStategy = value; + AssignCandidateValidations(value); + } + get => _encapsulationFieldStategy; + } + + public IEncapsulateFieldValidationsProvider ValidatorProvider => _validatorProvider; + + public IEncapsulateFieldConflictFinder ConflictDetector + => _validatorProvider.ConflictDetector(EncapsulateFieldStrategy, _declarationFinderProvider); public List EncapsulationCandidates { set; get; } = new List(); @@ -49,30 +69,69 @@ public IEncapsulateFieldCandidate this[string encapsulatedFieldTargetID] public IEncapsulateFieldCandidate this[Declaration fieldDeclaration] => EncapsulationCandidates.Where(c => c.Declaration == fieldDeclaration).Single(); + + ////TODO: Get rid of this property + //private bool _convertFieldsToUDTMembers; + //public bool ConvertFieldsToUDTMembers + //{ + // set + // { + // _convertFieldsToUDTMembers = value; + + // EncapsulateFieldStrategy = value + // ? EncapsulateFieldStrategy.ConvertFieldsToUDTMembers + // : EncapsulateFieldStrategy.UseBackingFields; + // } + // get => _convertFieldsToUDTMembers; + //} - private bool _convertFieldsToUDTMembers; - public bool ConvertFieldsToUDTMembers + private IObjectStateUDT _activeObjectStateUDT; + public IObjectStateUDT StateUDTField { set { - _convertFieldsToUDTMembers = value; - SetFieldsToUDTMemberFlags(value); + _activeObjectStateUDT = value; + foreach (var candidate in EncapsulationCandidates) + { + if (candidate is IConvertToUDTMember udtMember) + { + udtMember.ObjectStateUDT = value; + } + } } - get => _convertFieldsToUDTMembers; - } - - private IObjectStateUDT _activeObjectStateUDT; - public IObjectStateUDT StateUDTField - { - set => _activeObjectStateUDT = value; get => _activeObjectStateUDT ?? _newObjectStateUDT; } - private void SetFieldsToUDTMemberFlags(bool value) + public void AssignCandidateValidations(EncapsulateFieldStrategy strategy) { foreach (var candidate in EncapsulationCandidates) { - candidate.ConvertFieldToUDTMember = value; + candidate.ConvertFieldToUDTMember = strategy == EncapsulateFieldStrategy.ConvertFieldsToUDTMembers; + + candidate.ConflictFinder = ConflictDetector; + if (strategy == EncapsulateFieldStrategy.UseBackingFields) + { + if (candidate is IUserDefinedTypeCandidate) + { + candidate.NameValidator = _validatorProvider.NameOnlyValidator(Validators.UserDefinedType); + } + else if (candidate is IUserDefinedTypeMemberCandidate) + { + candidate.NameValidator = candidate.Declaration.IsArray + ? _validatorProvider.NameOnlyValidator(Validators.UserDefinedTypeMemberArray) + : _validatorProvider.NameOnlyValidator(Validators.UserDefinedTypeMember); + } + else + { + candidate.NameValidator = _validatorProvider.NameOnlyValidator(Validators.Default); + } + } + else + { + candidate.NameValidator = candidate.Declaration.IsArray + ? _validatorProvider.NameOnlyValidator(Validators.UserDefinedTypeMemberArray) + : _validatorProvider.NameOnlyValidator(Validators.UserDefinedTypeMember); + } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 12dacacba3..5759907efc 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -14,6 +14,12 @@ namespace Rubberduck.Refactorings.EncapsulateField { + public enum EncapsulateFieldStrategy + { + UseBackingFields, + ConvertFieldsToUDTMembers + } + public interface IEncapsulateFieldRefactoringTestAccess { EncapsulateFieldModel TestUserInteractionOnly(Declaration target, Func userInteraction); @@ -68,28 +74,15 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) _targetQMN = target.QualifiedModuleName; - var validator = new EncapsulateFieldValidator(_declarationFinderProvider); - var encapsulationCandidateFactory = new EncapsulateFieldElementFactory(_declarationFinderProvider, _targetQMN); - var candidates = encapsulationCandidateFactory.CreateEncapsulationCandidates(validator as IValidateEncapsulateFieldNames); - - validator.RegisterFieldCandidates(candidates); - - foreach (var candidate in candidates) - { - if (candidate is IAssignNoConflictNames namer) - { - namer.AssignIdentifiers(validator); - } - } + var validatorProvider = encapsulationCandidateFactory.ValidatorProvider; + var candidates = encapsulationCandidateFactory.Candidates; + var defaultObjectStateUDT = encapsulationCandidateFactory.ObjectStateUDT; var selected = candidates.Single(c => c.Declaration == target); selected.EncapsulateFlag = true; - var defaultObjectStateUDT = encapsulationCandidateFactory.CreateStateUDTField(validator); - defaultObjectStateUDT.IsSelected = true; - if (TryRetrieveExistingObjectStateUDT(target, candidates, out var objectStateUDT)) { objectStateUDT.IsSelected = true; @@ -101,12 +94,13 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) candidates, defaultObjectStateUDT, PreviewRewrite, - validator); + _declarationFinderProvider, + validatorProvider); if (objectStateUDT != null) { model.StateUDTField = objectStateUDT; - model.ConvertFieldsToUDTMembers = true; + model.EncapsulateFieldStrategy = EncapsulateFieldStrategy.ConvertFieldsToUDTMembers; } return model; @@ -167,9 +161,9 @@ private IEncapsulateFieldRewriteSession RefactorRewrite(EncapsulateFieldModel mo { if (!model.SelectedFieldCandidates.Any()) { return refactorRewriteSession; } - var strategy = model.ConvertFieldsToUDTMembers - ? new ConvertFieldsToUDTMembers(_declarationFinderProvider, _targetQMN, _indenter) as IEncapsulateStrategy - : new UseBackingFields(_declarationFinderProvider, _targetQMN, _indenter) as IEncapsulateStrategy; + var strategy = model.EncapsulateFieldStrategy == EncapsulateFieldStrategy.ConvertFieldsToUDTMembers // model.ConvertFieldsToUDTMembers + ? new ConvertFieldsToUDTMembers(_declarationFinderProvider, model, _indenter) as IEncapsulateStrategy + : new UseBackingFields(_declarationFinderProvider, model, _indenter) as IEncapsulateStrategy; return strategy.RefactorRewrite(model, refactorRewriteSession, asPreview); } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidationsProvider.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidationsProvider.cs new file mode 100644 index 0000000000..9912b1f353 --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidationsProvider.cs @@ -0,0 +1,116 @@ +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.Refactorings.Common; +using Rubberduck.VBEditor; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + public interface IValidateVBAIdentifiers + { + bool IsValidVBAIdentifier(string identifier, out string errorMessage); + bool IsValidUDTMemberIdentifier(string identifier, bool isArray, out string errorMessage); + } + + public enum Validators + { + Default, + UserDefinedType, + UserDefinedTypeMember, + UserDefinedTypeMemberArray + } + + public interface IValidateEncapsulateFieldNames + { + bool IsValidVBAIdentifier(string identifier, DeclarationType declarationType, out string errorMessage, bool isArray = false); + bool HasConflictingIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType, out string errorMessage); + bool HasConflictingIdentifierIgnoreEncapsulationFlag(IEncapsulateFieldCandidate field, DeclarationType declarationType, out string errorMessage); + bool IsConflictingProposedIdentifier(string fieldName, IEncapsulateFieldCandidate candidate, DeclarationType declarationType); + IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType); + } + + //public interface IEncapsulateFieldValidator : IValidateEncapsulateFieldNames + //{ + // string CreateNonConflictIdentifierForProposedType(string identifier, QualifiedModuleName qmn, DeclarationType declarationType); + //} + + public interface IEncapsulateFieldValidationsProvider + { + IValidateVBAIdentifiers NameOnlyValidator(Validators validatorType); + IEncapsulateFieldConflictFinder ConflictDetector(EncapsulateFieldStrategy strategy, IDeclarationFinderProvider declarationFinderProvider); + void RegisterCandidates(IEnumerable candidates); + void RegisterCandidate(IEncapsulateFieldCandidate candidate); + } + + public class EncapsulateFieldValidationsProvider : IEncapsulateFieldValidationsProvider + { + private Dictionary _nameOnlyValidators; + + private List _candidates; + private List _udtMemberCandidates; + + public EncapsulateFieldValidationsProvider() + { + _nameOnlyValidators = new Dictionary() + { + [Validators.Default] = new IdentifierOnlyValidator(DeclarationType.Variable, false), + [Validators.UserDefinedType] = new IdentifierOnlyValidator(DeclarationType.UserDefinedType, false), + [Validators.UserDefinedTypeMember] = new IdentifierOnlyValidator(DeclarationType.UserDefinedTypeMember, false), + [Validators.UserDefinedTypeMemberArray] = new IdentifierOnlyValidator(DeclarationType.UserDefinedTypeMember, true), + }; + + _candidates = new List(); + _udtMemberCandidates = new List(); + } + + public IValidateVBAIdentifiers NameOnlyValidator(Validators validatorType) + => _nameOnlyValidators[validatorType]; + + public IEncapsulateFieldConflictFinder ConflictDetector(EncapsulateFieldStrategy strategy, IDeclarationFinderProvider declarationFinderProvider) + { + if (strategy == EncapsulateFieldStrategy.UseBackingFields) + { + return new ConflictDetectorUseBackingFields(declarationFinderProvider, _candidates, _udtMemberCandidates); + } + return new ConflictDetectorConvertFieldsToUDTMembers(declarationFinderProvider, _candidates, _udtMemberCandidates); + } + + public void RegisterCandidate(IEncapsulateFieldCandidate candidate) + { + _candidates.Add(candidate); + } + + public void RegisterCandidates(IEnumerable candidates) + { + _candidates.AddRange(candidates); + foreach (var udtCandidate in candidates.Where(c => c is IUserDefinedTypeCandidate).Cast()) + { + foreach (var member in udtCandidate.Members) + { + _udtMemberCandidates.Add(member); + } + } + } + + private class IdentifierOnlyValidator : IValidateVBAIdentifiers + { + private DeclarationType _declarationType; + private bool _isArray; + public IdentifierOnlyValidator(DeclarationType declarationType, bool isArray = false) + { + _declarationType = declarationType; + _isArray = isArray; + } + + public bool IsValidVBAIdentifier(string identifier, out string errorMessage) + => !VBAIdentifierValidator.TryMatchInvalidIdentifierCriteria(identifier, _declarationType, out errorMessage, _isArray); + + public bool IsValidUDTMemberIdentifier(string identifier, bool isArray, out string errorMessage) + => !VBAIdentifierValidator.TryMatchInvalidIdentifierCriteria(identifier, DeclarationType.UserDefinedTypeMember, out errorMessage, _isArray); + } + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs deleted file mode 100644 index 3c9db3ec39..0000000000 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidator.cs +++ /dev/null @@ -1,217 +0,0 @@ -using Rubberduck.Parsing.Symbols; -using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.VBA.DeclarationCaching; -using Rubberduck.Refactorings.Common; -using Rubberduck.Refactorings.EncapsulateField.Extensions; -using System.Collections.Generic; -using System.Linq; - -namespace Rubberduck.Refactorings.EncapsulateField -{ - public interface IObjectStateUDTNamesValidator - { - bool IsConflictingStateUDTTypeIdentifier(IObjectStateUDT stateUDT); - bool IsConflictingStateUDTFieldIdentifier(IObjectStateUDT stateUDT); - } - - public interface IValidateEncapsulateFieldNames - { - bool IsValidVBAIdentifier(string identifier, DeclarationType declarationType, out string errorMessage, bool isArray = false); - bool HasConflictingIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType, out string errorMessage); - bool HasConflictingIdentifierIgnoreEncapsulationFlag(IEncapsulateFieldCandidate field, DeclarationType declarationType, out string errorMessage); - bool IsConflictingProposedIdentifier(string fieldName, IEncapsulateFieldCandidate candidate, DeclarationType declarationType); - } - - public interface IEncapsulateFieldValidator : IObjectStateUDTNamesValidator, IValidateEncapsulateFieldNames - { - void RegisterFieldCandidates(IEnumerable candidates); - } - - public class EncapsulateFieldValidator : IEncapsulateFieldValidator - { - private readonly IDeclarationFinderProvider _declarationFinderProvider; - - private List FieldCandidates { set; get; } - - private List UDTMemberCandidates { set; get; } - - private List FlaggedCandidates => FieldCandidates.Where(rc => rc.EncapsulateFlag).ToList(); - - public EncapsulateFieldValidator(IDeclarationFinderProvider declarationFinderProvider) - { - _declarationFinderProvider = declarationFinderProvider; - FieldCandidates = new List(); - UDTMemberCandidates = new List(); - } - - public void RegisterFieldCandidates(IEnumerable candidates) - { - FieldCandidates.AddRange(candidates); - foreach (var udtCandidate in candidates.Where(c => c is IUserDefinedTypeCandidate).Cast()) - { - foreach (var member in udtCandidate.Members) - { - UDTMemberCandidates.Add(member); - } - } - } - - private DeclarationFinder DeclarationFinder => _declarationFinderProvider.DeclarationFinder; - - public bool IsValidVBAIdentifier(string identifier, DeclarationType declarationType, out string errorMessage, bool isArray = false) - { - return !VBAIdentifierValidator.TryMatchInvalidIdentifierCriteria(identifier, declarationType, out errorMessage, isArray); - } - - private List PotentialConflictIdentifiers(IEncapsulateFieldCandidate candidate, DeclarationType declarationType) - { - var members = DeclarationFinder.Members(candidate.QualifiedModuleName) - .Where(d => d != candidate.Declaration); - - if (candidate.ConvertFieldToUDTMember) - { - var membersToRemove = FieldCandidates.Where(fc => fc.EncapsulateFlag && fc.Declaration.DeclarationType.HasFlag(DeclarationType.Variable)) - .Select(fc => fc.Declaration); - - members = members.Except(membersToRemove); - } - - var nameConflictCandidates = members - .Where(d => !IsAlwaysIgnoreNameConflictType(d, declarationType)).ToList(); - - var localReferences = candidate.Declaration.References.Where(rf => rf.QualifiedModuleName == candidate.QualifiedModuleName); - - if (localReferences.Any()) - { - foreach (var idRef in localReferences) - { - var locals = members.Except(nameConflictCandidates) - .Where(localDec => localDec.ParentScopeDeclaration.Equals(idRef.ParentScoping)); - - nameConflictCandidates.AddRange(locals); - } - } - return nameConflictCandidates.Select(c => c.IdentifierName).ToList(); - } - - private List PotentialConflictIdentifiers(IObjectStateUDT stateUDT, DeclarationType declarationType) - { - var stateUDTDeclaration = stateUDT as IEncapsulateFieldDeclaration; - var potentialDeclarationIdentifierConflicts = new List(); - - var members = DeclarationFinder.Members(stateUDTDeclaration.QualifiedModuleName); - - var nameConflictCandidates = members - .Where(d => !IsAlwaysIgnoreNameConflictType(d, declarationType)).ToList(); - - potentialDeclarationIdentifierConflicts.AddRange(nameConflictCandidates.Select(d => d.IdentifierName)); - - return potentialDeclarationIdentifierConflicts.ToList(); - } - - public bool HasConflictingIdentifierIgnoreEncapsulationFlag(IEncapsulateFieldCandidate field, DeclarationType declarationType, out string errorMessage) - => InternalHasConflictingIdentifier(field, declarationType, true, out errorMessage); - - public bool HasConflictingIdentifier(IEncapsulateFieldCandidate field, DeclarationType declarationType, out string errorMessage) - => InternalHasConflictingIdentifier(field, declarationType, false, out errorMessage); - - private bool InternalHasConflictingIdentifier(IEncapsulateFieldCandidate field, DeclarationType declarationType, bool ignoreEncapsulationFlags, out string errorMessage) - { - errorMessage = string.Empty; - - var potentialDeclarationIdentifierConflicts = new List(); - potentialDeclarationIdentifierConflicts.AddRange(PotentialConflictIdentifiers(field, declarationType)); - - if (ignoreEncapsulationFlags) - { - potentialDeclarationIdentifierConflicts.AddRange(FieldCandidates.Where(fc => fc != field).Select(fc => fc.PropertyName)); - } - else - { - potentialDeclarationIdentifierConflicts.AddRange(FlaggedCandidates.Where(fc => fc != field).Select(fc => fc.PropertyName)); - } - potentialDeclarationIdentifierConflicts.AddRange(UDTMemberCandidates.Where(udtm => udtm != field && udtm.EncapsulateFlag).Select(udtm => udtm.PropertyName)); - - var identifierToCompare = declarationType.HasFlag(DeclarationType.Property) - ? field.PropertyName - : field.FieldIdentifier; - - if (potentialDeclarationIdentifierConflicts.Any(m => m.IsEquivalentVBAIdentifierTo(identifierToCompare))) - { - errorMessage = EncapsulateFieldResources.NameConflictDetected; - return true; - } - return false; - } - - public bool IsConflictingProposedIdentifier(string fieldName, IEncapsulateFieldCandidate candidate, DeclarationType declarationType) - { - var members = PotentialConflictIdentifiers(candidate, declarationType); - - return members.Any(m => m.IsEquivalentVBAIdentifierTo(fieldName)); - } - - public bool IsConflictingStateUDTTypeIdentifier(IObjectStateUDT stateUDT) - { - var potentialConflictNames = PotentialConflictIdentifiers(stateUDT, DeclarationType.UserDefinedType); - - return potentialConflictNames.Any(m => m.IsEquivalentVBAIdentifierTo(stateUDT.TypeIdentifier)); - } - - public bool IsConflictingStateUDTFieldIdentifier(IObjectStateUDT stateUDT) - { - var potentialConflictNames = PotentialConflictIdentifiers(stateUDT, DeclarationType.Variable); - - return potentialConflictNames.Any(m => m.IsEquivalentVBAIdentifierTo(stateUDT.FieldIdentifier)); - } - - //The refactoring only inserts new code elements with the following Accessibilities: - //Variables => Private - //Properties => Public - //UDT => Private - private bool IsAlwaysIgnoreNameConflictType(Declaration d, DeclarationType toEnapsulateDeclarationType) - { - var NeverCauseNameConflictTypes = new List() - { - DeclarationType.Project, - DeclarationType.ProceduralModule, - DeclarationType.ClassModule, - DeclarationType.Parameter, - DeclarationType.EnumerationMember, - DeclarationType.Enumeration, - DeclarationType.UserDefinedType, - DeclarationType.UserDefinedTypeMember - }; - - if (toEnapsulateDeclarationType.HasFlag(DeclarationType.Variable)) - { - //5.2.3.4: An enum member name may not be the same as any variable name - //or constant name that is defined within the same module - NeverCauseNameConflictTypes.Remove(DeclarationType.EnumerationMember); - } - else if (toEnapsulateDeclarationType.HasFlag(DeclarationType.UserDefinedType)) - { - //5.2.3.3 If an is an element of a its - //UDT name cannot be the same as the enum name of any - //or the UDT name of any other within the same - NeverCauseNameConflictTypes.Remove(DeclarationType.UserDefinedType); - - //5.2.3.4 The enum name of a cannot be the same as the enum name of any other - // or as the UDT name of a within the same . - NeverCauseNameConflictTypes.Remove(DeclarationType.Enumeration); - } - else if (toEnapsulateDeclarationType.HasFlag(DeclarationType.Property)) - { - //Each < subroutine - declaration > and < function - declaration > must have a - //procedure name that is different from any other module variable name, - //module constant name, enum member name, or procedure name that is defined - //within the same module. - - NeverCauseNameConflictTypes.Remove(DeclarationType.EnumerationMember); - } - return d.IsLocalVariable() - || d.IsLocalConstant() - || NeverCauseNameConflictTypes.Contains(d.DeclarationType); - } - } -} diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs index 8973cd1fd1..b268540530 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs @@ -5,6 +5,7 @@ using Rubberduck.VBEditor; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -13,23 +14,50 @@ namespace Rubberduck.Refactorings.EncapsulateField { public class ConvertFieldsToUDTMembers : EncapsulateFieldStrategyBase { - public ConvertFieldsToUDTMembers(IDeclarationFinderProvider declarationFinderProvider, QualifiedModuleName qmn, IIndenter indenter) - : base(declarationFinderProvider, qmn, indenter) { } + private List _convertedFields; + private IObjectStateUDT _stateUDTField; + + public ConvertFieldsToUDTMembers(IDeclarationFinderProvider declarationFinderProvider, EncapsulateFieldModel model, IIndenter indenter) + : base(declarationFinderProvider, model, indenter) + { + model.AssignCandidateValidations(EncapsulateFieldStrategy.ConvertFieldsToUDTMembers); + _convertedFields = new List(); + if (File.Exists("C:\\Users\\Brian\\Documents\\UseNewUDTStructure.txt")) + { + foreach (var field in model.SelectedFieldCandidates) + { + _convertedFields.Add(new ConvertToUDTMember(field, model.StateUDTField)); + } + } + else + { + _convertedFields = model.SelectedFieldCandidates.Cast().ToList(); + } + foreach (var convert in _convertedFields) + { + convert.NameValidator = convert.Declaration.IsArray + ? model.ValidatorProvider.NameOnlyValidator(Validators.UserDefinedTypeMemberArray) + : model.ValidatorProvider.NameOnlyValidator(Validators.UserDefinedTypeMember); + + convert.ConflictFinder = model.ValidatorProvider.ConflictDetector(EncapsulateFieldStrategy.ConvertFieldsToUDTMembers, declarationFinderProvider); + } + _stateUDTField = model.StateUDTField; + } protected override void ModifyFields(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) { var rewriter = refactorRewriteSession.CheckOutModuleRewriter(_targetQMN); - foreach (var field in model.SelectedFieldCandidates) + foreach (var field in model.SelectedFieldCandidates) { refactorRewriteSession.Remove(field.Declaration, rewriter); } - if (model.StateUDTField.IsExistingDeclaration) + if (_stateUDTField.IsExistingDeclaration) { - model.StateUDTField.AddMembers(model.SelectedFieldCandidates); + _stateUDTField.AddMembers(_convertedFields); - rewriter.Replace(model.StateUDTField.AsTypeDeclaration, model.StateUDTField.TypeDeclarationBlock(_indenter)); + rewriter.Replace(_stateUDTField.AsTypeDeclaration, _stateUDTField.TypeDeclarationBlock(_indenter)); } } @@ -37,7 +65,7 @@ protected override void ModifyReferences(EncapsulateFieldModel model, IEncapsula { foreach (var field in model.SelectedFieldCandidates) { - field.LoadFieldReferenceContextReplacements(model.StateUDTField.FieldIdentifier); + field.LoadFieldReferenceContextReplacements(_stateUDTField.FieldIdentifier); } RewriteReferences(model, refactorRewriteSession); @@ -45,14 +73,26 @@ protected override void ModifyReferences(EncapsulateFieldModel model, IEncapsula protected override void LoadNewDeclarationBlocks(EncapsulateFieldModel model) { - if (model.StateUDTField.IsExistingDeclaration) { return; } + if (_stateUDTField.IsExistingDeclaration) { return; } - model.StateUDTField.AddMembers(model.SelectedFieldCandidates); + _stateUDTField.AddMembers(_convertedFields); - AddContentBlock(NewContentTypes.TypeDeclarationBlock, model.StateUDTField.TypeDeclarationBlock(_indenter)); + AddContentBlock(NewContentTypes.TypeDeclarationBlock, _stateUDTField.TypeDeclarationBlock(_indenter)); - AddContentBlock(NewContentTypes.DeclarationBlock, model.StateUDTField.FieldDeclarationBlock); + AddContentBlock(NewContentTypes.DeclarationBlock, _stateUDTField.FieldDeclarationBlock); return; } + + protected override void LoadNewPropertyBlocks(EncapsulateFieldModel model) + { + var propertyGenerationSpecs = _convertedFields // model.SelectedFieldCandidates + .SelectMany(f => f.PropertyAttributeSets); + + var generator = new PropertyGenerator(); + foreach (var spec in propertyGenerationSpecs) + { + AddContentBlock(NewContentTypes.MethodBlock, generator.AsPropertyBlock(spec, _indenter)); + } + } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs index 5858ee8165..0783fefa64 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs @@ -28,10 +28,13 @@ protected enum NewContentTypes { TypeDeclarationBlock, DeclarationBlock, MethodB protected Dictionary> _newContent { set; get; } private static string DoubleSpace => $"{Environment.NewLine}{Environment.NewLine}"; - public EncapsulateFieldStrategyBase(IDeclarationFinderProvider declarationFinderProvider, QualifiedModuleName qmn, IIndenter indenter) + protected IEnumerable SelectedFields { private set; get; } + + public EncapsulateFieldStrategyBase(IDeclarationFinderProvider declarationFinderProvider, EncapsulateFieldModel model, IIndenter indenter) { - _targetQMN = qmn; + _targetQMN = model.QualifiedModuleName; _indenter = indenter; + SelectedFields = model.SelectedFieldCandidates; _codeSectionStartIndex = declarationFinderProvider.DeclarationFinder .Members(_targetQMN).Where(m => m.IsMember()) @@ -58,7 +61,8 @@ public IEncapsulateFieldRewriteSession RefactorRewrite(EncapsulateFieldModel mod protected void RewriteReferences(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) { - foreach (var rewriteReplacement in model.SelectedFieldCandidates.SelectMany(field => field.ReferenceReplacements)) + //foreach (var rewriteReplacement in model.SelectedFieldCandidates.SelectMany(field => field.ReferenceReplacements)) + foreach (var rewriteReplacement in SelectedFields.SelectMany(field => field.ReferenceReplacements)) { (ParserRuleContext Context, string Text) = rewriteReplacement.Value; var rewriter = refactorRewriteSession.CheckOutModuleRewriter(rewriteReplacement.Key.QualifiedModuleName); @@ -106,9 +110,9 @@ private void InsertNewContent(EncapsulateFieldModel model, IEncapsulateFieldRewr } } - private void LoadNewPropertyBlocks(EncapsulateFieldModel model) + protected virtual void LoadNewPropertyBlocks(EncapsulateFieldModel model) { - var propertyGenerationSpecs = model.SelectedFieldCandidates + var propertyGenerationSpecs = SelectedFields // model.SelectedFieldCandidates .SelectMany(f => f.PropertyAttributeSets); var generator = new PropertyGenerator(); diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/UseBackingFields.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/UseBackingFields.cs index c91f9d5941..dd4692f0bb 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/UseBackingFields.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/UseBackingFields.cs @@ -15,14 +15,37 @@ namespace Rubberduck.Refactorings.EncapsulateField { public class UseBackingFields : EncapsulateFieldStrategyBase { - public UseBackingFields(IDeclarationFinderProvider declarationFinderProvider, QualifiedModuleName qmn, IIndenter indenter) - : base(declarationFinderProvider, qmn, indenter) { } + //private IEnumerable _convertedFields; + public UseBackingFields(IDeclarationFinderProvider declarationFinderProvider, EncapsulateFieldModel model, IIndenter indenter) + : base(declarationFinderProvider, model, indenter) + { + //_convertedFields = model.SelectedFieldCandidates; //.Cast().ToList(); + model.AssignCandidateValidations(EncapsulateFieldStrategy.UseBackingFields); + //foreach (var candidate in _convertedFields) + //{ + // if (candidate is IUserDefinedTypeCandidate) + // { + // candidate.NameValidator = model.ValidatorProvider.NameOnlyValidator(Validators.UserDefinedType); + // } + // else if (candidate is IUserDefinedTypeMemberCandidate) + // { + // candidate.NameValidator = candidate.Declaration.IsArray + // ? model.ValidatorProvider.NameOnlyValidator(Validators.UserDefinedTypeMemberArray) + // : model.ValidatorProvider.NameOnlyValidator(Validators.UserDefinedTypeMember); + // } + // else + // { + // candidate.NameValidator = model.ValidatorProvider.NameOnlyValidator(Validators.Default); + // } + // candidate.ConflictFinder = model.ValidatorProvider.ConflictDetector(EncapsulateFieldStrategy.UseBackingFields, declarationFinderProvider); + //} + } protected override void ModifyFields(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) { var rewriter = refactorRewriteSession.CheckOutModuleRewriter(_targetQMN); - foreach (var field in model.SelectedFieldCandidates) + foreach (var field in SelectedFields) { if (field.Declaration.HasPrivateAccessibility() && field.FieldIdentifier.Equals(field.Declaration.IdentifierName)) { @@ -44,7 +67,7 @@ protected override void ModifyFields(EncapsulateFieldModel model, IEncapsulateFi protected override void ModifyReferences(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) { - foreach (var field in model.SelectedFieldCandidates) + foreach (var field in SelectedFields) { field.LoadFieldReferenceContextReplacements(); } @@ -55,7 +78,7 @@ protected override void ModifyReferences(EncapsulateFieldModel model, IEncapsula protected override void LoadNewDeclarationBlocks(EncapsulateFieldModel model) { //New field declarations created here were removed from their list within ModifyFields(...) - var fieldsRequiringNewDeclaration = model.SelectedFieldCandidates + var fieldsRequiringNewDeclaration = SelectedFields .Where(field => field.Declaration.IsDeclaredInList() && field.Declaration.Accessibility != Accessibility.Private); diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs index 7c0070eed4..c1b5c553d6 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs @@ -2,24 +2,26 @@ using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; +using System; using System.Linq; namespace Rubberduck.Refactorings.EncapsulateField { public interface IArrayCandidate : IEncapsulateFieldCandidate { + string UDTMemberDeclaration { get;} } public class ArrayCandidate : EncapsulateFieldCandidate, IArrayCandidate { private string _subscripts; - public ArrayCandidate(Declaration declaration, IValidateEncapsulateFieldNames validator) + public ArrayCandidate(Declaration declaration, IValidateVBAIdentifiers validator) :base(declaration, validator) { ImplementLet = false; ImplementSet = false; - AsTypeName_Field = declaration.AsTypeName; - AsTypeName_Property = Tokens.Variant; + FieldAsTypeName = declaration.AsTypeName; + PropertyAsTypeName = Tokens.Variant; CanBeReadWrite = false; IsReadOnly = true; @@ -34,36 +36,9 @@ private bool HasExternalRedimOperation => Declaration.References.Any(rf => rf.QualifiedModuleName != QualifiedModuleName && rf.Context.TryGetAncestor(out _)); - - public override string AsUDTMemberDeclaration - => $"{PropertyName}({_subscripts}) {Tokens.As} {AsTypeName_Field}"; - public override bool TryValidateEncapsulationAttributes(out string errorMessage) { - errorMessage = string.Empty; - if (!EncapsulateFlag) { return true; } - - if (HasExternalRedimOperation) - { - errorMessage = string.Format(EncapsulateFieldResources.ArrayHasExternalRedimFormat, Declaration.IdentifierName, Declaration.QualifiedModuleName.ComponentName); - return false; - } - - if (ConvertFieldToUDTMember) - { - return TryValidateAsUDTMemberEncapsulationAttributes(out errorMessage, true); - } - - if (!TryValidateEncapsulationAttributes(DeclarationType.Property, out errorMessage, true)) - { - return false; - } - - if (NamesValidator.HasConflictingIdentifier(this, DeclarationType.Variable, out errorMessage)) - { - return false; - } - return true; + return ConflictFinder.TryValidateEncapsulationAttributes(this, out errorMessage); } public override void LoadFieldReferenceContextReplacements(string referenceQualifier = null) @@ -75,7 +50,7 @@ public override void LoadFieldReferenceContextReplacements(string referenceQuali if (idRef.QualifiedModuleName == QualifiedModuleName) { var accessor = ConvertFieldToUDTMember - ? ReferenceForPreExistingReferences + ? ReferenceForPreExistingReferences : FieldIdentifier; SetReferenceRewriteContent(idRef, accessor); @@ -104,5 +79,14 @@ protected override void SetReferenceRewriteContent(IdentifierReference idRef, st } IdentifierReplacements.Add(idRef, (context, replacementText)); } + + public override string AccessorInProperty + => $"{ObjectStateUDT.FieldIdentifier}.{UDTMemberIdentifier}"; + + public override string AccessorLocalReference + => $"{ObjectStateUDT.FieldIdentifier}.{UDTMemberIdentifier}"; + + public override string UDTMemberDeclaration + => $"{PropertyIdentifier}({_subscripts}) {Tokens.As} {Declaration.AsTypeName}"; } } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs new file mode 100644 index 0000000000..7e880323e5 --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs @@ -0,0 +1,162 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Rubberduck.Parsing.Symbols; +using Rubberduck.VBEditor; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + + public class ConvertToUDTMember : IConvertToUDTMember + { + private readonly IEncapsulatableField _wrapped; + public ConvertToUDTMember(IEncapsulatableField candidate, IObjectStateUDT objStateUDT) + { + _wrapped = candidate; + ObjectStateUDT = objStateUDT; + } + + public string UDTMemberIdentifier + { + set => _wrapped.PropertyIdentifier = value; + get => _wrapped.PropertyIdentifier; + } + + public virtual string UDTMemberDeclaration + { + get + { + if (_wrapped is IArrayCandidate array) + { + return array.UDTMemberDeclaration; + } + return $"{_wrapped.PropertyIdentifier} As {_wrapped.AsTypeName}"; + } + } + + public IObjectStateUDT ObjectStateUDT { set; get; } + + public string TargetID => _wrapped.TargetID; + + public Declaration Declaration => _wrapped.Declaration; + + public bool EncapsulateFlag + { + set => _wrapped.EncapsulateFlag = value; + get => _wrapped.EncapsulateFlag; + } + + public string PropertyIdentifier + { + set => _wrapped.PropertyIdentifier = value; + get => _wrapped.PropertyIdentifier; + } + + public string PropertyAsTypeName + { + set => _wrapped.PropertyAsTypeName = value; + get => _wrapped.PropertyAsTypeName; + } + + public bool CanBeReadWrite + { + set => _wrapped.CanBeReadWrite = value; + get => _wrapped.CanBeReadWrite; + } + + public bool ImplementLet => _wrapped.ImplementLet; + + public bool ImplementSet => _wrapped.ImplementSet; + + public bool IsReadOnly + { + set => _wrapped.IsReadOnly = value; + get => _wrapped.IsReadOnly; + } + + public string ParameterName => _wrapped.ParameterName; + + public IValidateVBAIdentifiers NameValidator + { + set => _wrapped.NameValidator = value; + get => _wrapped.NameValidator; + } + + public IEncapsulateFieldConflictFinder ConflictFinder + { + set => _wrapped.ConflictFinder = value; + get => _wrapped.ConflictFinder; + } + + public string AccessorInProperty + { + get + { + if (_wrapped is IUserDefinedTypeCandidate udt) + { + return $"{ObjectStateUDT.FieldIdentifier}.{udt.PropertyIdentifier}.{UDTMemberIdentifier}"; + } + return $"{ObjectStateUDT.FieldIdentifier}.{UDTMemberIdentifier}"; + } + } + + public string AccessorLocalReference + => $"{ObjectStateUDT.FieldIdentifier}.{UDTMemberIdentifier}"; + + public string AccessorExternalReference + => $"{QualifiedModuleName.ComponentName}.{PropertyIdentifier}"; + + public string IdentifierName => _wrapped.IdentifierName; + + public QualifiedModuleName QualifiedModuleName => _wrapped.QualifiedModuleName; + + public string AsTypeName => _wrapped.AsTypeName; + + public bool TryValidateEncapsulationAttributes(out string errorMessage) + { + return ConflictFinder.TryValidateEncapsulationAttributes(this, out errorMessage); + } + + public IEnumerable PropertyAttributeSets + { + get + { + //if (TypeDeclarationIsPrivate) + //{ + if (_wrapped is IUserDefinedTypeCandidate udt) + { + return _wrapped.PropertyAttributeSets; + } + //var specs = new List(); + //foreach (var member in Members) + //{ + // specs.Add(member.AsPropertyGeneratorSpec); + //} + //return specs; + //} + return new List() { AsPropertyAttributeSet }; + } + } + + + private IPropertyGeneratorAttributes AsPropertyAttributeSet + { + get + { + return new PropertyAttributeSet() + { + PropertyName = PropertyIdentifier, + BackingField = AccessorInProperty, // ReferenceWithinNewProperty, + AsTypeName = PropertyAsTypeName, + ParameterName = ParameterName, + GenerateLetter = ImplementLet, + GenerateSetter = ImplementSet, + UsesSetAssignment = Declaration.IsObject, + IsUDTProperty = true + }; + } + } + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateField.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateField.cs new file mode 100644 index 0000000000..e0bfdd7eae --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateField.cs @@ -0,0 +1,81 @@ +using Rubberduck.Parsing.Symbols; +using Rubberduck.VBEditor; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + public interface IEncapsulatableField : IEncapsulateFieldRefactoringElement + { + string TargetID { get; } + Declaration Declaration { get; } + bool EncapsulateFlag { get; set; } + string PropertyIdentifier { set; get; } + string PropertyAsTypeName { set; get; } + bool CanBeReadWrite { set; get; } + bool ImplementLet { get; } + bool ImplementSet { get; } + bool IsReadOnly { set; get; } + string ParameterName { get; } + IValidateVBAIdentifiers NameValidator { set; get; } + IEncapsulateFieldConflictFinder ConflictFinder { set; get; } + bool TryValidateEncapsulationAttributes(out string errorMessage); + string AccessorInProperty { get; } + string AccessorLocalReference { get; } + string AccessorExternalReference { /*set;*/ get; } + IEnumerable PropertyAttributeSets { get; } + } + + public interface IUsingBackingField : IEncapsulatableField + { + string FieldIdentifier { set; get; } + string FieldAsTypeName { set; get; } + //string AccessorInProperty { get; } + //string AccessorLocalReference { get; } + //string AccessorExternalReference { set; get; } + } + + public interface IConvertToUDTMember : IEncapsulatableField + { + //string AccessorInProperty { get; } + //string AccessorLocalReference { get; } + //string AccessorExternalReference { set; get; } + string UDTMemberIdentifier { set; get; } + string UDTMemberDeclaration { get; } + IObjectStateUDT ObjectStateUDT { set; get; } + } + + //public class EncapsulateField : IEncapsulatableField, IUsingBackingField//, IConvertToUDTMember + //{ + // private Declaration _declaration; + // public EncapsulateField(Declaration declaration) + // { + // _declaration = declaration; + // } + + // public string IdentifierName => _declaration.IdentifierName; + // public string TargetID => _declaration.IdentifierName; + // public Declaration Declaration => _declaration; + // public QualifiedModuleName QualifiedModuleName => _declaration.QualifiedModuleName; + // public string AsTypeName => _declaration.AsTypeName; + // public bool EncapsulateFlag { set; get; } + // public string PropertyIdentifier { set; get; } + // public string PropertyAsTypeName { set; get; } + // public bool CanBeReadWrite { set; get; } + // public bool ImplementLet { get; } + // public bool ImplementSet { get; } + // public bool IsReadOnly { set; get; } + // public string ParameterName { get; } + // public string AccessorInProperty { set; get; } + // public string AccessorLocalReference { set; get; } + // public string AccessorExternalReference { set; get; } + // public string FieldIdentifier { set; get; } + // public string FieldAsTypeName { set; get; } + // public string UDTMemberIdentifier { set; get; } + // public string UDTMemberDeclaration { set; get; } + // public IObjectStateUDT Parent { set; get; } + //} +} diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs index 67131d98cf..7279115a67 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs @@ -3,43 +3,24 @@ using Rubberduck.Parsing.Symbols; using Rubberduck.Refactorings.EncapsulateField.Extensions; using Rubberduck.VBEditor; +using System; using System.Collections.Generic; namespace Rubberduck.Refactorings.EncapsulateField { - public interface IEncapsulateFieldDeclaration + public interface IEncapsulateFieldRefactoringElement { string IdentifierName { get; } QualifiedModuleName QualifiedModuleName { get; } string AsTypeName { get; } } - public interface IAssignNoConflictNames + public interface IEncapsulateFieldCandidate : IUsingBackingField { - void AssignIdentifiers(IValidateEncapsulateFieldNames validator); - IValidateEncapsulateFieldNames NamesValidator { set; get; } - } - - public interface IEncapsulateFieldCandidate : IEncapsulateFieldDeclaration - { - Declaration Declaration { get; } - string TargetID { get; } - bool IsReadOnly { get; set; } - bool EncapsulateFlag { get; set; } - string FieldIdentifier { set; get; } - bool CanBeReadWrite { set; get; } - string PropertyName { get; set; } - string AsTypeName_Field { get; set; } - string AsTypeName_Property { get; set; } - string ParameterName { get; } - bool ImplementLet { get; } - bool ImplementSet { get; } - IEnumerable PropertyAttributeSets { get; } - string AsUDTMemberDeclaration { get; } + //IEnumerable PropertyAttributeSets { get; } IEnumerable> ReferenceReplacements { get; } string ReferenceQualifier { set; get; } void LoadFieldReferenceContextReplacements(string referenceQualifier = null); - bool TryValidateEncapsulationAttributes(out string errorMessage); bool ConvertFieldToUDTMember { set; get; } } @@ -51,7 +32,16 @@ public interface IEncapsulateFieldCandidateValidations bool HasConflictingFieldIdentifier { get; } } - public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate, IEncapsulateFieldCandidateValidations, IAssignNoConflictNames + //public class ConvertedToUDTMember : IConvertToUDTMember + //{ + // private IEncapsulatableField _field; + // public ConvertedToUDTMember(IEncapsulatableField field) + // { + + // } + //} + + public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate, IEncapsulateFieldCandidateValidations, IConvertToUDTMember//, IAssignNoConflictNames { protected Declaration _target; protected QualifiedModuleName _qmn; @@ -59,16 +49,18 @@ public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate, IEncapsulat private string _identifierName; protected EncapsulationIdentifiers _fieldAndProperty; - public EncapsulateFieldCandidate(Declaration declaration, IValidateEncapsulateFieldNames validator) + public EncapsulateFieldCandidate(Declaration declaration, IValidateVBAIdentifiers identifierValidator) // Predicate nameValidator/*, IValidateEncapsulateFieldNames validator*/) { _target = declaration; - NamesValidator = validator; - _fieldAndProperty = new EncapsulationIdentifiers(declaration.IdentifierName, (string name) => NamesValidator.IsValidVBAIdentifier(name, DeclarationType.Property, out _)); + NameValidator = identifierValidator; + + _fieldAndProperty = new EncapsulationIdentifiers(declaration.IdentifierName, identifierValidator); // (string name) => nameValidator(name)); // (string name) => NamesValidator.IsValidVBAIdentifier(name, DeclarationType.Property, out _)); IdentifierName = declaration.IdentifierName; - AsTypeName_Field = declaration.AsTypeName; - AsTypeName_Property = declaration.AsTypeName; + FieldAsTypeName = declaration.AsTypeName; + PropertyAsTypeName = declaration.AsTypeName; _qmn = declaration.QualifiedModuleName; NewPropertyAccessor = AccessorMember.Field; + //_accessoryInProperty = _fieldAndProperty.Field; ReferenceAccessor = AccessorMember.Property; CanBeReadWrite = true; @@ -82,7 +74,7 @@ public EncapsulateFieldCandidate(Declaration declaration, IValidateEncapsulateFi //5.3.1 The declared type of a function declaration may not be a private enum name. if (_target.AsTypeDeclaration.HasPrivateAccessibility()) { - AsTypeName_Property = Tokens.Long; + PropertyAsTypeName = Tokens.Long; } } else if (_target.AsTypeName.Equals(Tokens.Variant) @@ -103,70 +95,32 @@ public EncapsulateFieldCandidate(Declaration declaration, IValidateEncapsulateFi public string AsTypeName => _target.AsTypeName; - public IValidateEncapsulateFieldNames NamesValidator { set; get; } - - public bool HasConflictingPropertyIdentifier - => NamesValidator.HasConflictingIdentifier(this, DeclarationType.Property, out var errorMessage); - - public bool HasConflictingFieldIdentifier - => NamesValidator.HasConflictingIdentifier(this, DeclarationType.Variable, out var errorMessage); - - public virtual bool TryValidateEncapsulationAttributes(out string errorMessage) + public virtual string FieldIdentifier { - errorMessage = string.Empty; - if (!EncapsulateFlag) { return true; } - - if (ConvertFieldToUDTMember) - { - return TryValidateAsUDTMemberEncapsulationAttributes(out errorMessage); - } - - if (!TryValidateEncapsulationAttributes(DeclarationType.Property, out errorMessage)) - { - return false; - } - - if (NamesValidator.HasConflictingIdentifier(this, DeclarationType.Variable, out errorMessage)) - { - return false; - } - return true; + get => _fieldAndProperty.Field; + set => _fieldAndProperty.Field = value; } + public string FieldAsTypeName { set; get; } - protected virtual bool TryValidateAsUDTMemberEncapsulationAttributes(out string errorMessage, bool isArray = false) - { - errorMessage = string.Empty; - if (!EncapsulateFlag) { return true; } - - if (!TryValidateEncapsulationAttributes(DeclarationType.UserDefinedTypeMember, out errorMessage, isArray)) - { - return false; - } + //private string _accessoryInProperty; + //public virtual string AccessorInProperty //{ get; } + // => _fieldAndProperty.Field; // AccessorMemberToContent(NewPropertyAccessor); + //public string AccessorLocalReference { /*set;*/ get; } + //public string AccessorExternalReference { set; get; } - if (!TryValidateEncapsulationAttributes(DeclarationType.Property, out errorMessage, isArray)) - { - return false; - } + public virtual IValidateVBAIdentifiers NameValidator { set; get; } - return TryValidateEncapsulationAttributes(Declaration.DeclarationType, out errorMessage, isArray); - } + public virtual IEncapsulateFieldConflictFinder ConflictFinder { set; get; } - protected bool TryValidateEncapsulationAttributes(DeclarationType declarationType, out string errorMessage, bool isArray = false) - { - errorMessage = string.Empty; - if (!EncapsulateFlag) { return true; } + public bool HasConflictingPropertyIdentifier + => ConflictFinder.HasConflictingIdentifier(this, DeclarationType.Property, out var errorMessage); - if (!NamesValidator.IsValidVBAIdentifier(PropertyName, declarationType, out errorMessage, isArray)) - { - return false; - } - - if (NamesValidator.HasConflictingIdentifier(this, declarationType, out errorMessage)) - { - return false; - } + public bool HasConflictingFieldIdentifier + => ConflictFinder.HasConflictingIdentifier(this, DeclarationType.Variable, out var errorMessage); - return true; + public virtual bool TryValidateEncapsulationAttributes(out string errorMessage) + { + return ConflictFinder.TryValidateEncapsulationAttributes(this, out errorMessage); } public virtual IEnumerable> ReferenceReplacements @@ -204,9 +158,9 @@ public virtual bool EncapsulateFlag _encapsulateFlag = value; if (!_encapsulateFlag) { - PropertyName = _fieldAndProperty.DefaultPropertyName; - AssignNoConflictIdentifier(this, DeclarationType.Property, NamesValidator); - AssignNoConflictIdentifier(this, DeclarationType.Variable, NamesValidator); + PropertyIdentifier = _fieldAndProperty.DefaultPropertyName; + ConflictFinder.AssignNoConflictIdentifier(this, DeclarationType.Property); + ConflictFinder.AssignNoConflictIdentifier(this, DeclarationType.Variable); } } get => _encapsulateFlag; @@ -215,66 +169,53 @@ public virtual bool EncapsulateFlag public virtual bool IsReadOnly { set; get; } public bool CanBeReadWrite { set; get; } - public virtual string FieldIdentifier - { - get => _fieldAndProperty.Field; - set => _fieldAndProperty.Field = value; - } - public virtual string PropertyName { - get => _fieldAndProperty.Property; - set - { - _fieldAndProperty.Property = value; - - TryRestoreNewFieldNameAsOriginalFieldIdentifierName(); - } + get => PropertyIdentifier; + set => PropertyIdentifier = value; } public override bool Equals(object obj) { - return obj != null + return obj != null && obj is IEncapsulateFieldCandidate efc && $"{efc.QualifiedModuleName.Name}.{efc.TargetID}" == $"{_qmn.Name}.{IdentifierName}"; } public override int GetHashCode() => _hashCode; + /* + * IConvertToUDTMemberInterface + */ + public virtual string AccessorInProperty + => $"{ObjectStateUDT.FieldIdentifier}.{UDTMemberIdentifier}"; - public void AssignIdentifiers(IValidateEncapsulateFieldNames validator) - { - AssignNoConflictIdentifier(this, DeclarationType.Property, validator); - AssignNoConflictIdentifier(this, DeclarationType.Variable, validator); - } + public virtual string AccessorLocalReference + => $"{ObjectStateUDT.FieldIdentifier}.{PropertyIdentifier}"; - protected static IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType, IValidateEncapsulateFieldNames validator) + public string AccessorExternalReference { set; get; } + public string PropertyIdentifier { - var isConflictingIdentifier = validator.HasConflictingIdentifierIgnoreEncapsulationFlag(candidate, declarationType, out _); - for (var count = 1; count < 10 && isConflictingIdentifier; count++) + get => _fieldAndProperty.Property; + set { - var identifier = declarationType.HasFlag(DeclarationType.Property) - ? candidate.PropertyName - : candidate.FieldIdentifier; + _fieldAndProperty.Property = value; + UDTMemberIdentifier = value; - if (declarationType.HasFlag(DeclarationType.Property)) - { - candidate.PropertyName = identifier.IncrementEncapsulationIdentifier(); - } - else - { - candidate.FieldIdentifier = identifier.IncrementEncapsulationIdentifier(); - } - isConflictingIdentifier = validator.HasConflictingIdentifierIgnoreEncapsulationFlag(candidate, declarationType, out _); + TryRestoreNewFieldNameAsOriginalFieldIdentifierName(); } - return candidate; } + public string UDTMemberIdentifier { set; get; } + + public virtual string UDTMemberDeclaration + => $"{PropertyIdentifier} {Tokens.As} {FieldAsTypeName}"; + + public IObjectStateUDT ObjectStateUDT { set; get; } - //The preferred NewFieldName is the original Identifier private void TryRestoreNewFieldNameAsOriginalFieldIdentifierName() { var canNowUseOriginalFieldName = !_fieldAndProperty.TargetFieldName.IsEquivalentVBAIdentifierTo(_fieldAndProperty.Property) - && !NamesValidator.IsConflictingProposedIdentifier(_fieldAndProperty.TargetFieldName, this, DeclarationType.Variable); + && !ConflictFinder.IsConflictingProposedIdentifier(_fieldAndProperty.TargetFieldName, this, DeclarationType.Variable); if (canNowUseOriginalFieldName) { @@ -285,18 +226,16 @@ private void TryRestoreNewFieldNameAsOriginalFieldIdentifierName() if (_fieldAndProperty.Field.IsEquivalentVBAIdentifierTo(_fieldAndProperty.TargetFieldName)) { _fieldAndProperty.Field = _fieldAndProperty.DefaultNewFieldName; - var isConflictingFieldIdentifier = NamesValidator.HasConflictingIdentifier(this, DeclarationType.Variable, out _); + var isConflictingFieldIdentifier = ConflictFinder.HasConflictingIdentifier(this, DeclarationType.Variable, out _); for (var count = 1; count < 10 && isConflictingFieldIdentifier; count++) { FieldIdentifier = FieldIdentifier.IncrementEncapsulationIdentifier(); - isConflictingFieldIdentifier = NamesValidator.HasConflictingIdentifier(this, DeclarationType.Variable, out _); + isConflictingFieldIdentifier = ConflictFinder.HasConflictingIdentifier(this, DeclarationType.Variable, out _); } } } - public string AsTypeName_Field { set; get; } - - public string AsTypeName_Property { get; set; } + public string PropertyAsTypeName { get; set; } public QualifiedModuleName QualifiedModuleName => _qmn; @@ -318,8 +257,7 @@ public string IdentifierName public bool ConvertFieldToUDTMember { set; get; } - public virtual string AsUDTMemberDeclaration - => $"{PropertyName} {Tokens.As} {AsTypeName_Field}"; + public EncapsulateFieldStrategy EncapsulateFieldStrategy { set; get; } = EncapsulateFieldStrategy.UseBackingFields; public virtual IEnumerable PropertyAttributeSets => new List() { AsPropertyAttributeSet }; @@ -351,12 +289,12 @@ private string AccessorMemberToContent(AccessorMember accessorMember) { if ((ReferenceQualifier?.Length ?? 0) > 0) { - return $"{ReferenceQualifier}.{PropertyName}"; + return $"{ReferenceQualifier}.{PropertyIdentifier}"; } return accessorMember == AccessorMember.Field ? FieldIdentifier - : PropertyName; + : PropertyIdentifier; } protected virtual IPropertyGeneratorAttributes AsPropertyAttributeSet @@ -365,9 +303,9 @@ protected virtual IPropertyGeneratorAttributes AsPropertyAttributeSet { return new PropertyAttributeSet() { - PropertyName = PropertyName, + PropertyName = PropertyIdentifier, BackingField = ReferenceWithinNewProperty, - AsTypeName = AsTypeName_Property, + AsTypeName = PropertyAsTypeName, ParameterName = ParameterName, GenerateLetter = ImplementLet, GenerateSetter = ImplementSet, diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs index 7b04f5e621..4c44cb1c72 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs @@ -15,7 +15,7 @@ public class EncapsulationIdentifiers private string _targetIdentifier; private string _setLetParameter; - public EncapsulationIdentifiers(string field, Predicate IsValidPropertyName) + public EncapsulationIdentifiers(string field, IValidateVBAIdentifiers identifierValidator) // Predicate IsValidPropertyName) { _targetIdentifier = field; @@ -24,7 +24,7 @@ public EncapsulationIdentifiers(string field, Predicate IsValidPropertyN if (field.TryMatchHungarianNotationCriteria(out var nonHungarianName)) { - if (IsValidPropertyName(nonHungarianName)) + if (identifierValidator.IsValidVBAIdentifier(nonHungarianName, out _)) { DefaultPropertyName = nonHungarianName; DefaultNewFieldName = field; @@ -33,7 +33,7 @@ public EncapsulationIdentifiers(string field, Predicate IsValidPropertyN else if (field.StartsWith("m_")) { var propertyName = field.Substring(2).CapitalizeFirstLetter(); - if (IsValidPropertyName(propertyName)) + if (identifierValidator.IsValidVBAIdentifier(propertyName, out _)) { DefaultPropertyName = propertyName; DefaultNewFieldName = field; diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs index a8064c0d2b..9fe158f0ee 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs @@ -8,29 +8,33 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using Rubberduck.Refactorings.EncapsulateField.Extensions; namespace Rubberduck.Refactorings.EncapsulateField { - public interface IObjectStateUDT : IEncapsulateFieldDeclaration + public interface IObjectStateUDT : IEncapsulateFieldRefactoringElement { string TypeIdentifier { set; get; } string FieldIdentifier { set; get; } string TypeDeclarationBlock(IIndenter indenter = null); string FieldDeclarationBlock { get; } - void AddMembers(IEnumerable fields); + //void AddMembers(IEnumerable fields); + void AddMembers(IEnumerable fields); bool IsExistingDeclaration { get; } Declaration AsTypeDeclaration { get; } bool IsSelected { set; get; } - bool IsEncapsulateFieldCandidate(IEncapsulateFieldCandidate efc); + //bool IsEncapsulateFieldCandidate(IEncapsulateFieldCandidate efc); IEnumerable ExistingMembers { get; } } //ObjectStateUDT can be an existing UDT (Private only) selected by the user, or a //newly inserted declaration - public class ObjectStateUDT : IObjectStateUDT + public class ObjectStateUDT : IObjectStateUDT//, IAssignNoConflictNames { private static string _defaultNewFieldName = EncapsulateFieldResources.DefaultStateUDTFieldName; - private List _members; + //private List _members; + private List _convertedMembers; + private readonly IUserDefinedTypeCandidate _wrappedUDT; private int _hashCode; @@ -57,7 +61,40 @@ private ObjectStateUDT(string typeIdentifier) { FieldIdentifier = _defaultNewFieldName; TypeIdentifier = typeIdentifier; - _members = new List(); + //_members = new List(); + _convertedMembers = new List(); + } + + //public void AssignIdentifiers(IEncapsulateFieldValidator validator) + //{ + // FieldIdentifier = validator.CreateNonConflictIdentifierForProposedType(FieldIdentifier, QualifiedModuleName, DeclarationType.Variable); + // TypeIdentifier = validator.CreateNonConflictIdentifierForProposedType(TypeIdentifier, QualifiedModuleName, DeclarationType.UserDefinedType); + //} + + protected static IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType, IValidateEncapsulateFieldNames validator) + { + var isConflictingIdentifier = validator.HasConflictingIdentifierIgnoreEncapsulationFlag(candidate, declarationType, out _); + for (var count = 1; count < 10 && isConflictingIdentifier; count++) + { + var identifier = declarationType.HasFlag(DeclarationType.Property) + //? candidate.PropertyName + ? candidate.PropertyIdentifier + : candidate.FieldIdentifier; + //: candidate.FieldIdentifierOld; + + if (declarationType.HasFlag(DeclarationType.Property)) + { + //candidate.PropertyName = identifier.IncrementEncapsulationIdentifier(); + candidate.PropertyIdentifier = identifier.IncrementEncapsulationIdentifier(); + } + else + { + //candidate.FieldIdentifierOld = identifier.IncrementEncapsulationIdentifier(); + candidate.FieldIdentifier = identifier.IncrementEncapsulationIdentifier(); + } + isConflictingIdentifier = validator.HasConflictingIdentifierIgnoreEncapsulationFlag(candidate, declarationType, out _); + } + return candidate; } public string IdentifierName => _wrappedUDT?.IdentifierName ?? FieldIdentifier; @@ -106,13 +143,24 @@ public QualifiedModuleName QualifiedModuleName public string FieldIdentifier { set; get; } - public void AddMembers(IEnumerable fields) + //public void AddMembers(IEnumerable fields) + //{ + // AddMembers(fields.Cast()); + // //if (IsExistingDeclaration) + // //{ + // // _members = _wrappedUDT.Members.Select(m => m).Cast().ToList(); + // //} + // //_members.AddRange(fields); + //} + + public void AddMembers(IEnumerable fields) { if (IsExistingDeclaration) { - _members = _wrappedUDT.Members.Select(m => m).Cast().ToList(); + _convertedMembers = _wrappedUDT.Members.Select(m => m).Cast().ToList(); } - _members.AddRange(fields); + //_members.AddRange(fields); + _convertedMembers.AddRange(fields); } public string FieldDeclarationBlock @@ -133,21 +181,21 @@ public override bool Equals(object obj) { return true; } - if (obj is IEncapsulateFieldDeclaration fd && fd.IdentifierName == IdentifierName) + if (obj is IEncapsulateFieldRefactoringElement fd && fd.IdentifierName == IdentifierName) { return true; } return false; } - public bool IsEncapsulateFieldCandidate(IEncapsulateFieldCandidate efc) - { - if (efc is IEncapsulateFieldDeclaration fd && fd.IdentifierName == IdentifierName) - { - return true; - } - return false; - } + //public bool IsEncapsulateFieldCandidate(IEncapsulateFieldCandidate efc) + //{ + // if (efc is IEncapsulateFieldDeclaration fd && fd.IdentifierName == IdentifierName) + // { + // return true; + // } + // return false; + //} public override int GetHashCode() => _hashCode; @@ -157,7 +205,8 @@ private IEnumerable BlockLines(Accessibility accessibility) blockLines.Add($"{accessibility.TokenString()} {Tokens.Type} {TypeIdentifier}"); - _members.ForEach(m => blockLines.Add($"{m.AsUDTMemberDeclaration}")); + //_members.ForEach(m => blockLines.Add($"{m.AsUDTMemberDeclaration}")); + _convertedMembers.ForEach(m => blockLines.Add($"{m.UDTMemberDeclaration}")); blockLines.Add($"{Tokens.End} {Tokens.Type}"); diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs index b6b90b0e79..436bae01a8 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs @@ -4,6 +4,7 @@ using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.Refactorings.EncapsulateField.Extensions; +using System; using System.Collections.Generic; using System.Linq; @@ -19,11 +20,12 @@ public interface IUserDefinedTypeCandidate : IEncapsulateFieldCandidate public class UserDefinedTypeCandidate : EncapsulateFieldCandidate, IUserDefinedTypeCandidate { - public UserDefinedTypeCandidate(Declaration declaration, IValidateEncapsulateFieldNames validator) - : base(declaration, validator) + public UserDefinedTypeCandidate(Declaration declaration, IValidateVBAIdentifiers identifierValidator) // Predicate nameValidator/*, IValidateEncapsulateFieldNames validator*/) + : base(declaration, identifierValidator) { NewPropertyAccessor = AccessorMember.Field; ReferenceAccessor = AccessorMember.Field; + //AccessorInProperty = AccessorMember.Field; } public void AddMember(IUserDefinedTypeMemberCandidate member) @@ -49,6 +51,36 @@ public override string FieldIdentifier set => _fieldAndProperty.Field = value; } + private IValidateVBAIdentifiers _namesValidator; + public override IValidateVBAIdentifiers NameValidator + { + set + { + _namesValidator = value; + foreach (var member in Members) + { + member.NameValidator = value; + } + } + get => _namesValidator; + } + + private IEncapsulateFieldConflictFinder _conflictsValidator; + public override IEncapsulateFieldConflictFinder ConflictFinder + { + set + { + _conflictsValidator = value; + foreach (var member in Members) + { + member.ConflictFinder = value; + } + } + get => _conflictsValidator; + } + + + private string _referenceQualifier; public override string ReferenceQualifier { @@ -77,6 +109,9 @@ public override bool IsReadOnly } } + //public override string AccessorInProperty + // => AccessorMemberToContent(NewPropertyAccessor); + public override bool EncapsulateFlag { set @@ -86,7 +121,7 @@ public override bool EncapsulateFlag foreach (var member in Members.Where(m => !m.ConvertFieldToUDTMember && m.IsExistingMember)) { member.EncapsulateFlag = value; - if (!member.EncapsulateFlag || !NamesValidator.HasConflictingIdentifier(member, DeclarationType.Property, out _)) + if (!member.EncapsulateFlag || !ConflictFinder.HasConflictingIdentifier(member, DeclarationType.Property, out _)) { continue; } @@ -95,9 +130,8 @@ public override bool EncapsulateFlag //Type within the module. //Try to use a name involving the parent's identifier to make it unique/meaningful //before giving up and creating incremented value(s). - member.PropertyName = $"{FieldIdentifier.CapitalizeFirstLetter()}{member.PropertyName.CapitalizeFirstLetter()}"; - //_validator.AssignNoConflictIdentifier(member, DeclarationType.Property); - AssignNoConflictIdentifier(member, DeclarationType.Property, NamesValidator); + member.PropertyIdentifier = $"{FieldIdentifier.CapitalizeFirstLetter()}{member.PropertyIdentifier.CapitalizeFirstLetter()}"; + ConflictFinder.AssignNoConflictIdentifier(member, DeclarationType.Property); } } base.EncapsulateFlag = value; @@ -118,8 +152,8 @@ public override void LoadFieldReferenceContextReplacements(string referenceQuali foreach (var idRef in Declaration.References) { var replacementText = RequiresAccessQualification(idRef) - ? $"{QualifiedModuleName.ComponentName}.{PropertyName}" - : PropertyName; + ? $"{QualifiedModuleName.ComponentName}.{PropertyIdentifier}" + : PropertyIdentifier; SetReferenceRewriteContent(idRef, replacementText); } @@ -180,24 +214,25 @@ public override int GetHashCode() public override bool TryValidateEncapsulationAttributes(out string errorMessage) { - errorMessage = string.Empty; - if (!EncapsulateFlag) { return true; } + return ConflictFinder.TryValidateEncapsulationAttributes(this, out errorMessage); + //errorMessage = string.Empty; + //if (!EncapsulateFlag) { return true; } - if (!NamesValidator.IsValidVBAIdentifier(PropertyName, DeclarationType.Property, out errorMessage)) - { - return false; - } + //if (!NameValidator.IsValidVBAIdentifier(PropertyName, out errorMessage)) + //{ + // return false; + //} - if (NamesValidator.HasConflictingIdentifier(this, DeclarationType.Property, out errorMessage)) - { - return false; - } + //if (ConflictFinder.HasConflictingIdentifier(this, DeclarationType.Property, out errorMessage)) + //{ + // return false; + //} - if (NamesValidator.HasConflictingIdentifier(this, DeclarationType.Variable, out errorMessage)) - { - return false; - } - return true; + //if (ConflictFinder.HasConflictingIdentifier(this, DeclarationType.Variable, out errorMessage)) + //{ + // return false; + //} + //return true; } protected override IPropertyGeneratorAttributes AsPropertyAttributeSet @@ -206,9 +241,9 @@ protected override IPropertyGeneratorAttributes AsPropertyAttributeSet { return new PropertyAttributeSet() { - PropertyName = PropertyName, + PropertyName = PropertyIdentifier, BackingField = ReferenceWithinNewProperty, - AsTypeName = AsTypeName_Property, + AsTypeName = PropertyAsTypeName, ParameterName = ParameterName, GenerateLetter = ImplementLet, GenerateSetter = ImplementSet, diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs index 5bd0e66d06..a73c855e4b 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs @@ -19,17 +19,15 @@ public interface IUserDefinedTypeMemberCandidate : IEncapsulateFieldCandidate bool IsExistingMember { get; } } - public class UserDefinedTypeMemberCandidate : IUserDefinedTypeMemberCandidate + public class UserDefinedTypeMemberCandidate : IUserDefinedTypeMemberCandidate, IConvertToUDTMember { - private readonly IValidateEncapsulateFieldNames _validator; private int _hashCode; private readonly string _uniqueID; - public UserDefinedTypeMemberCandidate(IEncapsulateFieldCandidate candidate, IUserDefinedTypeCandidate udtVariable, IValidateEncapsulateFieldNames validator) + public UserDefinedTypeMemberCandidate(IEncapsulateFieldCandidate candidate, IUserDefinedTypeCandidate udtVariable/*, IValidateEncapsulateFieldNames validator*/) { _wrappedCandidate = candidate; Parent = udtVariable; - _validator = validator; - PropertyName = IdentifierName; + PropertyIdentifier = IdentifierName; _uniqueID = BuildUniqueID(candidate); _hashCode = _uniqueID.GetHashCode(); } @@ -38,6 +36,8 @@ public UserDefinedTypeMemberCandidate(IEncapsulateFieldCandidate candidate, IUse public string AsTypeName => _wrappedCandidate.AsTypeName; + //public string AccessorInProperty { /*set;*/ get; } + public IUserDefinedTypeCandidate Parent { private set; get; } public void LoadFieldReferenceContextReplacements(string referenceQualifier = null) @@ -45,6 +45,18 @@ public void LoadFieldReferenceContextReplacements(string referenceQualifier = nu ReferenceQualifier = referenceQualifier; } + public IValidateVBAIdentifiers NameValidator + { + set => _wrappedCandidate.NameValidator = value; + get => _wrappedCandidate.NameValidator; + } + + public IEncapsulateFieldConflictFinder ConflictFinder + { + set => _wrappedCandidate.ConflictFinder = value; + get => _wrappedCandidate.ConflictFinder; + } + public string ReferenceQualifier { set; get; } public string TargetID => $"{Parent.IdentifierName}.{IdentifierName}"; @@ -59,7 +71,7 @@ public void LoadReferenceExpressions() if (rf.QualifiedModuleName == QualifiedModuleName && !rf.Context.TryGetAncestor(out _)) { - SetReferenceRewriteContent(rf, PropertyName); + SetReferenceRewriteContent(rf, PropertyIdentifier); continue; } var moduleQualifier = rf.Context.TryGetAncestor(out _) @@ -67,11 +79,10 @@ public void LoadReferenceExpressions() ? string.Empty : $"{QualifiedModuleName.ComponentName}"; - SetReferenceRewriteContent(rf, $"{moduleQualifier}.{PropertyName}"); + SetReferenceRewriteContent(rf, $"{moduleQualifier}.{PropertyIdentifier}"); } } - protected void SetReferenceRewriteContent(IdentifierReference idRef, string replacementText) { Debug.Assert(idRef.Context.Parent is ParserRuleContext, "idRef.Context.Parent is not convertable to ParserRuleContext"); @@ -90,13 +101,14 @@ public IPropertyGeneratorAttributes AsPropertyGeneratorSpec { return new PropertyAttributeSet() { - PropertyName = PropertyName, + PropertyName = PropertyIdentifier, BackingField = ReferenceWithinNewProperty, - AsTypeName = AsTypeName_Property, + AsTypeName = PropertyAsTypeName, ParameterName = ParameterName, GenerateLetter = ImplementLet, GenerateSetter = ImplementSet, - UsesSetAssignment = Declaration.IsObject + UsesSetAssignment = Declaration.IsObject, + IsUDTProperty = false //TODO: If the member is a UDT, this needs to be true }; } } @@ -112,6 +124,26 @@ public override bool Equals(object obj) public override int GetHashCode() => _hashCode; + /* + * IConvertToUDTMemberInterface + */ + public string AccessorInProperty + => $"{Parent.FieldIdentifier}.{Declaration.IdentifierName}"; + + public string AccessorLocalReference + => $"{Parent.FieldIdentifier}.{PropertyIdentifier}"; + + public string AccessorExternalReference { set; get; } + public string PropertyIdentifier { set; get; } + + public string PropertyAsTypeName2 { set; get; } + public string UDTMemberIdentifier { set; get; } + + public virtual string UDTMemberDeclaration + => $"{Declaration.IdentifierName} {Tokens.As} {FieldAsTypeName}"; + + public IObjectStateUDT ObjectStateUDT { set; get; } + private static string BuildUniqueID(IEncapsulateFieldCandidate candidate) => $"{candidate.QualifiedModuleName.Name}.{candidate.IdentifierName}"; private static IEnumerable GetUDTMemberReferencesForField(IEncapsulateFieldCandidate udtMember, IUserDefinedTypeCandidate field) @@ -184,7 +216,7 @@ public bool EncapsulateFlag } } - get => _encapsulateFlag; //=> _wrappedCandidate.EncapsulateFlag; + get => _encapsulateFlag; } public bool IsExistingMember => _wrappedCandidate.Declaration.ParentDeclaration.DeclarationType is DeclarationType.UserDefinedType; @@ -194,6 +226,7 @@ public string FieldIdentifier set => _wrappedCandidate.FieldIdentifier = value; get => _wrappedCandidate.FieldIdentifier; } + public bool CanBeReadWrite { set => _wrappedCandidate.CanBeReadWrite = value; @@ -204,20 +237,15 @@ public bool CanBeReadWrite public QualifiedModuleName QualifiedModuleName => _wrappedCandidate.QualifiedModuleName; - public string PropertyName - { - set => _wrappedCandidate.PropertyName = value; - get => _wrappedCandidate.PropertyName; - } - public string AsTypeName_Field + public string FieldAsTypeName // AsTypeName_Field { - set => _wrappedCandidate.AsTypeName_Field = value; - get => _wrappedCandidate.AsTypeName_Field; + set => _wrappedCandidate.FieldAsTypeName = value; + get => _wrappedCandidate.FieldAsTypeName; } - public string AsTypeName_Property + public string PropertyAsTypeName { - set => _wrappedCandidate.AsTypeName_Property = value; - get => _wrappedCandidate.AsTypeName_Property; + set => _wrappedCandidate.PropertyAsTypeName = value; + get => _wrappedCandidate.PropertyAsTypeName; } public string ParameterName => _wrappedCandidate.ParameterName; @@ -232,9 +260,9 @@ public bool ConvertFieldToUDTMember get => false; } + public EncapsulateFieldStrategy EncapsulateFieldStrategy { set; get; } = EncapsulateFieldStrategy.UseBackingFields; + public IEnumerable PropertyAttributeSets => _wrappedCandidate.PropertyAttributeSets; - public string AsUDTMemberDeclaration - => _wrappedCandidate.AsUDTMemberDeclaration; public IEnumerable> ReferenceReplacements => _wrappedCandidate.ReferenceReplacements; diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs index fb4c875805..175b30a64f 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs @@ -472,7 +472,8 @@ Sub Bar(ByVal name As Integer) var presenterAction = Support.SetParametersForSingleTarget("fizz", "Name"); - var enapsulationIdentifiers = new EncapsulationIdentifiers("fizz", (string name) => true) { Property = "Name" }; + var validator = new EncapsulateFieldValidationsProvider().NameOnlyValidator(Validators.Default); + var enapsulationIdentifiers = new EncapsulationIdentifiers("fizz", validator/*(string name) => true*/) { Property = "Name" }; var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.AreEqualIgnoringCase(enapsulationIdentifiers.TargetFieldName, "fizz"); diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs index f1dadd5778..fcf97374f2 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs @@ -33,7 +33,8 @@ public void VBAIdentifier_Property(string originalFieldName, string newPropertyN var encapsulatedField = Support.RetrieveEncapsulateFieldCandidate(inputCode, originalFieldName); - encapsulatedField.PropertyName = newPropertyName; + //encapsulatedField.PropertyName = newPropertyName; + encapsulatedField.PropertyIdentifier = newPropertyName; encapsulatedField.EncapsulateFlag = true; Assert.AreEqual(expectedResult, encapsulatedField.TryValidateEncapsulationAttributes(out _)); } @@ -94,16 +95,15 @@ First As String Second As Long End Type -Public myBar As TBar +Private myBar As TBar Private Function First() As String First = myBar.First End Function"; - var candidate = Support.RetrieveEncapsulateFieldCandidate(inputCode, "First", DeclarationType.UserDefinedTypeMember); - var validation = candidate as IEncapsulateFieldCandidateValidations; - var result = validation.HasConflictingPropertyIdentifier; - Assert.AreEqual(true, validation.HasConflictingPropertyIdentifier); + var candidate = Support.RetrieveEncapsulateFieldCandidate(inputCode, "myBar", DeclarationType.Variable); + var result = candidate.ConflictFinder/*NamesValidator*/.IsConflictingProposedIdentifier("First", candidate, DeclarationType.Property); + Assert.AreEqual(true, result); } [Test] diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs index 50ae67c0fc..3a1fc85c3c 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs @@ -64,8 +64,9 @@ End Type Public th|is As TBar Public that As TBar"; - var expectedThis = new EncapsulationIdentifiers("this", (string name) => true); - var expectedThat = new EncapsulationIdentifiers("that", (string name) => true); + var validator = new EncapsulateFieldValidationsProvider().NameOnlyValidator(Validators.Default); + var expectedThis = new EncapsulationIdentifiers("this", validator); + var expectedThat = new EncapsulationIdentifiers("that", validator); var userInput = new UserInputDataObject() .AddUserInputSet(expectedThis.TargetFieldName, encapsulationFlag: encapsulateThis) diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs index 69bb49b116..5983f5861f 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs @@ -48,17 +48,26 @@ public void FieldNameValuesPerSequenceOfPropertyNameChanges() var encapsulatedField = Support.RetrieveEncapsulateFieldCandidate(inputCode, "fizz"); StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.FieldIdentifier); + //StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.FieldIdentifierOld); - encapsulatedField.PropertyName = "Test"; + //encapsulatedField.PropertyName = "Test"; + encapsulatedField.PropertyIdentifier = "Test"; + //StringAssert.AreEqualIgnoringCase("fizz", encapsulatedField.FieldIdentifierOld); StringAssert.AreEqualIgnoringCase("fizz", encapsulatedField.FieldIdentifier); - encapsulatedField.PropertyName = "Fizz"; + //encapsulatedField.PropertyName = "Fizz"; + encapsulatedField.PropertyIdentifier = "Fizz"; + //StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.FieldIdentifierOld); StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.FieldIdentifier); - encapsulatedField.PropertyName = "Fiz"; + //encapsulatedField.PropertyName = "Fiz"; + encapsulatedField.PropertyIdentifier = "Fiz"; + //StringAssert.AreEqualIgnoringCase("fizz", encapsulatedField.FieldIdentifierOld); StringAssert.AreEqualIgnoringCase("fizz", encapsulatedField.FieldIdentifier); - encapsulatedField.PropertyName = "Fizz"; + //encapsulatedField.PropertyName = "Fizz"; + encapsulatedField.PropertyIdentifier = "Fizz"; + //StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.FieldIdentifierOld); StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.FieldIdentifier); } @@ -71,10 +80,12 @@ public void PropertyNameChange_UniqueParamName() var encapsulatedField = Support.RetrieveEncapsulateFieldCandidate(inputCode, "value"); - encapsulatedField.PropertyName = "Test"; + //encapsulatedField.PropertyName = "Test"; + encapsulatedField.PropertyIdentifier = "Test"; StringAssert.AreEqualIgnoringCase("value_1", encapsulatedField.ParameterName); - encapsulatedField.PropertyName = "Value"; + //encapsulatedField.PropertyName = "Value"; + encapsulatedField.PropertyIdentifier = "Value"; StringAssert.AreEqualIgnoringCase("value_2", encapsulatedField.ParameterName); } @@ -85,7 +96,8 @@ public void PropertyNameChange_UniqueParamName() [Category("Encapsulate Field")] public void AccountsForHungarianNamesAndMemberPrefix(string inputName, string expectedPropertyName, string expectedFieldName) { - var sut = new EncapsulationIdentifiers(inputName, (string name) => true); + var validator = new EncapsulateFieldValidationsProvider().NameOnlyValidator(Validators.Default); + var sut = new EncapsulationIdentifiers(inputName, validator); Assert.AreEqual(expectedPropertyName, sut.DefaultPropertyName); Assert.AreEqual(expectedFieldName, sut.DefaultNewFieldName); diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index 101a883650..47e41ffedd 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -36,7 +36,10 @@ public Func UserAcceptsDefaults(bo { return model => { - model.ConvertFieldsToUDTMembers = convertFieldToUDTMember; + //model.ConvertFieldsToUDTMembers = convertFieldToUDTMember; + model.EncapsulateFieldStrategy = convertFieldToUDTMember + ? EncapsulateFieldStrategy.ConvertFieldsToUDTMembers + : EncapsulateFieldStrategy.UseBackingFields; return model; }; } @@ -64,7 +67,11 @@ public Func SetParameters(UserInpu { return model => { - model.ConvertFieldsToUDTMembers = userInput.ConvertFieldsToUDTMembers; + //model.ConvertFieldsToUDTMembers = userInput.ConvertFieldsToUDTMembers; + model.EncapsulateFieldStrategy = userInput.ConvertFieldsToUDTMembers + ? EncapsulateFieldStrategy.ConvertFieldsToUDTMembers + : EncapsulateFieldStrategy.UseBackingFields; + if (userInput.ConvertFieldsToUDTMembers) { var stateUDT = model.EncapsulationCandidates.Where(sfc => sfc is IUserDefinedTypeCandidate udt && udt.TargetID == userInput.ObjectStateUDTTargetID) @@ -81,7 +88,8 @@ public Func SetParameters(UserInpu { var attrsInitializedByTheRefactoring = model[testModifiedAttribute.TargetFieldName]; - attrsInitializedByTheRefactoring.PropertyName = testModifiedAttribute.PropertyName; + //attrsInitializedByTheRefactoring.PropertyName = testModifiedAttribute.PropertyName; + attrsInitializedByTheRefactoring.PropertyIdentifier = testModifiedAttribute.PropertyName; attrsInitializedByTheRefactoring.EncapsulateFlag = testModifiedAttribute.EncapsulateFlag; attrsInitializedByTheRefactoring.IsReadOnly = testModifiedAttribute.IsReadOnly; } @@ -94,11 +102,15 @@ public Func SetParameters(string o return model => { var encapsulatedField = model[originalField]; - encapsulatedField.PropertyName = attrs.PropertyName; + //encapsulatedField.PropertyName = attrs.PropertyName; + encapsulatedField.PropertyIdentifier = attrs.PropertyName; encapsulatedField.IsReadOnly = attrs.IsReadOnly; encapsulatedField.EncapsulateFlag = attrs.EncapsulateFlag; - model.ConvertFieldsToUDTMembers = convertFieldsToUDTMembers; + //model.ConvertFieldsToUDTMembers = convertFieldsToUDTMembers; + model.EncapsulateFieldStrategy = convertFieldsToUDTMembers + ? EncapsulateFieldStrategy.ConvertFieldsToUDTMembers + : EncapsulateFieldStrategy.UseBackingFields; return model; }; } @@ -135,7 +147,13 @@ public IEncapsulateFieldCandidate RetrieveEncapsulateFieldCandidate(IVBE vbe, st using (state) { var match = state.DeclarationFinder.MatchName(fieldName).Where(m => m.DeclarationType.Equals(declarationType)).Single(); - return new EncapsulateFieldCandidate(match, new EncapsulateFieldValidator(state)) as IEncapsulateFieldCandidate; + var factory = new EncapsulateFieldElementFactory(state, match.QualifiedModuleName); + //var validator = new EncapsulateFieldValidator(state, factory.Candidates); + foreach (var candidate in factory.Candidates) + { + candidate.NameValidator = factory.ValidatorProvider.NameOnlyValidator(Validators.Default); + } + return factory.Candidates.First(); } } @@ -178,7 +196,8 @@ public class TestEncapsulationAttributes { public TestEncapsulationAttributes(string fieldName, bool encapsulationFlag = true, bool isReadOnly = false) { - _identifiers = new EncapsulationIdentifiers(fieldName, (string name) => true); + var validator = new EncapsulateFieldValidationsProvider().NameOnlyValidator(Validators.Default); + _identifiers = new EncapsulationIdentifiers(fieldName, validator); EncapsulateFlag = encapsulationFlag; IsReadOnly = isReadOnly; } From 0ab3be8c24711053e9d3ce50c0adf019d753220d Mon Sep 17 00:00:00 2001 From: IvenBach Date: Mon, 6 Jan 2020 11:44:05 -0800 Subject: [PATCH 110/461] Replace "" with string.Empty --- Rubberduck.Parsing/Symbols/Declaration.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rubberduck.Parsing/Symbols/Declaration.cs b/Rubberduck.Parsing/Symbols/Declaration.cs index 0660e56110..f29c501192 100644 --- a/Rubberduck.Parsing/Symbols/Declaration.cs +++ b/Rubberduck.Parsing/Symbols/Declaration.cs @@ -478,7 +478,7 @@ public string AsTypeNameWithoutArrayDesignator { return AsTypeName; } - return AsTypeName.Replace("(", "").Replace(")", "").Trim(); + return AsTypeName.Replace("(", string.Empty).Replace(")", string.Empty).Trim(); } } From 658df55165875e3cd453fd93cac8517ddf67ff58 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Tue, 7 Jan 2020 00:00:05 +0100 Subject: [PATCH 111/461] Make ObsoleteMemberUsageInspection use the appropriate base class --- .../IdentifierReferenceInspectionBase.cs | 1 - .../Concrete/ObsoleteMemberUsageInspection.cs | 39 +++++++++---------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs index 24362fa2b5..c0f4f88277 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs index 409048ff5e..3343037c3d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs @@ -48,34 +48,31 @@ namespace Rubberduck.Inspections.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ObsoleteMemberUsageInspection : InspectionBase + public sealed class ObsoleteMemberUsageInspection : IdentifierReferenceInspectionBase { public ObsoleteMemberUsageInspection(RubberduckParserState state) : base(state) { } - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultReference(IdentifierReference reference) { - var declarations = State.AllUserDeclarations - .Where(declaration => declaration.DeclarationType.HasFlag(DeclarationType.Member) && - declaration.Annotations.Any(pta => pta.Annotation is ObsoleteAnnotation)); - - var issues = new List(); - - foreach (var declaration in declarations) - { - var replacementDocumentation = declaration.Annotations - .First(pta => pta.Annotation is ObsoleteAnnotation) - .AnnotationArguments - .FirstOrDefault() ?? string.Empty; - - issues.AddRange(declaration.References.Select(reference => - new IdentifierReferenceInspectionResult(this, - string.Format(InspectionResults.ObsoleteMemberUsageInspection, reference.IdentifierName, replacementDocumentation), - State, reference))); - } + var declaration = reference?.Declaration; + return declaration != null + && declaration.IsUserDefined + && declaration.DeclarationType.HasFlag(DeclarationType.Member) + && declaration.Annotations.Any(pta => pta.Annotation is ObsoleteAnnotation); + } - return issues; + protected override string ResultDescription(IdentifierReference reference) + { + var replacementDocumentation = reference.Declaration.Annotations + .First(pta => pta.Annotation is ObsoleteAnnotation) + .AnnotationArguments + .FirstOrDefault() ?? string.Empty; + return string.Format( + InspectionResults.ObsoleteMemberUsageInspection, + reference.IdentifierName, + replacementDocumentation); } } } From 68c425add719862eeb705a6af1b818d75baa4930 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Tue, 7 Jan 2020 00:00:53 +0100 Subject: [PATCH 112/461] Introduce IdentifierReferenceInspectionFromDeclarationsBase Also moves two inspections to this base class. --- ...ReferenceInspectionFromDeclarationsBase.cs | 63 +++++++++++++++++++ .../ApplicationWorksheetFunctionInspection.cs | 47 ++++++++------ .../ImplicitActiveSheetReferenceInspection.cs | 63 +++++++++++-------- ...icitActiveSheetReferenceInspectionTests.cs | 42 +++++++++++++ 4 files changed, 169 insertions(+), 46 deletions(-) create mode 100644 Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs new file mode 100644 index 0000000000..abb6b627f0 --- /dev/null +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs @@ -0,0 +1,63 @@ +using System.Collections.Generic; +using System.Linq; +using Rubberduck.Inspections.Results; +using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.VBEditor; + +namespace Rubberduck.Inspections.Abstract +{ + public abstract class IdentifierReferenceInspectionFromDeclarationsBase : InspectionBase + { + protected readonly IDeclarationFinderProvider DeclarationFinderProvider; + + protected IdentifierReferenceInspectionFromDeclarationsBase(RubberduckParserState state) + : base(state) + { + DeclarationFinderProvider = state; + } + + protected abstract IEnumerable ObjectionableDeclarations(DeclarationFinder finder); + protected abstract string ResultDescription(IdentifierReference reference); + + protected override IEnumerable DoGetInspectionResults() + { + var finder = DeclarationFinderProvider.DeclarationFinder; + var objectionableReferences = ObjectionableReferences(finder); + return objectionableReferences + .Select(reference => InspectionResult(reference, DeclarationFinderProvider)) + .ToList(); + } + + private IEnumerable ObjectionableReferences(DeclarationFinder finder) + { + var objectionableDeclarations = ObjectionableDeclarations(finder); + return objectionableDeclarations + .SelectMany(declaration => declaration.References) + .Where(IsResultReference); + } + + protected virtual bool IsResultReference(IdentifierReference reference) => true; + + protected IEnumerable DoGetInspectionResults(QualifiedModuleName module) + { + var finder = DeclarationFinderProvider.DeclarationFinder; + var objectionableReferences = ObjectionableReferences(finder); + return objectionableReferences + .Where(reference => reference.QualifiedModuleName.Equals(module)) + .Select(reference => InspectionResult(reference, DeclarationFinderProvider)) + .ToList(); + } + + protected virtual IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider) + { + return new IdentifierReferenceInspectionResult( + this, + ResultDescription(reference), + declarationFinderProvider, + reference); + } + } +} \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs index df4e61cbf0..b8bea5cb81 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs @@ -9,6 +9,8 @@ using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor; using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.JunkDrawer.Extensions; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -54,34 +56,41 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [RequiredLibrary("Excel")] - public class ApplicationWorksheetFunctionInspection : InspectionBase + public class ApplicationWorksheetFunctionInspection : IdentifierReferenceInspectionFromDeclarationsBase { public ApplicationWorksheetFunctionInspection(RubberduckParserState state) : base(state) { } - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable ObjectionableDeclarations(DeclarationFinder finder) { var excel = State.DeclarationFinder.Projects.SingleOrDefault(item => !item.IsUserDefined && item.IdentifierName == "Excel"); - if (excel == null) { return Enumerable.Empty(); } + if (excel == null) + { + return Enumerable.Empty(); + } - var members = new HashSet(BuiltInDeclarations.Where(decl => decl.DeclarationType == DeclarationType.Function && - decl.ParentDeclaration != null && - decl.ParentDeclaration.ComponentName.Equals("WorksheetFunction")) - .Select(decl => decl.IdentifierName)); + if (!(State.DeclarationFinder.FindClassModule("WorksheetFunction", excel, true) is ModuleDeclaration worksheetFunctionsModule)) + { + return Enumerable.Empty(); + } - var usages = BuiltInDeclarations.Where(decl => decl.References.Any() && - decl.ProjectName.Equals("Excel") && - decl.ComponentName.Equals("Application") && - members.Contains(decl.IdentifierName)); + if (!(State.DeclarationFinder.FindClassModule("Application", excel, true) is ModuleDeclaration excelApplicationClass)) + { + return Enumerable.Empty(); + } - return from usage in usages - // filtering on references isn't the default ignore filtering - from reference in usage.References.Where(use => !use.IsIgnoringInspectionResultFor(AnnotationName)) - let qualifiedSelection = new QualifiedSelection(reference.QualifiedModuleName, reference.Selection) - select new IdentifierReferenceInspectionResult(this, - string.Format(InspectionResults.ApplicationWorksheetFunctionInspection, usage.IdentifierName), - State, - reference); + var worksheetFunctionNames = worksheetFunctionsModule.Members + .Where(decl => decl.DeclarationType == DeclarationType.Function) + .Select(decl => decl.IdentifierName) + .ToHashSet(); + + return excelApplicationClass.Members + .Where(decl => worksheetFunctionNames.Contains(decl.IdentifierName)); + } + + protected override string ResultDescription(IdentifierReference reference) + { + return string.Format(InspectionResults.ApplicationWorksheetFunctionInspection, reference.IdentifierName); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs index 175ca874af..7018921528 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs @@ -1,12 +1,11 @@ using System.Collections.Generic; using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Inspections; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Parsing.Symbols; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -39,38 +38,48 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [RequiredLibrary("Excel")] - public sealed class ImplicitActiveSheetReferenceInspection : InspectionBase + public sealed class ImplicitActiveSheetReferenceInspection : IdentifierReferenceInspectionFromDeclarationsBase { public ImplicitActiveSheetReferenceInspection(RubberduckParserState state) - : base(state) { } + : base(state) + {} - private static readonly string[] Targets = + protected override IEnumerable ObjectionableDeclarations(DeclarationFinder finder) { - "Cells", "Range", "Columns", "Rows" - }; + var excel = finder.Projects + .SingleOrDefault(item => !item.IsUserDefined + && item.IdentifierName == "Excel"); + if (excel == null) + { + return Enumerable.Empty(); + } - protected override IEnumerable DoGetInspectionResults() - { - var excel = State.DeclarationFinder.Projects.SingleOrDefault(item => !item.IsUserDefined && item.IdentifierName == "Excel"); - if (excel == null) { return Enumerable.Empty(); } + var globalModules = GlobalObjectClassNames + .Select(className => finder.FindClassModule(className, excel, true)) + .OfType(); - var globalModules = new[] - { - State.DeclarationFinder.FindClassModule("Global", excel, true), - State.DeclarationFinder.FindClassModule("_Global", excel, true) - }; + return globalModules + .SelectMany(moduleClass => moduleClass.Members) + .Where(declaration => TargetMemberNames.Contains(declaration.IdentifierName) + && declaration.DeclarationType.HasFlag(DeclarationType.Member) + && declaration.AsTypeName == "Range"); + } - var members = Targets - .SelectMany(target => globalModules.SelectMany(global => - State.DeclarationFinder.FindMemberMatches(global, target)) - .Where(member => member.AsTypeName == "Range" && member.References.Any())); + private static readonly string[] GlobalObjectClassNames = + { + "Global", "_Global" + }; + + private static readonly string[] TargetMemberNames = + { + "Cells", "Range", "Columns", "Rows" + }; - return members - .SelectMany(declaration => declaration.References) - .Select(issue => new IdentifierReferenceInspectionResult(this, - string.Format(InspectionResults.ImplicitActiveSheetReferenceInspection, issue.Declaration.IdentifierName), - State, - issue)); + protected override string ResultDescription(IdentifierReference reference) + { + return string.Format( + InspectionResults.ImplicitActiveSheetReferenceInspection, + reference.Declaration.IdentifierName); } } } diff --git a/RubberduckTests/Inspections/ImplicitActiveSheetReferenceInspectionTests.cs b/RubberduckTests/Inspections/ImplicitActiveSheetReferenceInspectionTests.cs index bab1a5a48a..04d5d5ccf5 100644 --- a/RubberduckTests/Inspections/ImplicitActiveSheetReferenceInspectionTests.cs +++ b/RubberduckTests/Inspections/ImplicitActiveSheetReferenceInspectionTests.cs @@ -24,6 +24,48 @@ End Sub Assert.AreEqual(1, InspectionResultsForModules(modules, "Excel").Count()); } + [Test] + [Category("Inspections")] + public void ImplicitActiveSheetReference_ReportsCells() + { + const string inputCode = + @"Sub foo() + Dim arr1() As Variant + arr1 = Cells(1,2) +End Sub +"; + var modules = new (string, string, ComponentType)[] { ("Class1", inputCode, ComponentType.ClassModule) }; + Assert.AreEqual(1, InspectionResultsForModules(modules, "Excel").Count()); + } + + [Test] + [Category("Inspections")] + public void ImplicitActiveSheetReference_ReportsColumns() + { + const string inputCode = + @"Sub foo() + Dim arr1() As Variant + arr1 = Columns(3) +End Sub +"; + var modules = new (string, string, ComponentType)[] { ("Class1", inputCode, ComponentType.ClassModule) }; + Assert.AreEqual(1, InspectionResultsForModules(modules, "Excel").Count()); + } + + [Test] + [Category("Inspections")] + public void ImplicitActiveSheetReference_ReportsRows() + { + const string inputCode = + @"Sub foo() + Dim arr1() As Variant + arr1 = Rows(3) +End Sub +"; + var modules = new (string, string, ComponentType)[] { ("Class1", inputCode, ComponentType.ClassModule) }; + Assert.AreEqual(1, InspectionResultsForModules(modules, "Excel").Count()); + } + [Test] [Category("Inspections")] public void ImplicitActiveSheetReference_Ignored_DoesNotReportRange() From 38cdac3e326ce7b65376abb0bb24ba8836026545 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Tue, 7 Jan 2020 00:54:40 +0100 Subject: [PATCH 113/461] Get DeclarationFinder only once in IdentifierReferenceInspectionBase Also improves a bunch of inspections. --- .../IdentifierReferenceInspectionBase.cs | 19 ++++-- .../DefaultMemberRequiredInspection.cs | 5 +- ...citUnboundDefaultMemberAccessInspection.cs | 5 +- ...xedUnboundDefaultMemberAccessInspection.cs | 5 +- .../ObjectVariableNotSetInspection.cs | 66 +++++++++++++------ ...bjectWhereProcedureIsRequiredInspection.cs | 1 - .../Concrete/ProcedureRequiredInspection.cs | 5 +- .../UnassignedVariableUsageInspection.cs | 1 - .../UseOfUnboundBangNotationInspection.cs | 5 +- .../Concrete/ValueRequiredInspection.cs | 5 +- 10 files changed, 77 insertions(+), 40 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs index c0f4f88277..92f97d5b1d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs @@ -4,6 +4,7 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Abstract @@ -23,6 +24,8 @@ public IdentifierReferenceInspectionBase(RubberduckParserState state) protected override IEnumerable DoGetInspectionResults() { + var finder = DeclarationFinderProvider.DeclarationFinder; + var results = new List(); foreach (var moduleDeclaration in State.DeclarationFinder.UserDeclarations(DeclarationType.Module)) { @@ -32,15 +35,15 @@ protected override IEnumerable DoGetInspectionResults() } var module = moduleDeclaration.QualifiedModuleName; - results.AddRange(DoGetInspectionResults(module)); + results.AddRange(DoGetInspectionResults(module, finder)); } return results; } - private IEnumerable DoGetInspectionResults(QualifiedModuleName module) + protected IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { - var objectionableReferences = ReferencesInModule(module) + var objectionableReferences = ReferencesInModule(module, finder) .Where(IsResultReference); return objectionableReferences @@ -48,9 +51,15 @@ private IEnumerable DoGetInspectionResults(QualifiedModuleNam .ToList(); } - protected virtual IEnumerable ReferencesInModule(QualifiedModuleName module) + protected IEnumerable DoGetInspectionResults(QualifiedModuleName module) + { + var finder = DeclarationFinderProvider.DeclarationFinder; + return DoGetInspectionResults(module, finder); + } + + protected virtual IEnumerable ReferencesInModule(QualifiedModuleName module, DeclarationFinder finder) { - return DeclarationFinderProvider.DeclarationFinder.IdentifierReferences(module); + return finder.IdentifierReferences(module); } protected virtual IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs index 1a60847ceb..d6e72f9871 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs @@ -4,6 +4,7 @@ using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; using Rubberduck.VBEditor; @@ -62,9 +63,9 @@ public DefaultMemberRequiredInspection(RubberduckParserState state) Severity = CodeInspectionSeverity.Error; } - protected override IEnumerable ReferencesInModule(QualifiedModuleName module) + protected override IEnumerable ReferencesInModule(QualifiedModuleName module, DeclarationFinder finder) { - return DeclarationFinderProvider.DeclarationFinder.FailedIndexedDefaultMemberAccesses(module); + return finder.FailedIndexedDefaultMemberAccesses(module); } protected override bool IsResultReference(IdentifierReference failedIndexedDefaultMemberAccess) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs index 14e52a2f1a..57128a2356 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs @@ -5,6 +5,7 @@ using Rubberduck.Parsing.VBA; using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.Inspections; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete @@ -57,9 +58,9 @@ public ImplicitUnboundDefaultMemberAccessInspection(RubberduckParserState state) Severity = CodeInspectionSeverity.Warning; } - protected override IEnumerable ReferencesInModule(QualifiedModuleName module) + protected override IEnumerable ReferencesInModule(QualifiedModuleName module, DeclarationFinder finder) { - return DeclarationFinderProvider.DeclarationFinder.UnboundDefaultMemberAccesses(module); + return finder.UnboundDefaultMemberAccesses(module); } protected override bool IsResultReference(IdentifierReference reference) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs index 7ceec494c5..73a811830f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs @@ -6,6 +6,7 @@ using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete @@ -41,9 +42,9 @@ public IndexedUnboundDefaultMemberAccessInspection(RubberduckParserState state) Severity = CodeInspectionSeverity.Warning; } - protected override IEnumerable ReferencesInModule(QualifiedModuleName module) + protected override IEnumerable ReferencesInModule(QualifiedModuleName module, DeclarationFinder finder) { - return DeclarationFinderProvider.DeclarationFinder.UnboundDefaultMemberAccesses(module); + return finder.UnboundDefaultMemberAccesses(module); } protected override bool IsResultReference(IdentifierReference reference) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs index 3d4f21e7c5..8ef0cd83eb 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs @@ -8,7 +8,6 @@ using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.VBA.DeclarationCaching; @@ -43,27 +42,19 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ObjectVariableNotSetInspection : InspectionBase { - public ObjectVariableNotSetInspection(RubberduckParserState state) - : base(state) { } + private IDeclarationFinderProvider _declarationFinderProvider; - protected override IEnumerable DoGetInspectionResults() + public ObjectVariableNotSetInspection(RubberduckParserState state) + : base(state) { - var finder = State.DeclarationFinder; - - var failedLetResolutionResults = FailedLetResolutionResults(finder); - - return failedLetResolutionResults - .Select(reference => - new IdentifierReferenceInspectionResult( - this, - string.Format(InspectionResults.ObjectVariableNotSetInspection, reference.IdentifierName), - State, - reference)); + _declarationFinderProvider = state; } - private IEnumerable FailedLetResolutionResults(DeclarationFinder finder) + protected override IEnumerable DoGetInspectionResults() { - var results = new List(); + var finder = _declarationFinderProvider.DeclarationFinder; + + var results = new List(); foreach (var moduleDeclaration in finder.UserDeclarations(DeclarationType.Module)) { if (moduleDeclaration == null) @@ -72,15 +63,34 @@ private IEnumerable FailedLetResolutionResults(DeclarationF } var module = moduleDeclaration.QualifiedModuleName; - var failedLetCoercionAssignmentsInModule = FailedLetResolutionAssignments(module, finder); - var possiblyObjectLhsLetAssignmentsWithFailedLetResolutionOnRhs = PossiblyObjectLhsLetAssignmentsWithNonValueOnRhs(module, finder); - results.AddRange(failedLetCoercionAssignmentsInModule); - results.AddRange(possiblyObjectLhsLetAssignmentsWithFailedLetResolutionOnRhs); + results.AddRange(DoGetInspectionResults(module, finder)); } return results; } + private IEnumerable DoGetInspectionResults(QualifiedModuleName module) + { + var finder = _declarationFinderProvider.DeclarationFinder; + return DoGetInspectionResults(module, finder); + } + + private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + { + var failedailedLetResolutionResultReferences = FailedLetResolutionResultReferences(module, finder); + + return failedailedLetResolutionResultReferences + .Select(reference => InspectionResult(reference, _declarationFinderProvider)); + } + + private IEnumerable FailedLetResolutionResultReferences(QualifiedModuleName module, DeclarationFinder finder) + { + var failedLetCoercionAssignmentsInModule = FailedLetResolutionAssignments(module, finder); + var possiblyObjectLhsLetAssignmentsWithFailedLetResolutionOnRhs = PossiblyObjectLhsLetAssignmentsWithNonValueOnRhs(module, finder); + return failedLetCoercionAssignmentsInModule + .Concat(possiblyObjectLhsLetAssignmentsWithFailedLetResolutionOnRhs); + } + private static IEnumerable FailedLetResolutionAssignments(QualifiedModuleName module, DeclarationFinder finder) { return finder.FailedLetCoercions(module) @@ -121,5 +131,19 @@ private static IEnumerable PossiblyObjectNonSetAssignments( return assignments.Concat(unboundAssignments); } + + private IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider) + { + return new IdentifierReferenceInspectionResult( + this, + ResultDescription(reference), + declarationFinderProvider, + reference); + } + + private static string ResultDescription(IdentifierReference reference) + { + return string.Format(InspectionResults.ObjectVariableNotSetInspection, reference.IdentifierName); + } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs index 9fa2fc649a..f39bd4d386 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Inspections.Abstract; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs index bd1257a78b..4f14f1edd2 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs @@ -4,6 +4,7 @@ using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; using Rubberduck.VBEditor; @@ -60,9 +61,9 @@ public ProcedureRequiredInspection(RubberduckParserState state) Severity = CodeInspectionSeverity.Error; } - protected override IEnumerable ReferencesInModule(QualifiedModuleName module) + protected override IEnumerable ReferencesInModule(QualifiedModuleName module, DeclarationFinder finder) { - return DeclarationFinderProvider.DeclarationFinder.FailedProcedureCoercions(module); + return finder.FailedProcedureCoercions(module); } protected override bool IsResultReference(IdentifierReference failedCoercion) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs index 903fbfd113..40537dc5c5 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs @@ -10,7 +10,6 @@ using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; namespace Rubberduck.Inspections.Concrete { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs index 0b0c192a5f..1685b507cd 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs @@ -6,6 +6,7 @@ using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete @@ -64,9 +65,9 @@ public UseOfUnboundBangNotationInspection(RubberduckParserState state) Severity = CodeInspectionSeverity.Warning; } - protected override IEnumerable ReferencesInModule(QualifiedModuleName module) + protected override IEnumerable ReferencesInModule(QualifiedModuleName module, DeclarationFinder finder) { - return DeclarationFinderProvider.DeclarationFinder.UnboundDefaultMemberAccesses(module); + return finder.UnboundDefaultMemberAccesses(module); } protected override bool IsResultReference(IdentifierReference reference) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs index 2a2cacaadb..b5730c4541 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs @@ -4,6 +4,7 @@ using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; using Rubberduck.VBEditor; @@ -64,9 +65,9 @@ public ValueRequiredInspection(RubberduckParserState state) Severity = CodeInspectionSeverity.Error; } - protected override IEnumerable ReferencesInModule(QualifiedModuleName module) + protected override IEnumerable ReferencesInModule(QualifiedModuleName module, DeclarationFinder finder) { - return DeclarationFinderProvider.DeclarationFinder.FailedLetCoercions(module); + return finder.FailedLetCoercions(module); } protected override bool IsResultReference(IdentifierReference failedLetCoercion) From a08e65b0a083f8c95cb8202b28a084a1ec7aa2ee Mon Sep 17 00:00:00 2001 From: IvenBach Date: Mon, 6 Jan 2020 14:57:27 -0800 Subject: [PATCH 114/461] Prevent rewrites adding continous extra linefeeds Previously when a rewriter would perform its rewrite, an extra linefeed was added. This comes about because when the last line in a module is replaced in the VBA IDE an extra linefeed is added. --- Rubberduck.Parsing/Rewriter/ModuleRewriter.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Rubberduck.Parsing/Rewriter/ModuleRewriter.cs b/Rubberduck.Parsing/Rewriter/ModuleRewriter.cs index 753e801cf2..6863db9c75 100644 --- a/Rubberduck.Parsing/Rewriter/ModuleRewriter.cs +++ b/Rubberduck.Parsing/Rewriter/ModuleRewriter.cs @@ -33,7 +33,14 @@ public void Rewrite() return; } - var newCode = _rewriter.GetText(); + var tentativeCode = _rewriter.GetText(); + + while (tentativeCode.EndsWith(Environment.NewLine)) + { + tentativeCode = tentativeCode.Remove(tentativeCode.Length - 2); + }; + var newCode = tentativeCode; + _sourceCodeHandler.SubstituteCode(_module, newCode); } From 9584c579e5ef6b22051ece33b5be17002f7a2479 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Tue, 7 Jan 2020 02:07:25 +0100 Subject: [PATCH 115/461] Make ObsoleteTypeHintInspection more structured --- .../Concrete/ObsoleteTypeHintInspection.cs | 115 ++++++++++++++---- 1 file changed, 93 insertions(+), 22 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs index 608cdc797c..6b1100e654 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs @@ -3,8 +3,11 @@ using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Parsing.Symbols; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete { @@ -32,32 +35,100 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ObsoleteTypeHintInspection : InspectionBase { + private readonly IDeclarationFinderProvider _declarationFinderProvider; + public ObsoleteTypeHintInspection(RubberduckParserState state) - : base(state) { } + : base(state) + { + _declarationFinderProvider = state; + } protected override IEnumerable DoGetInspectionResults() { - var results = UserDeclarations.ToList(); - - var declarations = from item in results - where item.HasTypeHint - select - new DeclarationInspectionResult(this, - string.Format(InspectionResults.ObsoleteTypeHintInspection, - InspectionsUI.Inspections_Declaration, item.DeclarationType.ToString().ToLower(), - item.IdentifierName), item); - - var references = from item in results.SelectMany(d => d.References) - where item.HasTypeHint() - select - new IdentifierReferenceInspectionResult(this, - string.Format(InspectionResults.ObsoleteTypeHintInspection, - InspectionsUI.Inspections_Usage, item.Declaration.DeclarationType.ToString().ToLower(), - item.IdentifierName), - State, - item); - - return declarations.Union(references); + var finder = _declarationFinderProvider.DeclarationFinder; + + var results = new List(); + foreach (var moduleDeclaration in State.DeclarationFinder.UserDeclarations(DeclarationType.Module)) + { + if (moduleDeclaration == null) + { + continue; + } + + var module = moduleDeclaration.QualifiedModuleName; + results.AddRange(DoGetInspectionResults(module, finder)); + } + + return results; + } + + private IEnumerable DoGetInspectionResults(QualifiedModuleName module) + { + var finder = _declarationFinderProvider.DeclarationFinder; + return DoGetInspectionResults(module, finder); + } + + private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + { + var declarationResults = DeclarationResults(module, finder); + var referenceResults = ReferenceResults(module, finder); + return declarationResults + .Concat(referenceResults); + } + + private IEnumerable DeclarationResults(QualifiedModuleName module, DeclarationFinder finder) + { + var objectionableDeclarations = finder.Members(module) + .Where(declaration => declaration.HasTypeHint); + return objectionableDeclarations.Select(InspectionResult); + } + + private IInspectionResult InspectionResult(Declaration declaration) + { + return new DeclarationInspectionResult( + this, + ResultDescription(declaration), + declaration); + } + + private string ResultDescription(Declaration declaration) + { + var declarationTypeName = declaration.DeclarationType.ToString().ToLower(); + var identifierName = declaration.IdentifierName; + return string.Format( + InspectionResults.ObsoleteTypeHintInspection, + InspectionsUI.Inspections_Declaration, + declarationTypeName, + identifierName); + } + + private IEnumerable ReferenceResults(QualifiedModuleName module, DeclarationFinder finder) + { + var objectionableReferences = finder.IdentifierReferences(module) + .Where(reference => reference?.Declaration != null + && reference.Declaration.IsUserDefined + && reference.HasTypeHint()); + return objectionableReferences + .Select(reference => InspectionResult(reference, _declarationFinderProvider)); + } + + private IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider) + { + return new IdentifierReferenceInspectionResult( + this, + ResultDescription(reference), + declarationFinderProvider, + reference); + } + + private string ResultDescription(IdentifierReference reference) + { + var declarationTypeName = reference.Declaration.DeclarationType.ToString().ToLower(); + var identifierName = reference.IdentifierName; + return string.Format(InspectionResults.ObsoleteTypeHintInspection, + InspectionsUI.Inspections_Usage, + declarationTypeName, + identifierName); } } } From 1cee0fdcbf748d88f443c031d112c7ee97e8365a Mon Sep 17 00:00:00 2001 From: IvenBach Date: Tue, 7 Jan 2020 10:19:12 -0800 Subject: [PATCH 116/461] Opportunistic updates Make boolean usage more apparent. Correct typo. Simplify member access. Simplify string initialization. --- .../UI/Command/ComCommands/ExportAllCommand.cs | 8 +++----- .../SafeComWrappers/VB/Abstract/IVBComponent.cs | 2 +- Rubberduck.VBEditor.VB6/SafeComWrappers/VB/VBComponent.cs | 6 +++--- Rubberduck.VBEditor.VBA/SafeComWrappers/VB/VBComponent.cs | 8 ++++---- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/Rubberduck.Core/UI/Command/ComCommands/ExportAllCommand.cs b/Rubberduck.Core/UI/Command/ComCommands/ExportAllCommand.cs index 21c777cc98..cc1cfe6174 100644 --- a/Rubberduck.Core/UI/Command/ComCommands/ExportAllCommand.cs +++ b/Rubberduck.Core/UI/Command/ComCommands/ExportAllCommand.cs @@ -92,11 +92,9 @@ private void Export(IVBProject project) // If .GetDirectoryName is passed an empty string for a RootFolder, // it defaults to the Documents library (Win 7+) or equivalent. - var path = string.Empty; - if (!string.IsNullOrWhiteSpace(project.FileName)) - { - path = Path.GetDirectoryName(project.FileName); - } + var path = string.IsNullOrWhiteSpace(project.FileName) + ? string.Empty + : Path.GetDirectoryName(project.FileName); using (var _folderBrowser = _factory.CreateFolderBrowser(desc, true, path)) { diff --git a/Rubberduck.VBEEditor/SafeComWrappers/VB/Abstract/IVBComponent.cs b/Rubberduck.VBEEditor/SafeComWrappers/VB/Abstract/IVBComponent.cs index 117eecc132..24bbe3c384 100644 --- a/Rubberduck.VBEEditor/SafeComWrappers/VB/Abstract/IVBComponent.cs +++ b/Rubberduck.VBEEditor/SafeComWrappers/VB/Abstract/IVBComponent.cs @@ -20,7 +20,7 @@ public interface IVBComponent : ISafeComWrapper, IEquatable IWindow DesignerWindow(); void Activate(); void Export(string path); - string ExportAsSourceFile(string folder, bool tempFile = false, bool specialCaseDocumentModules = true); + string ExportAsSourceFile(string folder, bool isTempFile = false, bool specialCaseDocumentModules = true); int FileCount { get; } string GetFileName(short index); IVBProject ParentProject { get; } diff --git a/Rubberduck.VBEditor.VB6/SafeComWrappers/VB/VBComponent.cs b/Rubberduck.VBEditor.VB6/SafeComWrappers/VB/VBComponent.cs index a52bdf7c1c..b38bdd9da9 100644 --- a/Rubberduck.VBEditor.VB6/SafeComWrappers/VB/VBComponent.cs +++ b/Rubberduck.VBEditor.VB6/SafeComWrappers/VB/VBComponent.cs @@ -123,9 +123,9 @@ public bool HasDesigner /// Exports the component to the folder. The file name matches the component name and file extension is based on the component's type. /// /// Destination folder for the resulting source file. - /// True if a unique temp file name should be generated. WARNING: filenames generated with this flag are not persisted. - /// If reimpot of a document file is required later, it has to receive special treatment. - public string ExportAsSourceFile(string folder, bool tempFile = false, bool specialCaseDocumentModules = true) + /// True if a unique temp file name should be generated. WARNING: filenames generated with this flag are not persisted. + /// If reimport of a document file is required later, it has to receive special treatment. + public string ExportAsSourceFile(string folder, bool isTempFile = false, bool specialCaseDocumentModules = true) { throw new NotSupportedException("Export as source file is not supported in VB6"); } diff --git a/Rubberduck.VBEditor.VBA/SafeComWrappers/VB/VBComponent.cs b/Rubberduck.VBEditor.VBA/SafeComWrappers/VB/VBComponent.cs index 8d6e12b501..b25ea13678 100644 --- a/Rubberduck.VBEditor.VBA/SafeComWrappers/VB/VBComponent.cs +++ b/Rubberduck.VBEditor.VBA/SafeComWrappers/VB/VBComponent.cs @@ -95,14 +95,14 @@ public bool HasDesigner /// Exports the component to the folder. The file name matches the component name and file extension is based on the component's type. /// /// Destination folder for the resulting source file. - /// True if a unique temp file name should be generated. WARNING: filenames generated with this flag are not persisted. + /// True if a unique temp file name should be generated. WARNING: filenames generated with this flag are not persisted. /// If reimport of a document file is required later, it has to receive special treatment. - public string ExportAsSourceFile(string folder, bool tempFile = false, bool specialCaseDocumentModules = true) + public string ExportAsSourceFile(string folder, bool isTempFile = false, bool specialCaseDocumentModules = true) { //TODO: this entire thign needs to be reworked. IO is not the class' concern. //We probably need to leverage IPersistancePathProvider? ITempSourceFileHandler? //Just not here. - var fullPath = tempFile + var fullPath = isTempFile ? Path.Combine(folder, Path.GetRandomFileName()) : Path.Combine(folder, SafeName + Type.FileExtension()); @@ -160,7 +160,7 @@ private void ExportUserFormModule(string path) var tempFile = ExportToTempFile(); var tempFilePath = Directory.GetParent(tempFile).FullName; - var fileEncoding = System.Text.Encoding.Default; //We use the current ANSI codepage because that is what the VBE does. + var fileEncoding = Encoding.Default; //We use the current ANSI codepage because that is what the VBE does. var contents = File.ReadAllLines(tempFile, fileEncoding); var nonAttributeLines = contents.TakeWhile(line => !line.StartsWith("Attribute")).Count(); var attributeLines = contents.Skip(nonAttributeLines).TakeWhile(line => line.StartsWith("Attribute")).Count(); From b6efda0ceabce023879a79566f33620a621347fc Mon Sep 17 00:00:00 2001 From: IvenBach Date: Tue, 7 Jan 2020 11:16:59 -0800 Subject: [PATCH 117/461] Export document modules without attributes --- .../UI/CodeExplorer/Commands/ExportCommand.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Rubberduck.Core/UI/CodeExplorer/Commands/ExportCommand.cs b/Rubberduck.Core/UI/CodeExplorer/Commands/ExportCommand.cs index 872cba767e..0d41a2db60 100644 --- a/Rubberduck.Core/UI/CodeExplorer/Commands/ExportCommand.cs +++ b/Rubberduck.Core/UI/CodeExplorer/Commands/ExportCommand.cs @@ -100,7 +100,15 @@ public bool PromptFileNameAndExport(QualifiedModuleName qualifiedModule) var component = ProjectsProvider.Component(qualifiedModule); try { - component.Export(dialog.FileName); + if (component.Type == ComponentType.Document) + { + var path = System.IO.Path.GetDirectoryName(dialog.FileName); + component.ExportAsSourceFile(path); + } + else + { + component.Export(dialog.FileName); + } } catch (Exception ex) { From 2ecbc423a7b7f9f4f63ce4e7795509a19743c3cb Mon Sep 17 00:00:00 2001 From: Michael Barros Date: Tue, 7 Jan 2020 15:04:28 -0500 Subject: [PATCH 118/461] Updated Sdk for VS 2019 compatibility. Fixes #4872 --- Rubberduck.CodeAnalysis/Rubberduck.CodeAnalysis.csproj | 2 +- Rubberduck.Core/Rubberduck.Core.csproj | 2 +- Rubberduck.Deployment.Build/Rubberduck.Deployment.Build.csproj | 2 +- Rubberduck.Deployment/Rubberduck.Deployment.csproj | 2 +- Rubberduck.Interaction/Rubberduck.Interaction.csproj | 2 +- Rubberduck.JunkDrawer/Rubberduck.JunkDrawer.csproj | 2 +- Rubberduck.Main/Rubberduck.Main.csproj | 2 +- Rubberduck.Parsing/Rubberduck.Parsing.csproj | 2 +- Rubberduck.Refactorings/Rubberduck.Refactorings.csproj | 2 +- RubberduckBaseMetaProject.csproj | 2 +- RubberduckBaseProject.csproj | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Rubberduck.CodeAnalysis.csproj b/Rubberduck.CodeAnalysis/Rubberduck.CodeAnalysis.csproj index a9214672a2..0ed59ed71c 100644 --- a/Rubberduck.CodeAnalysis/Rubberduck.CodeAnalysis.csproj +++ b/Rubberduck.CodeAnalysis/Rubberduck.CodeAnalysis.csproj @@ -1,5 +1,5 @@  - + Rubberduck.CodeAnalysis Assembly Containing the Code Analysis features exposed by Rubberduck diff --git a/Rubberduck.Core/Rubberduck.Core.csproj b/Rubberduck.Core/Rubberduck.Core.csproj index 0175b7fe45..cd75dcc28a 100644 --- a/Rubberduck.Core/Rubberduck.Core.csproj +++ b/Rubberduck.Core/Rubberduck.Core.csproj @@ -1,5 +1,5 @@  - + Rubberduck Rubberduck.Core diff --git a/Rubberduck.Deployment.Build/Rubberduck.Deployment.Build.csproj b/Rubberduck.Deployment.Build/Rubberduck.Deployment.Build.csproj index 09eaa985da..91ded8cca5 100644 --- a/Rubberduck.Deployment.Build/Rubberduck.Deployment.Build.csproj +++ b/Rubberduck.Deployment.Build/Rubberduck.Deployment.Build.csproj @@ -1,5 +1,5 @@  - + Rubberduck.Deployment.Build Copyright © 2018 diff --git a/Rubberduck.Deployment/Rubberduck.Deployment.csproj b/Rubberduck.Deployment/Rubberduck.Deployment.csproj index 07e04496eb..80c84ab673 100644 --- a/Rubberduck.Deployment/Rubberduck.Deployment.csproj +++ b/Rubberduck.Deployment/Rubberduck.Deployment.csproj @@ -1,5 +1,5 @@  - + Rubberduck.Deployment Copyright © 2018-2019 diff --git a/Rubberduck.Interaction/Rubberduck.Interaction.csproj b/Rubberduck.Interaction/Rubberduck.Interaction.csproj index 4929e5d9c5..862bddc8c1 100644 --- a/Rubberduck.Interaction/Rubberduck.Interaction.csproj +++ b/Rubberduck.Interaction/Rubberduck.Interaction.csproj @@ -1,5 +1,5 @@  - + Copyright © 2018-2019 Rubberduck.Interaction diff --git a/Rubberduck.JunkDrawer/Rubberduck.JunkDrawer.csproj b/Rubberduck.JunkDrawer/Rubberduck.JunkDrawer.csproj index 40d59ed93f..395718f6fd 100644 --- a/Rubberduck.JunkDrawer/Rubberduck.JunkDrawer.csproj +++ b/Rubberduck.JunkDrawer/Rubberduck.JunkDrawer.csproj @@ -1,5 +1,5 @@  - + Rubberduck.JunkDrawer Rubberduck.JunkDrawer diff --git a/Rubberduck.Main/Rubberduck.Main.csproj b/Rubberduck.Main/Rubberduck.Main.csproj index df0d0e19a1..5fab0fc6b4 100644 --- a/Rubberduck.Main/Rubberduck.Main.csproj +++ b/Rubberduck.Main/Rubberduck.Main.csproj @@ -1,5 +1,5 @@  - + Rubberduck Rubberduck diff --git a/Rubberduck.Parsing/Rubberduck.Parsing.csproj b/Rubberduck.Parsing/Rubberduck.Parsing.csproj index 8cc4879f64..72aedf612d 100644 --- a/Rubberduck.Parsing/Rubberduck.Parsing.csproj +++ b/Rubberduck.Parsing/Rubberduck.Parsing.csproj @@ -1,5 +1,5 @@  - + Rubberduck.Parsing Rubberduck.Parsing diff --git a/Rubberduck.Refactorings/Rubberduck.Refactorings.csproj b/Rubberduck.Refactorings/Rubberduck.Refactorings.csproj index 077a3e0f68..78a137d982 100644 --- a/Rubberduck.Refactorings/Rubberduck.Refactorings.csproj +++ b/Rubberduck.Refactorings/Rubberduck.Refactorings.csproj @@ -1,5 +1,5 @@  - + {D4B6A510-14E1-420A-A8D5-6A09890FD7D8} Rubberduck.Refactorings diff --git a/RubberduckBaseMetaProject.csproj b/RubberduckBaseMetaProject.csproj index c73c4e216d..efd86faea2 100644 --- a/RubberduckBaseMetaProject.csproj +++ b/RubberduckBaseMetaProject.csproj @@ -1,4 +1,4 @@ - + Library diff --git a/RubberduckBaseProject.csproj b/RubberduckBaseProject.csproj index e6180ce81b..ec8de27b89 100644 --- a/RubberduckBaseProject.csproj +++ b/RubberduckBaseProject.csproj @@ -1,4 +1,4 @@ - + Library From e08972e49783758a56703094235c235003f597a1 Mon Sep 17 00:00:00 2001 From: IvenBach Date: Tue, 7 Jan 2020 15:30:42 -0800 Subject: [PATCH 119/461] Add ImplicitlyTypedConstInspection and tests --- .../ImplicitlyTypedConstInspection.cs | 44 +++++++++++++ .../ImplicitlyTypedConstInspectionTests.cs | 61 +++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs create mode 100644 RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs new file mode 100644 index 0000000000..076a831331 --- /dev/null +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; +using System.Linq; +using Rubberduck.Inspections.Abstract; +using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Inspections.Results; +using Rubberduck.Parsing.Symbols; + +namespace Rubberduck.CodeAnalysis.Inspections.Concrete +{ + public sealed class ImplicitlyTypedConstInspection : InspectionBase + { + public ImplicitlyTypedConstInspection(RubberduckParserState state) + : base(state) { } + + protected override IEnumerable DoGetInspectionResults() + { + var declarationFinder = State.DeclarationFinder; + + var implicitlyTypedConsts = declarationFinder.AllDeclarations + .Where(declaration => declaration.DeclarationType == DeclarationType.Constant + && declaration.AsTypeContext == null); + + return implicitlyTypedConsts.Select(Result); + } + + private IInspectionResult Result(Declaration declaration) + { + return new IdentifierReferenceInspectionResult( + this, + declaration.DescriptionString, + State, + new IdentifierReference( + declaration.QualifiedModuleName, + declaration.ParentScopeDeclaration, + declaration.ParentDeclaration, + declaration.IdentifierName, + declaration.Selection, + declaration.Context, + declaration) + ); + } + } +} diff --git a/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs b/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs new file mode 100644 index 0000000000..c535e77861 --- /dev/null +++ b/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs @@ -0,0 +1,61 @@ +using System.Linq; +using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections.Concrete; +using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Parsing.VBA; +using Rubberduck.VBEditor.SafeComWrappers; + +namespace RubberduckTests.Inspections +{ + [TestFixture] + public class ImplicitlyTypedConstInspectionTests : InspectionTestsBase + { + [Test] + [Category("Inspections")] + public void InspectionName() + { + var inspection = new ImplicitlyTypedConstInspection(null); + + var expected = nameof(ImplicitlyTypedConstInspection); + var actual = inspection.Name; + Assert.AreEqual(expected, actual); + } + + [Test] + [Category("Inspections")] + public void ImplicitlyTypedConst_ReturnsResult() + { + const string inputCode = +@"Public Sub Foo() + Const bar = 0 +End Sub"; + + const int expected = 1; + + var results = InspectionResultsForModules(("FooClass", inputCode, ComponentType.ClassModule)); + var actual = results.Count(); + Assert.AreEqual(expected , actual); + } + + [Test] + [Category("Inspections")] + public void ImplicitlyTypedConst_DoesNotReturnResult() + { + const string inputCode = +@"Public Sub Foo() + Const bar As Long = 0 +End Sub"; + + const int expected = 0; + + var results = InspectionResultsForModules(("FooClass", inputCode, ComponentType.ClassModule)); + var actual = results.Count(); + Assert.AreEqual(expected, actual); + } + + protected override IInspection InspectionUnderTest(RubberduckParserState state) + { + return new ImplicitlyTypedConstInspection(state); + } + } +} From 4f8df3e83b08b620acf9288e4e94eaca80c54768 Mon Sep 17 00:00:00 2001 From: IvenBach Date: Tue, 7 Jan 2020 15:30:42 -0800 Subject: [PATCH 120/461] Add ImplicitlyTypedConstInspection and tests --- .../ImplicitlyTypedConstInspection.cs | 43 +++++++++++++ .../ImplicitlyTypedConstInspectionTests.cs | 61 +++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs create mode 100644 RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs new file mode 100644 index 0000000000..1853e98a19 --- /dev/null +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using System.Linq; +using Rubberduck.Inspections.Abstract; +using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Inspections.Results; +using Rubberduck.Parsing.Symbols; + +namespace Rubberduck.CodeAnalysis.Inspections.Concrete +{ + public sealed class ImplicitlyTypedConstInspection : InspectionBase + { + public ImplicitlyTypedConstInspection(RubberduckParserState state) + : base(state) { } + + protected override IEnumerable DoGetInspectionResults() + { + var declarationFinder = State.DeclarationFinder; + + var implicitlyTypedConsts = declarationFinder.AllDeclarations + .Where(declaration => declaration.DeclarationType == DeclarationType.Constant + && declaration.AsTypeContext == null); + + return implicitlyTypedConsts.Select(Result); + } + + private IInspectionResult Result(Declaration declaration) + { + return new IdentifierReferenceInspectionResult( + this, + declaration.DescriptionString, + State, + new IdentifierReference( + declaration.QualifiedModuleName, + declaration.ParentScopeDeclaration, + declaration.ParentDeclaration, + declaration.IdentifierName, + declaration.Selection, + declaration.Context, + declaration)); + } + } +} diff --git a/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs b/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs new file mode 100644 index 0000000000..c535e77861 --- /dev/null +++ b/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs @@ -0,0 +1,61 @@ +using System.Linq; +using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections.Concrete; +using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Parsing.VBA; +using Rubberduck.VBEditor.SafeComWrappers; + +namespace RubberduckTests.Inspections +{ + [TestFixture] + public class ImplicitlyTypedConstInspectionTests : InspectionTestsBase + { + [Test] + [Category("Inspections")] + public void InspectionName() + { + var inspection = new ImplicitlyTypedConstInspection(null); + + var expected = nameof(ImplicitlyTypedConstInspection); + var actual = inspection.Name; + Assert.AreEqual(expected, actual); + } + + [Test] + [Category("Inspections")] + public void ImplicitlyTypedConst_ReturnsResult() + { + const string inputCode = +@"Public Sub Foo() + Const bar = 0 +End Sub"; + + const int expected = 1; + + var results = InspectionResultsForModules(("FooClass", inputCode, ComponentType.ClassModule)); + var actual = results.Count(); + Assert.AreEqual(expected , actual); + } + + [Test] + [Category("Inspections")] + public void ImplicitlyTypedConst_DoesNotReturnResult() + { + const string inputCode = +@"Public Sub Foo() + Const bar As Long = 0 +End Sub"; + + const int expected = 0; + + var results = InspectionResultsForModules(("FooClass", inputCode, ComponentType.ClassModule)); + var actual = results.Count(); + Assert.AreEqual(expected, actual); + } + + protected override IInspection InspectionUnderTest(RubberduckParserState state) + { + return new ImplicitlyTypedConstInspection(state); + } + } +} From d7519adffa04f8f7d33e9c6720c8715959af7329 Mon Sep 17 00:00:00 2001 From: IvenBach Date: Tue, 7 Jan 2020 15:57:23 -0800 Subject: [PATCH 121/461] Convert to autoproperty --- RubberduckTests/Mocks/MockVbeBuilder.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/RubberduckTests/Mocks/MockVbeBuilder.cs b/RubberduckTests/Mocks/MockVbeBuilder.cs index 1fb3000087..acad78aa93 100644 --- a/RubberduckTests/Mocks/MockVbeBuilder.cs +++ b/RubberduckTests/Mocks/MockVbeBuilder.cs @@ -65,8 +65,6 @@ public class MockVbeBuilder //private Mock _vbWindows; private readonly Windows _windows = new Windows(); - - private Mock _vbProjects; private readonly ICollection _projects = new List(); private Mock _vbCodePanes; @@ -94,7 +92,7 @@ public MockVbeBuilder AddProject(Mock project) AddOpenCodePanes(allCodePanes); _vbe.SetupGet(vbe => vbe.ActiveVBProject).Returns(project.Object); - _vbe.SetupGet(m => m.VBProjects).Returns(() => _vbProjects.Object); + _vbe.SetupGet(m => m.VBProjects).Returns(() => MockProjectsCollection.Object); return this; } @@ -275,8 +273,8 @@ private Mock CreateVbeMock() vbe.SetupGet(m => m.MainWindow).Returns(() => mainWindow.Object); - _vbProjects = CreateProjectsMock(); - vbe.SetupGet(m => m.VBProjects).Returns(() => _vbProjects.Object); + MockProjectsCollection = CreateProjectsMock(); + vbe.SetupGet(m => m.VBProjects).Returns(() => MockProjectsCollection.Object); _vbCodePanes = CreateCodePanesMock(); vbe.SetupGet(m => m.CodePanes).Returns(() => _vbCodePanes.Object); @@ -379,6 +377,6 @@ private Mock CreateCodePanesMock() return result; } - public Mock MockProjectsCollection => _vbProjects; + public Mock MockProjectsCollection { get; private set; } } } From 25441bc334ae735e38cd721a563545cafc88c76a Mon Sep 17 00:00:00 2001 From: IvenBach Date: Wed, 8 Jan 2020 11:24:10 -0800 Subject: [PATCH 122/461] Inline variable declarations --- .../VBAParserPartialExtensions.cs | 48 +++++++------------ 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/Rubberduck.Parsing/Grammar/PartialExtensions/VBAParserPartialExtensions.cs b/Rubberduck.Parsing/Grammar/PartialExtensions/VBAParserPartialExtensions.cs index 5e257fe680..73ad54d7da 100644 --- a/Rubberduck.Parsing/Grammar/PartialExtensions/VBAParserPartialExtensions.cs +++ b/Rubberduck.Parsing/Grammar/PartialExtensions/VBAParserPartialExtensions.cs @@ -47,8 +47,7 @@ public Interval IdentifierTokens { get { - Interval tokenInterval; - Identifier.GetName(this, out tokenInterval); + Identifier.GetName(this, out Interval tokenInterval); return tokenInterval; } } @@ -84,8 +83,7 @@ public Interval IdentifierTokens { get { - Interval tokenInterval; - Identifier.GetName(this, out tokenInterval); + Identifier.GetName(this, out Interval tokenInterval); return tokenInterval; } } @@ -122,8 +120,7 @@ public Interval IdentifierTokens { get { - Interval tokenInterval; - Identifier.GetName(this, out tokenInterval); + Identifier.GetName(this, out Interval tokenInterval); return tokenInterval; } } @@ -160,8 +157,7 @@ public Interval IdentifierTokens { get { - Interval tokenInterval; - Identifier.GetName(this, out tokenInterval); + Identifier.GetName(this, out Interval tokenInterval); return tokenInterval; } } @@ -198,8 +194,7 @@ public Interval IdentifierTokens { get { - Interval tokenInterval; - Identifier.GetName(this, out tokenInterval); + Identifier.GetName(this, out Interval tokenInterval); return tokenInterval; } } @@ -213,8 +208,7 @@ public Interval IdentifierTokens { get { - Interval tokenInterval; - Identifier.GetName(this, out tokenInterval); + Identifier.GetName(this, out Interval tokenInterval); return tokenInterval; } } @@ -249,8 +243,7 @@ public Interval IdentifierTokens { get { - Interval tokenInterval; - Identifier.GetName(this, out tokenInterval); + Identifier.GetName(this, out Interval tokenInterval); return tokenInterval; } } @@ -285,8 +278,7 @@ public Interval IdentifierTokens { get { - Interval tokenInterval; - Identifier.GetName(this, out tokenInterval); + Identifier.GetName(this, out Interval tokenInterval); return tokenInterval; } } @@ -321,8 +313,7 @@ public Interval IdentifierTokens { get { - Interval tokenInterval; - Identifier.GetName(this, out tokenInterval); + Identifier.GetName(this, out Interval tokenInterval); return tokenInterval; } } @@ -357,8 +348,7 @@ public Interval IdentifierTokens { get { - Interval tokenInterval; - Identifier.GetName(this, out tokenInterval); + Identifier.GetName(this, out Interval tokenInterval); return tokenInterval; } } @@ -393,8 +383,7 @@ public Interval IdentifierTokens { get { - Interval tokenInterval; - Identifier.GetName(this, out tokenInterval); + Identifier.GetName(this, out Interval tokenInterval); return tokenInterval; } } @@ -429,8 +418,7 @@ public Interval IdentifierTokens { get { - Interval tokenInterval; - Identifier.GetName(this, out tokenInterval); + Identifier.GetName(this, out Interval tokenInterval); return tokenInterval; } } @@ -465,8 +453,7 @@ public Interval IdentifierTokens { get { - Interval tokenInterval; - Identifier.GetName(this, out tokenInterval); + Identifier.GetName(this, out Interval tokenInterval); return tokenInterval; } } @@ -501,8 +488,7 @@ public Interval IdentifierTokens { get { - Interval tokenInterval; - Identifier.GetName(this, out tokenInterval); + Identifier.GetName(this, out Interval tokenInterval); return tokenInterval; } } @@ -537,8 +523,7 @@ public Interval IdentifierTokens { get { - Interval tokenInterval; - Identifier.GetName(this, out tokenInterval); + Identifier.GetName(this, out Interval tokenInterval); return tokenInterval; } } @@ -573,8 +558,7 @@ public Interval IdentifierTokens { get { - Interval tokenInterval; - Identifier.GetName(this, out tokenInterval); + Identifier.GetName(this, out Interval tokenInterval); return tokenInterval; } } From 46bd6338a8b29a7a3f760959caf2ae691abcf170 Mon Sep 17 00:00:00 2001 From: IvenBach Date: Wed, 8 Jan 2020 15:19:11 -0800 Subject: [PATCH 123/461] Remove unused using directives --- Rubberduck.CodeAnalysis/Inspections/Abstract/QuickFixBase.cs | 1 - RubberduckTests/StringExtensionsTests.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/QuickFixBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/QuickFixBase.cs index 4569cf28ca..f8c246b357 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/QuickFixBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/QuickFixBase.cs @@ -6,7 +6,6 @@ using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; -using Rubberduck.Parsing.VBA.Extensions; using Rubberduck.Parsing.VBA.Parsing; namespace Rubberduck.Inspections.Abstract diff --git a/RubberduckTests/StringExtensionsTests.cs b/RubberduckTests/StringExtensionsTests.cs index ff7f544a51..a1cebe1ab0 100644 --- a/RubberduckTests/StringExtensionsTests.cs +++ b/RubberduckTests/StringExtensionsTests.cs @@ -1,6 +1,5 @@ using System; using NUnit.Framework; -using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.Extensions; using Rubberduck.VBEditor.Extensions; From 02bc804e16aea20607bee341b3a9c237bf104e90 Mon Sep 17 00:00:00 2001 From: IvenBach Date: Wed, 8 Jan 2020 16:35:09 -0800 Subject: [PATCH 124/461] Add resource strings Alerted to their omission because unit tests flagged them as missing. --- .../Inspections/InspectionInfo.Designer.cs | 9 +++++++++ Rubberduck.Resources/Inspections/InspectionInfo.resx | 3 +++ .../Inspections/InspectionNames.Designer.cs | 9 +++++++++ Rubberduck.Resources/Inspections/InspectionNames.resx | 3 +++ .../Inspections/InspectionResults.Designer.cs | 9 +++++++++ Rubberduck.Resources/Inspections/InspectionResults.resx | 5 ++++- 6 files changed, 37 insertions(+), 1 deletion(-) diff --git a/Rubberduck.Resources/Inspections/InspectionInfo.Designer.cs b/Rubberduck.Resources/Inspections/InspectionInfo.Designer.cs index 1a9408dac8..f7f6c3452c 100644 --- a/Rubberduck.Resources/Inspections/InspectionInfo.Designer.cs +++ b/Rubberduck.Resources/Inspections/InspectionInfo.Designer.cs @@ -357,6 +357,15 @@ public static string ImplicitDefaultMemberAccessInspection { } } + /// + /// Looks up a localized string similar to If the type clause for a Const isn't included it is implicitly typed. Include an explicit ' As <Type>' replacing '<Type>' with the correct data type to explicitly type your const value.. + /// + public static string ImplicitlyTypedConstInspection { + get { + return ResourceManager.GetString("ImplicitlyTypedConstInspection", resourceCulture); + } + } + /// /// Looks up a localized string similar to Module members are public by default, which can be counter-intuitive. Consider specifying explicit access modifiers to avoid ambiguity.. /// diff --git a/Rubberduck.Resources/Inspections/InspectionInfo.resx b/Rubberduck.Resources/Inspections/InspectionInfo.resx index e825f2951b..6730f9430a 100644 --- a/Rubberduck.Resources/Inspections/InspectionInfo.resx +++ b/Rubberduck.Resources/Inspections/InspectionInfo.resx @@ -433,4 +433,7 @@ If the parameter can be null, ignore this inspection result; passing a null valu Whenever both sides of an assignment without Set are objects, there is an assignment from the default member of the RHS to the one on the LHS. Although this might be intentional, in many situations it will just mask an erroneously forgotten Set. + + If the type clause for a Const isn't included it is implicitly typed. Include an explicit ' As <Type>' replacing '<Type>' with the correct data type to explicitly type your const value. + \ No newline at end of file diff --git a/Rubberduck.Resources/Inspections/InspectionNames.Designer.cs b/Rubberduck.Resources/Inspections/InspectionNames.Designer.cs index 2b41b34db8..1280f44c30 100644 --- a/Rubberduck.Resources/Inspections/InspectionNames.Designer.cs +++ b/Rubberduck.Resources/Inspections/InspectionNames.Designer.cs @@ -357,6 +357,15 @@ public static string ImplicitDefaultMemberAccessInspection { } } + /// + /// Looks up a localized string similar to Implicitly typed Const. + /// + public static string ImplicitlyTypedConstInspection { + get { + return ResourceManager.GetString("ImplicitlyTypedConstInspection", resourceCulture); + } + } + /// /// Looks up a localized string similar to Implicitly public member. /// diff --git a/Rubberduck.Resources/Inspections/InspectionNames.resx b/Rubberduck.Resources/Inspections/InspectionNames.resx index 4dde116c1a..0792d3dc8f 100644 --- a/Rubberduck.Resources/Inspections/InspectionNames.resx +++ b/Rubberduck.Resources/Inspections/InspectionNames.resx @@ -437,4 +437,7 @@ Suspicious Let assignment + + Implicitly typed Const + \ No newline at end of file diff --git a/Rubberduck.Resources/Inspections/InspectionResults.Designer.cs b/Rubberduck.Resources/Inspections/InspectionResults.Designer.cs index 0de5757f9f..b516dc70af 100644 --- a/Rubberduck.Resources/Inspections/InspectionResults.Designer.cs +++ b/Rubberduck.Resources/Inspections/InspectionResults.Designer.cs @@ -366,6 +366,15 @@ public static string ImplicitDefaultMemberAccessInspection { } } + /// + /// Looks up a localized string similar to Constant '{0}' is implicitly typed.. + /// + public static string ImplicitlyTypedConstInspection { + get { + return ResourceManager.GetString("ImplicitlyTypedConstInspection", resourceCulture); + } + } + /// /// Looks up a localized string similar to Member '{0}' is implicitly public.. /// diff --git a/Rubberduck.Resources/Inspections/InspectionResults.resx b/Rubberduck.Resources/Inspections/InspectionResults.resx index 7fc185cf90..2794f065cf 100644 --- a/Rubberduck.Resources/Inspections/InspectionResults.resx +++ b/Rubberduck.Resources/Inspections/InspectionResults.resx @@ -498,4 +498,7 @@ In memoriam, 1972-2018 There is an assignment from the default member of the result of expression '{1}' to that of the expression '{0}'. {0} lhsExpression; {1} rhsExpression - + + Constant '{0}' is implicitly typed. + + \ No newline at end of file From 9cf61d5ea64f7eb6138627e4d67c6b785cfecf28 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Wed, 8 Jan 2020 17:57:22 -0800 Subject: [PATCH 125/461] Completed interfaces refactoring changes Significant modification of interfaces and class responsibilities. The refactoring is really two refactorings in one. Classes re-written re-organized to represent this more explicitly. --- .../EncapsulateFieldViewModel.cs | 2 +- .../ViewableEncapsulatedField.cs | 5 +- .../EncapsulateFIeldResources.cs | 20 +- ....cs => EncapsulateFieldElementsBuilder.cs} | 29 ++- .../EncapsulateField/EncapsulateFieldModel.cs | 98 ++++----- .../EncapsulateFieldRefactoring.cs | 82 +++---- .../EncapsulateFieldRewriteSession.cs | 11 + .../EncapsulateFieldValidationsProvider.cs | 116 ---------- .../ConvertFieldsToUDTMembers.cs | 72 ++++-- .../EncapsulateFieldStrategyBase.cs | 102 ++++++++- .../UseBackingFields.cs | 33 +-- .../FieldCandidates/ArrayCandidate.cs | 65 +----- .../ConvertToUDTMemberCandidate.cs | 91 +++++--- .../FieldCandidates/EncapsulateField.cs | 81 ------- .../EncapsulateFieldCandidate.cs | 195 +++++------------ .../UserDefinedTypeCandidate.cs | 127 ++--------- .../UserDefinedTypeMemberCandidate.cs | 138 ++---------- .../{FieldCandidates => }/ObjectStateUDT.cs | 69 +----- .../EncapsulateField/PropertyGenerator.cs | 118 ++++------ .../EncapsulateFieldConflictFinders.cs} | 206 ++++-------------- .../EncapsulateFieldNamesValidator.cs | 29 +++ .../EncapsulateFieldValidationsProvider.cs | 73 +++++++ .../EncapsulateField/EncapsulateFieldTests.cs | 14 +- .../EncapsulatedUDTFieldTests.cs | 159 +++++++++++--- .../EncapsulationIdentifiersTests.cs | 14 +- .../EncapsulateField/TestSupport.cs | 17 +- 26 files changed, 742 insertions(+), 1224 deletions(-) rename Rubberduck.Refactorings/EncapsulateField/{EncapsulateFieldElementFactory.cs => EncapsulateFieldElementsBuilder.cs} (75%) delete mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidationsProvider.cs delete mode 100644 Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateField.cs rename Rubberduck.Refactorings/EncapsulateField/{FieldCandidates => }/ObjectStateUDT.cs (60%) rename Rubberduck.Refactorings/EncapsulateField/{ConflictDetectors.cs => Validations/EncapsulateFieldConflictFinders.cs} (52%) create mode 100644 Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldNamesValidator.cs create mode 100644 Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldValidationsProvider.cs diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs index 7295a10c97..4ded817051 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs @@ -17,7 +17,7 @@ private class MasterDetailSelectionManager private const string _neverATargetID = "_Never_a_TargetID_"; private bool _detailFieldIsFlagged; - public MasterDetailSelectionManager(IEncapsulateFieldCandidate selected) + public MasterDetailSelectionManager(IEncapsulatableField selected) : this(selected?.TargetID) { if (selected != null) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs index 03ed544bb4..34775291a4 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs @@ -19,9 +19,9 @@ public interface IEncapsulatedFieldViewData public class ViewableEncapsulatedField : IEncapsulatedFieldViewData { - private IEncapsulateFieldCandidate _efd; + private IEncapsulatableField _efd; private readonly int _hashCode; - public ViewableEncapsulatedField(IEncapsulateFieldCandidate efd) + public ViewableEncapsulatedField(IEncapsulatableField efd) { _efd = efd; _hashCode = efd.TargetID.GetHashCode(); @@ -74,7 +74,6 @@ public bool TryValidateEncapsulationAttributes(out string errorMessage) public bool CanBeReadWrite => _efd.CanBeReadWrite; public string PropertyName { get => _efd.PropertyIdentifier; set => _efd.PropertyIdentifier = value; } - //public string PropertyIdentifier { get => _efd.PropertyIdentifier; set => _efd.PropertyIdentifier = value; } public bool EncapsulateFlag { get => _efd.EncapsulateFlag; set => _efd.EncapsulateFlag = value; } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs index c7076c0c38..00389da161 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs @@ -11,24 +11,20 @@ namespace Rubberduck.Refactorings.EncapsulateField //just before the 'WIP' annotation is removed public class EncapsulateFieldResources { - public static string PreviewEndOfChangesMarker + public static string PreviewMarker => "'<===== Property and Declaration changes above this line =====>"; public static string DefaultPropertyParameter => "value"; public static string DefaultStateUDTFieldName => "this"; - //TODO: Is it meaningful to change the Type prefix for different cultures? - //If not, remove this declaration - public static string StateUserDefinedTypeIdentifierPrefix => "T"; - - public static string GroupBoxHeaderSuffix = "Encapsulation Property Name:"; + public static string GroupBoxHeaderSuffix = "Property Name:"; public static string Caption => RubberduckUI.EncapsulateField_Caption; public static string InstructionText /* => RubberduckUI.EncapsulateField_InstructionText*/ - => "Select one or more fields to encapsulate. Optionally edit property names or accept the default value(s)"; + => "Select one or more fields to encapsulate. Accept the default values or edit property names"; public static string Preview => RubberduckUI.EncapsulateField_Preview; @@ -37,15 +33,7 @@ public static string TitleText => RubberduckUI.EncapsulateField_TitleText; public static string PrivateUDTPropertyText - => "Encapsulates Each UDT Member"; - - public static string Conflict => "Conflict"; - - public static string Property => "Property"; - - public static string Field => "Field"; - - public static string Parameter => "Parameter"; + => "Creates a Property for Each UDT Member"; public static string NameConflictDetected => "Name Conflict Detected"; diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementsBuilder.cs similarity index 75% rename from Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs rename to Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementsBuilder.cs index bbfc7f8afa..5f80734b88 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementFactory.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementsBuilder.cs @@ -11,12 +11,12 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public class EncapsulateFieldElementFactory + public class EncapsulateFieldElementsBuilder { private readonly IDeclarationFinderProvider _declarationFinderProvider; private QualifiedModuleName _targetQMN; - public EncapsulateFieldElementFactory(IDeclarationFinderProvider declarationFinderProvider, QualifiedModuleName targetQMN)//, IEncapsulateFieldValidator validator ) + public EncapsulateFieldElementsBuilder(IDeclarationFinderProvider declarationFinderProvider, QualifiedModuleName targetQMN)//, IEncapsulateFieldValidator validator ) { _declarationFinderProvider = declarationFinderProvider; _targetQMN = targetQMN; @@ -25,9 +25,9 @@ public EncapsulateFieldElementFactory(IDeclarationFinderProvider declarationFind public IObjectStateUDT ObjectStateUDT { private set; get; } - public IEncapsulateFieldValidationsProvider ValidatorProvider { private set; get; } + public IEncapsulateFieldValidationsProvider ValidationsProvider { private set; get; } - public IEnumerable Candidates { private set; get; } + public IEnumerable Candidates { private set; get; } private void CreateRefactoringElements() { @@ -35,11 +35,11 @@ private void CreateRefactoringElements() .Members(_targetQMN) .Where(v => v.IsMemberVariable() && !v.IsWithEvents); - ValidatorProvider = new EncapsulateFieldValidationsProvider(); + ValidationsProvider = new EncapsulateFieldValidationsProvider(); - var nameValidator = ValidatorProvider.NameOnlyValidator(Validators.Default); + var nameValidator = ValidationsProvider.NameOnlyValidator(NameValidators.Default); - var candidates = new List(); + var candidates = new List(); foreach (var fieldDeclaration in fieldDeclarations) { Debug.Assert(!fieldDeclaration.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)); @@ -50,9 +50,9 @@ private void CreateRefactoringElements() candidates.Add(fieldEncapsulationCandidate); } - ValidatorProvider.RegisterCandidates(candidates); + ValidationsProvider.RegisterCandidates(candidates); - var conflictsValidator = ValidatorProvider.ConflictDetector(EncapsulateFieldStrategy.UseBackingFields, _declarationFinderProvider); + var conflictsValidator = ValidationsProvider.ConflictDetector(EncapsulateFieldStrategy.UseBackingFields, _declarationFinderProvider); ObjectStateUDT = CreateStateUDTField(conflictsValidator); foreach (var candidate in candidates) @@ -60,9 +60,6 @@ private void CreateRefactoringElements() candidate.ConflictFinder = conflictsValidator; conflictsValidator.AssignNoConflictIdentifier(candidate, DeclarationType.Property); conflictsValidator.AssignNoConflictIdentifier(candidate, DeclarationType.Variable); - - var converted = candidate as IConvertToUDTMember; - converted.ObjectStateUDT = ObjectStateUDT; } Candidates = candidates; @@ -81,11 +78,11 @@ private IObjectStateUDT CreateStateUDTField(IEncapsulateFieldConflictFinder vali return stateUDT; } - private IEncapsulateFieldCandidate CreateCandidate(Declaration target, IValidateVBAIdentifiers validator)// Predicate nameValidator) + private IEncapsulatableField CreateCandidate(Declaration target, IValidateVBAIdentifiers validator)// Predicate nameValidator) { if (target.IsUserDefinedTypeField()) { - var udtValidator = ValidatorProvider.NameOnlyValidator(Validators.UserDefinedType); + var udtValidator = ValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedType); var udtField = new UserDefinedTypeCandidate(target, udtValidator) as IUserDefinedTypeCandidate; (Declaration udtDeclaration, IEnumerable udtMembers) = GetUDTAndMembersForField(udtField); @@ -96,10 +93,10 @@ private IEncapsulateFieldCandidate CreateCandidate(Declaration target, IValidate foreach (var udtMemberDeclaration in udtMembers) { - var udtMemberValidator = ValidatorProvider.NameOnlyValidator(Validators.UserDefinedTypeMember); + var udtMemberValidator = ValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMember); if (udtMemberDeclaration.IsArray) { - udtMemberValidator = ValidatorProvider.NameOnlyValidator(Validators.UserDefinedTypeMemberArray); + udtMemberValidator = ValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMemberArray); } var candidateUDTMember = new UserDefinedTypeMemberCandidate(CreateCandidate(udtMemberDeclaration, udtMemberValidator), udtField) as IUserDefinedTypeMemberCandidate; diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index d34a60b602..7d35bc429f 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -12,14 +12,13 @@ public class EncapsulateFieldModel : IRefactoringModel { private readonly Func _previewDelegate; private QualifiedModuleName _targetQMN; - //private IValidateEncapsulateFieldNames _validator; private IDeclarationFinderProvider _declarationFinderProvider; private IEncapsulateFieldValidationsProvider _validatorProvider; private IObjectStateUDT _newObjectStateUDT; private IDictionary)> _udtFieldToUdtDeclarationMap = new Dictionary)>(); - public EncapsulateFieldModel(Declaration target, IEnumerable candidates, IObjectStateUDT stateUDTField, Func previewDelegate, IDeclarationFinderProvider declarationFinderProvider, IEncapsulateFieldValidationsProvider validatorProvider) // IEncapsulateFieldValidator validator) + public EncapsulateFieldModel(Declaration target, IEnumerable candidates, IObjectStateUDT stateUDTField, Func previewDelegate, IDeclarationFinderProvider declarationFinderProvider, IEncapsulateFieldValidationsProvider validatorProvider) // IEncapsulateFieldValidator validator) { _previewDelegate = previewDelegate; _targetQMN = target.QualifiedModuleName; @@ -36,22 +35,49 @@ public EncapsulateFieldModel(Declaration target, IEnumerable _encapsulationFieldStategy; set { _encapsulationFieldStategy = value; - AssignCandidateValidations(value); + if (_encapsulationFieldStategy == EncapsulateFieldStrategy.UseBackingFields) + { + foreach (var candidate in EncapsulationCandidates) + { + candidate.ConflictFinder = _validatorProvider.ConflictDetector(_encapsulationFieldStategy, _declarationFinderProvider);// ConflictDetector; + switch (candidate) + { + case IUserDefinedTypeCandidate udt: + candidate.NameValidator = _validatorProvider.NameOnlyValidator(NameValidators.UserDefinedType); + break; + case IUserDefinedTypeMemberCandidate udtm: + candidate.NameValidator = candidate.Declaration.IsArray + ? _validatorProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMemberArray) + : _validatorProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMember); + break; + default: + candidate.NameValidator = _validatorProvider.NameOnlyValidator(NameValidators.Default); + break; + } + } + } + else + { + foreach (var candidate in EncapsulationCandidates) + { + candidate.ConflictFinder = _validatorProvider.ConflictDetector(_encapsulationFieldStategy, _declarationFinderProvider);// ConflictDetector; + candidate.NameValidator = candidate.Declaration.IsArray + ? _validatorProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMemberArray) + : _validatorProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMember); + } + } } - get => _encapsulationFieldStategy; } - public IEncapsulateFieldValidationsProvider ValidatorProvider => _validatorProvider; + public IEncapsulateFieldValidationsProvider ValidationsProvider => _validatorProvider; - public IEncapsulateFieldConflictFinder ConflictDetector - => _validatorProvider.ConflictDetector(EncapsulateFieldStrategy, _declarationFinderProvider); + public List EncapsulationCandidates { set; get; } = new List(); - public List EncapsulationCandidates { set; get; } = new List(); - - public IEnumerable SelectedFieldCandidates + public IEnumerable SelectedFieldCandidates => EncapsulationCandidates.Where(v => v.EncapsulateFlag); public IEnumerable UDTFieldCandidates @@ -64,27 +90,12 @@ public IEnumerable SelectedUDTFieldCandidates .Where(v => v is IUserDefinedTypeCandidate) .Cast(); - public IEncapsulateFieldCandidate this[string encapsulatedFieldTargetID] + public IEncapsulatableField this[string encapsulatedFieldTargetID] => EncapsulationCandidates.Where(c => c.TargetID.Equals(encapsulatedFieldTargetID)).Single(); - public IEncapsulateFieldCandidate this[Declaration fieldDeclaration] + public IEncapsulatableField this[Declaration fieldDeclaration] => EncapsulationCandidates.Where(c => c.Declaration == fieldDeclaration).Single(); - ////TODO: Get rid of this property - //private bool _convertFieldsToUDTMembers; - //public bool ConvertFieldsToUDTMembers - //{ - // set - // { - // _convertFieldsToUDTMembers = value; - - // EncapsulateFieldStrategy = value - // ? EncapsulateFieldStrategy.ConvertFieldsToUDTMembers - // : EncapsulateFieldStrategy.UseBackingFields; - // } - // get => _convertFieldsToUDTMembers; - //} - private IObjectStateUDT _activeObjectStateUDT; public IObjectStateUDT StateUDTField { @@ -102,39 +113,6 @@ public IObjectStateUDT StateUDTField get => _activeObjectStateUDT ?? _newObjectStateUDT; } - public void AssignCandidateValidations(EncapsulateFieldStrategy strategy) - { - foreach (var candidate in EncapsulationCandidates) - { - candidate.ConvertFieldToUDTMember = strategy == EncapsulateFieldStrategy.ConvertFieldsToUDTMembers; - - candidate.ConflictFinder = ConflictDetector; - if (strategy == EncapsulateFieldStrategy.UseBackingFields) - { - if (candidate is IUserDefinedTypeCandidate) - { - candidate.NameValidator = _validatorProvider.NameOnlyValidator(Validators.UserDefinedType); - } - else if (candidate is IUserDefinedTypeMemberCandidate) - { - candidate.NameValidator = candidate.Declaration.IsArray - ? _validatorProvider.NameOnlyValidator(Validators.UserDefinedTypeMemberArray) - : _validatorProvider.NameOnlyValidator(Validators.UserDefinedTypeMember); - } - else - { - candidate.NameValidator = _validatorProvider.NameOnlyValidator(Validators.Default); - } - } - else - { - candidate.NameValidator = candidate.Declaration.IsArray - ? _validatorProvider.NameOnlyValidator(Validators.UserDefinedTypeMemberArray) - : _validatorProvider.NameOnlyValidator(Validators.UserDefinedTypeMember); - } - } - } - public string PreviewRefactoring() => _previewDelegate(this); private HashSet _objStateCandidates; diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 5759907efc..4c1bad55e1 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -33,14 +33,14 @@ public class EncapsulateFieldRefactoring : InteractiveRefactoringBase c.Declaration == target); selected.EncapsulateFlag = true; @@ -95,7 +95,7 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) defaultObjectStateUDT, PreviewRewrite, _declarationFinderProvider, - validatorProvider); + validationsProvider); if (objectStateUDT != null) { @@ -106,34 +106,6 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) return model; } - //Identify an existing objectStateUDT and make it unavailable for the user to select for encapsulation. - //This prevents the user from inadvertently nesting a stateUDT within a new stateUDT - private bool TryRetrieveExistingObjectStateUDT(Declaration target, IEnumerable candidates, out IObjectStateUDT objectStateUDT) - { - objectStateUDT = null; - //Determination relies on matching the refactoring-generated name and a couple other UDT attributes - //to determine if an objectStateUDT pre-exists the refactoring. - - //Question: would using an Annotations (like '@IsObjectStateUDT) be better? - //The logic would then be: if Annotated => it's the one. else => apply the matching criteria below - - //e.g., In cases where the user chooses an existing UDT for the initial encapsulation, the matching - //refactoring will not assign the name and the criteria below will fail => so applying an Annotation would - //make it possible to find again - var objectStateUDTIdentifier = $"{EncapsulateFieldResources.StateUserDefinedTypeIdentifierPrefix}{target.QualifiedModuleName.ComponentName}"; - - var objectStateUDTMatches = candidates.Where(c => c is IUserDefinedTypeCandidate udt - && udt.Declaration.HasPrivateAccessibility() - && udt.Declaration.AsTypeDeclaration.IdentifierName.StartsWith(objectStateUDTIdentifier, StringComparison.InvariantCultureIgnoreCase)) - .Select(pm => pm as IUserDefinedTypeCandidate); - - if (objectStateUDTMatches.Count() == 1) - { - objectStateUDT = new ObjectStateUDT(objectStateUDTMatches.First()) { IsSelected = true }; - } - return objectStateUDT != null; - } - protected override void RefactorImpl(EncapsulateFieldModel model) { var refactorRewriteSession = new EncapsulateFieldRewriteSession(RewritingManager.CheckOutCodePaneSession()) as IEncapsulateFieldRewriteSession; @@ -148,24 +120,40 @@ protected override void RefactorImpl(EncapsulateFieldModel model) private string PreviewRewrite(EncapsulateFieldModel model) { - IEncapsulateFieldRewriteSession refactorRewriteSession = new EncapsulateFieldRewriteSession(RewritingManager.CheckOutCodePaneSession()); - - refactorRewriteSession = RefactorRewrite(model, refactorRewriteSession, true); + var previewSession = new EncapsulateFieldRewriteSession(RewritingManager.CheckOutCodePaneSession()) as IEncapsulateFieldRewriteSession; ; - var previewRewriter = refactorRewriteSession.CheckOutModuleRewriter(_targetQMN); + previewSession = RefactorRewrite(model, previewSession, true); - return previewRewriter.GetText(maxConsecutiveNewLines: 3); + return previewSession.CreatePreview(_targetQMN); } private IEncapsulateFieldRewriteSession RefactorRewrite(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession, bool asPreview = false) { if (!model.SelectedFieldCandidates.Any()) { return refactorRewriteSession; } - var strategy = model.EncapsulateFieldStrategy == EncapsulateFieldStrategy.ConvertFieldsToUDTMembers // model.ConvertFieldsToUDTMembers + var strategy = model.EncapsulateFieldStrategy == EncapsulateFieldStrategy.ConvertFieldsToUDTMembers ? new ConvertFieldsToUDTMembers(_declarationFinderProvider, model, _indenter) as IEncapsulateStrategy : new UseBackingFields(_declarationFinderProvider, model, _indenter) as IEncapsulateStrategy; return strategy.RefactorRewrite(model, refactorRewriteSession, asPreview); } + + private bool TryRetrieveExistingObjectStateUDT(Declaration target, IEnumerable candidates, out IObjectStateUDT objectStateUDT) + { + objectStateUDT = null; + + var objectStateUDTIdentifier = $"T{target.QualifiedModuleName.ComponentName}"; + + var objectStateUDTMatches = candidates.Where(c => c is IUserDefinedTypeCandidate udt + && udt.Declaration.HasPrivateAccessibility() + && udt.Declaration.AsTypeDeclaration.IdentifierName.StartsWith(objectStateUDTIdentifier, StringComparison.InvariantCultureIgnoreCase)) + .Select(pm => pm as IUserDefinedTypeCandidate); + + if (objectStateUDTMatches.Count() == 1) + { + objectStateUDT = new ObjectStateUDT(objectStateUDTMatches.First()) { IsSelected = true }; + } + return objectStateUDT != null; + } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriteSession.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriteSession.cs index 282808af92..107187c7fe 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriteSession.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRewriteSession.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using Rubberduck.Refactorings.EncapsulateField.Extensions; namespace Rubberduck.Refactorings.EncapsulateField { @@ -16,6 +17,7 @@ public interface IEncapsulateFieldRewriteSession IExecutableRewriteSession RewriteSession { get; } IModuleRewriter CheckOutModuleRewriter(QualifiedModuleName qmn); bool TryRewrite(); + string CreatePreview(QualifiedModuleName qmn); void Remove(Declaration target, IModuleRewriter rewriter); } @@ -41,6 +43,15 @@ public bool TryRewrite() return _rewriteSession.TryRewrite(); } + public string CreatePreview(QualifiedModuleName qmn) + { + ExecuteCachedRemoveRequests(); + + var previewRewriter = _rewriteSession.CheckOutModuleRewriter(qmn); + + return previewRewriter.GetText(maxConsecutiveNewLines: 3); + } + public void Remove(Declaration target, IModuleRewriter rewriter) { var varList = target.Context.GetAncestor(); diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidationsProvider.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidationsProvider.cs deleted file mode 100644 index 9912b1f353..0000000000 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldValidationsProvider.cs +++ /dev/null @@ -1,116 +0,0 @@ -using Rubberduck.Parsing.Symbols; -using Rubberduck.Parsing.VBA; -using Rubberduck.Refactorings.Common; -using Rubberduck.VBEditor; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Rubberduck.Refactorings.EncapsulateField -{ - public interface IValidateVBAIdentifiers - { - bool IsValidVBAIdentifier(string identifier, out string errorMessage); - bool IsValidUDTMemberIdentifier(string identifier, bool isArray, out string errorMessage); - } - - public enum Validators - { - Default, - UserDefinedType, - UserDefinedTypeMember, - UserDefinedTypeMemberArray - } - - public interface IValidateEncapsulateFieldNames - { - bool IsValidVBAIdentifier(string identifier, DeclarationType declarationType, out string errorMessage, bool isArray = false); - bool HasConflictingIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType, out string errorMessage); - bool HasConflictingIdentifierIgnoreEncapsulationFlag(IEncapsulateFieldCandidate field, DeclarationType declarationType, out string errorMessage); - bool IsConflictingProposedIdentifier(string fieldName, IEncapsulateFieldCandidate candidate, DeclarationType declarationType); - IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType); - } - - //public interface IEncapsulateFieldValidator : IValidateEncapsulateFieldNames - //{ - // string CreateNonConflictIdentifierForProposedType(string identifier, QualifiedModuleName qmn, DeclarationType declarationType); - //} - - public interface IEncapsulateFieldValidationsProvider - { - IValidateVBAIdentifiers NameOnlyValidator(Validators validatorType); - IEncapsulateFieldConflictFinder ConflictDetector(EncapsulateFieldStrategy strategy, IDeclarationFinderProvider declarationFinderProvider); - void RegisterCandidates(IEnumerable candidates); - void RegisterCandidate(IEncapsulateFieldCandidate candidate); - } - - public class EncapsulateFieldValidationsProvider : IEncapsulateFieldValidationsProvider - { - private Dictionary _nameOnlyValidators; - - private List _candidates; - private List _udtMemberCandidates; - - public EncapsulateFieldValidationsProvider() - { - _nameOnlyValidators = new Dictionary() - { - [Validators.Default] = new IdentifierOnlyValidator(DeclarationType.Variable, false), - [Validators.UserDefinedType] = new IdentifierOnlyValidator(DeclarationType.UserDefinedType, false), - [Validators.UserDefinedTypeMember] = new IdentifierOnlyValidator(DeclarationType.UserDefinedTypeMember, false), - [Validators.UserDefinedTypeMemberArray] = new IdentifierOnlyValidator(DeclarationType.UserDefinedTypeMember, true), - }; - - _candidates = new List(); - _udtMemberCandidates = new List(); - } - - public IValidateVBAIdentifiers NameOnlyValidator(Validators validatorType) - => _nameOnlyValidators[validatorType]; - - public IEncapsulateFieldConflictFinder ConflictDetector(EncapsulateFieldStrategy strategy, IDeclarationFinderProvider declarationFinderProvider) - { - if (strategy == EncapsulateFieldStrategy.UseBackingFields) - { - return new ConflictDetectorUseBackingFields(declarationFinderProvider, _candidates, _udtMemberCandidates); - } - return new ConflictDetectorConvertFieldsToUDTMembers(declarationFinderProvider, _candidates, _udtMemberCandidates); - } - - public void RegisterCandidate(IEncapsulateFieldCandidate candidate) - { - _candidates.Add(candidate); - } - - public void RegisterCandidates(IEnumerable candidates) - { - _candidates.AddRange(candidates); - foreach (var udtCandidate in candidates.Where(c => c is IUserDefinedTypeCandidate).Cast()) - { - foreach (var member in udtCandidate.Members) - { - _udtMemberCandidates.Add(member); - } - } - } - - private class IdentifierOnlyValidator : IValidateVBAIdentifiers - { - private DeclarationType _declarationType; - private bool _isArray; - public IdentifierOnlyValidator(DeclarationType declarationType, bool isArray = false) - { - _declarationType = declarationType; - _isArray = isArray; - } - - public bool IsValidVBAIdentifier(string identifier, out string errorMessage) - => !VBAIdentifierValidator.TryMatchInvalidIdentifierCriteria(identifier, _declarationType, out errorMessage, _isArray); - - public bool IsValidUDTMemberIdentifier(string identifier, bool isArray, out string errorMessage) - => !VBAIdentifierValidator.TryMatchInvalidIdentifierCriteria(identifier, DeclarationType.UserDefinedTypeMember, out errorMessage, _isArray); - } - } -} diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs index b268540530..7a8929c7ba 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs @@ -5,6 +5,7 @@ using Rubberduck.VBEditor; using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Text; @@ -20,26 +21,10 @@ public class ConvertFieldsToUDTMembers : EncapsulateFieldStrategyBase public ConvertFieldsToUDTMembers(IDeclarationFinderProvider declarationFinderProvider, EncapsulateFieldModel model, IIndenter indenter) : base(declarationFinderProvider, model, indenter) { - model.AssignCandidateValidations(EncapsulateFieldStrategy.ConvertFieldsToUDTMembers); _convertedFields = new List(); - if (File.Exists("C:\\Users\\Brian\\Documents\\UseNewUDTStructure.txt")) - { - foreach (var field in model.SelectedFieldCandidates) - { - _convertedFields.Add(new ConvertToUDTMember(field, model.StateUDTField)); - } - } - else - { - _convertedFields = model.SelectedFieldCandidates.Cast().ToList(); - } - foreach (var convert in _convertedFields) + foreach (var field in model.SelectedFieldCandidates) { - convert.NameValidator = convert.Declaration.IsArray - ? model.ValidatorProvider.NameOnlyValidator(Validators.UserDefinedTypeMemberArray) - : model.ValidatorProvider.NameOnlyValidator(Validators.UserDefinedTypeMember); - - convert.ConflictFinder = model.ValidatorProvider.ConflictDetector(EncapsulateFieldStrategy.ConvertFieldsToUDTMembers, declarationFinderProvider); + _convertedFields.Add(new ConvertToUDTMember(field, model.StateUDTField)); } _stateUDTField = model.StateUDTField; } @@ -48,7 +33,7 @@ protected override void ModifyFields(EncapsulateFieldModel model, IEncapsulateFi { var rewriter = refactorRewriteSession.CheckOutModuleRewriter(_targetQMN); - foreach (var field in model.SelectedFieldCandidates) + foreach (var field in _convertedFields) { refactorRewriteSession.Remove(field.Declaration, rewriter); } @@ -63,9 +48,9 @@ protected override void ModifyFields(EncapsulateFieldModel model, IEncapsulateFi protected override void ModifyReferences(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) { - foreach (var field in model.SelectedFieldCandidates) + foreach (var field in _convertedFields) { - field.LoadFieldReferenceContextReplacements(_stateUDTField.FieldIdentifier); + LoadFieldReferenceContextReplacements(field); } RewriteReferences(model, refactorRewriteSession); @@ -85,8 +70,7 @@ protected override void LoadNewDeclarationBlocks(EncapsulateFieldModel model) protected override void LoadNewPropertyBlocks(EncapsulateFieldModel model) { - var propertyGenerationSpecs = _convertedFields // model.SelectedFieldCandidates - .SelectMany(f => f.PropertyAttributeSets); + var propertyGenerationSpecs = _convertedFields.SelectMany(f => f.PropertyAttributeSets); var generator = new PropertyGenerator(); foreach (var spec in propertyGenerationSpecs) @@ -94,5 +78,47 @@ protected override void LoadNewPropertyBlocks(EncapsulateFieldModel model) AddContentBlock(NewContentTypes.MethodBlock, generator.AsPropertyBlock(spec, _indenter)); } } + + protected override void LoadFieldReferenceContextReplacements(IEncapsulatableField field) + { + Debug.Assert(field is IConvertToUDTMember); + + var converted = field as IConvertToUDTMember; + if (converted.WrappedCandidate is IUserDefinedTypeCandidate udt && udt.TypeDeclarationIsPrivate) + { + foreach (var member in udt.Members) + { + foreach (var idRef in member.ParentContextReferences) + { + var replacementText = member.ReferenceAccessor(idRef); + if (IsExternalReferenceRequiringModuleQualification(idRef)) + { + replacementText = $"{udt.QualifiedModuleName.ComponentName}.{replacementText}"; + } + + SetUDTMemberReferenceRewriteContent(idRef, replacementText); + } + } + } + else + { + foreach (var idRef in field.Declaration.References) + { + var replacementText = converted.ReferenceAccessor(idRef); + + if (IsExternalReferenceRequiringModuleQualification(idRef)) + { + replacementText = $"{converted.QualifiedModuleName.ComponentName}.{replacementText}"; + } + + if (converted.Declaration.IsArray) + { + replacementText = $"{_stateUDTField.FieldIdentifier}.{replacementText}"; + } + + SetReferenceRewriteContent(idRef, replacementText); + } + } + } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs index 0783fefa64..1e15e872cc 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs @@ -1,4 +1,5 @@ using Antlr4.Runtime; +using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; @@ -24,11 +25,13 @@ public abstract class EncapsulateFieldStrategyBase : IEncapsulateStrategy protected QualifiedModuleName _targetQMN; private readonly int? _codeSectionStartIndex; + protected Dictionary IdentifierReplacements { get; } = new Dictionary(); + protected enum NewContentTypes { TypeDeclarationBlock, DeclarationBlock, MethodBlock, PostContentMessage }; protected Dictionary> _newContent { set; get; } private static string DoubleSpace => $"{Environment.NewLine}{Environment.NewLine}"; - protected IEnumerable SelectedFields { private set; get; } + protected IEnumerable SelectedFields { private set; get; } public EncapsulateFieldStrategyBase(IDeclarationFinderProvider declarationFinderProvider, EncapsulateFieldModel model, IIndenter indenter) { @@ -61,11 +64,10 @@ public IEncapsulateFieldRewriteSession RefactorRewrite(EncapsulateFieldModel mod protected void RewriteReferences(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) { - //foreach (var rewriteReplacement in model.SelectedFieldCandidates.SelectMany(field => field.ReferenceReplacements)) - foreach (var rewriteReplacement in SelectedFields.SelectMany(field => field.ReferenceReplacements)) + foreach (var replacement in IdentifierReplacements) { - (ParserRuleContext Context, string Text) = rewriteReplacement.Value; - var rewriter = refactorRewriteSession.CheckOutModuleRewriter(rewriteReplacement.Key.QualifiedModuleName); + (ParserRuleContext Context, string Text) = replacement.Value; + var rewriter = refactorRewriteSession.CheckOutModuleRewriter(replacement.Key.QualifiedModuleName); rewriter.Replace(Context, Text); } } @@ -89,7 +91,7 @@ private void InsertNewContent(EncapsulateFieldModel model, IEncapsulateFieldRewr if (isPreview) { - AddContentBlock(NewContentTypes.PostContentMessage, EncapsulateFieldResources.PreviewEndOfChangesMarker); + AddContentBlock(NewContentTypes.PostContentMessage, EncapsulateFieldResources.PreviewMarker); } var newContentBlock = string.Join(DoubleSpace, @@ -112,8 +114,7 @@ private void InsertNewContent(EncapsulateFieldModel model, IEncapsulateFieldRewr protected virtual void LoadNewPropertyBlocks(EncapsulateFieldModel model) { - var propertyGenerationSpecs = SelectedFields // model.SelectedFieldCandidates - .SelectMany(f => f.PropertyAttributeSets); + var propertyGenerationSpecs = SelectedFields.SelectMany(f => f.PropertyAttributeSets); var generator = new PropertyGenerator(); foreach (var spec in propertyGenerationSpecs) @@ -121,5 +122,90 @@ protected virtual void LoadNewPropertyBlocks(EncapsulateFieldModel model) AddContentBlock(NewContentTypes.MethodBlock, generator.AsPropertyBlock(spec, _indenter)); } } + + protected virtual void LoadFieldReferenceContextReplacements(IEncapsulatableField field) + { + if (field is IUserDefinedTypeCandidate udt && udt.TypeDeclarationIsPrivate) + { + foreach (var member in udt.Members) + { + foreach (var idRef in member.ParentContextReferences) + { + var replacementText = member.ReferenceAccessor(idRef); + SetUDTMemberReferenceRewriteContent(idRef, replacementText); + } + } + } + else + { + foreach (var idRef in field.Declaration.References) + { + var replacementText = field.ReferenceAccessor(idRef); + if (IsExternalReferenceRequiringModuleQualification(idRef)) + { + replacementText = $"{field.QualifiedModuleName.ComponentName}.{replacementText}"; + } + SetReferenceRewriteContent(idRef, replacementText); + } + } + } + + protected bool IsExternalReferenceRequiringModuleQualification(IdentifierReference idRef) + { + var isLHSOfMemberAccess = + (idRef.Context.Parent is VBAParser.MemberAccessExprContext + || idRef.Context.Parent is VBAParser.WithMemberAccessExprContext) + && !(idRef.Context == idRef.Context.Parent.GetChild(0)); + + return idRef.QualifiedModuleName != idRef.Declaration.QualifiedModuleName + && !isLHSOfMemberAccess; + } + + protected virtual void SetReferenceRewriteContent(IdentifierReference idRef, string replacementText) + { + if (idRef.Context is VBAParser.IndexExprContext idxExpression) + { + AddIdentifierReplacement(idRef, idxExpression.children.ElementAt(0) as ParserRuleContext, replacementText); + } + else if (idRef.Context is VBAParser.UnrestrictedIdentifierContext + || idRef.Context is VBAParser.SimpleNameExprContext) + { + AddIdentifierReplacement(idRef, idRef.Context, replacementText); + } + else if (idRef.Context.TryGetAncestor(out var wmac)) + { + AddIdentifierReplacement(idRef, wmac.GetChild(), replacementText); + } + else if (idRef.Context.TryGetAncestor(out var maec)) + { + AddIdentifierReplacement(idRef, maec, replacementText); + } + } + + protected virtual void SetUDTMemberReferenceRewriteContent(IdentifierReference idRef, string replacementText) + { + if (idRef.Context is VBAParser.IndexExprContext idxExpression) + { + AddIdentifierReplacement(idRef, idxExpression.children.ElementAt(0) as ParserRuleContext, replacementText); + } + else if (idRef.Context.TryGetAncestor(out var wmac)) + { + AddIdentifierReplacement(idRef, wmac.GetChild(), replacementText); + } + else if (idRef.Context.TryGetAncestor(out var maec)) + { + AddIdentifierReplacement(idRef, maec, replacementText); + } + } + + private void AddIdentifierReplacement( IdentifierReference idRef, ParserRuleContext context, string replacementText) + { + if (IdentifierReplacements.ContainsKey(idRef)) + { + IdentifierReplacements[idRef] = (context, replacementText); + return; + } + IdentifierReplacements.Add(idRef, (context, replacementText)); + } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/UseBackingFields.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/UseBackingFields.cs index dd4692f0bb..8a88efee9c 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/UseBackingFields.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/UseBackingFields.cs @@ -15,31 +15,8 @@ namespace Rubberduck.Refactorings.EncapsulateField { public class UseBackingFields : EncapsulateFieldStrategyBase { - //private IEnumerable _convertedFields; public UseBackingFields(IDeclarationFinderProvider declarationFinderProvider, EncapsulateFieldModel model, IIndenter indenter) - : base(declarationFinderProvider, model, indenter) - { - //_convertedFields = model.SelectedFieldCandidates; //.Cast().ToList(); - model.AssignCandidateValidations(EncapsulateFieldStrategy.UseBackingFields); - //foreach (var candidate in _convertedFields) - //{ - // if (candidate is IUserDefinedTypeCandidate) - // { - // candidate.NameValidator = model.ValidatorProvider.NameOnlyValidator(Validators.UserDefinedType); - // } - // else if (candidate is IUserDefinedTypeMemberCandidate) - // { - // candidate.NameValidator = candidate.Declaration.IsArray - // ? model.ValidatorProvider.NameOnlyValidator(Validators.UserDefinedTypeMemberArray) - // : model.ValidatorProvider.NameOnlyValidator(Validators.UserDefinedTypeMember); - // } - // else - // { - // candidate.NameValidator = model.ValidatorProvider.NameOnlyValidator(Validators.Default); - // } - // candidate.ConflictFinder = model.ValidatorProvider.ConflictDetector(EncapsulateFieldStrategy.UseBackingFields, declarationFinderProvider); - //} - } + : base(declarationFinderProvider, model, indenter) { } protected override void ModifyFields(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) { @@ -47,7 +24,7 @@ protected override void ModifyFields(EncapsulateFieldModel model, IEncapsulateFi foreach (var field in SelectedFields) { - if (field.Declaration.HasPrivateAccessibility() && field.FieldIdentifier.Equals(field.Declaration.IdentifierName)) + if (field.Declaration.HasPrivateAccessibility() && field.BackingIdentifier.Equals(field.Declaration.IdentifierName)) { rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); continue; @@ -59,7 +36,7 @@ protected override void ModifyFields(EncapsulateFieldModel model, IEncapsulateFi continue; } - rewriter.Rename(field.Declaration, field.FieldIdentifier); + rewriter.Rename(field.Declaration, field.BackingIdentifier); rewriter.SetVariableVisiblity(field.Declaration, Accessibility.Private.TokenString()); rewriter.MakeImplicitDeclarationTypeExplicit(field.Declaration); } @@ -69,7 +46,7 @@ protected override void ModifyReferences(EncapsulateFieldModel model, IEncapsula { foreach (var field in SelectedFields) { - field.LoadFieldReferenceContextReplacements(); + LoadFieldReferenceContextReplacements(field); } RewriteReferences(model, refactorRewriteSession); @@ -84,7 +61,7 @@ protected override void LoadNewDeclarationBlocks(EncapsulateFieldModel model) foreach (var field in fieldsRequiringNewDeclaration) { - var targetIdentifier = field.Declaration.Context.GetText().Replace(field.IdentifierName, field.FieldIdentifier); + var targetIdentifier = field.Declaration.Context.GetText().Replace(field.IdentifierName, field.BackingIdentifier); var newField = field.Declaration.IsTypeSpecified ? $"{Tokens.Private} {targetIdentifier}" : $"{Tokens.Private} {targetIdentifier} {Tokens.As} {field.Declaration.AsTypeName}"; diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs index c1b5c553d6..6dadb8506d 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs @@ -7,7 +7,7 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface IArrayCandidate : IEncapsulateFieldCandidate + public interface IArrayCandidate : IEncapsulatableField { string UDTMemberDeclaration { get;} } @@ -20,7 +20,6 @@ public ArrayCandidate(Declaration declaration, IValidateVBAIdentifiers validator { ImplementLet = false; ImplementSet = false; - FieldAsTypeName = declaration.AsTypeName; PropertyAsTypeName = Tokens.Variant; CanBeReadWrite = false; IsReadOnly = true; @@ -32,61 +31,17 @@ public ArrayCandidate(Declaration declaration, IValidateVBAIdentifiers validator } } - private bool HasExternalRedimOperation - => Declaration.References.Any(rf => rf.QualifiedModuleName != QualifiedModuleName - && rf.Context.TryGetAncestor(out _)); - - public override bool TryValidateEncapsulationAttributes(out string errorMessage) - { - return ConflictFinder.TryValidateEncapsulationAttributes(this, out errorMessage); - } - - public override void LoadFieldReferenceContextReplacements(string referenceQualifier = null) - { - ReferenceQualifier = referenceQualifier; - foreach (var idRef in Declaration.References) - { - //Locally, we do all operations using the backing field - if (idRef.QualifiedModuleName == QualifiedModuleName) - { - var accessor = ConvertFieldToUDTMember - ? ReferenceForPreExistingReferences - : FieldIdentifier; - - SetReferenceRewriteContent(idRef, accessor); - continue; - } - - var replacementText = RequiresAccessQualification(idRef) - ? $"{QualifiedModuleName.ComponentName}.{ReferenceForPreExistingReferences}" - : ReferenceForPreExistingReferences; - - SetReferenceRewriteContent(idRef, replacementText); - } - } - - protected override void SetReferenceRewriteContent(IdentifierReference idRef, string replacementText) - { - var context = idRef.Context; - if (idRef.Context is VBAParser.IndexExprContext idxExpression) - { - context = idxExpression.children.ElementAt(0) as ParserRuleContext; - } - if (IdentifierReplacements.ContainsKey(idRef)) - { - IdentifierReplacements[idRef] = (context, replacementText); - return; - } - IdentifierReplacements.Add(idRef, (context, replacementText)); - } + public string UDTMemberDeclaration + => $"{PropertyIdentifier}({_subscripts}) {Tokens.As} {Declaration.AsTypeName}"; - public override string AccessorInProperty - => $"{ObjectStateUDT.FieldIdentifier}.{UDTMemberIdentifier}"; + protected override string AccessorInProperty + => $"{BackingIdentifier}"; - public override string AccessorLocalReference - => $"{ObjectStateUDT.FieldIdentifier}.{UDTMemberIdentifier}"; + protected override string AccessorLocalReference(IdentifierReference idRef) + => $"{BackingIdentifier}"; - public override string UDTMemberDeclaration - => $"{PropertyIdentifier}({_subscripts}) {Tokens.As} {Declaration.AsTypeName}"; + private bool HasExternalRedimOperation + => Declaration.References.Any(rf => rf.QualifiedModuleName != QualifiedModuleName + && rf.Context.TryGetAncestor(out _)); } } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs index 7e880323e5..874251cd91 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs @@ -3,27 +3,31 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using Antlr4.Runtime; +using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.VBEditor; namespace Rubberduck.Refactorings.EncapsulateField { + public interface IConvertToUDTMember : IEncapsulatableField + { + string UDTMemberDeclaration { get; } + IObjectStateUDT ObjectStateUDT { set; get; } + IEncapsulatableField WrappedCandidate { get; } + } + public class ConvertToUDTMember : IConvertToUDTMember { private readonly IEncapsulatableField _wrapped; public ConvertToUDTMember(IEncapsulatableField candidate, IObjectStateUDT objStateUDT) { _wrapped = candidate; + BackingIdentifier = _wrapped.PropertyIdentifier; ObjectStateUDT = objStateUDT; } - public string UDTMemberIdentifier - { - set => _wrapped.PropertyIdentifier = value; - get => _wrapped.PropertyIdentifier; - } - public virtual string UDTMemberDeclaration { get @@ -32,10 +36,12 @@ public virtual string UDTMemberDeclaration { return array.UDTMemberDeclaration; } - return $"{_wrapped.PropertyIdentifier} As {_wrapped.AsTypeName}"; + return $"{BackingIdentifier} As {_wrapped.AsTypeName}"; } } + public IEncapsulatableField WrappedCandidate => _wrapped; + public IObjectStateUDT ObjectStateUDT { set; get; } public string TargetID => _wrapped.TargetID; @@ -54,11 +60,11 @@ public string PropertyIdentifier get => _wrapped.PropertyIdentifier; } - public string PropertyAsTypeName - { - set => _wrapped.PropertyAsTypeName = value; - get => _wrapped.PropertyAsTypeName; - } + public string PropertyAsTypeName => _wrapped.PropertyAsTypeName; + + public string BackingIdentifier { get; set; } + + public string BackingAsTypeName => Declaration.AsTypeName; public bool CanBeReadWrite { @@ -90,23 +96,26 @@ public IEncapsulateFieldConflictFinder ConflictFinder get => _wrapped.ConflictFinder; } - public string AccessorInProperty + private string AccessorInProperty { get { - if (_wrapped is IUserDefinedTypeCandidate udt) + if (_wrapped is IUserDefinedTypeMemberCandidate udtm) { - return $"{ObjectStateUDT.FieldIdentifier}.{udt.PropertyIdentifier}.{UDTMemberIdentifier}"; + return $"{ObjectStateUDT.FieldIdentifier}.{udtm.Parent.PropertyIdentifier}.{BackingIdentifier}"; } - return $"{ObjectStateUDT.FieldIdentifier}.{UDTMemberIdentifier}"; + return $"{ObjectStateUDT.FieldIdentifier}.{BackingIdentifier}"; } } - public string AccessorLocalReference - => $"{ObjectStateUDT.FieldIdentifier}.{UDTMemberIdentifier}"; - - public string AccessorExternalReference - => $"{QualifiedModuleName.ComponentName}.{PropertyIdentifier}"; + public string ReferenceAccessor(IdentifierReference idRef) + { + if (idRef.QualifiedModuleName != QualifiedModuleName) + { + return $"{QualifiedModuleName.ComponentName}.{PropertyIdentifier}"; + } + return $"{BackingIdentifier}"; + } public string IdentifierName => _wrapped.IdentifierName; @@ -119,36 +128,46 @@ public bool TryValidateEncapsulationAttributes(out string errorMessage) return ConflictFinder.TryValidateEncapsulationAttributes(this, out errorMessage); } - public IEnumerable PropertyAttributeSets + public IEnumerable PropertyAttributeSets { get { - //if (TypeDeclarationIsPrivate) - //{ - if (_wrapped is IUserDefinedTypeCandidate udt) + if (_wrapped is IUserDefinedTypeCandidate udt && udt.TypeDeclarationIsPrivate) { - return _wrapped.PropertyAttributeSets; + var sets = new List(); + foreach (var member in udt.Members) + { + sets.Add(CreateMemberPropertyAttributeSet(member)); + } + return sets; } - //var specs = new List(); - //foreach (var member in Members) - //{ - // specs.Add(member.AsPropertyGeneratorSpec); - //} - //return specs; - //} - return new List() { AsPropertyAttributeSet }; + return new List() { AsPropertyAttributeSet }; } } + private PropertyAttributeSet CreateMemberPropertyAttributeSet (IUserDefinedTypeMemberCandidate udtMember) + { + return new PropertyAttributeSet() + { + PropertyName = udtMember.PropertyIdentifier, + BackingField = $"{ObjectStateUDT.FieldIdentifier}.{udtMember.Parent.PropertyIdentifier}.{udtMember.BackingIdentifier}", + AsTypeName = udtMember.PropertyAsTypeName, + ParameterName = udtMember.ParameterName, + GenerateLetter = udtMember.ImplementLet, + GenerateSetter = udtMember.ImplementSet, + UsesSetAssignment = udtMember.Declaration.IsObject, + IsUDTProperty = false //TODO: If udtMember is a UDT, this needs to be true + }; + } - private IPropertyGeneratorAttributes AsPropertyAttributeSet + private PropertyAttributeSet AsPropertyAttributeSet { get { return new PropertyAttributeSet() { PropertyName = PropertyIdentifier, - BackingField = AccessorInProperty, // ReferenceWithinNewProperty, + BackingField = AccessorInProperty, AsTypeName = PropertyAsTypeName, ParameterName = ParameterName, GenerateLetter = ImplementLet, diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateField.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateField.cs deleted file mode 100644 index e0bfdd7eae..0000000000 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateField.cs +++ /dev/null @@ -1,81 +0,0 @@ -using Rubberduck.Parsing.Symbols; -using Rubberduck.VBEditor; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Rubberduck.Refactorings.EncapsulateField -{ - public interface IEncapsulatableField : IEncapsulateFieldRefactoringElement - { - string TargetID { get; } - Declaration Declaration { get; } - bool EncapsulateFlag { get; set; } - string PropertyIdentifier { set; get; } - string PropertyAsTypeName { set; get; } - bool CanBeReadWrite { set; get; } - bool ImplementLet { get; } - bool ImplementSet { get; } - bool IsReadOnly { set; get; } - string ParameterName { get; } - IValidateVBAIdentifiers NameValidator { set; get; } - IEncapsulateFieldConflictFinder ConflictFinder { set; get; } - bool TryValidateEncapsulationAttributes(out string errorMessage); - string AccessorInProperty { get; } - string AccessorLocalReference { get; } - string AccessorExternalReference { /*set;*/ get; } - IEnumerable PropertyAttributeSets { get; } - } - - public interface IUsingBackingField : IEncapsulatableField - { - string FieldIdentifier { set; get; } - string FieldAsTypeName { set; get; } - //string AccessorInProperty { get; } - //string AccessorLocalReference { get; } - //string AccessorExternalReference { set; get; } - } - - public interface IConvertToUDTMember : IEncapsulatableField - { - //string AccessorInProperty { get; } - //string AccessorLocalReference { get; } - //string AccessorExternalReference { set; get; } - string UDTMemberIdentifier { set; get; } - string UDTMemberDeclaration { get; } - IObjectStateUDT ObjectStateUDT { set; get; } - } - - //public class EncapsulateField : IEncapsulatableField, IUsingBackingField//, IConvertToUDTMember - //{ - // private Declaration _declaration; - // public EncapsulateField(Declaration declaration) - // { - // _declaration = declaration; - // } - - // public string IdentifierName => _declaration.IdentifierName; - // public string TargetID => _declaration.IdentifierName; - // public Declaration Declaration => _declaration; - // public QualifiedModuleName QualifiedModuleName => _declaration.QualifiedModuleName; - // public string AsTypeName => _declaration.AsTypeName; - // public bool EncapsulateFlag { set; get; } - // public string PropertyIdentifier { set; get; } - // public string PropertyAsTypeName { set; get; } - // public bool CanBeReadWrite { set; get; } - // public bool ImplementLet { get; } - // public bool ImplementSet { get; } - // public bool IsReadOnly { set; get; } - // public string ParameterName { get; } - // public string AccessorInProperty { set; get; } - // public string AccessorLocalReference { set; get; } - // public string AccessorExternalReference { set; get; } - // public string FieldIdentifier { set; get; } - // public string FieldAsTypeName { set; get; } - // public string UDTMemberIdentifier { set; get; } - // public string UDTMemberDeclaration { set; get; } - // public IObjectStateUDT Parent { set; get; } - //} -} diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs index 7279115a67..d99fcec4ff 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs @@ -3,6 +3,7 @@ using Rubberduck.Parsing.Symbols; using Rubberduck.Refactorings.EncapsulateField.Extensions; using Rubberduck.VBEditor; +using Rubberduck.VBEditor.SafeComWrappers; using System; using System.Collections.Generic; @@ -15,33 +16,32 @@ public interface IEncapsulateFieldRefactoringElement string AsTypeName { get; } } - public interface IEncapsulateFieldCandidate : IUsingBackingField + public interface IEncapsulatableField : IEncapsulateFieldRefactoringElement { - //IEnumerable PropertyAttributeSets { get; } - IEnumerable> ReferenceReplacements { get; } - string ReferenceQualifier { set; get; } - void LoadFieldReferenceContextReplacements(string referenceQualifier = null); - bool ConvertFieldToUDTMember { set; get; } + string TargetID { get; } + Declaration Declaration { get; } + bool EncapsulateFlag { get; set; } + string BackingIdentifier { set; get; } + string BackingAsTypeName { /*set;*/ get; } + string PropertyIdentifier { set; get; } + string PropertyAsTypeName { /*set;*/ get; } + bool CanBeReadWrite { set; get; } + bool ImplementLet { get; } + bool ImplementSet { get; } + bool IsReadOnly { set; get; } + string ParameterName { get; } + IValidateVBAIdentifiers NameValidator { set; get; } + IEncapsulateFieldConflictFinder ConflictFinder { set; get; } + bool TryValidateEncapsulationAttributes(out string errorMessage); + string ReferenceAccessor(IdentifierReference idRef); + IEnumerable PropertyAttributeSets { get; } } - public enum AccessorMember { Field, Property } - - public interface IEncapsulateFieldCandidateValidations + public interface IUsingBackingField : IEncapsulatableField { - bool HasConflictingPropertyIdentifier { get; } - bool HasConflictingFieldIdentifier { get; } } - //public class ConvertedToUDTMember : IConvertToUDTMember - //{ - // private IEncapsulatableField _field; - // public ConvertedToUDTMember(IEncapsulatableField field) - // { - - // } - //} - - public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate, IEncapsulateFieldCandidateValidations, IConvertToUDTMember//, IAssignNoConflictNames + public class EncapsulateFieldCandidate : IEncapsulatableField { protected Declaration _target; protected QualifiedModuleName _qmn; @@ -49,19 +49,15 @@ public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate, IEncapsulat private string _identifierName; protected EncapsulationIdentifiers _fieldAndProperty; - public EncapsulateFieldCandidate(Declaration declaration, IValidateVBAIdentifiers identifierValidator) // Predicate nameValidator/*, IValidateEncapsulateFieldNames validator*/) + public EncapsulateFieldCandidate(Declaration declaration, IValidateVBAIdentifiers identifierValidator) { _target = declaration; NameValidator = identifierValidator; - _fieldAndProperty = new EncapsulationIdentifiers(declaration.IdentifierName, identifierValidator); // (string name) => nameValidator(name)); // (string name) => NamesValidator.IsValidVBAIdentifier(name, DeclarationType.Property, out _)); + _fieldAndProperty = new EncapsulationIdentifiers(declaration.IdentifierName, identifierValidator); IdentifierName = declaration.IdentifierName; - FieldAsTypeName = declaration.AsTypeName; PropertyAsTypeName = declaration.AsTypeName; _qmn = declaration.QualifiedModuleName; - NewPropertyAccessor = AccessorMember.Field; - //_accessoryInProperty = _fieldAndProperty.Field; - ReferenceAccessor = AccessorMember.Property; CanBeReadWrite = true; @@ -95,58 +91,20 @@ public EncapsulateFieldCandidate(Declaration declaration, IValidateVBAIdentifier public string AsTypeName => _target.AsTypeName; - public virtual string FieldIdentifier + public virtual string BackingIdentifier { get => _fieldAndProperty.Field; set => _fieldAndProperty.Field = value; } - public string FieldAsTypeName { set; get; } - //private string _accessoryInProperty; - //public virtual string AccessorInProperty //{ get; } - // => _fieldAndProperty.Field; // AccessorMemberToContent(NewPropertyAccessor); - //public string AccessorLocalReference { /*set;*/ get; } - //public string AccessorExternalReference { set; get; } + public string BackingAsTypeName => Declaration.AsTypeName; public virtual IValidateVBAIdentifiers NameValidator { set; get; } public virtual IEncapsulateFieldConflictFinder ConflictFinder { set; get; } - public bool HasConflictingPropertyIdentifier - => ConflictFinder.HasConflictingIdentifier(this, DeclarationType.Property, out var errorMessage); - - public bool HasConflictingFieldIdentifier - => ConflictFinder.HasConflictingIdentifier(this, DeclarationType.Variable, out var errorMessage); - - public virtual bool TryValidateEncapsulationAttributes(out string errorMessage) - { - return ConflictFinder.TryValidateEncapsulationAttributes(this, out errorMessage); - } - - public virtual IEnumerable> ReferenceReplacements - { - get - { - var results = new List>(); - foreach (var replacement in IdentifierReplacements) - { - var kv = new KeyValuePair - (replacement.Key, replacement.Value); - results.Add(kv); - } - return results; - } - } - - protected virtual void SetReferenceRewriteContent(IdentifierReference idRef, string replacementText) - { - if (IdentifierReplacements.ContainsKey(idRef)) - { - IdentifierReplacements[idRef] = (idRef.Context, replacementText); - return; - } - IdentifierReplacements.Add(idRef, (idRef.Context, replacementText)); - } + public bool TryValidateEncapsulationAttributes(out string errorMessage) + => ConflictFinder.TryValidateEncapsulationAttributes(this, out errorMessage); public virtual string TargetID => _target?.IdentifierName ?? IdentifierName; @@ -169,49 +127,44 @@ public virtual bool EncapsulateFlag public virtual bool IsReadOnly { set; get; } public bool CanBeReadWrite { set; get; } - public virtual string PropertyName - { - get => PropertyIdentifier; - set => PropertyIdentifier = value; - } - public override bool Equals(object obj) { return obj != null - && obj is IEncapsulateFieldCandidate efc + && obj is IEncapsulatableField efc && $"{efc.QualifiedModuleName.Name}.{efc.TargetID}" == $"{_qmn.Name}.{IdentifierName}"; } public override int GetHashCode() => _hashCode; - /* - * IConvertToUDTMemberInterface - */ - public virtual string AccessorInProperty - => $"{ObjectStateUDT.FieldIdentifier}.{UDTMemberIdentifier}"; - public virtual string AccessorLocalReference - => $"{ObjectStateUDT.FieldIdentifier}.{PropertyIdentifier}"; + protected virtual string AccessorInProperty + => $"{BackingIdentifier}"; + + public string ReferenceAccessor(IdentifierReference idRef) + { + if (idRef.QualifiedModuleName != QualifiedModuleName) + { + return AccessorExternalReference(idRef); + } + return AccessorLocalReference(idRef); + } + + protected virtual string AccessorLocalReference(IdentifierReference idRef) + => PropertyIdentifier; + + protected virtual string AccessorExternalReference(IdentifierReference idRef) + => PropertyIdentifier; - public string AccessorExternalReference { set; get; } public string PropertyIdentifier { get => _fieldAndProperty.Property; set { _fieldAndProperty.Property = value; - UDTMemberIdentifier = value; TryRestoreNewFieldNameAsOriginalFieldIdentifierName(); } } - public string UDTMemberIdentifier { set; get; } - - public virtual string UDTMemberDeclaration - => $"{PropertyIdentifier} {Tokens.As} {FieldAsTypeName}"; - - public IObjectStateUDT ObjectStateUDT { set; get; } - private void TryRestoreNewFieldNameAsOriginalFieldIdentifierName() { var canNowUseOriginalFieldName = !_fieldAndProperty.TargetFieldName.IsEquivalentVBAIdentifierTo(_fieldAndProperty.Property) @@ -229,7 +182,7 @@ private void TryRestoreNewFieldNameAsOriginalFieldIdentifierName() var isConflictingFieldIdentifier = ConflictFinder.HasConflictingIdentifier(this, DeclarationType.Variable, out _); for (var count = 1; count < 10 && isConflictingFieldIdentifier; count++) { - FieldIdentifier = FieldIdentifier.IncrementEncapsulationIdentifier(); + BackingIdentifier = BackingIdentifier.IncrementEncapsulationIdentifier(); isConflictingFieldIdentifier = ConflictFinder.HasConflictingIdentifier(this, DeclarationType.Variable, out _); } } @@ -255,56 +208,19 @@ public string IdentifierName private bool _implSet; public bool ImplementSet { get => !IsReadOnly && _implSet; set => _implSet = value; } - public bool ConvertFieldToUDTMember { set; get; } - public EncapsulateFieldStrategy EncapsulateFieldStrategy { set; get; } = EncapsulateFieldStrategy.UseBackingFields; - public virtual IEnumerable PropertyAttributeSets - => new List() { AsPropertyAttributeSet }; + public virtual IEnumerable PropertyAttributeSets + => new List() { AsPropertyAttributeSet }; - public virtual void LoadFieldReferenceContextReplacements(string referenceQualifier = null) - { - ReferenceQualifier = referenceQualifier; - foreach (var idRef in Declaration.References) - { - var replacementText = RequiresAccessQualification(idRef) - ? $"{QualifiedModuleName.ComponentName}.{ReferenceForPreExistingReferences}" - : ReferenceForPreExistingReferences; - - SetReferenceRewriteContent(idRef, replacementText); - } - } - - protected AccessorMember NewPropertyAccessor { set; get; } - - protected AccessorMember ReferenceAccessor { set; get; } - - protected virtual string ReferenceWithinNewProperty - => AccessorMemberToContent(NewPropertyAccessor); - - protected virtual string ReferenceForPreExistingReferences - => AccessorMemberToContent(ReferenceAccessor); - - private string AccessorMemberToContent(AccessorMember accessorMember) - { - if ((ReferenceQualifier?.Length ?? 0) > 0) - { - return $"{ReferenceQualifier}.{PropertyIdentifier}"; - } - - return accessorMember == AccessorMember.Field - ? FieldIdentifier - : PropertyIdentifier; - } - - protected virtual IPropertyGeneratorAttributes AsPropertyAttributeSet + protected virtual PropertyAttributeSet AsPropertyAttributeSet { get { return new PropertyAttributeSet() { PropertyName = PropertyIdentifier, - BackingField = ReferenceWithinNewProperty, + BackingField = AccessorInProperty, AsTypeName = PropertyAsTypeName, ParameterName = ParameterName, GenerateLetter = ImplementLet, @@ -314,16 +230,5 @@ protected virtual IPropertyGeneratorAttributes AsPropertyAttributeSet }; } } - - protected virtual bool RequiresAccessQualification(IdentifierReference idRef) - { - var isLHSOfMemberAccess = - (idRef.Context.Parent is VBAParser.MemberAccessExprContext - || idRef.Context.Parent is VBAParser.WithMemberAccessExprContext) - && !(idRef.Context == idRef.Context.Parent.GetChild(0)); - - return idRef.QualifiedModuleName != idRef.Declaration.QualifiedModuleName - && !isLHSOfMemberAccess; - } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs index 436bae01a8..9ac7882d12 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs @@ -10,7 +10,7 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface IUserDefinedTypeCandidate : IEncapsulateFieldCandidate + public interface IUserDefinedTypeCandidate : IEncapsulatableField { IEnumerable Members { get; } void AddMember(IUserDefinedTypeMemberCandidate member); @@ -20,12 +20,9 @@ public interface IUserDefinedTypeCandidate : IEncapsulateFieldCandidate public class UserDefinedTypeCandidate : EncapsulateFieldCandidate, IUserDefinedTypeCandidate { - public UserDefinedTypeCandidate(Declaration declaration, IValidateVBAIdentifiers identifierValidator) // Predicate nameValidator/*, IValidateEncapsulateFieldNames validator*/) + public UserDefinedTypeCandidate(Declaration declaration, IValidateVBAIdentifiers identifierValidator) : base(declaration, identifierValidator) { - NewPropertyAccessor = AccessorMember.Field; - ReferenceAccessor = AccessorMember.Field; - //AccessorInProperty = AccessorMember.Field; } public void AddMember(IUserDefinedTypeMemberCandidate member) @@ -45,7 +42,7 @@ public bool CanBeObjectStateUDT get => _canBeObjectStateUDT; } - public override string FieldIdentifier + public override string BackingIdentifier { get => TypeDeclarationIsPrivate ? _fieldAndProperty.TargetFieldName : _fieldAndProperty.Field; set => _fieldAndProperty.Field = value; @@ -79,22 +76,6 @@ public override IEncapsulateFieldConflictFinder ConflictFinder get => _conflictsValidator; } - - - private string _referenceQualifier; - public override string ReferenceQualifier - { - set - { - _referenceQualifier = value; - foreach( var member in Members) - { - member.ReferenceQualifier = ReferenceWithinNewProperty; - } - } - get => _referenceQualifier; - } - private bool _isReadOnly; public override bool IsReadOnly { @@ -109,16 +90,13 @@ public override bool IsReadOnly } } - //public override string AccessorInProperty - // => AccessorMemberToContent(NewPropertyAccessor); - public override bool EncapsulateFlag { set { if (TypeDeclarationIsPrivate) { - foreach (var member in Members.Where(m => !m.ConvertFieldToUDTMember && m.IsExistingMember)) + foreach (var member in Members) { member.EncapsulateFlag = value; if (!member.EncapsulateFlag || !ConflictFinder.HasConflictingIdentifier(member, DeclarationType.Property, out _)) @@ -130,7 +108,7 @@ public override bool EncapsulateFlag //Type within the module. //Try to use a name involving the parent's identifier to make it unique/meaningful //before giving up and creating incremented value(s). - member.PropertyIdentifier = $"{FieldIdentifier.CapitalizeFirstLetter()}{member.PropertyIdentifier.CapitalizeFirstLetter()}"; + member.PropertyIdentifier = $"{BackingIdentifier.CapitalizeFirstLetter()}{member.PropertyIdentifier.CapitalizeFirstLetter()}"; ConflictFinder.AssignNoConflictIdentifier(member, DeclarationType.Property); } } @@ -139,62 +117,33 @@ public override bool EncapsulateFlag get => _encapsulateFlag; } - public override void LoadFieldReferenceContextReplacements(string referenceQualifier = null) + protected override string AccessorInProperty + => $"{BackingIdentifier}"; + + protected override string AccessorLocalReference(IdentifierReference idRef) { - ReferenceQualifier = referenceQualifier; - if (TypeDeclarationIsPrivate) + if (idRef.Context.Parent.Parent is VBAParser.WithStmtContext wsc) { - LoadPrivateUDTFieldLocalReferenceExpressions(); - LoadUDTMemberReferenceExpressions(); - return; + return BackingIdentifier; } - foreach (var idRef in Declaration.References) - { - var replacementText = RequiresAccessQualification(idRef) - ? $"{QualifiedModuleName.ComponentName}.{PropertyIdentifier}" - : PropertyIdentifier; - - SetReferenceRewriteContent(idRef, replacementText); - } + return TypeDeclarationIsPrivate ? $"{BackingIdentifier}" : $"{PropertyIdentifier}"; } - public override IEnumerable PropertyAttributeSets + public override IEnumerable PropertyAttributeSets { get { if (TypeDeclarationIsPrivate) { - var specs = new List(); + var specs = new List(); foreach (var member in Members) { specs.Add(member.AsPropertyGeneratorSpec); } return specs; } - return new List() { AsPropertyAttributeSet }; - } - } - - public override IEnumerable> ReferenceReplacements - { - get - { - var results = new List>(); - foreach (var replacement in IdentifierReplacements) - { - var kv = new KeyValuePair - (replacement.Key, replacement.Value); - results.Add(kv); - } - - foreach (var replacement in Members.SelectMany(m => m.IdentifierReplacements)) - { - var kv = new KeyValuePair - (replacement.Key, replacement.Value); - results.Add(kv); - } - return results; + return new List() { AsPropertyAttributeSet }; } } @@ -212,37 +161,14 @@ public override int GetHashCode() return base.GetHashCode(); } - public override bool TryValidateEncapsulationAttributes(out string errorMessage) - { - return ConflictFinder.TryValidateEncapsulationAttributes(this, out errorMessage); - //errorMessage = string.Empty; - //if (!EncapsulateFlag) { return true; } - - //if (!NameValidator.IsValidVBAIdentifier(PropertyName, out errorMessage)) - //{ - // return false; - //} - - //if (ConflictFinder.HasConflictingIdentifier(this, DeclarationType.Property, out errorMessage)) - //{ - // return false; - //} - - //if (ConflictFinder.HasConflictingIdentifier(this, DeclarationType.Variable, out errorMessage)) - //{ - // return false; - //} - //return true; - } - - protected override IPropertyGeneratorAttributes AsPropertyAttributeSet + protected override PropertyAttributeSet AsPropertyAttributeSet { get { return new PropertyAttributeSet() { PropertyName = PropertyIdentifier, - BackingField = ReferenceWithinNewProperty, + BackingField = AccessorInProperty, AsTypeName = PropertyAsTypeName, ParameterName = ParameterName, GenerateLetter = ImplementLet, @@ -253,24 +179,5 @@ protected override IPropertyGeneratorAttributes AsPropertyAttributeSet } } - private void LoadPrivateUDTFieldLocalReferenceExpressions() - { - foreach (var idRef in Declaration.References) - { - if (idRef.QualifiedModuleName == QualifiedModuleName - && idRef.Context.Parent.Parent is VBAParser.WithStmtContext wsc) - { - SetReferenceRewriteContent(idRef, FieldIdentifier); - } - } - } - - private void LoadUDTMemberReferenceExpressions() - { - foreach (var member in Members) - { - member.LoadReferenceExpressions(); - } - } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs index a73c855e4b..c7e420d418 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs @@ -9,41 +9,36 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface IUserDefinedTypeMemberCandidate : IEncapsulateFieldCandidate + public interface IUserDefinedTypeMemberCandidate : IEncapsulatableField { IUserDefinedTypeCandidate Parent { get; } - IPropertyGeneratorAttributes AsPropertyGeneratorSpec { get; } - Dictionary IdentifierReplacements { get; } + PropertyAttributeSet AsPropertyGeneratorSpec { get; } IEnumerable ParentContextReferences { get; } - void LoadReferenceExpressions(); - bool IsExistingMember { get; } } - public class UserDefinedTypeMemberCandidate : IUserDefinedTypeMemberCandidate, IConvertToUDTMember + public class UserDefinedTypeMemberCandidate : IUserDefinedTypeMemberCandidate { private int _hashCode; private readonly string _uniqueID; - public UserDefinedTypeMemberCandidate(IEncapsulateFieldCandidate candidate, IUserDefinedTypeCandidate udtVariable/*, IValidateEncapsulateFieldNames validator*/) + public UserDefinedTypeMemberCandidate(IEncapsulatableField candidate, IUserDefinedTypeCandidate udtVariable) { _wrappedCandidate = candidate; Parent = udtVariable; PropertyIdentifier = IdentifierName; + BackingIdentifier = IdentifierName; _uniqueID = BuildUniqueID(candidate); _hashCode = _uniqueID.GetHashCode(); } - private IEncapsulateFieldCandidate _wrappedCandidate; + private IEncapsulatableField _wrappedCandidate; public string AsTypeName => _wrappedCandidate.AsTypeName; - //public string AccessorInProperty { /*set;*/ get; } + public string BackingIdentifier { get; set; } - public IUserDefinedTypeCandidate Parent { private set; get; } + public string BackingAsTypeName => Declaration.AsTypeName; - public void LoadFieldReferenceContextReplacements(string referenceQualifier = null) - { - ReferenceQualifier = referenceQualifier; - } + public IUserDefinedTypeCandidate Parent { private set; get; } public IValidateVBAIdentifiers NameValidator { @@ -57,64 +52,32 @@ public IEncapsulateFieldConflictFinder ConflictFinder get => _wrappedCandidate.ConflictFinder; } - public string ReferenceQualifier { set; get; } - public string TargetID => $"{Parent.IdentifierName}.{IdentifierName}"; public IEnumerable ParentContextReferences => GetUDTMemberReferencesForField(this, Parent); - public void LoadReferenceExpressions() - { - foreach (var rf in ParentContextReferences) - { - if (rf.QualifiedModuleName == QualifiedModuleName - && !rf.Context.TryGetAncestor(out _)) - { - SetReferenceRewriteContent(rf, PropertyIdentifier); - continue; - } - var moduleQualifier = rf.Context.TryGetAncestor(out _) - || rf.QualifiedModuleName == QualifiedModuleName - ? string.Empty - : $"{QualifiedModuleName.ComponentName}"; - - SetReferenceRewriteContent(rf, $"{moduleQualifier}.{PropertyIdentifier}"); - } - } - - protected void SetReferenceRewriteContent(IdentifierReference idRef, string replacementText) - { - Debug.Assert(idRef.Context.Parent is ParserRuleContext, "idRef.Context.Parent is not convertable to ParserRuleContext"); - - if (IdentifierReplacements.ContainsKey(idRef)) - { - IdentifierReplacements[idRef] = (idRef.Context.Parent as ParserRuleContext, replacementText); - return; - } - IdentifierReplacements.Add(idRef, (idRef.Context.Parent as ParserRuleContext, replacementText)); - } + public string ReferenceAccessor(IdentifierReference idRef) + => PropertyIdentifier; - public IPropertyGeneratorAttributes AsPropertyGeneratorSpec + public PropertyAttributeSet AsPropertyGeneratorSpec { get { return new PropertyAttributeSet() { PropertyName = PropertyIdentifier, - BackingField = ReferenceWithinNewProperty, + BackingField = $"{Parent.BackingIdentifier}.{BackingIdentifier}", AsTypeName = PropertyAsTypeName, ParameterName = ParameterName, GenerateLetter = ImplementLet, GenerateSetter = ImplementSet, UsesSetAssignment = Declaration.IsObject, - IsUDTProperty = false //TODO: If the member is a UDT, this needs to be true + IsUDTProperty = false //TODO: If udtMember is a UDT, this needs to be true }; } } - public Dictionary IdentifierReplacements { get; } = new Dictionary(); - public override bool Equals(object obj) { return obj != null @@ -124,29 +87,11 @@ public override bool Equals(object obj) public override int GetHashCode() => _hashCode; - /* - * IConvertToUDTMemberInterface - */ - public string AccessorInProperty - => $"{Parent.FieldIdentifier}.{Declaration.IdentifierName}"; - - public string AccessorLocalReference - => $"{Parent.FieldIdentifier}.{PropertyIdentifier}"; - - public string AccessorExternalReference { set; get; } public string PropertyIdentifier { set; get; } - public string PropertyAsTypeName2 { set; get; } - public string UDTMemberIdentifier { set; get; } - - public virtual string UDTMemberDeclaration - => $"{Declaration.IdentifierName} {Tokens.As} {FieldAsTypeName}"; - - public IObjectStateUDT ObjectStateUDT { set; get; } - - private static string BuildUniqueID(IEncapsulateFieldCandidate candidate) => $"{candidate.QualifiedModuleName.Name}.{candidate.IdentifierName}"; + private static string BuildUniqueID(IEncapsulatableField candidate) => $"{candidate.QualifiedModuleName.Name}.{candidate.IdentifierName}"; - private static IEnumerable GetUDTMemberReferencesForField(IEncapsulateFieldCandidate udtMember, IUserDefinedTypeCandidate field) + private static IEnumerable GetUDTMemberReferencesForField(IEncapsulatableField udtMember, IUserDefinedTypeCandidate field) { var refs = new List(); foreach (var idRef in udtMember.Declaration.References) @@ -190,6 +135,7 @@ private static IEnumerable GetUDTMemberReferencesForField(I } public Declaration Declaration => _wrappedCandidate.Declaration; + public string IdentifierName => _wrappedCandidate.IdentifierName; public bool TryValidateEncapsulationAttributes(out string errorMessage) @@ -204,28 +150,7 @@ public bool IsReadOnly get => _wrappedCandidate.IsReadOnly; } - private bool _encapsulateFlag; - public bool EncapsulateFlag - { - set - { - _encapsulateFlag = value; - if (!IsExistingMember) - { - _wrappedCandidate.EncapsulateFlag = value; - } - } - - get => _encapsulateFlag; - } - - public bool IsExistingMember => _wrappedCandidate.Declaration.ParentDeclaration.DeclarationType is DeclarationType.UserDefinedType; - - public string FieldIdentifier - { - set => _wrappedCandidate.FieldIdentifier = value; - get => _wrappedCandidate.FieldIdentifier; - } + public bool EncapsulateFlag { set; get; } public bool CanBeReadWrite { @@ -237,35 +162,14 @@ public bool CanBeReadWrite public QualifiedModuleName QualifiedModuleName => _wrappedCandidate.QualifiedModuleName; - public string FieldAsTypeName // AsTypeName_Field - { - set => _wrappedCandidate.FieldAsTypeName = value; - get => _wrappedCandidate.FieldAsTypeName; - } - public string PropertyAsTypeName - { - set => _wrappedCandidate.PropertyAsTypeName = value; - get => _wrappedCandidate.PropertyAsTypeName; - } + public string PropertyAsTypeName => _wrappedCandidate.PropertyAsTypeName; + public string ParameterName => _wrappedCandidate.ParameterName; public bool ImplementLet => _wrappedCandidate.ImplementLet; public bool ImplementSet => _wrappedCandidate.ImplementSet; - private bool _convertFieldToUDTMember; - public bool ConvertFieldToUDTMember - { - set => _convertFieldToUDTMember = value; - get => false; - } - - public EncapsulateFieldStrategy EncapsulateFieldStrategy { set; get; } = EncapsulateFieldStrategy.UseBackingFields; - - public IEnumerable PropertyAttributeSets => _wrappedCandidate.PropertyAttributeSets; - - public IEnumerable> ReferenceReplacements => _wrappedCandidate.ReferenceReplacements; - - private string ReferenceWithinNewProperty => $"{ReferenceQualifier}.{_wrappedCandidate.IdentifierName}"; + public IEnumerable PropertyAttributeSets => _wrappedCandidate.PropertyAttributeSets; } } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs b/Rubberduck.Refactorings/EncapsulateField/ObjectStateUDT.cs similarity index 60% rename from Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs rename to Rubberduck.Refactorings/EncapsulateField/ObjectStateUDT.cs index 9fe158f0ee..81e420941a 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ObjectStateUDT.cs +++ b/Rubberduck.Refactorings/EncapsulateField/ObjectStateUDT.cs @@ -18,21 +18,18 @@ public interface IObjectStateUDT : IEncapsulateFieldRefactoringElement string FieldIdentifier { set; get; } string TypeDeclarationBlock(IIndenter indenter = null); string FieldDeclarationBlock { get; } - //void AddMembers(IEnumerable fields); void AddMembers(IEnumerable fields); bool IsExistingDeclaration { get; } Declaration AsTypeDeclaration { get; } bool IsSelected { set; get; } - //bool IsEncapsulateFieldCandidate(IEncapsulateFieldCandidate efc); IEnumerable ExistingMembers { get; } } //ObjectStateUDT can be an existing UDT (Private only) selected by the user, or a //newly inserted declaration - public class ObjectStateUDT : IObjectStateUDT//, IAssignNoConflictNames + public class ObjectStateUDT : IObjectStateUDT { private static string _defaultNewFieldName = EncapsulateFieldResources.DefaultStateUDTFieldName; - //private List _members; private List _convertedMembers; private readonly IUserDefinedTypeCandidate _wrappedUDT; @@ -52,7 +49,7 @@ public ObjectStateUDT(IUserDefinedTypeCandidate udt) } public ObjectStateUDT(QualifiedModuleName qmn) - :this($"{EncapsulateFieldResources.StateUserDefinedTypeIdentifierPrefix}{qmn.ComponentName.CapitalizeFirstLetter()}") + :this($"T{qmn.ComponentName.CapitalizeFirstLetter()}") { QualifiedModuleName = qmn; } @@ -61,42 +58,9 @@ private ObjectStateUDT(string typeIdentifier) { FieldIdentifier = _defaultNewFieldName; TypeIdentifier = typeIdentifier; - //_members = new List(); _convertedMembers = new List(); } - //public void AssignIdentifiers(IEncapsulateFieldValidator validator) - //{ - // FieldIdentifier = validator.CreateNonConflictIdentifierForProposedType(FieldIdentifier, QualifiedModuleName, DeclarationType.Variable); - // TypeIdentifier = validator.CreateNonConflictIdentifierForProposedType(TypeIdentifier, QualifiedModuleName, DeclarationType.UserDefinedType); - //} - - protected static IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType, IValidateEncapsulateFieldNames validator) - { - var isConflictingIdentifier = validator.HasConflictingIdentifierIgnoreEncapsulationFlag(candidate, declarationType, out _); - for (var count = 1; count < 10 && isConflictingIdentifier; count++) - { - var identifier = declarationType.HasFlag(DeclarationType.Property) - //? candidate.PropertyName - ? candidate.PropertyIdentifier - : candidate.FieldIdentifier; - //: candidate.FieldIdentifierOld; - - if (declarationType.HasFlag(DeclarationType.Property)) - { - //candidate.PropertyName = identifier.IncrementEncapsulationIdentifier(); - candidate.PropertyIdentifier = identifier.IncrementEncapsulationIdentifier(); - } - else - { - //candidate.FieldIdentifierOld = identifier.IncrementEncapsulationIdentifier(); - candidate.FieldIdentifier = identifier.IncrementEncapsulationIdentifier(); - } - isConflictingIdentifier = validator.HasConflictingIdentifierIgnoreEncapsulationFlag(candidate, declarationType, out _); - } - return candidate; - } - public string IdentifierName => _wrappedUDT?.IdentifierName ?? FieldIdentifier; public string AsTypeName => _wrappedUDT?.AsTypeName ?? TypeIdentifier; @@ -143,23 +107,16 @@ public QualifiedModuleName QualifiedModuleName public string FieldIdentifier { set; get; } - //public void AddMembers(IEnumerable fields) - //{ - // AddMembers(fields.Cast()); - // //if (IsExistingDeclaration) - // //{ - // // _members = _wrappedUDT.Members.Select(m => m).Cast().ToList(); - // //} - // //_members.AddRange(fields); - //} - public void AddMembers(IEnumerable fields) { + _convertedMembers = new List(); if (IsExistingDeclaration) { - _convertedMembers = _wrappedUDT.Members.Select(m => m).Cast().ToList(); + foreach (var member in _wrappedUDT.Members) + { + _convertedMembers.Add(new ConvertToUDTMember(member, this)); + } } - //_members.AddRange(fields); _convertedMembers.AddRange(fields); } @@ -188,16 +145,7 @@ public override bool Equals(object obj) return false; } - //public bool IsEncapsulateFieldCandidate(IEncapsulateFieldCandidate efc) - //{ - // if (efc is IEncapsulateFieldDeclaration fd && fd.IdentifierName == IdentifierName) - // { - // return true; - // } - // return false; - //} - - public override int GetHashCode() => _hashCode; + public override int GetHashCode() => _hashCode; private IEnumerable BlockLines(Accessibility accessibility) { @@ -205,7 +153,6 @@ private IEnumerable BlockLines(Accessibility accessibility) blockLines.Add($"{accessibility.TokenString()} {Tokens.Type} {TypeIdentifier}"); - //_members.ForEach(m => blockLines.Add($"{m.AsUDTMemberDeclaration}")); _convertedMembers.ForEach(m => blockLines.Add($"{m.UDTMemberDeclaration}")); blockLines.Add($"{Tokens.End} {Tokens.Type}"); diff --git a/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs b/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs index 9ec76cf3d9..f042ca9267 100644 --- a/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs +++ b/Rubberduck.Refactorings/EncapsulateField/PropertyGenerator.cs @@ -5,19 +5,7 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface IPropertyGeneratorAttributes - { - string PropertyName { get; } - string BackingField { get; } - string AsTypeName { get; } - string ParameterName { get; } - bool GenerateLetter { get; } - bool GenerateSetter { get; } - bool UsesSetAssignment { get; } - bool IsUDTProperty { get; } - } - - public class PropertyAttributeSet : IPropertyGeneratorAttributes + public struct PropertyAttributeSet { public string PropertyName { get; set; } public string BackingField { get; set; } @@ -33,91 +21,65 @@ public class PropertyGenerator { public PropertyGenerator() { } - public string PropertyName { get; set; } - public string BackingField { get; set; } - public string AsTypeName { get; set; } - public string ParameterName { get; set; } - public bool GenerateLetter { get; set; } - public bool GenerateSetter { get; set; } - public bool UsesSetAssignment { get; set; } - public bool IsUDTProperty { get; set; } - - public string AsPropertyBlock(IPropertyGeneratorAttributes spec, IIndenter indenter) + public string AsPropertyBlock(PropertyAttributeSet attrSet, IIndenter indenter) { - PropertyName = spec.PropertyName; - BackingField = spec.BackingField; - AsTypeName = spec.AsTypeName; - ParameterName = spec.ParameterName; - GenerateLetter = spec.GenerateLetter; - GenerateSetter = spec.GenerateSetter; - UsesSetAssignment = spec.UsesSetAssignment; - IsUDTProperty = spec.IsUDTProperty; - return string.Join(Environment.NewLine, indenter.Indent(AsLines, true)); + return string.Join(Environment.NewLine, indenter.Indent(AsLines(attrSet), true)); } - private string AllPropertyCode => - $"{GetterCode}{(GenerateLetter ? LetterCode : string.Empty)}{(GenerateSetter ? SetterCode : string.Empty)}"; + private string AllPropertyCode(PropertyAttributeSet attrSet) => + $"{GetterCode(attrSet)}{(attrSet.GenerateLetter ? LetterCode(attrSet) : string.Empty)}{(attrSet.GenerateSetter ? SetterCode(attrSet) : string.Empty)}"; - private IEnumerable AsLines => AllPropertyCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None); + private IEnumerable AsLines(PropertyAttributeSet _spec) => AllPropertyCode(_spec).Split(new[] { Environment.NewLine }, StringSplitOptions.None); - private string GetterCode + private string GetterCode(PropertyAttributeSet attrSet) { - get + if (attrSet.GenerateSetter && attrSet.GenerateLetter) { - if (GenerateSetter && GenerateLetter) - { - return string.Join(Environment.NewLine, - $"Public Property Get {PropertyName}() As {AsTypeName}", - $" If IsObject({BackingField}) Then", - $" Set {PropertyName} = {BackingField}", - " Else", - $" {PropertyName} = {BackingField}", - " End If", - "End Property", - Environment.NewLine); - } - return string.Join(Environment.NewLine, - $"Public Property Get {PropertyName}() As {AsTypeName}", - $" {(UsesSetAssignment ? "Set " : string.Empty)}{PropertyName} = {BackingField}", - "End Property", - Environment.NewLine); + $"Public Property Get {attrSet.PropertyName}() As {attrSet.AsTypeName}", + $" If IsObject({attrSet.BackingField}) Then", + $" Set {attrSet.PropertyName} = {attrSet.BackingField}", + " Else", + $" {attrSet.PropertyName} = {attrSet.BackingField}", + " End If", + "End Property", + Environment.NewLine); } + + return string.Join(Environment.NewLine, + $"Public Property Get {attrSet.PropertyName}() As {attrSet.AsTypeName}", + $" {(attrSet.UsesSetAssignment ? "Set " : string.Empty)}{attrSet.PropertyName} = {attrSet.BackingField}", + "End Property", + Environment.NewLine); } - private string SetterCode + private string SetterCode(PropertyAttributeSet attrSet) { - get + if (!attrSet.GenerateSetter) { - if (!GenerateSetter) - { - return string.Empty; - } - return string.Join(Environment.NewLine, - $"Public Property Set {PropertyName}(ByVal {ParameterName} As {AsTypeName})", - $" Set {BackingField} = {ParameterName}", - "End Property", - Environment.NewLine); + return string.Empty; } + return string.Join(Environment.NewLine, + $"Public Property Set {attrSet.PropertyName}(ByVal {attrSet.ParameterName} As {attrSet.AsTypeName})", + $" Set {attrSet.BackingField} = {attrSet.ParameterName}", + "End Property", + Environment.NewLine); } - private string LetterCode + private string LetterCode(PropertyAttributeSet attrSet) { - get + if (!attrSet.GenerateLetter) { - if (!GenerateLetter) - { - return string.Empty; - } + return string.Empty; + } - var byVal_byRef = IsUDTProperty ? Tokens.ByRef : Tokens.ByVal; + var byVal_byRef = attrSet.IsUDTProperty ? Tokens.ByRef : Tokens.ByVal; - return string.Join(Environment.NewLine, - $"Public Property Let {PropertyName}({byVal_byRef} {ParameterName} As {AsTypeName})", - $" {BackingField} = {ParameterName}", - "End Property", - Environment.NewLine); - } + return string.Join(Environment.NewLine, + $"Public Property Let {attrSet.PropertyName}({byVal_byRef} {attrSet.ParameterName} As {attrSet.AsTypeName})", + $" {attrSet.BackingField} = {attrSet.ParameterName}", + "End Property", + Environment.NewLine); } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/ConflictDetectors.cs b/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldConflictFinders.cs similarity index 52% rename from Rubberduck.Refactorings/EncapsulateField/ConflictDetectors.cs rename to Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldConflictFinders.cs index e4d815a445..06967dba30 100644 --- a/Rubberduck.Refactorings/EncapsulateField/ConflictDetectors.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldConflictFinders.cs @@ -12,96 +12,28 @@ namespace Rubberduck.Refactorings.EncapsulateField { public interface IEncapsulateFieldConflictFinder { - //bool HasConflictingIdentifier(IEncapsulateFieldCandidate candidate, out string errorMessage); - //bool HasConflictingIdentifier(IEncapsulateFieldCandidate field, DeclarationType declarationType, out string errorMessage); - bool HasConflictingIdentifier(IEncapsulatableField candidate, out string errorMessage); bool HasConflictingIdentifier(IEncapsulatableField field, DeclarationType declarationType, out string errorMessage); - IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType); + IEncapsulatableField AssignNoConflictIdentifier(IEncapsulatableField candidate, DeclarationType declarationType); string CreateNonConflictIdentifierForProposedType(string identifier, QualifiedModuleName qmn, DeclarationType declarationType); - bool IsConflictingProposedIdentifier(string fieldName, IEncapsulateFieldCandidate candidate, DeclarationType declarationType); + bool IsConflictingProposedIdentifier(string fieldName, IEncapsulatableField candidate, DeclarationType declarationType); bool TryValidateEncapsulationAttributes(IEncapsulatableField field, out string errorMessage); } - public class ConflictDetectorUseBackingFields : ConflictDetectorBase + public class UseBackingFieldsConflictFinder : EncapsulateFieldConflictFinderBase { - public ConflictDetectorUseBackingFields(IDeclarationFinderProvider declarationFinderProvider, IEnumerable candidates, IEnumerable udtCandidates) + public UseBackingFieldsConflictFinder(IDeclarationFinderProvider declarationFinderProvider, IEnumerable candidates, IEnumerable udtCandidates) : base(declarationFinderProvider, candidates, udtCandidates) { } - public override bool TryValidateEncapsulationAttributes(IEncapsulatableField field, out string errorMessage) - { - errorMessage = string.Empty; - if (!field.EncapsulateFlag) { return true; } - - if (!field.NameValidator.IsValidVBAIdentifier(field.PropertyIdentifier, out errorMessage)) - { - return false; - } - - if (HasConflictingIdentifier(field, DeclarationType.Property, out errorMessage)) - { - return false; - } - return true; - } - - protected override string IdentifierToCompare(IEncapsulatableField field, DeclarationType declarationType) - { - if (field is IUsingBackingField useBackingField) - { - return declarationType.HasFlag(DeclarationType.Property) - ? useBackingField.PropertyIdentifier - : useBackingField.FieldIdentifier; - } - return field.PropertyIdentifier; - } - + protected override IEnumerable FindRelevantMembers(IEncapsulatableField candidate) + => _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) + .Where(d => d != candidate.Declaration); } - public class ConflictDetectorConvertFieldsToUDTMembers : ConflictDetectorBase + public class ConvertFieldsToUDTMembersConflictFinder : EncapsulateFieldConflictFinderBase { - public ConflictDetectorConvertFieldsToUDTMembers(IDeclarationFinderProvider declarationFinderProvider, IEnumerable candidates, IEnumerable udtCandidates) + public ConvertFieldsToUDTMembersConflictFinder(IDeclarationFinderProvider declarationFinderProvider, IEnumerable candidates, IEnumerable udtCandidates) : base(declarationFinderProvider, candidates, udtCandidates) { } - public override bool TryValidateEncapsulationAttributes(IEncapsulatableField field, out string errorMessage) - { - errorMessage = string.Empty; - if (!field.EncapsulateFlag) { return true; } - - if (!field.NameValidator.IsValidVBAIdentifier(field.PropertyIdentifier, out errorMessage)) - { - return false; - } - - if (HasConflictingIdentifier(field, DeclarationType.Property, out errorMessage)) - { - return false; - } - - return true; - } - - protected override string IdentifierToCompare(IEncapsulatableField field, DeclarationType declarationType) - { - if (field is IConvertToUDTMember convertedField) - { - return declarationType.HasFlag(DeclarationType.Property) - ? convertedField.PropertyIdentifier - : convertedField.UDTMemberIdentifier; - } - return field.PropertyIdentifier; - } - - //protected override IEnumerable FindRelevantMembers(IEncapsulateFieldCandidate candidate) - //{ - // var members = _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) - // .Where(d => d != candidate.Declaration); - - // var membersToRemove = _fieldCandidates.Where(fc => fc.EncapsulateFlag && fc.Declaration.DeclarationType.HasFlag(DeclarationType.Variable)) - // .Select(fc => fc.Declaration); - - // return members.Except(membersToRemove); - //} - protected override IEnumerable FindRelevantMembers(IEncapsulatableField candidate) { var members = _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) @@ -114,42 +46,47 @@ protected override IEnumerable FindRelevantMembers(IEncapsulatableF } } - public abstract class ConflictDetectorBase : IEncapsulateFieldConflictFinder + public abstract class EncapsulateFieldConflictFinderBase : IEncapsulateFieldConflictFinder { protected readonly IDeclarationFinderProvider _declarationFinderProvider; - protected List _fieldCandidates { set; get; } = new List(); + protected List _fieldCandidates { set; get; } = new List(); protected List _udtMemberCandidates { set; get; } = new List(); - public ConflictDetectorBase(IDeclarationFinderProvider declarationFinderProvider, IEnumerable candidates, IEnumerable udtCandidates)//, IValidateVBAIdentifiers nameValidator) + public EncapsulateFieldConflictFinderBase(IDeclarationFinderProvider declarationFinderProvider, IEnumerable candidates, IEnumerable udtCandidates) { _declarationFinderProvider = declarationFinderProvider; _fieldCandidates.AddRange(candidates); _udtMemberCandidates.AddRange(udtCandidates); } - public abstract bool TryValidateEncapsulationAttributes(IEncapsulatableField field, out string errorMessage); + public bool TryValidateEncapsulationAttributes(IEncapsulatableField field, out string errorMessage) + { + errorMessage = string.Empty; + if (!field.EncapsulateFlag) { return true; } - //public bool HasConflictingIdentifier(IEncapsulateFieldCandidate candidate, out string errorMessage) - // => InternalHasConflictingIdentifier(candidate, DeclarationType.Property, false, out errorMessage); + if (!field.NameValidator.IsValidVBAIdentifier(field.PropertyIdentifier, out errorMessage)) + { + return false; + } - public bool HasConflictingIdentifier(IEncapsulatableField candidate, out string errorMessage) - => InternalHasConflictingIdentifier(candidate, DeclarationType.Property, false, out errorMessage); + if (HasConflictingIdentifier(field, DeclarationType.Property, out errorMessage)) + { + return false; + } - //public bool HasConflictingIdentifier(IEncapsulateFieldCandidate field, DeclarationType declarationType, out string errorMessage) - // => InternalHasConflictingIdentifier(field, declarationType, false, out errorMessage); + return true; + } public bool HasConflictingIdentifier(IEncapsulatableField field, DeclarationType declarationType, out string errorMessage) => InternalHasConflictingIdentifier(field, declarationType, false, out errorMessage); - public IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType) //, IValidateEncapsulateFieldNames validator) + public IEncapsulatableField AssignNoConflictIdentifier(IEncapsulatableField candidate, DeclarationType declarationType) { var isConflictingIdentifier = HasConflictingIdentifierIgnoreEncapsulationFlag(candidate, declarationType, out _); var guard = 0; while (guard++ < 10 && isConflictingIdentifier) { - var identifier = declarationType.HasFlag(DeclarationType.Property) - ? candidate.PropertyIdentifier - : candidate.FieldIdentifier; + var identifier = IdentifierToCompare(candidate, declarationType); if (declarationType.HasFlag(DeclarationType.Property)) { @@ -157,7 +94,7 @@ public IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncapsulateFieldCa } else { - candidate.FieldIdentifier = identifier.IncrementEncapsulationIdentifier(); + candidate.BackingIdentifier = identifier.IncrementEncapsulationIdentifier(); } isConflictingIdentifier = HasConflictingIdentifierIgnoreEncapsulationFlag(candidate, declarationType, out _); } @@ -174,22 +111,13 @@ public string CreateNonConflictIdentifierForProposedType(string identifier, Qual return identifier; } - public bool IsConflictingProposedIdentifier(string fieldName, IEncapsulateFieldCandidate candidate, DeclarationType declarationType) - { - var members = PotentialConflictIdentifiers(candidate, declarationType); - - return members.Any(m => m.IsEquivalentVBAIdentifierTo(fieldName)); - } + public bool IsConflictingProposedIdentifier(string fieldName, IEncapsulatableField candidate, DeclarationType declarationType) + => PotentialConflictIdentifiers(candidate, declarationType) + .Any(m => m.IsEquivalentVBAIdentifierTo(fieldName)); - //protected virtual IEnumerable FindRelevantMembers(IEncapsulateFieldCandidate candidate) - // => _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) - // .Where(d => d != candidate.Declaration); + protected abstract IEnumerable FindRelevantMembers(IEncapsulatableField candidate); - protected virtual IEnumerable FindRelevantMembers(IEncapsulatableField candidate) - => _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) - .Where(d => d != candidate.Declaration); - - private bool InternalHasConflictingIdentifier(IEncapsulateFieldCandidate field, DeclarationType declarationType, bool ignoreEncapsulationFlags, out string errorMessage) + protected virtual bool InternalHasConflictingIdentifier(IEncapsulatableField field, DeclarationType declarationType, bool ignoreEncapsulationFlags, out string errorMessage) { errorMessage = string.Empty; @@ -207,9 +135,7 @@ private bool InternalHasConflictingIdentifier(IEncapsulateFieldCandidate field, potentialDeclarationIdentifierConflicts.AddRange(_udtMemberCandidates.Where(udtm => udtm != field && udtm.EncapsulateFlag).Select(udtm => udtm.PropertyIdentifier)); - var identifierToCompare = declarationType.HasFlag(DeclarationType.Property) - ? field.PropertyIdentifier - : field.FieldIdentifier; + var identifierToCompare = IdentifierToCompare(field, declarationType); if (potentialDeclarationIdentifierConflicts.Any(m => m.IsEquivalentVBAIdentifierTo(identifierToCompare))) { @@ -219,40 +145,13 @@ private bool InternalHasConflictingIdentifier(IEncapsulateFieldCandidate field, return false; } - protected virtual bool InternalHasConflictingIdentifier(IEncapsulatableField field, DeclarationType declarationType, bool ignoreEncapsulationFlags, out string errorMessage) + protected string IdentifierToCompare(IEncapsulatableField field, DeclarationType declarationType) { - errorMessage = string.Empty; - - var potentialDeclarationIdentifierConflicts = new List(); - potentialDeclarationIdentifierConflicts.AddRange(PotentialConflictIdentifiers(field, declarationType)); - - if (ignoreEncapsulationFlags) - { - potentialDeclarationIdentifierConflicts.AddRange(_fieldCandidates.Where(fc => fc != field).Select(fc => fc.PropertyIdentifier)); - } - else - { - potentialDeclarationIdentifierConflicts.AddRange(FlaggedCandidates.Where(fc => fc != field).Select(fc => fc.PropertyIdentifier)); - } - - potentialDeclarationIdentifierConflicts.AddRange(_udtMemberCandidates.Where(udtm => udtm != field && udtm.EncapsulateFlag).Select(udtm => udtm.PropertyIdentifier)); - - //var identifierToCompare = declarationType.HasFlag(DeclarationType.Property) - // ? field.PropertyIdentifier - // //: field.FieldIdentifier; - // : field.Declaration.IdentifierName; //TODO: Temporary - var identifierToCompare = IdentifierToCompare(field, DeclarationType.Property); - - if (potentialDeclarationIdentifierConflicts.Any(m => m.IsEquivalentVBAIdentifierTo(identifierToCompare))) - { - errorMessage = EncapsulateFieldResources.NameConflictDetected; - return true; - } - return false; + return declarationType.HasFlag(DeclarationType.Property) + ? field.PropertyIdentifier + : field.BackingIdentifier; } - protected abstract string IdentifierToCompare(IEncapsulatableField field, DeclarationType declarationType); - //The refactoring only inserts new code elements with the following Accessibilities: //Variables => Private //Properties => Public @@ -302,28 +201,6 @@ private bool IsAlwaysIgnoreNameConflictType(Declaration d, DeclarationType toEna || NeverCauseNameConflictTypes.Contains(d.DeclarationType); } - private List PotentialConflictIdentifiers(IEncapsulateFieldCandidate candidate, DeclarationType declarationType) - { - var members = FindRelevantMembers(candidate); - - var nameConflictCandidates = members - .Where(d => !IsAlwaysIgnoreNameConflictType(d, declarationType)).ToList(); - - var localReferences = candidate.Declaration.References.Where(rf => rf.QualifiedModuleName == candidate.QualifiedModuleName); - - if (localReferences.Any()) - { - foreach (var idRef in localReferences) - { - var locals = members.Except(nameConflictCandidates) - .Where(localDec => localDec.ParentScopeDeclaration.Equals(idRef.ParentScoping)); - - nameConflictCandidates.AddRange(locals); - } - } - return nameConflictCandidates.Select(c => c.IdentifierName).ToList(); - } - private List PotentialConflictIdentifiers(IEncapsulatableField candidate, DeclarationType declarationType) { var members = FindRelevantMembers(candidate); @@ -346,9 +223,10 @@ private List PotentialConflictIdentifiers(IEncapsulatableField candidate return nameConflictCandidates.Select(c => c.IdentifierName).ToList(); } - private List FlaggedCandidates => _fieldCandidates.Where(f => f.EncapsulateFlag).ToList(); + private List FlaggedCandidates + => _fieldCandidates.Where(f => f.EncapsulateFlag).ToList(); - private bool HasConflictingIdentifierIgnoreEncapsulationFlag(IEncapsulateFieldCandidate field, DeclarationType declarationType, out string errorMessage) + protected bool HasConflictingIdentifierIgnoreEncapsulationFlag(IEncapsulatableField field, DeclarationType declarationType, out string errorMessage) => InternalHasConflictingIdentifier(field, declarationType, true, out errorMessage); private bool IsConflictIdentifier(string fieldName, QualifiedModuleName qmn, DeclarationType declarationType) diff --git a/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldNamesValidator.cs b/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldNamesValidator.cs new file mode 100644 index 0000000000..781fd33cc2 --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldNamesValidator.cs @@ -0,0 +1,29 @@ +using Rubberduck.Parsing.Symbols; +using Rubberduck.Refactorings.Common; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + public interface IValidateVBAIdentifiers + { + bool IsValidVBAIdentifier(string identifier, out string errorMessage); + } + + public class IdentifierOnlyValidator : IValidateVBAIdentifiers + { + private DeclarationType _declarationType; + private bool _isArray; + public IdentifierOnlyValidator(DeclarationType declarationType, bool isArray = false) + { + _declarationType = declarationType; + _isArray = isArray; + } + + public bool IsValidVBAIdentifier(string identifier, out string errorMessage) + => !VBAIdentifierValidator.TryMatchInvalidIdentifierCriteria(identifier, _declarationType, out errorMessage, _isArray); + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldValidationsProvider.cs b/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldValidationsProvider.cs new file mode 100644 index 0000000000..7693ea6ab9 --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldValidationsProvider.cs @@ -0,0 +1,73 @@ +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.Refactorings.Common; +using Rubberduck.VBEditor; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + public enum NameValidators + { + Default, + UserDefinedType, + UserDefinedTypeMember, + UserDefinedTypeMemberArray + } + + public interface IEncapsulateFieldValidationsProvider + { + IValidateVBAIdentifiers NameOnlyValidator(NameValidators validatorType); + IEncapsulateFieldConflictFinder ConflictDetector(EncapsulateFieldStrategy strategy, IDeclarationFinderProvider declarationFinderProvider); + void RegisterCandidates(IEnumerable candidates); + } + + public class EncapsulateFieldValidationsProvider : IEncapsulateFieldValidationsProvider + { + private Dictionary _nameOnlyValidators; + + private List _candidates; + private List _udtMemberCandidates; + + public EncapsulateFieldValidationsProvider() + { + _nameOnlyValidators = new Dictionary() + { + [NameValidators.Default] = new IdentifierOnlyValidator(DeclarationType.Variable, false), + [NameValidators.UserDefinedType] = new IdentifierOnlyValidator(DeclarationType.UserDefinedType, false), + [NameValidators.UserDefinedTypeMember] = new IdentifierOnlyValidator(DeclarationType.UserDefinedTypeMember, false), + [NameValidators.UserDefinedTypeMemberArray] = new IdentifierOnlyValidator(DeclarationType.UserDefinedTypeMember, true), + }; + + _candidates = new List(); + _udtMemberCandidates = new List(); + } + + public IValidateVBAIdentifiers NameOnlyValidator(NameValidators validatorType) + => _nameOnlyValidators[validatorType]; + + public IEncapsulateFieldConflictFinder ConflictDetector(EncapsulateFieldStrategy strategy, IDeclarationFinderProvider declarationFinderProvider) + { + if (strategy == EncapsulateFieldStrategy.UseBackingFields) + { + return new UseBackingFieldsConflictFinder(declarationFinderProvider, _candidates, _udtMemberCandidates); + } + return new ConvertFieldsToUDTMembersConflictFinder(declarationFinderProvider, _candidates, _udtMemberCandidates); + } + + public void RegisterCandidates(IEnumerable candidates) + { + _candidates.AddRange(candidates); + foreach (var udtCandidate in candidates.Where(c => c is IUserDefinedTypeCandidate).Cast()) + { + foreach (var member in udtCandidate.Members) + { + _udtMemberCandidates.Add(member); + } + } + } + } +} diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs index 175b30a64f..15a2713313 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs @@ -472,7 +472,7 @@ Sub Bar(ByVal name As Integer) var presenterAction = Support.SetParametersForSingleTarget("fizz", "Name"); - var validator = new EncapsulateFieldValidationsProvider().NameOnlyValidator(Validators.Default); + var validator = new EncapsulateFieldValidationsProvider().NameOnlyValidator(NameValidators.Default); var enapsulationIdentifiers = new EncapsulationIdentifiers("fizz", validator/*(string name) => true*/) { Property = "Name" }; var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); @@ -496,10 +496,10 @@ Sub Foo() fizz = 1 End Sub"; const string codeClass2 = - @"Sub Foo() - Dim c As Class1 - c.fizz = 0 - Bar c.fizz +@"Sub Foo() + Dim theClass As Class1 + theClass.fizz = 0 + Bar theClass.fizz End Sub Sub Bar(ByVal v As Integer) @@ -518,8 +518,8 @@ Sub Bar(ByVal v As Integer) ("Class2", codeClass2, ComponentType.ClassModule)); StringAssert.Contains("Name = 1", actualCode["Class1"]); - StringAssert.Contains("c.Name = 0", actualCode["Class2"]); - StringAssert.Contains("Bar c.Name", actualCode["Class2"]); + StringAssert.Contains("theClass.Name = 0", actualCode["Class2"]); + StringAssert.Contains("Bar theClass.Name", actualCode["Class2"]); StringAssert.DoesNotContain("fizz", actualCode["Class2"]); } diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs index 3a1fc85c3c..19fbeb9edc 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs @@ -64,7 +64,7 @@ End Type Public th|is As TBar Public that As TBar"; - var validator = new EncapsulateFieldValidationsProvider().NameOnlyValidator(Validators.Default); + var validator = new EncapsulateFieldValidationsProvider().NameOnlyValidator(NameValidators.Default); var expectedThis = new EncapsulationIdentifiers("this", validator); var expectedThat = new EncapsulationIdentifiers("that", validator); @@ -517,15 +517,14 @@ End Sub StringAssert.Contains($"Public Property Set TheClass", actualCode); } - [TestCase("SourceModule", "this", "Public")] - [TestCase("SourceModule", "SourceModule.this", "Private")] + [TestCase("SourceModule", "this")] [Category("Refactorings")] [Category("Encapsulate Field")] - public void StdModuleSource_UDTField_StdModuleReferences(string sourceModuleName, string referenceQualifier, string typeDeclarationAccessibility) + public void StdModuleSource_PublicUDTField_PublicType_StdModuleReference(string sourceModuleName, string referenceQualifier) { var sourceModuleCode = $@" -{typeDeclarationAccessibility} Type TBar +Public Type TBar First As String Second As Long End Type @@ -572,22 +571,10 @@ End Sub ("StdModule", moduleReferencingCode, ComponentType.StandardModule), (sourceModuleName, sourceCodeString.Code, ComponentType.StandardModule)); - if (typeDeclarationAccessibility.Equals("Public")) - { - var referencingModuleCode = actualModuleCode["StdModule"]; - StringAssert.Contains($"{sourceModuleName}.MyType.First = ", referencingModuleCode); - StringAssert.Contains($"{sourceModuleName}.MyType.Second = ", referencingModuleCode); - StringAssert.Contains($" .MyType.Second = ", referencingModuleCode); - } - - if (typeDeclarationAccessibility.Equals("Private")) - { - var referencingModuleCode = actualModuleCode["StdModule"]; - StringAssert.Contains($"{sourceModuleName}.First = ", referencingModuleCode); - StringAssert.Contains($"{sourceModuleName}.Second = ", referencingModuleCode); - StringAssert.Contains($" .First = ", referencingModuleCode); - StringAssert.Contains($" .Second = ", referencingModuleCode); - } + var referencingModuleCode = actualModuleCode["StdModule"]; + StringAssert.Contains($"{sourceModuleName}.MyType.First = ", referencingModuleCode); + StringAssert.Contains($"{sourceModuleName}.MyType.Second = ", referencingModuleCode); + StringAssert.Contains($" .MyType.Second = ", referencingModuleCode); } private IDictionary Scenario_StdModuleSource_StandardAndClassReferencingModules(string referenceQualifier, string typeDeclarationAccessibility, string sourceModuleName, UserInputDataObject userInput) @@ -683,7 +670,7 @@ End Sub [Test] [Category("Refactorings")] [Category("Encapsulate Field")] - public void ClassModuleSource_UDTFieldSelection_ExternalReferences() + public void ClassModuleUDTFieldSelection_ExternalReferences_ClassModule() { var sourceModuleName = "SourceModule"; var sourceClassName = "theClass"; @@ -692,19 +679,46 @@ public void ClassModuleSource_UDTFieldSelection_ExternalReferences() Public th|is As TBar"; - var procedureModuleReferencingCode = -$@"Option Explicit +// var procedureModuleReferencingCode = +//$@"Option Explicit -Public Type TBar - First As String - Second As Long -End Type +//Public Type TBar +// First As String +// Second As Long +//End Type + +//Private {sourceClassName} As {sourceModuleName} +//Private Const foo As String = ""Foo"" +//Private Const bar As Long = 7 + +//Public Sub Initialize() +// Set {sourceClassName} = New {sourceModuleName} +//End Sub + +//Public Sub Foo() +// {sourceClassName}.this.First = foo +//End Sub + +//Public Sub Bar() +// {sourceClassName}.this.Second = bar +//End Sub + +//Public Sub FooBar() +// With {sourceClassName} +// .this.First = foo +// .this.Second = bar +// End With +//End Sub +//"; + + string classModuleReferencingCode = +$@"Option Explicit Private {sourceClassName} As {sourceModuleName} Private Const foo As String = ""Foo"" Private Const bar As Long = 7 -Public Sub Initialize() +Private Sub Class_Initialize() Set {sourceClassName} = New {sourceModuleName} End Sub @@ -724,14 +738,60 @@ End With End Sub "; - string classModuleReferencingCode = + var userInput = new UserInputDataObject() + .UserSelectsField("this", "MyType"); + + var presenterAction = Support.SetParameters(userInput); + + var sourceCodeString = sourceModuleCode.ToCodeString(); + + var actualModuleCode = RefactoredCode( + sourceModuleName, + sourceCodeString.CaretPosition.ToOneBased(), + presenterAction, + null, + false, + //("StdModule", procedureModuleReferencingCode, ComponentType.StandardModule), + ("ClassModule", classModuleReferencingCode, ComponentType.ClassModule), + (sourceModuleName, sourceCodeString.Code, ComponentType.ClassModule)); + + //var referencingModuleCode = actualModuleCode["StdModule"]; + //StringAssert.Contains($"{sourceClassName}.MyType.First = ", referencingModuleCode); + //StringAssert.Contains($"{sourceClassName}.MyType.Second = ", referencingModuleCode); + //StringAssert.Contains($" .MyType.Second = ", referencingModuleCode); + + var referencingClassCode = actualModuleCode["ClassModule"]; + StringAssert.Contains($"{sourceClassName}.MyType.First = ", referencingClassCode); + StringAssert.Contains($"{sourceClassName}.MyType.Second = ", referencingClassCode); + StringAssert.Contains($" .MyType.Second = ", referencingClassCode); + } + + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void ClassModuleUDTFieldSelection_ExternalReferences_StdModule() + { + var sourceModuleName = "SourceModule"; + var sourceClassName = "theClass"; + var sourceModuleCode = +$@" + +Public th|is As TBar"; + + var procedureModuleReferencingCode = $@"Option Explicit +Public Type TBar + First As String + Second As Long +End Type + Private {sourceClassName} As {sourceModuleName} Private Const foo As String = ""Foo"" Private Const bar As Long = 7 -Private Sub Class_Initialize() +Public Sub Initialize() Set {sourceClassName} = New {sourceModuleName} End Sub @@ -751,6 +811,33 @@ End With End Sub "; +// string classModuleReferencingCode = +//$@"Option Explicit + +//Private {sourceClassName} As {sourceModuleName} +//Private Const foo As String = ""Foo"" +//Private Const bar As Long = 7 + +//Private Sub Class_Initialize() +// Set {sourceClassName} = New {sourceModuleName} +//End Sub + +//Public Sub Foo() +// {sourceClassName}.this.First = foo +//End Sub + +//Public Sub Bar() +// {sourceClassName}.this.Second = bar +//End Sub + +//Public Sub FooBar() +// With {sourceClassName} +// .this.First = foo +// .this.Second = bar +// End With +//End Sub +//"; + var userInput = new UserInputDataObject() .UserSelectsField("this", "MyType"); @@ -765,7 +852,7 @@ End Sub null, false, ("StdModule", procedureModuleReferencingCode, ComponentType.StandardModule), - ("ClassModule", classModuleReferencingCode, ComponentType.ClassModule), + //("ClassModule", classModuleReferencingCode, ComponentType.ClassModule), (sourceModuleName, sourceCodeString.Code, ComponentType.ClassModule)); var referencingModuleCode = actualModuleCode["StdModule"]; @@ -773,10 +860,10 @@ End Sub StringAssert.Contains($"{sourceClassName}.MyType.Second = ", referencingModuleCode); StringAssert.Contains($" .MyType.Second = ", referencingModuleCode); - var referencingClassCode = actualModuleCode["ClassModule"]; - StringAssert.Contains($"{sourceClassName}.MyType.First = ", referencingClassCode); - StringAssert.Contains($"{sourceClassName}.MyType.Second = ", referencingClassCode); - StringAssert.Contains($" .MyType.Second = ", referencingClassCode); + //var referencingClassCode = actualModuleCode["ClassModule"]; + //StringAssert.Contains($"{sourceClassName}.MyType.First = ", referencingClassCode); + //StringAssert.Contains($"{sourceClassName}.MyType.Second = ", referencingClassCode); + //StringAssert.Contains($" .MyType.Second = ", referencingClassCode); } [Test] diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs index 5983f5861f..1fa6c92ab4 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs @@ -46,29 +46,29 @@ public void FieldNameValuesPerSequenceOfPropertyNameChanges() { string inputCode = "Public fizz As String"; - var encapsulatedField = Support.RetrieveEncapsulateFieldCandidate(inputCode, "fizz"); - StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.FieldIdentifier); + var encapsulatedField = Support.RetrieveEncapsulateFieldCandidate(inputCode, "fizz"); // as IUsingBackingField; + StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.BackingIdentifier); //StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.FieldIdentifierOld); //encapsulatedField.PropertyName = "Test"; encapsulatedField.PropertyIdentifier = "Test"; //StringAssert.AreEqualIgnoringCase("fizz", encapsulatedField.FieldIdentifierOld); - StringAssert.AreEqualIgnoringCase("fizz", encapsulatedField.FieldIdentifier); + StringAssert.AreEqualIgnoringCase("fizz", encapsulatedField.BackingIdentifier); //encapsulatedField.PropertyName = "Fizz"; encapsulatedField.PropertyIdentifier = "Fizz"; //StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.FieldIdentifierOld); - StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.FieldIdentifier); + StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.BackingIdentifier); //encapsulatedField.PropertyName = "Fiz"; encapsulatedField.PropertyIdentifier = "Fiz"; //StringAssert.AreEqualIgnoringCase("fizz", encapsulatedField.FieldIdentifierOld); - StringAssert.AreEqualIgnoringCase("fizz", encapsulatedField.FieldIdentifier); + StringAssert.AreEqualIgnoringCase("fizz", encapsulatedField.BackingIdentifier); //encapsulatedField.PropertyName = "Fizz"; encapsulatedField.PropertyIdentifier = "Fizz"; //StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.FieldIdentifierOld); - StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.FieldIdentifier); + StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.BackingIdentifier); } [Test] @@ -96,7 +96,7 @@ public void PropertyNameChange_UniqueParamName() [Category("Encapsulate Field")] public void AccountsForHungarianNamesAndMemberPrefix(string inputName, string expectedPropertyName, string expectedFieldName) { - var validator = new EncapsulateFieldValidationsProvider().NameOnlyValidator(Validators.Default); + var validator = new EncapsulateFieldValidationsProvider().NameOnlyValidator(NameValidators.Default); var sut = new EncapsulationIdentifiers(inputName, validator); Assert.AreEqual(expectedPropertyName, sut.DefaultPropertyName); diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index 47e41ffedd..beb49de560 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -129,31 +129,30 @@ public IRefactoring SupportTestRefactoring(IRewritingManager rewritingManager, R return new EncapsulateFieldRefactoring(state, indenter, factory, rewritingManager, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); } - public IEncapsulateFieldCandidate RetrieveEncapsulateFieldCandidate(string inputCode, string fieldName) + public IEncapsulatableField RetrieveEncapsulateFieldCandidate(string inputCode, string fieldName) { var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; return RetrieveEncapsulateFieldCandidate(vbe, fieldName); } - public IEncapsulateFieldCandidate RetrieveEncapsulateFieldCandidate(string inputCode, string fieldName, DeclarationType declarationType) + public IEncapsulatableField RetrieveEncapsulateFieldCandidate(string inputCode, string fieldName, DeclarationType declarationType) { var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; return RetrieveEncapsulateFieldCandidate(vbe, fieldName, declarationType); } - public IEncapsulateFieldCandidate RetrieveEncapsulateFieldCandidate(IVBE vbe, string fieldName, DeclarationType declarationType = DeclarationType.Variable) + public IEncapsulatableField RetrieveEncapsulateFieldCandidate(IVBE vbe, string fieldName, DeclarationType declarationType = DeclarationType.Variable) { var state = MockParser.CreateAndParse(vbe); using (state) { var match = state.DeclarationFinder.MatchName(fieldName).Where(m => m.DeclarationType.Equals(declarationType)).Single(); - var factory = new EncapsulateFieldElementFactory(state, match.QualifiedModuleName); - //var validator = new EncapsulateFieldValidator(state, factory.Candidates); - foreach (var candidate in factory.Candidates) + var builder = new EncapsulateFieldElementsBuilder(state, match.QualifiedModuleName); + foreach (var candidate in builder.Candidates) { - candidate.NameValidator = factory.ValidatorProvider.NameOnlyValidator(Validators.Default); + candidate.NameValidator = builder.ValidationsProvider.NameOnlyValidator(NameValidators.Default); } - return factory.Candidates.First(); + return builder.Candidates.First(); } } @@ -196,7 +195,7 @@ public class TestEncapsulationAttributes { public TestEncapsulationAttributes(string fieldName, bool encapsulationFlag = true, bool isReadOnly = false) { - var validator = new EncapsulateFieldValidationsProvider().NameOnlyValidator(Validators.Default); + var validator = new EncapsulateFieldValidationsProvider().NameOnlyValidator(NameValidators.Default); _identifiers = new EncapsulationIdentifiers(fieldName, validator); EncapsulateFlag = encapsulationFlag; IsReadOnly = isReadOnly; From fbbb867be780362e539caba54ecd4ea1bf66480c Mon Sep 17 00:00:00 2001 From: IvenBach Date: Thu, 9 Jan 2020 09:20:44 -0800 Subject: [PATCH 126/461] Display correct result in inspections window --- .../Inspections/Concrete/ImplicitlyTypedConstInspection.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs index 1853e98a19..5d3c60c2e2 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs @@ -5,6 +5,7 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Symbols; +using Rubberduck.Resources.Inspections; namespace Rubberduck.CodeAnalysis.Inspections.Concrete { @@ -26,9 +27,11 @@ protected override IEnumerable DoGetInspectionResults() private IInspectionResult Result(Declaration declaration) { + var description = string.Format(InspectionResults.ImplicitlyTypedConstInspection, declaration.IdentifierName); + return new IdentifierReferenceInspectionResult( this, - declaration.DescriptionString, + description, State, new IdentifierReference( declaration.QualifiedModuleName, From c0f63efc27137fed0c4281b72473d0015981dfea Mon Sep 17 00:00:00 2001 From: IvenBach Date: Thu, 9 Jan 2020 10:24:17 -0800 Subject: [PATCH 127/461] Add unit tests Add @Ignore annotation test. @Ignore annotation is working test. --- .../ImplicitlyTypedConstInspection.cs | 2 +- .../ImplicitlyTypedConstInspectionTests.cs | 18 ++++++++++++++++ .../QuickFixes/IgnoreOnceQuickFixTests.cs | 21 +++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs index 5d3c60c2e2..9bdc60cd04 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs @@ -20,7 +20,7 @@ protected override IEnumerable DoGetInspectionResults() var implicitlyTypedConsts = declarationFinder.AllDeclarations .Where(declaration => declaration.DeclarationType == DeclarationType.Constant - && declaration.AsTypeContext == null); + && !declaration.IsTypeSpecified); return implicitlyTypedConsts.Select(Result); } diff --git a/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs b/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs index c535e77861..f82335605e 100644 --- a/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs +++ b/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs @@ -53,6 +53,24 @@ public void ImplicitlyTypedConst_DoesNotReturnResult() Assert.AreEqual(expected, actual); } + [Test] + [Category("Inspections")] + public void ImplicitlyTypedConst_Ignored_DoesNotReturnResult() + { + const string inputCode = +@"Sub Foo() + '@Ignore ImplicitlyTypedConst + Const bar = 0 +End Sub"; + + const int expected = 0; + + var results = InspectionResultsForModules(("FooClass", inputCode, ComponentType.ClassModule)); + var actual = results.Count(); + + Assert.AreEqual(expected, actual); + } + protected override IInspection InspectionUnderTest(RubberduckParserState state) { return new ImplicitlyTypedConstInspection(state); diff --git a/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs b/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs index b987e56f88..521f1e95ac 100644 --- a/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs @@ -12,6 +12,7 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.VBEditor; using Rubberduck.VBEditor.SafeComWrappers.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Concrete; namespace RubberduckTests.QuickFixes { @@ -1050,6 +1051,26 @@ line _ Assert.AreEqual(expectedCode, actualCode); } + [Test] + [Category("QuickFixes")] + public void ImplicitlyTypedConst_IgnoreOnceQuickFixWorks() + { + const string inputCode = +@"Public Sub Foo() + Const bar = 0 +End Sub"; + + const string expected = +@"Public Sub Foo() + '@Ignore ImplicitlyTypedConst + Const bar = 0 +End Sub"; + + var actual = ApplyIgnoreOnceToFirstResult(inputCode, state => new ImplicitlyTypedConstInspection(state), TestStandardModuleVbeSetup); + + Assert.AreEqual(expected, actual); + } + private string ApplyIgnoreOnceToFirstResult( string inputCode, Func inspectionFactory, From d2c116e5c52b000c258cb27a866ab5be0f2dd62a Mon Sep 17 00:00:00 2001 From: IvenBach Date: Thu, 9 Jan 2020 11:02:46 -0800 Subject: [PATCH 128/461] Use correct inspection type --- .../Concrete/ImplicitlyTypedConstInspection.cs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs index 9bdc60cd04..b77f29237b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs @@ -29,18 +29,10 @@ private IInspectionResult Result(Declaration declaration) { var description = string.Format(InspectionResults.ImplicitlyTypedConstInspection, declaration.IdentifierName); - return new IdentifierReferenceInspectionResult( + return new DeclarationInspectionResult( this, description, - State, - new IdentifierReference( - declaration.QualifiedModuleName, - declaration.ParentScopeDeclaration, - declaration.ParentDeclaration, - declaration.IdentifierName, - declaration.Selection, - declaration.Context, - declaration)); + declaration); } } } From cae79671269e2771005e5cea896d96f5a0d6fcdc Mon Sep 17 00:00:00 2001 From: IvenBach Date: Thu, 9 Jan 2020 11:06:46 -0800 Subject: [PATCH 129/461] Improve variable name --- .../Inspections/ImplicitlyTypedConstInspectionTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs b/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs index f82335605e..b0b049144d 100644 --- a/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs +++ b/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs @@ -14,10 +14,10 @@ public class ImplicitlyTypedConstInspectionTests : InspectionTestsBase [Category("Inspections")] public void InspectionName() { - var inspection = new ImplicitlyTypedConstInspection(null); + var inspectionUnderTest = new ImplicitlyTypedConstInspection(null); var expected = nameof(ImplicitlyTypedConstInspection); - var actual = inspection.Name; + var actual = inspectionUnderTest.Name; Assert.AreEqual(expected, actual); } From e81decf07a269248af52cc329dc0b21834fe2038 Mon Sep 17 00:00:00 2001 From: IvenBach Date: Thu, 9 Jan 2020 13:49:09 -0800 Subject: [PATCH 130/461] Add unit tests for type hints --- .../ImplicitlyTypedConstInspectionTests.cs | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs b/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs index b0b049144d..36911c524b 100644 --- a/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs +++ b/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs @@ -53,6 +53,52 @@ public void ImplicitlyTypedConst_DoesNotReturnResult() Assert.AreEqual(expected, actual); } + [Test] + [Category("Inspections")] + [TestCase("!")] + [TestCase("@")] + [TestCase("#")] + [TestCase("$")] + [TestCase("%")] + [TestCase("^")] + [TestCase("&")] + public void ImplicitlyTypedConst_HasTypeHint_DoesNotReturnResult(string typeHint) + { + string inputCode = +$@"Public Sub Foo() + Const bar{typeHint} = 0 +End Sub"; + + const int expected = 0; + + var results = InspectionResultsForModules(("FooClass", inputCode, ComponentType.ClassModule)); + var actual = results.Count(); + Assert.AreEqual(expected, actual); + } + + [Test] + [Category("Inspections")] + [TestCase("!")] + [TestCase("@")] + [TestCase("#")] + //[TestCase("$")] Errors out + [TestCase("%")] + [TestCase("^")] + [TestCase("&")] + public void ImplicitlyTypedConst_AssignedValueHasTypeHint_ReturnsResult(string typeHint) + { + string inputCode = +$@"Public Sub Foo() + Const bar = 0{typeHint} +End Sub"; + + const int expected = 1; + + var results = InspectionResultsForModules(("FooClass", inputCode, ComponentType.ClassModule)); + var actual = results.Count(); + Assert.AreEqual(expected, actual); + } + [Test] [Category("Inspections")] public void ImplicitlyTypedConst_Ignored_DoesNotReturnResult() From 7d977d54d712c513073dfcd3681fc5f1b2319893 Mon Sep 17 00:00:00 2001 From: IvenBach Date: Fri, 10 Jan 2020 11:03:50 -0800 Subject: [PATCH 131/461] Update constant declaration retrieval --- .../Inspections/Concrete/ImplicitlyTypedConstInspection.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs index b77f29237b..b6f4864f79 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs @@ -18,9 +18,8 @@ protected override IEnumerable DoGetInspectionResults() { var declarationFinder = State.DeclarationFinder; - var implicitlyTypedConsts = declarationFinder.AllDeclarations - .Where(declaration => declaration.DeclarationType == DeclarationType.Constant - && !declaration.IsTypeSpecified); + var implicitlyTypedConsts = declarationFinder.UserDeclarations(DeclarationType.Constant) + .Where(declaration => !declaration.IsTypeSpecified); return implicitlyTypedConsts.Select(Result); } From b15e61891c3c50f1412785b406d8a69250611cf0 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sat, 11 Jan 2020 00:53:17 +0100 Subject: [PATCH 132/461] Add declaration finder as parameter to IsResultReference on inspection base class Also moves further identifier reference inspections to the appropriate base classes. --- .../Extensions/NodeExtensions.cs | 41 ++---- .../IdentifierReferenceInspectionBase.cs | 10 +- ...ReferenceInspectionFromDeclarationsBase.cs | 12 +- .../Inspections/Abstract/InspectionBase.cs | 54 ++++---- .../Abstract/IsMissingInspectionBase.cs | 77 +++++++--- ...berAccessMayReturnNothingInspectionBase.cs | 131 +++++++++--------- .../Concrete/AssignmentNotUsedInspection.cs | 81 +++++++---- .../DefaultMemberRequiredInspection.cs | 2 +- .../ExcelMemberMayReturnNothingInspection.cs | 32 ++++- .../ImplicitDefaultMemberAccessInspection.cs | 3 +- ...tRecursiveDefaultMemberAccessInspection.cs | 3 +- ...citUnboundDefaultMemberAccessInspection.cs | 2 +- .../IndexedDefaultMemberAccessInspection.cs | 3 +- ...dRecursiveDefaultMemberAccessInspection.cs | 3 +- ...xedUnboundDefaultMemberAccessInspection.cs | 2 +- ...issingOnInappropriateArgumentInspection.cs | 45 +++--- ...ssingWithNonArgumentParameterInspection.cs | 27 ++-- .../ObjectVariableNotSetInspection.cs | 55 +------- .../Concrete/ObsoleteMemberUsageInspection.cs | 3 +- .../Concrete/ProcedureRequiredInspection.cs | 2 +- .../Concrete/UseOfBangNotationInspection.cs | 3 +- .../UseOfRecursiveBangNotationInspection.cs | 3 +- .../UseOfUnboundBangNotationInspection.cs | 2 +- .../Concrete/ValueRequiredInspection.cs | 2 +- ...elMemberMayReturnNothingInspectionTests.cs | 129 ++++++++++++++++- 25 files changed, 435 insertions(+), 292 deletions(-) diff --git a/Rubberduck.CodeAnalysis/CodePathAnalysis/Extensions/NodeExtensions.cs b/Rubberduck.CodeAnalysis/CodePathAnalysis/Extensions/NodeExtensions.cs index f9c66e5622..50cc03b9bd 100644 --- a/Rubberduck.CodeAnalysis/CodePathAnalysis/Extensions/NodeExtensions.cs +++ b/Rubberduck.CodeAnalysis/CodePathAnalysis/Extensions/NodeExtensions.cs @@ -2,13 +2,12 @@ using System; using System.Collections.Generic; using System.Linq; -using Rubberduck.Parsing.Symbols; namespace Rubberduck.Inspections.CodePathAnalysis.Extensions { public static class NodeExtensions { - public static IEnumerable GetFlattenedNodes(this INode node, IEnumerable excludedTypes) + public static IEnumerable FlattenedNodes(this INode node, IEnumerable excludedTypes) { foreach (var child in node.Children) { @@ -18,7 +17,7 @@ public static IEnumerable GetFlattenedNodes(this INode node, IEnumerable< } else { - foreach (var nextChild in GetFlattenedNodes(child, excludedTypes)) + foreach (var nextChild in FlattenedNodes(child, excludedTypes)) { yield return nextChild; } @@ -26,7 +25,7 @@ public static IEnumerable GetFlattenedNodes(this INode node, IEnumerable< } } - public static IEnumerable GetNodes(this INode node, IEnumerable types) + public static IEnumerable Nodes(this INode node, ICollection types) { if (types.Contains(node.GetType())) { @@ -35,50 +34,26 @@ public static IEnumerable GetNodes(this INode node, IEnumerable typ foreach (var child in node.Children) { - foreach (var childNode in GetNodes(child, types)) + foreach (var childNode in Nodes(child, types)) { yield return childNode; } } } - public static INode GetFirstNode(this INode node, IEnumerable excludedTypes) + public static INode GetFirstNode(this INode node, ICollection excludedTypes) { if (!excludedTypes.Contains(node.GetType())) { return node; } - return GetFirstNode(node.Children[0], excludedTypes); - } - - public static List GetIdentifierReferences(this INode node) - { - var nodes = new List(); - - var blockNodes = node.GetNodes(new[] { typeof(BlockNode) }); - foreach (var block in blockNodes) + if (!node.Children.Any()) { - INode lastNode = default; - foreach (var flattenedNode in block.GetFlattenedNodes(new[] { typeof(GenericNode), typeof(BlockNode) })) - { - if (flattenedNode is AssignmentNode && - lastNode is AssignmentNode) - { - nodes.Add(lastNode.Reference); - } - - lastNode = flattenedNode; - } - - if (lastNode is AssignmentNode && - block.Children[0].GetFirstNode(new[] { typeof(GenericNode) }) is DeclarationNode) - { - nodes.Add(lastNode.Reference); - } + return null; } - return nodes; + return GetFirstNode(node.Children[0], excludedTypes); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs index 92f97d5b1d..60bc68a3f9 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs @@ -11,15 +11,11 @@ namespace Rubberduck.Inspections.Abstract { public abstract class IdentifierReferenceInspectionBase : InspectionBase { - protected readonly IDeclarationFinderProvider DeclarationFinderProvider; - public IdentifierReferenceInspectionBase(RubberduckParserState state) : base(state) - { - DeclarationFinderProvider = state; - } + {} - protected abstract bool IsResultReference(IdentifierReference reference); + protected abstract bool IsResultReference(IdentifierReference reference, DeclarationFinder finder); protected abstract string ResultDescription(IdentifierReference reference); protected override IEnumerable DoGetInspectionResults() @@ -44,7 +40,7 @@ protected override IEnumerable DoGetInspectionResults() protected IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { var objectionableReferences = ReferencesInModule(module, finder) - .Where(IsResultReference); + .Where(reference => IsResultReference(reference, finder)); return objectionableReferences .Select(reference => InspectionResult(reference, DeclarationFinderProvider)) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs index abb6b627f0..c7ea463410 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs @@ -11,13 +11,9 @@ namespace Rubberduck.Inspections.Abstract { public abstract class IdentifierReferenceInspectionFromDeclarationsBase : InspectionBase { - protected readonly IDeclarationFinderProvider DeclarationFinderProvider; - protected IdentifierReferenceInspectionFromDeclarationsBase(RubberduckParserState state) : base(state) - { - DeclarationFinderProvider = state; - } + {} protected abstract IEnumerable ObjectionableDeclarations(DeclarationFinder finder); protected abstract string ResultDescription(IdentifierReference reference); @@ -31,15 +27,15 @@ protected override IEnumerable DoGetInspectionResults() .ToList(); } - private IEnumerable ObjectionableReferences(DeclarationFinder finder) + protected virtual IEnumerable ObjectionableReferences(DeclarationFinder finder) { var objectionableDeclarations = ObjectionableDeclarations(finder); return objectionableDeclarations .SelectMany(declaration => declaration.References) - .Where(IsResultReference); + .Where(reference => IsResultReference(reference, finder)); } - protected virtual bool IsResultReference(IdentifierReference reference) => true; + protected virtual bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) => true; protected IEnumerable DoGetInspectionResults(QualifiedModuleName module) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs index 99f6b0065d..ab846af7ec 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs @@ -17,12 +17,16 @@ namespace Rubberduck.Inspections.Abstract public abstract class InspectionBase : IInspection { protected readonly RubberduckParserState State; + protected readonly IDeclarationFinderProvider DeclarationFinderProvider; - private readonly ILogger _logger = LogManager.GetCurrentClassLogger(); + protected readonly ILogger Logger; protected InspectionBase(RubberduckParserState state) { + Logger = LogManager.GetLogger(GetType().FullName); + State = state; + DeclarationFinderProvider = state; Name = GetType().Name; } @@ -66,33 +70,26 @@ protected InspectionBase(RubberduckParserState state) /// /// Gets all declarations in the parser state without an @Ignore annotation for this inspection. /// - protected virtual IEnumerable Declarations - { - get { return State.AllDeclarations.Where(declaration => !declaration.IsIgnoringInspectionResultFor(AnnotationName)); } - } + protected virtual IEnumerable Declarations => DeclarationFinderProvider + .DeclarationFinder + .AllDeclarations + .Where(declaration => !declaration.IsIgnoringInspectionResultFor(AnnotationName)); /// /// Gets all user declarations in the parser state without an @Ignore annotation for this inspection. /// - protected virtual IEnumerable UserDeclarations - { - get { return State.AllUserDeclarations.Where(declaration => !declaration.IsIgnoringInspectionResultFor(AnnotationName)); } - } + protected virtual IEnumerable UserDeclarations => DeclarationFinderProvider + .DeclarationFinder + .AllUserDeclarations + .Where(declaration => !declaration.IsIgnoringInspectionResultFor(AnnotationName)); - protected virtual IEnumerable BuiltInDeclarations - { - get { return State.AllDeclarations.Where(declaration => !declaration.IsUserDefined); } - } + protected virtual IEnumerable BuiltInDeclarations => DeclarationFinderProvider + .DeclarationFinder + .AllBuiltInDeclarations; - public int CompareTo(IInspection other) - { - return string.Compare(InspectionType + Name, other.InspectionType + other.Name, StringComparison.Ordinal); - } + public int CompareTo(IInspection other) => string.Compare(InspectionType + Name, other.InspectionType + other.Name, StringComparison.Ordinal); + public int CompareTo(object obj) => CompareTo(obj as IInspection); - public int CompareTo(object obj) - { - return CompareTo(obj as IInspection); - } protected abstract IEnumerable DoGetInspectionResults(); /// @@ -102,14 +99,15 @@ public int CompareTo(object obj) /// public IEnumerable GetInspectionResults(CancellationToken token) { - var _stopwatch = new Stopwatch(); - _stopwatch.Start(); - var declarationFinder = State.DeclarationFinder; + var stopwatch = new Stopwatch(); + stopwatch.Start(); + var declarationFinder = DeclarationFinderProvider.DeclarationFinder; var result = DoGetInspectionResults() - .Where(ir => !ir.IsIgnoringInspectionResult(declarationFinder)); - _stopwatch.Stop(); - _logger.Trace("Intercepted invocation of '{0}.{1}' returned {2} objects.", GetType().Name, nameof(DoGetInspectionResults), result.Count()); - _logger.Trace("Intercepted invocation of '{0}.{1}' ran for {2}ms", GetType().Name, nameof(DoGetInspectionResults), _stopwatch.ElapsedMilliseconds); + .Where(ir => !ir.IsIgnoringInspectionResult(declarationFinder)) + .ToList(); + stopwatch.Stop(); + Logger.Trace("Intercepted invocation of '{0}.{1}' returned {2} objects.", GetType().Name, nameof(DoGetInspectionResults), result.Count); + Logger.Trace("Intercepted invocation of '{0}.{1}' ran for {2}ms", GetType().Name, nameof(DoGetInspectionResults), stopwatch.ElapsedMilliseconds); return result; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs index 24b0d56b00..813673522c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs @@ -4,16 +4,16 @@ using NLog; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; +using Rubberduck.Parsing.Binding; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Inspections.Abstract { - public abstract class IsMissingInspectionBase : InspectionBase + public abstract class IsMissingInspectionBase : IdentifierReferenceInspectionFromDeclarationsBase { - private readonly ILogger _logger = LogManager.GetCurrentClassLogger(); - protected IsMissingInspectionBase(RubberduckParserState state) : base(state) { } @@ -23,39 +23,72 @@ protected IsMissingInspectionBase(RubberduckParserState state) "VBA6.DLL;VBA.Information.IsMissing" }; - protected IReadOnlyList IsMissingDeclarations + protected abstract bool IsUnsuitableArgument(ArgumentReference reference, DeclarationFinder finder); + + + protected override IEnumerable ObjectionableDeclarations(DeclarationFinder finder) + { + return IsMissingDeclarations(finder); + } + + protected IReadOnlyList IsMissingDeclarations(DeclarationFinder finder) { - get + var vbaProjects = finder.Projects + .Where(project => project.IdentifierName == "VBA") + .ToList(); + + if (!vbaProjects.Any()) { - var isMissing = BuiltInDeclarations.Where(decl => IsMissingQualifiedNames.Contains(decl.QualifiedName.ToString())).ToList(); + return new List(); + } - if (isMissing.Count == 0) - { - _logger.Trace("No 'IsMissing' Declarations were found in IsMissingInspectionBase."); - } + var informationModules = vbaProjects + .Select(project => finder.FindStdModule("Information", project, true)) + .OfType() + .ToList(); - return isMissing; + if (!informationModules.Any()) + { + return new List(); } + + var isMissing = informationModules + .SelectMany(module => module.Members) + .Where(decl => IsMissingQualifiedNames.Contains(decl.QualifiedName.ToString())) + .ToList(); + + return isMissing; + } + + protected override IEnumerable ObjectionableReferences(DeclarationFinder finder) + { + return ObjectionableDeclarations(finder) + .OfType() + .SelectMany(declaration => declaration.Parameters) + .SelectMany(parameter => parameter.ArgumentReferences) + .Where(reference => IsResultReference(reference, finder)); } - protected ParameterDeclaration GetParameterForReference(IdentifierReference reference) + protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) { - // First case is for unqualified use: IsMissing(foo) - // Second case if for use as a member access: VBA.IsMissing(foo) - var argument = ((ParserRuleContext)reference.Context.Parent).GetDescendent() ?? - ((ParserRuleContext)reference.Context.Parent.Parent).GetDescendent(); + return reference is ArgumentReference argumentReference + && IsUnsuitableArgument(argumentReference, finder); + } - var name = argument?.GetDescendent(); - if (name == null || name.Parent.Parent != argument) + protected ParameterDeclaration GetParameterForReference(ArgumentReference reference, DeclarationFinder finder) + { + var argumentContext = reference.Context as VBAParser.LExprContext; + if (!(argumentContext?.lExpression() is VBAParser.SimpleNameExprContext name)) { return null; } var procedure = reference.Context.GetAncestor(); - return UserDeclarations.Where(decl => decl is ModuleBodyElementDeclaration) - .Cast() - .FirstOrDefault(decl => decl.Context.Parent == procedure)? - .Parameters.FirstOrDefault(param => param.IdentifierName.Equals(name.GetText())); + //TODO: revisit this once PR #5338 is merged. + return finder.UserDeclarations(DeclarationType.Member) + .OfType() + .FirstOrDefault(decl => decl.Context.Parent == procedure)?.Parameters + .FirstOrDefault(param => param.IdentifierName.Equals(name.GetText())); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/MemberAccessMayReturnNothingInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/MemberAccessMayReturnNothingInspectionBase.cs index b190901a20..0a197ad7ed 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/MemberAccessMayReturnNothingInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/MemberAccessMayReturnNothingInspectionBase.cs @@ -1,104 +1,109 @@ using System.Collections.Generic; using System.Linq; +using Antlr4.Runtime; using Antlr4.Runtime.Tree; using Rubberduck.Inspections.CodePathAnalysis; using Rubberduck.Inspections.CodePathAnalysis.Nodes; using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Abstract { - public abstract class MemberAccessMayReturnNothingInspectionBase : InspectionBase + public abstract class MemberAccessMayReturnNothingInspectionBase : IdentifierReferenceInspectionFromDeclarationsBase { protected MemberAccessMayReturnNothingInspectionBase(RubberduckParserState state) : base(state) { } - public abstract List MembersUnderTest { get; } + public abstract IEnumerable MembersUnderTest(DeclarationFinder finder); public abstract string ResultTemplate { get; } - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable ObjectionableDeclarations(DeclarationFinder finder) { - var interesting = MembersUnderTest.SelectMany(member => member.References).ToList(); - if (!interesting.Any()) + return MembersUnderTest(finder); + } + + protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) + { + // prefilter to reduce search space + if (reference.IsIgnoringInspectionResultFor(AnnotationName)) { - return Enumerable.Empty(); + return false; } - var output = new List(); - // prefilter to reduce search space - var prefilteredReferences = interesting.Where(use => !use.IsIgnoringInspectionResultFor(AnnotationName)); - foreach (var reference in prefilteredReferences) + var usageContext = UsageContext(reference); + + var setter = usageContext is VBAParser.LExprContext lexpr + && lexpr.Parent is VBAParser.SetStmtContext + ? lexpr.Parent + : null; + + if (setter is null) { - var access = reference.Context.GetAncestor(); - var usageContext = access.Parent is VBAParser.IndexExprContext - ? access.Parent.Parent - : access.Parent; - - var setter = usageContext is VBAParser.LExprContext lexpr && lexpr.Parent is VBAParser.SetStmtContext - ? lexpr.Parent - : null; - - if (setter is null) - { - if (usageContext is VBAParser.MemberAccessExprContext || !ContextIsNothingTest(usageContext)) - { - output.Add(new IdentifierReferenceInspectionResult(this, - string.Format(ResultTemplate, - $"{reference.Declaration.ParentDeclaration.IdentifierName}.{reference.IdentifierName}"), - State, reference)); - } - continue; - } - - var assignedTo = Declarations.SelectMany(decl => decl.References).SingleOrDefault(assign => - assign.IsAssignment && (assign.Context.GetAncestor()?.Equals(setter) ?? false)); - if (assignedTo is null) - { - continue; - } - - var tree = new Walker().GenerateTree(assignedTo.Declaration.ParentScopeDeclaration.Context, assignedTo.Declaration); - var firstUse = GetReferenceNodes(tree).FirstOrDefault(); - if (firstUse is null || ContextIsNothingTest(firstUse.Reference.Context.Parent)) - { - continue; - } - - output.Add(new IdentifierReferenceInspectionResult(this, - string.Format(ResultTemplate, - $"{reference.Declaration.ParentDeclaration.IdentifierName}.{reference.IdentifierName}"), - State, reference)); + return usageContext is VBAParser.MemberAccessExprContext + || !(usageContext is VBAParser.CallStmtContext) + && !ContextIsNothingTest(usageContext); } - return output; + var assignedTo = AssignmentTarget(reference, finder, setter); + return assignedTo != null + && IsUsedBeforeCheckingForNothing(assignedTo); } - private bool ContextIsNothingTest(IParseTree context) + private static IdentifierReference AssignmentTarget(IdentifierReference reference, DeclarationFinder finder, ITree setter) { - return context is VBAParser.LExprContext && - context.Parent is VBAParser.RelationalOpContext comparison && - comparison.IS() != null + var assignedTo = finder.IdentifierReferences(reference.QualifiedModuleName) + .SingleOrDefault(assign => + assign.IsAssignment + && (assign.Context.GetAncestor()?.Equals(setter) ?? false)); + return assignedTo; + } + + private static RuleContext UsageContext(IdentifierReference reference) + { + var access = reference.Context.GetAncestor(); + var usageContext = access.Parent is VBAParser.IndexExprContext indexExpr + ? indexExpr.Parent + : access.Parent; + return usageContext; + } + + private static bool ContextIsNothingTest(IParseTree context) + { + return context is VBAParser.LExprContext + && context.Parent is VBAParser.RelationalOpContext comparison + && comparison.IS() != null && comparison.GetDescendent() != null; } - private IEnumerable GetReferenceNodes(INode node) + private static bool IsUsedBeforeCheckingForNothing(IdentifierReference assignedTo) + { + var tree = new Walker().GenerateTree(assignedTo.Declaration.ParentScopeDeclaration.Context, assignedTo.Declaration); + var firstUse = GetReferenceNodes(tree).FirstOrDefault(); + + return !(firstUse is null) + && !ContextIsNothingTest(firstUse.Reference.Context.Parent); + } + + private static IEnumerable GetReferenceNodes(INode node) { if (node is ReferenceNode && node.Reference != null) { yield return node; } - - foreach (var child in node.Children) + + foreach (var childNode in node.Children.SelectMany(GetReferenceNodes)) { - foreach (var childNode in GetReferenceNodes(child)) - { - yield return childNode; - } + yield return childNode; } } + + protected override string ResultDescription(IdentifierReference reference) + { + var semiQualifiedName = $"{reference.Declaration.ParentDeclaration.IdentifierName}.{reference.IdentifierName}"; + return string.Format(ResultTemplate, semiQualifiedName); + } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs index d6e6dac61d..1dd6c8312b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs @@ -1,14 +1,15 @@ using System.Collections.Generic; using Rubberduck.Inspections.Abstract; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Inspections.CodePathAnalysis; using Rubberduck.Parsing.Symbols; using Rubberduck.Inspections.CodePathAnalysis.Extensions; using System.Linq; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Grammar; +using Rubberduck.Inspections.CodePathAnalysis.Nodes; using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete { @@ -36,7 +37,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class AssignmentNotUsedInspection : InspectionBase + public sealed class AssignmentNotUsedInspection : IdentifierReferenceInspectionBase { private readonly Walker _walker; @@ -45,36 +46,68 @@ public AssignmentNotUsedInspection(RubberduckParserState state, Walker walker) _walker = walker; } - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable ReferencesInModule(QualifiedModuleName module, DeclarationFinder finder) + { + //TODO: Revisit this once PR #5338 is merged. + var localNonArrayVariables = finder.Members(module) + .Where(declaration => declaration.DeclarationType == DeclarationType.Variable + && !declaration.IsArray + && !declaration.ParentScopeDeclaration.DeclarationType.HasFlag(DeclarationType.Module)); + return localNonArrayVariables + .Where(declaration => !declaration.IsIgnoringInspectionResultFor(AnnotationName)) + .SelectMany(UnusedAssignments); + } + + private IEnumerable UnusedAssignments(Declaration localVariable) { - var variables = State.DeclarationFinder - .UserDeclarations(DeclarationType.Variable) - .Where(d => !d.IsArray); + var tree = _walker.GenerateTree(localVariable.ParentScopeDeclaration.Context, localVariable); + return UnusedAssignmentReferences(tree); + } + public static List UnusedAssignmentReferences(INode node) + { var nodes = new List(); - foreach (var variable in variables) + + var blockNodes = node.Nodes(new[] { typeof(BlockNode) }); + foreach (var block in blockNodes) { - var parentScopeDeclaration = variable.ParentScopeDeclaration; + INode lastNode = default; + foreach (var flattenedNode in block.FlattenedNodes(new[] { typeof(GenericNode), typeof(BlockNode) })) + { + if (flattenedNode is AssignmentNode && + lastNode is AssignmentNode) + { + nodes.Add(lastNode.Reference); + } + + lastNode = flattenedNode; + } - if (parentScopeDeclaration.DeclarationType.HasFlag(DeclarationType.Module)) + if (lastNode is AssignmentNode && + block.Children[0].GetFirstNode(new[] { typeof(GenericNode) }) is DeclarationNode) { - continue; + nodes.Add(lastNode.Reference); } + } - var tree = _walker.GenerateTree(parentScopeDeclaration.Context, variable); + return nodes; + } - var references = tree.GetIdentifierReferences(); - // ignore set-assignments to 'Nothing' - nodes.AddRange(references.Where(r => - !(r.Context.Parent is VBAParser.SetStmtContext setStmtContext && - setStmtContext.expression().GetText().Equals(Tokens.Nothing)))); - } + protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) + { + return !IsAssignmentOfNothing(reference); + } - return nodes - // Ignoring the Declaration disqualifies all assignments - .Where(issue => !issue.Declaration.IsIgnoringInspectionResultFor(AnnotationName)) - .Select(issue => new IdentifierReferenceInspectionResult(this, Description, State, issue)) - .ToList(); + private static bool IsAssignmentOfNothing(IdentifierReference reference) + { + return reference.IsSetAssignment + && reference.Context.Parent is VBAParser.SetStmtContext setStmtContext + && setStmtContext.expression().GetText().Equals(Tokens.Nothing); + } + + protected override string ResultDescription(IdentifierReference reference) + { + return Description; } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs index d6e72f9871..64bfe5c634 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs @@ -68,7 +68,7 @@ protected override IEnumerable ReferencesInModule(Qualified return finder.FailedIndexedDefaultMemberAccesses(module); } - protected override bool IsResultReference(IdentifierReference failedIndexedDefaultMemberAccess) + protected override bool IsResultReference(IdentifierReference failedIndexedDefaultMemberAccess, DeclarationFinder finder) { return true; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelMemberMayReturnNothingInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelMemberMayReturnNothingInspection.cs index 5818439f02..243152c163 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelMemberMayReturnNothingInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelMemberMayReturnNothingInspection.cs @@ -5,6 +5,7 @@ using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; namespace Rubberduck.Inspections.Concrete @@ -43,16 +44,33 @@ public class ExcelMemberMayReturnNothingInspection : MemberAccessMayReturnNothin { public ExcelMemberMayReturnNothingInspection(RubberduckParserState state) : base(state) { } - private static readonly List ExcelMembers = new List + private static readonly List<(string className, string memberName)> ExcelMembers = new List<(string className, string memberName)> { - "Range.Find", - "Range.FindNext", - "Range.FindPrevious" + ("Range","Find"), + ("Range","FindNext"), + ("Range","FindPrevious") }; - public override List MembersUnderTest => BuiltInDeclarations - .Where(decl => decl.ProjectName.Equals("Excel") && ExcelMembers.Any(member => decl.QualifiedName.ToString().EndsWith(member))) - .ToList(); + public override IEnumerable MembersUnderTest(DeclarationFinder finder) + { + var excel = finder.Projects + .SingleOrDefault(item => !item.IsUserDefined + && item.IdentifierName == "Excel"); + if (excel == null) + { + return Enumerable.Empty(); + } + + var memberModules = ExcelMembers + .Select(tpl => tpl.className) + .Distinct() + .Select(className => finder.FindClassModule(className, excel, true)) + .OfType(); + + return memberModules + .SelectMany(module => module.Members) + .Where(member => ExcelMembers.Contains((member.ComponentName, member.IdentifierName))); + } public override string ResultTemplate => InspectionResults.ExcelMemberMayReturnNothingInspection; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs index 030636c0d4..4eb9538eb4 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs @@ -4,6 +4,7 @@ using Rubberduck.Parsing.VBA; using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.Inspections; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -54,7 +55,7 @@ public ImplicitDefaultMemberAccessInspection(RubberduckParserState state) Severity = CodeInspectionSeverity.Suggestion; } - protected override bool IsResultReference(IdentifierReference reference) + protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) { return reference.IsNonIndexedDefaultMemberAccess && reference.DefaultMemberRecursionDepth == 1 diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs index c1b0eb1c7e..f2dae91a23 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs @@ -4,6 +4,7 @@ using Rubberduck.Parsing.VBA; using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.Inspections; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -74,7 +75,7 @@ public ImplicitRecursiveDefaultMemberAccessInspection(RubberduckParserState stat Severity = CodeInspectionSeverity.Suggestion; } - protected override bool IsResultReference(IdentifierReference reference) + protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) { return reference.IsNonIndexedDefaultMemberAccess && reference.DefaultMemberRecursionDepth > 1 diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs index 57128a2356..230f79ae34 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs @@ -63,7 +63,7 @@ protected override IEnumerable ReferencesInModule(Qualified return finder.UnboundDefaultMemberAccesses(module); } - protected override bool IsResultReference(IdentifierReference reference) + protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) { return reference.IsNonIndexedDefaultMemberAccess && !reference.IsProcedureCoercion diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs index 5d728a4576..66adec3eb6 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs @@ -5,6 +5,7 @@ using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -38,7 +39,7 @@ public IndexedDefaultMemberAccessInspection(RubberduckParserState state) Severity = CodeInspectionSeverity.Hint; } - protected override bool IsResultReference(IdentifierReference reference) + protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) { return reference.IsIndexedDefaultMemberAccess && reference.DefaultMemberRecursionDepth == 1 diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs index 7ca5934201..f37bb2305e 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs @@ -5,6 +5,7 @@ using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -38,7 +39,7 @@ public IndexedRecursiveDefaultMemberAccessInspection(RubberduckParserState state Severity = CodeInspectionSeverity.Suggestion; } - protected override bool IsResultReference(IdentifierReference reference) + protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) { return reference.IsIndexedDefaultMemberAccess && reference.DefaultMemberRecursionDepth > 1 diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs index 73a811830f..5fabddaf34 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs @@ -47,7 +47,7 @@ protected override IEnumerable ReferencesInModule(Qualified return finder.UnboundDefaultMemberAccesses(module); } - protected override bool IsResultReference(IdentifierReference reference) + protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) { return reference.IsIndexedDefaultMemberAccess && !(reference.Context is VBAParser.DictionaryAccessContext) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs index 986bf6c965..c1a74c5bf6 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs @@ -5,7 +5,9 @@ using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; namespace Rubberduck.Inspections.Concrete @@ -38,30 +40,35 @@ public class IsMissingOnInappropriateArgumentInspection : IsMissingInspectionBas public IsMissingOnInappropriateArgumentInspection(RubberduckParserState state) : base(state) { } - protected override IEnumerable DoGetInspectionResults() + protected override bool IsUnsuitableArgument(ArgumentReference reference, DeclarationFinder finder) { - var results = new List(); + var parameter = GetParameterForReference(reference, finder); - var prefilteredReferences = IsMissingDeclarations.SelectMany(decl => decl.References - .Where(candidate => !candidate.IsIgnoringInspectionResultFor(AnnotationName))); - - foreach (var reference in prefilteredReferences) - { - var parameter = GetParameterForReference(reference); + return parameter != null + && (!parameter.IsOptional + || !parameter.AsTypeName.Equals(Tokens.Variant) + || !string.IsNullOrEmpty(parameter.DefaultValue) + || parameter.IsArray); + } - if (parameter == null || - parameter.IsOptional - && parameter.AsTypeName.Equals(Tokens.Variant) - && string.IsNullOrEmpty(parameter.DefaultValue) - && !parameter.IsArray) - { - continue; - } + protected override IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider) + { + //This is not ideal, put passing along the declaration finder used in the test itself or the parameter requires reimplementing half of the base class. + var argumentReference = reference as ArgumentReference; + var finder = declarationFinderProvider.DeclarationFinder; + var parameter = GetParameterForReference(argumentReference, finder); - results.Add(new IdentifierReferenceInspectionResult(this, InspectionResults.IsMissingOnInappropriateArgumentInspection, State, reference, parameter)); - } + return new IdentifierReferenceInspectionResult( + this, + ResultDescription(reference), + declarationFinderProvider, + reference, + parameter); + } - return results; + protected override string ResultDescription(IdentifierReference reference) + { + return InspectionResults.IsMissingOnInappropriateArgumentInspection; } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs index f442d18703..99597d0532 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs @@ -4,7 +4,9 @@ using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; namespace Rubberduck.Inspections.Inspections.Concrete @@ -38,27 +40,16 @@ public class IsMissingWithNonArgumentParameterInspection : IsMissingInspectionBa public IsMissingWithNonArgumentParameterInspection(RubberduckParserState state) : base(state) { } - protected override IEnumerable DoGetInspectionResults() + protected override bool IsUnsuitableArgument(ArgumentReference reference, DeclarationFinder finder) { - var results = new List(); + var parameter = GetParameterForReference(reference, finder); - // prefilter to reduce searchspace - var prefilteredReferences = IsMissingDeclarations.SelectMany(decl => decl.References - .Where(candidate => !candidate.IsIgnoringInspectionResultFor(AnnotationName))); - - foreach (var reference in prefilteredReferences) - { - var parameter = GetParameterForReference(reference); - - if (parameter != null) - { - continue; - } - - results.Add(new IdentifierReferenceInspectionResult(this, InspectionResults.IsMissingWithNonArgumentParameterInspection, State, reference)); - } + return parameter == null; + } - return results; + protected override string ResultDescription(IdentifierReference reference) + { + return InspectionResults.IsMissingWithNonArgumentParameterInspection; } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs index 8ef0cd83eb..d8d811ea60 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs @@ -3,8 +3,6 @@ using System.Linq; using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; @@ -40,50 +38,13 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ObjectVariableNotSetInspection : InspectionBase + public sealed class ObjectVariableNotSetInspection : IdentifierReferenceInspectionBase { - private IDeclarationFinderProvider _declarationFinderProvider; - public ObjectVariableNotSetInspection(RubberduckParserState state) : base(state) - { - _declarationFinderProvider = state; - } - - protected override IEnumerable DoGetInspectionResults() - { - var finder = _declarationFinderProvider.DeclarationFinder; - - var results = new List(); - foreach (var moduleDeclaration in finder.UserDeclarations(DeclarationType.Module)) - { - if (moduleDeclaration == null) - { - continue; - } - - var module = moduleDeclaration.QualifiedModuleName; - results.AddRange(DoGetInspectionResults(module, finder)); - } - - return results; - } - - private IEnumerable DoGetInspectionResults(QualifiedModuleName module) - { - var finder = _declarationFinderProvider.DeclarationFinder; - return DoGetInspectionResults(module, finder); - } - - private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) - { - var failedailedLetResolutionResultReferences = FailedLetResolutionResultReferences(module, finder); - - return failedailedLetResolutionResultReferences - .Select(reference => InspectionResult(reference, _declarationFinderProvider)); - } + {} - private IEnumerable FailedLetResolutionResultReferences(QualifiedModuleName module, DeclarationFinder finder) + protected override IEnumerable ReferencesInModule(QualifiedModuleName module, DeclarationFinder finder) { var failedLetCoercionAssignmentsInModule = FailedLetResolutionAssignments(module, finder); var possiblyObjectLhsLetAssignmentsWithFailedLetResolutionOnRhs = PossiblyObjectLhsLetAssignmentsWithNonValueOnRhs(module, finder); @@ -132,16 +93,12 @@ private static IEnumerable PossiblyObjectNonSetAssignments( return assignments.Concat(unboundAssignments); } - private IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider) + protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) { - return new IdentifierReferenceInspectionResult( - this, - ResultDescription(reference), - declarationFinderProvider, - reference); + return true; } - private static string ResultDescription(IdentifierReference reference) + protected override string ResultDescription(IdentifierReference reference) { return string.Format(InspectionResults.ObjectVariableNotSetInspection, reference.IdentifierName); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs index 3343037c3d..15881ffd29 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs @@ -6,6 +6,7 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; namespace Rubberduck.Inspections.Inspections.Concrete @@ -54,7 +55,7 @@ public ObsoleteMemberUsageInspection(RubberduckParserState state) : base(state) { } - protected override bool IsResultReference(IdentifierReference reference) + protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) { var declaration = reference?.Declaration; return declaration != null diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs index 4f14f1edd2..a1d0f811b3 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs @@ -66,7 +66,7 @@ protected override IEnumerable ReferencesInModule(Qualified return finder.FailedProcedureCoercions(module); } - protected override bool IsResultReference(IdentifierReference failedCoercion) + protected override bool IsResultReference(IdentifierReference failedCoercion, DeclarationFinder finder) { // return true because no special ignore checking is required return true; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfBangNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfBangNotationInspection.cs index 6d147e63d2..998e3a5ca4 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfBangNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfBangNotationInspection.cs @@ -5,6 +5,7 @@ using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -61,7 +62,7 @@ public UseOfBangNotationInspection(RubberduckParserState state) Severity = CodeInspectionSeverity.Suggestion; } - protected override bool IsResultReference(IdentifierReference reference) + protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) { return reference.IsIndexedDefaultMemberAccess && reference.DefaultMemberRecursionDepth == 1 diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs index ac71a72d2c..a33860da11 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs @@ -5,6 +5,7 @@ using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -69,7 +70,7 @@ public UseOfRecursiveBangNotationInspection(RubberduckParserState state) Severity = CodeInspectionSeverity.Suggestion; } - protected override bool IsResultReference(IdentifierReference reference) + protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) { return reference.IsIndexedDefaultMemberAccess && reference.DefaultMemberRecursionDepth > 1 diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs index 1685b507cd..a568cdfd40 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs @@ -70,7 +70,7 @@ protected override IEnumerable ReferencesInModule(Qualified return finder.UnboundDefaultMemberAccesses(module); } - protected override bool IsResultReference(IdentifierReference reference) + protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) { return reference.IsIndexedDefaultMemberAccess && reference.Context is VBAParser.DictionaryAccessContext; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs index b5730c4541..7334e1cebf 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs @@ -70,7 +70,7 @@ protected override IEnumerable ReferencesInModule(Qualified return finder.FailedLetCoercions(module); } - protected override bool IsResultReference(IdentifierReference failedLetCoercion) + protected override bool IsResultReference(IdentifierReference failedLetCoercion, DeclarationFinder finder) { return !failedLetCoercion.IsAssignment; } diff --git a/RubberduckTests/Inspections/ExcelMemberMayReturnNothingInspectionTests.cs b/RubberduckTests/Inspections/ExcelMemberMayReturnNothingInspectionTests.cs index 756093dce2..e2125bee83 100644 --- a/RubberduckTests/Inspections/ExcelMemberMayReturnNothingInspectionTests.cs +++ b/RubberduckTests/Inspections/ExcelMemberMayReturnNothingInspectionTests.cs @@ -169,7 +169,7 @@ End Sub [Test] [Category("Inspections")] - public void ExcelMemberMayReturnNothing_ReturnsResult_DefaultAccessExpression() + public void ExcelMemberMayReturnNothing_ReturnsResult_DefaultAccessExpression_Let() { const string inputCode = @"Sub UnderTest() @@ -184,6 +184,133 @@ End Sub Assert.AreEqual(1, InspectionResults(inputCode).Count()); } + [Test] + [Category("Inspections")] + public void ExcelMemberMayReturnNothing_ReturnsResult_DefaultAccessExpression_Argument() + { + const string inputCode = + @"Sub UnderTest() + Dim ws As Worksheet + Set ws = Sheet1 + Bar ws.Range(""B:B"").Find(""bar"") +End Sub + +Private Sub Bar(arg As Long) +End Sub +"; + + Assert.AreEqual(1, InspectionResults(inputCode).Count()); + } + + [Test] + [Category("Inspections")] + public void ExcelMemberMayReturnNothing_ReturnsResult_ObjectArgument() + { + const string inputCode = + @"Sub UnderTest() + Dim ws As Worksheet + Set ws = Sheet1 + Bar ws.Range(""B:B"").Find(""bar"") +End Sub + +Private Sub Bar(arg As Range) +End Sub +"; + + Assert.AreEqual(1, InspectionResults(inputCode).Count()); + } + + [Test] + [Category("Inspections")] + public void ExcelMemberMayReturnNothing_ReturnsResult_DefaultAccessExpression_Argument_ExplicitCall() + { + const string inputCode = + @"Sub UnderTest() + Dim ws As Worksheet + Set ws = Sheet1 + Call Bar(ws.Range(""B:B"").Find(""bar"")) +End Sub + +Private Sub Bar(arg As Long) +End Sub +"; + + Assert.AreEqual(1, InspectionResults(inputCode).Count()); + } + + [Test] + [Category("Inspections")] + public void ExcelMemberMayReturnNothing_ReturnsResult_ObjectArgument_ExplicitCall() + { + const string inputCode = + @"Sub UnderTest() + Dim ws As Worksheet + Set ws = Sheet1 + Call Bar(ws.Range(""B:B"").Find(""bar"")) +End Sub + +Private Sub Bar(arg As Range) +End Sub +"; + + Assert.AreEqual(1, InspectionResults(inputCode).Count()); + } + + [Test] + [Category("Inspections")] + public void ExcelMemberMayReturnNothing_ReturnsResult_WithBlock() + { + const string inputCode = + @"Sub UnderTest() + Dim ws As Worksheet + Set ws = Sheet1 + With ws.Range(""B:B"").Find(""bar"") + End With +End Sub + +Private Sub Bar(arg As Range) +End Sub +"; + + Assert.AreEqual(1, InspectionResults(inputCode).Count()); + } + + [Test] + [Category("Inspections")] + public void ExcelMemberMayReturnNothing_DoesNotReturnResult_CallStatement() + { + const string inputCode = + @"Sub UnderTest() + Dim ws As Worksheet + Set ws = Sheet1 + ws.Range(""B:B"").Find ""bar"" +End Sub + +Private Sub Bar(arg As Range) +End Sub +"; + + Assert.AreEqual(0, InspectionResults(inputCode).Count()); + } + + [Test] + [Category("Inspections")] + public void ExcelMemberMayReturnNothing_DoesNotReturnResult_ExplicitCallStatement() + { + const string inputCode = + @"Sub UnderTest() + Dim ws As Worksheet + Set ws = Sheet1 + Call ws.Range(""B:B"").Find(""bar"") +End Sub + +Private Sub Bar(arg As Range) +End Sub +"; + + Assert.AreEqual(0, InspectionResults(inputCode).Count()); + } + [Test] [Category("Inspections")] public void ExcelMemberMayReturnNothing_ReturnsResult_FindAsWithBlockVariable() From 2fbfc1252fbefdd8e50d165a30b6d457387e2aa9 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Fri, 10 Jan 2020 18:20:18 -0800 Subject: [PATCH 133/461] Refactoring of Validations and conflict detection Conflict detectors need to align with the two versions of refactoring strategies as well. --- .../EncapsulateFieldViewModel.cs | 14 +- .../ViewableEncapsulatedField.cs | 4 +- .../EncapsulateFIeldResources.cs | 2 +- .../EncapsulateFieldElementsBuilder.cs | 75 +++++--- .../EncapsulateField/EncapsulateFieldModel.cs | 172 ++++++++++++------ .../EncapsulateFieldRefactoring.cs | 41 +---- .../ConvertFieldsToUDTMembers.cs | 18 +- .../EncapsulateFieldStrategyBase.cs | 4 +- .../UseBackingFields.cs | 2 +- .../FieldCandidates/ArrayCandidate.cs | 2 +- .../ConvertToUDTMemberCandidate.cs | 27 ++- .../EncapsulateFieldCandidate.cs | 38 ++-- .../EncapsulationIdentifiers.cs | 17 +- .../UserDefinedTypeCandidate.cs | 15 +- .../UserDefinedTypeMemberCandidate.cs | 45 ++++- ...ieldsToUDTMembersStrategyConflictFinder.cs | 83 +++++++++ ... => EncapsulateFieldConflictFinderBase.cs} | 103 ++++------- .../EncapsulateFieldValidationsProvider.cs | 94 +++++++--- ...alidator.cs => IdentifierOnlyValidator.cs} | 0 .../UseBackingFieldsStrategyConflictFinder.cs | 20 ++ .../EncapsulateField/EncapsulateFieldTests.cs | 2 +- .../EncapsulateFieldValidatorTests.cs | 34 +++- .../EncapsulateUsingStateUDTTests.cs | 25 +-- .../EncapsulatedUDTFieldTests.cs | 82 +-------- .../EncapsulationIdentifiersTests.cs | 30 +-- .../EncapsulateField/TestSupport.cs | 47 +++-- 26 files changed, 561 insertions(+), 435 deletions(-) create mode 100644 Rubberduck.Refactorings/EncapsulateField/Validations/ConvertFieldsToUDTMembersStrategyConflictFinder.cs rename Rubberduck.Refactorings/EncapsulateField/Validations/{EncapsulateFieldConflictFinders.cs => EncapsulateFieldConflictFinderBase.cs} (65%) rename Rubberduck.Refactorings/EncapsulateField/Validations/{EncapsulateFieldNamesValidator.cs => IdentifierOnlyValidator.cs} (100%) create mode 100644 Rubberduck.Refactorings/EncapsulateField/Validations/UseBackingFieldsStrategyConflictFinder.cs diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs index 4ded817051..3a49ce297c 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs @@ -17,7 +17,7 @@ private class MasterDetailSelectionManager private const string _neverATargetID = "_Never_a_TargetID_"; private bool _detailFieldIsFlagged; - public MasterDetailSelectionManager(IEncapsulatableField selected) + public MasterDetailSelectionManager(IEncapsulateFieldCandidate selected) : this(selected?.TargetID) { if (selected != null) @@ -101,12 +101,12 @@ public ObservableCollection EncapsulationFields { var viewableFields = new ObservableCollection(); - //var orderedFields = Model.EncapsulationCandidates.Where(ec => !(_selectedObjectStateUDT?.IsEncapsulateFieldCandidate(ec) ?? false)) - // .OrderBy(efd => efd.Declaration.Selection).ToList(); - - var orderedFields = Model.EncapsulationCandidates.Where(ec => !(_selectedObjectStateUDT?.IsExistingDeclaration ?? false)) - .OrderBy(efd => efd.Declaration.Selection).ToList(); - + var orderedFields = Model.EncapsulationCandidates.OrderBy(efd => efd.Declaration.Selection).ToList(); + if (_selectedObjectStateUDT != null && _selectedObjectStateUDT.IsExistingDeclaration) + { + orderedFields = Model.EncapsulationCandidates.Where(ec => !_selectedObjectStateUDT.FieldIdentifier.Equals(ec.IdentifierName)) + .OrderBy(efd => efd.Declaration.Selection).ToList(); + } foreach (var efd in orderedFields) { viewableFields.Add(new ViewableEncapsulatedField(efd)); diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs index 34775291a4..23fad97b7c 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs @@ -19,9 +19,9 @@ public interface IEncapsulatedFieldViewData public class ViewableEncapsulatedField : IEncapsulatedFieldViewData { - private IEncapsulatableField _efd; + private IEncapsulateFieldCandidate _efd; private readonly int _hashCode; - public ViewableEncapsulatedField(IEncapsulatableField efd) + public ViewableEncapsulatedField(IEncapsulateFieldCandidate efd) { _efd = efd; _hashCode = efd.TargetID.GetHashCode(); diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs index 00389da161..7146628ae2 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs @@ -18,7 +18,7 @@ public static string PreviewMarker public static string DefaultStateUDTFieldName => "this"; - public static string GroupBoxHeaderSuffix = "Property Name:"; + public static string GroupBoxHeaderSuffix = "Property Name"; public static string Caption => RubberduckUI.EncapsulateField_Caption; diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementsBuilder.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementsBuilder.cs index 5f80734b88..fa845622fd 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementsBuilder.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementsBuilder.cs @@ -23,11 +23,15 @@ public EncapsulateFieldElementsBuilder(IDeclarationFinderProvider declarationFin CreateRefactoringElements(); } + public IObjectStateUDT DefaultObjectStateUDT { private set; get; } + public IObjectStateUDT ObjectStateUDT { private set; get; } public IEncapsulateFieldValidationsProvider ValidationsProvider { private set; get; } - public IEnumerable Candidates { private set; get; } + public IEnumerable Candidates { private set; get; } + + public IEnumerable ObjectStateUDTCandidates { private set; get; } = new List(); private void CreateRefactoringElements() { @@ -35,54 +39,77 @@ private void CreateRefactoringElements() .Members(_targetQMN) .Where(v => v.IsMemberVariable() && !v.IsWithEvents); - ValidationsProvider = new EncapsulateFieldValidationsProvider(); - - var nameValidator = ValidationsProvider.NameOnlyValidator(NameValidators.Default); + var defaultNamesValidator = EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.Default); - var candidates = new List(); + var candidates = new List(); foreach (var fieldDeclaration in fieldDeclarations) { Debug.Assert(!fieldDeclaration.DeclarationType.Equals(DeclarationType.UserDefinedTypeMember)); - var fieldEncapsulationCandidate = CreateCandidate(fieldDeclaration, nameValidator); - + var fieldEncapsulationCandidate = CreateCandidate(fieldDeclaration, defaultNamesValidator); candidates.Add(fieldEncapsulationCandidate); } - ValidationsProvider.RegisterCandidates(candidates); + Candidates = candidates; + + ObjectStateUDTCandidates = BuildObjectStateUDTCandidates(candidates).ToList(); + + var objectStateUDTIdentifier = $"T{_targetQMN.ComponentName}"; + ObjectStateUDT = ObjectStateUDTCandidates.FirstOrDefault(os => os.AsTypeDeclaration.IdentifierName.StartsWith(objectStateUDTIdentifier, StringComparison.InvariantCultureIgnoreCase)); + + DefaultObjectStateUDT = CreateStateUDTField(); + DefaultObjectStateUDT.IsSelected = true; + if (ObjectStateUDT != null) + { + ObjectStateUDT.IsSelected = true; + DefaultObjectStateUDT.IsSelected = false; + } + + ObjectStateUDTCandidates = ObjectStateUDTCandidates.Concat(new IObjectStateUDT[] { DefaultObjectStateUDT }); - var conflictsValidator = ValidationsProvider.ConflictDetector(EncapsulateFieldStrategy.UseBackingFields, _declarationFinderProvider); + ValidationsProvider = new EncapsulateFieldValidationsProvider(Candidates, ObjectStateUDTCandidates); - ObjectStateUDT = CreateStateUDTField(conflictsValidator); + var conflictsFinder = ValidationsProvider.ConflictDetector(EncapsulateFieldStrategy.UseBackingFields, _declarationFinderProvider); foreach (var candidate in candidates) { - candidate.ConflictFinder = conflictsValidator; - conflictsValidator.AssignNoConflictIdentifier(candidate, DeclarationType.Property); - conflictsValidator.AssignNoConflictIdentifier(candidate, DeclarationType.Variable); + candidate.ConflictFinder = conflictsFinder; } + } - Candidates = candidates; + private IEnumerable BuildObjectStateUDTCandidates(IEnumerable candidates) //, IObjectStateUDT defaultObjectStateUDT) + { + var udtCandidates = candidates.Where(c => c is IUserDefinedTypeCandidate udt + && udt.CanBeObjectStateUDT); + + var objectStateUDTs = new List(); + foreach (var udt in udtCandidates) + { + objectStateUDTs.Add(new ObjectStateUDT(udt as IUserDefinedTypeCandidate)); + } + + var objectStateUDTIdentifier = $"T{_targetQMN.ComponentName}"; + var objectStateUDT = objectStateUDTs.FirstOrDefault(os => os.AsTypeDeclaration.IdentifierName.StartsWith(objectStateUDTIdentifier, StringComparison.InvariantCultureIgnoreCase)); + + return objectStateUDTs; } - private IObjectStateUDT CreateStateUDTField(IEncapsulateFieldConflictFinder validator) + private IObjectStateUDT CreateStateUDTField() { var stateUDT = new ObjectStateUDT(_targetQMN) as IObjectStateUDT; - stateUDT.FieldIdentifier = validator.CreateNonConflictIdentifierForProposedType(stateUDT.FieldIdentifier, _targetQMN, DeclarationType.Variable); - - stateUDT.TypeIdentifier = validator.CreateNonConflictIdentifierForProposedType(stateUDT.TypeIdentifier, _targetQMN, DeclarationType.UserDefinedType); + EncapsulateFieldValidationsProvider.AssignNoConflictIdentifiers(stateUDT, _declarationFinderProvider); stateUDT.IsSelected = true; return stateUDT; } - private IEncapsulatableField CreateCandidate(Declaration target, IValidateVBAIdentifiers validator)// Predicate nameValidator) + private IEncapsulateFieldCandidate CreateCandidate(Declaration target, IValidateVBAIdentifiers validator)// Predicate nameValidator) { if (target.IsUserDefinedTypeField()) { - var udtValidator = ValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedType); + var udtValidator = EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedType); var udtField = new UserDefinedTypeCandidate(target, udtValidator) as IUserDefinedTypeCandidate; (Declaration udtDeclaration, IEnumerable udtMembers) = GetUDTAndMembersForField(udtField); @@ -93,10 +120,10 @@ private IEncapsulatableField CreateCandidate(Declaration target, IValidateVBAIde foreach (var udtMemberDeclaration in udtMembers) { - var udtMemberValidator = ValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMember); + var udtMemberValidator = EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMember); if (udtMemberDeclaration.IsArray) { - udtMemberValidator = ValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMemberArray); + udtMemberValidator = EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMemberArray); } var candidateUDTMember = new UserDefinedTypeMemberCandidate(CreateCandidate(udtMemberDeclaration, udtMemberValidator), udtField) as IUserDefinedTypeMemberCandidate; @@ -106,7 +133,9 @@ private IEncapsulatableField CreateCandidate(Declaration target, IValidateVBAIde var udtVariablesOfSameType = _declarationFinderProvider.DeclarationFinder.UserDeclarations(DeclarationType.Variable) .Where(v => v.AsTypeDeclaration == udtDeclaration); - udtField.CanBeObjectStateUDT = udtField.TypeDeclarationIsPrivate && udtVariablesOfSameType.Count() == 1; + udtField.CanBeObjectStateUDT = udtField.TypeDeclarationIsPrivate + && udtField.Declaration.HasPrivateAccessibility() + && udtVariablesOfSameType.Count() == 1; return udtField; } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index 7d35bc429f..7b3956cd59 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -13,21 +13,35 @@ public class EncapsulateFieldModel : IRefactoringModel private readonly Func _previewDelegate; private QualifiedModuleName _targetQMN; private IDeclarationFinderProvider _declarationFinderProvider; - private IEncapsulateFieldValidationsProvider _validatorProvider; + private IEncapsulateFieldValidationsProvider _validationsProvider; private IObjectStateUDT _newObjectStateUDT; + private List _convertedFields; + private HashSet _objStateCandidates; + private IDictionary)> _udtFieldToUdtDeclarationMap = new Dictionary)>(); - public EncapsulateFieldModel(Declaration target, IEnumerable candidates, IObjectStateUDT stateUDTField, Func previewDelegate, IDeclarationFinderProvider declarationFinderProvider, IEncapsulateFieldValidationsProvider validatorProvider) // IEncapsulateFieldValidator validator) + public EncapsulateFieldModel( + Declaration target, + IEnumerable candidates, + IEnumerable objectStateUDTCandidates, + IObjectStateUDT stateUDTField, + Func previewDelegate, + IDeclarationFinderProvider declarationFinderProvider, + IEncapsulateFieldValidationsProvider validationsProvider) { _previewDelegate = previewDelegate; _targetQMN = target.QualifiedModuleName; _newObjectStateUDT = stateUDTField; _declarationFinderProvider = declarationFinderProvider; - _validatorProvider = validatorProvider; + _validationsProvider = validationsProvider; + + _useBackingFieldCandidates = candidates.ToList(); + _objStateCandidates = new HashSet(objectStateUDTCandidates); + _objStateCandidates.Add(_newObjectStateUDT); - EncapsulationCandidates = candidates.ToList(); EncapsulateFieldStrategy = EncapsulateFieldStrategy.UseBackingFields; + _activeObjectStateUDT = StateUDTField; } public QualifiedModuleName QualifiedModuleName => _targetQMN; @@ -38,46 +52,81 @@ public EncapsulateFieldStrategy EncapsulateFieldStrategy get => _encapsulationFieldStategy; set { + if (_encapsulationFieldStategy == value) { return; } + _encapsulationFieldStategy = value; + if (_encapsulationFieldStategy == EncapsulateFieldStrategy.UseBackingFields) { - foreach (var candidate in EncapsulationCandidates) - { - candidate.ConflictFinder = _validatorProvider.ConflictDetector(_encapsulationFieldStategy, _declarationFinderProvider);// ConflictDetector; - switch (candidate) - { - case IUserDefinedTypeCandidate udt: - candidate.NameValidator = _validatorProvider.NameOnlyValidator(NameValidators.UserDefinedType); - break; - case IUserDefinedTypeMemberCandidate udtm: - candidate.NameValidator = candidate.Declaration.IsArray - ? _validatorProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMemberArray) - : _validatorProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMember); - break; - default: - candidate.NameValidator = _validatorProvider.NameOnlyValidator(NameValidators.Default); - break; - } - } + ChangeSettingToUseBackingFieldsStrategy(); + return; } - else + ChangeSettingsToConvertFieldsToUDTMembersStrategy(); + } + } + + private void ChangeSettingToUseBackingFieldsStrategy() + { + foreach (var candidate in EncapsulationCandidates) + { + candidate.ConflictFinder = _validationsProvider.ConflictDetector(EncapsulateFieldStrategy, _declarationFinderProvider); + switch (candidate) { - foreach (var candidate in EncapsulationCandidates) - { - candidate.ConflictFinder = _validatorProvider.ConflictDetector(_encapsulationFieldStategy, _declarationFinderProvider);// ConflictDetector; + case IUserDefinedTypeCandidate udt: + candidate.NameValidator = EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedType); + break; + case IUserDefinedTypeMemberCandidate udtm: candidate.NameValidator = candidate.Declaration.IsArray - ? _validatorProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMemberArray) - : _validatorProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMember); - } + ? EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMemberArray) + : EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMember); + break; + default: + candidate.NameValidator = EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.Default); + break; } + EditIdentifiersAsRequired(); } - } + } + + private void ChangeSettingsToConvertFieldsToUDTMembersStrategy() + { + foreach (var candidate in EncapsulationCandidates) + { + candidate.ConflictFinder = _validationsProvider.ConflictDetector(EncapsulateFieldStrategy , _declarationFinderProvider);// ConflictDetector; + candidate.NameValidator = candidate.Declaration.IsArray + ? EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMemberArray) + : EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMember); + + EditIdentifiersAsRequired(); + } + } + + public IEncapsulateFieldValidationsProvider ValidationsProvider => _validationsProvider; + + private List _useBackingFieldCandidates; + public List EncapsulationCandidates + { + get + { + if (EncapsulateFieldStrategy == EncapsulateFieldStrategy.UseBackingFields) + { + return _useBackingFieldCandidates; + } - public IEncapsulateFieldValidationsProvider ValidationsProvider => _validatorProvider; + if (_convertedFields is null) + { + _convertedFields = new List(); + foreach (var field in _useBackingFieldCandidates) + { + _convertedFields.Add(new ConvertToUDTMember(field, StateUDTField)); + } + } - public List EncapsulationCandidates { set; get; } = new List(); + return _convertedFields; + } + } - public IEnumerable SelectedFieldCandidates + public IEnumerable SelectedFieldCandidates => EncapsulationCandidates.Where(v => v.EncapsulateFlag); public IEnumerable UDTFieldCandidates @@ -90,50 +139,57 @@ public IEnumerable SelectedUDTFieldCandidates .Where(v => v is IUserDefinedTypeCandidate) .Cast(); - public IEncapsulatableField this[string encapsulatedFieldTargetID] + public IEncapsulateFieldCandidate this[string encapsulatedFieldTargetID] => EncapsulationCandidates.Where(c => c.TargetID.Equals(encapsulatedFieldTargetID)).Single(); - public IEncapsulatableField this[Declaration fieldDeclaration] + public IEncapsulateFieldCandidate this[Declaration fieldDeclaration] => EncapsulationCandidates.Where(c => c.Declaration == fieldDeclaration).Single(); private IObjectStateUDT _activeObjectStateUDT; public IObjectStateUDT StateUDTField { + get + { + _activeObjectStateUDT = ObjectStateUDTCandidates + .SingleOrDefault(os => os.IsSelected) ?? _newObjectStateUDT; + + return _activeObjectStateUDT; + } set { - _activeObjectStateUDT = value; - foreach (var candidate in EncapsulationCandidates) + if (_activeObjectStateUDT.FieldIdentifier == (value?.FieldIdentifier ?? string.Empty)) { - if (candidate is IConvertToUDTMember udtMember) - { - udtMember.ObjectStateUDT = value; - } + return; } - } - get => _activeObjectStateUDT ?? _newObjectStateUDT; - } - public string PreviewRefactoring() => _previewDelegate(this); - - private HashSet _objStateCandidates; - public IEnumerable ObjectStateUDTCandidates - { - get - { - if (_objStateCandidates != null) + foreach (var objectStateUDT in ObjectStateUDTCandidates) { - return _objStateCandidates; + objectStateUDT.IsSelected = false; } - _objStateCandidates = new HashSet(); - foreach (var candidate in UDTFieldCandidates.Where(udt => udt.CanBeObjectStateUDT)) + _activeObjectStateUDT = + ObjectStateUDTCandidates.SingleOrDefault(os => os.FieldIdentifier.Equals(value?.FieldIdentifier ?? null)) + ?? _newObjectStateUDT; + + _activeObjectStateUDT.IsSelected = true; + + if (EncapsulateFieldStrategy == EncapsulateFieldStrategy.ConvertFieldsToUDTMembers) { - _objStateCandidates.Add(new ObjectStateUDT(candidate)); + EditIdentifiersAsRequired(); } + } + } - _objStateCandidates.Add(_newObjectStateUDT); - return _objStateCandidates; + private void EditIdentifiersAsRequired() + { + foreach (var candidate in EncapsulationCandidates) + { + candidate.ConflictFinder.AssignNoConflictIdentifiers(candidate); } } + + public string PreviewRefactoring() => _previewDelegate(this); + + public IEnumerable ObjectStateUDTCandidates => _objStateCandidates; } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 4c1bad55e1..51ca92c175 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -76,31 +76,22 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) var builder = new EncapsulateFieldElementsBuilder(_declarationFinderProvider, _targetQMN); - var validationsProvider = builder.ValidationsProvider; - var candidates = builder.Candidates; - var defaultObjectStateUDT = builder.ObjectStateUDT; - - var selected = candidates.Single(c => c.Declaration == target); + var selected = builder.Candidates.Single(c => c.Declaration == target); selected.EncapsulateFlag = true; - if (TryRetrieveExistingObjectStateUDT(target, candidates, out var objectStateUDT)) - { - objectStateUDT.IsSelected = true; - defaultObjectStateUDT.IsSelected = false; - } - var model = new EncapsulateFieldModel( target, - candidates, - defaultObjectStateUDT, + builder.Candidates, + builder.ObjectStateUDTCandidates, + builder.DefaultObjectStateUDT, PreviewRewrite, _declarationFinderProvider, - validationsProvider); + builder.ValidationsProvider); - if (objectStateUDT != null) + if (builder.ObjectStateUDT != null) { - model.StateUDTField = objectStateUDT; model.EncapsulateFieldStrategy = EncapsulateFieldStrategy.ConvertFieldsToUDTMembers; + model.StateUDTField = builder.ObjectStateUDT; } return model; @@ -137,23 +128,5 @@ private IEncapsulateFieldRewriteSession RefactorRewrite(EncapsulateFieldModel mo return strategy.RefactorRewrite(model, refactorRewriteSession, asPreview); } - - private bool TryRetrieveExistingObjectStateUDT(Declaration target, IEnumerable candidates, out IObjectStateUDT objectStateUDT) - { - objectStateUDT = null; - - var objectStateUDTIdentifier = $"T{target.QualifiedModuleName.ComponentName}"; - - var objectStateUDTMatches = candidates.Where(c => c is IUserDefinedTypeCandidate udt - && udt.Declaration.HasPrivateAccessibility() - && udt.Declaration.AsTypeDeclaration.IdentifierName.StartsWith(objectStateUDTIdentifier, StringComparison.InvariantCultureIgnoreCase)) - .Select(pm => pm as IUserDefinedTypeCandidate); - - if (objectStateUDTMatches.Count() == 1) - { - objectStateUDT = new ObjectStateUDT(objectStateUDTMatches.First()) { IsSelected = true }; - } - return objectStateUDT != null; - } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs index 7a8929c7ba..a30231a101 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs @@ -15,17 +15,11 @@ namespace Rubberduck.Refactorings.EncapsulateField { public class ConvertFieldsToUDTMembers : EncapsulateFieldStrategyBase { - private List _convertedFields; private IObjectStateUDT _stateUDTField; public ConvertFieldsToUDTMembers(IDeclarationFinderProvider declarationFinderProvider, EncapsulateFieldModel model, IIndenter indenter) : base(declarationFinderProvider, model, indenter) { - _convertedFields = new List(); - foreach (var field in model.SelectedFieldCandidates) - { - _convertedFields.Add(new ConvertToUDTMember(field, model.StateUDTField)); - } _stateUDTField = model.StateUDTField; } @@ -33,14 +27,14 @@ protected override void ModifyFields(EncapsulateFieldModel model, IEncapsulateFi { var rewriter = refactorRewriteSession.CheckOutModuleRewriter(_targetQMN); - foreach (var field in _convertedFields) + foreach (var field in model.SelectedFieldCandidates) { refactorRewriteSession.Remove(field.Declaration, rewriter); } if (_stateUDTField.IsExistingDeclaration) { - _stateUDTField.AddMembers(_convertedFields); + _stateUDTField.AddMembers(model.SelectedFieldCandidates.Cast()); rewriter.Replace(_stateUDTField.AsTypeDeclaration, _stateUDTField.TypeDeclarationBlock(_indenter)); } @@ -48,7 +42,7 @@ protected override void ModifyFields(EncapsulateFieldModel model, IEncapsulateFi protected override void ModifyReferences(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) { - foreach (var field in _convertedFields) + foreach (var field in model.SelectedFieldCandidates) { LoadFieldReferenceContextReplacements(field); } @@ -60,7 +54,7 @@ protected override void LoadNewDeclarationBlocks(EncapsulateFieldModel model) { if (_stateUDTField.IsExistingDeclaration) { return; } - _stateUDTField.AddMembers(_convertedFields); + _stateUDTField.AddMembers(model.SelectedFieldCandidates.Cast()); AddContentBlock(NewContentTypes.TypeDeclarationBlock, _stateUDTField.TypeDeclarationBlock(_indenter)); @@ -70,7 +64,7 @@ protected override void LoadNewDeclarationBlocks(EncapsulateFieldModel model) protected override void LoadNewPropertyBlocks(EncapsulateFieldModel model) { - var propertyGenerationSpecs = _convertedFields.SelectMany(f => f.PropertyAttributeSets); + var propertyGenerationSpecs = model.SelectedFieldCandidates.SelectMany(f => f.PropertyAttributeSets); var generator = new PropertyGenerator(); foreach (var spec in propertyGenerationSpecs) @@ -79,7 +73,7 @@ protected override void LoadNewPropertyBlocks(EncapsulateFieldModel model) } } - protected override void LoadFieldReferenceContextReplacements(IEncapsulatableField field) + 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 1e15e872cc..4bfb961ba2 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs @@ -31,7 +31,7 @@ protected enum NewContentTypes { TypeDeclarationBlock, DeclarationBlock, MethodB protected Dictionary> _newContent { set; get; } private static string DoubleSpace => $"{Environment.NewLine}{Environment.NewLine}"; - protected IEnumerable SelectedFields { private set; get; } + protected IEnumerable SelectedFields { private set; get; } public EncapsulateFieldStrategyBase(IDeclarationFinderProvider declarationFinderProvider, EncapsulateFieldModel model, IIndenter indenter) { @@ -123,7 +123,7 @@ protected virtual void LoadNewPropertyBlocks(EncapsulateFieldModel model) } } - protected virtual void LoadFieldReferenceContextReplacements(IEncapsulatableField field) + protected virtual void LoadFieldReferenceContextReplacements(IEncapsulateFieldCandidate field) { if (field is IUserDefinedTypeCandidate udt && udt.TypeDeclarationIsPrivate) { diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/UseBackingFields.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/UseBackingFields.cs index 8a88efee9c..3cdedf0191 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/UseBackingFields.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/UseBackingFields.cs @@ -16,7 +16,7 @@ namespace Rubberduck.Refactorings.EncapsulateField public class UseBackingFields : EncapsulateFieldStrategyBase { public UseBackingFields(IDeclarationFinderProvider declarationFinderProvider, EncapsulateFieldModel model, IIndenter indenter) - : base(declarationFinderProvider, model, indenter) { } + : base(declarationFinderProvider, model, indenter){ } protected override void ModifyFields(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) { diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs index 6dadb8506d..04bf5cb2dd 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs @@ -7,7 +7,7 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface IArrayCandidate : IEncapsulatableField + public interface IArrayCandidate : IEncapsulateFieldCandidate { string UDTMemberDeclaration { get;} } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs index 874251cd91..b9ac57e645 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs @@ -11,20 +11,20 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface IConvertToUDTMember : IEncapsulatableField + public interface IConvertToUDTMember : IEncapsulateFieldCandidate { string UDTMemberDeclaration { get; } IObjectStateUDT ObjectStateUDT { set; get; } - IEncapsulatableField WrappedCandidate { get; } + IEncapsulateFieldCandidate WrappedCandidate { get; } } public class ConvertToUDTMember : IConvertToUDTMember { - private readonly IEncapsulatableField _wrapped; - public ConvertToUDTMember(IEncapsulatableField candidate, IObjectStateUDT objStateUDT) + private readonly IEncapsulateFieldCandidate _wrapped; + public ConvertToUDTMember(IEncapsulateFieldCandidate candidate, IObjectStateUDT objStateUDT) { _wrapped = candidate; - BackingIdentifier = _wrapped.PropertyIdentifier; + PropertyIdentifier = _wrapped.PropertyIdentifier; ObjectStateUDT = objStateUDT; } @@ -40,7 +40,7 @@ public virtual string UDTMemberDeclaration } } - public IEncapsulatableField WrappedCandidate => _wrapped; + public IEncapsulateFieldCandidate WrappedCandidate => _wrapped; public IObjectStateUDT ObjectStateUDT { set; get; } @@ -62,8 +62,11 @@ public string PropertyIdentifier public string PropertyAsTypeName => _wrapped.PropertyAsTypeName; - public string BackingIdentifier { get; set; } - + public string BackingIdentifier + { + set { } + get => PropertyIdentifier; + } public string BackingAsTypeName => Declaration.AsTypeName; public bool CanBeReadWrite @@ -82,9 +85,13 @@ public bool IsReadOnly get => _wrapped.IsReadOnly; } - public string ParameterName => _wrapped.ParameterName; + public string ParameterName + { + set => _wrapped.ParameterName = value; + get => _wrapped.ParameterName; + } - public IValidateVBAIdentifiers NameValidator + public IValidateVBAIdentifiers NameValidator { set => _wrapped.NameValidator = value; get => _wrapped.NameValidator; diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs index d99fcec4ff..c5b615a2a3 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs @@ -16,20 +16,20 @@ public interface IEncapsulateFieldRefactoringElement string AsTypeName { get; } } - public interface IEncapsulatableField : IEncapsulateFieldRefactoringElement + public interface IEncapsulateFieldCandidate : IEncapsulateFieldRefactoringElement { string TargetID { get; } Declaration Declaration { get; } bool EncapsulateFlag { get; set; } string BackingIdentifier { set; get; } - string BackingAsTypeName { /*set;*/ get; } + string BackingAsTypeName { get; } string PropertyIdentifier { set; get; } - string PropertyAsTypeName { /*set;*/ get; } + string PropertyAsTypeName { get; } bool CanBeReadWrite { set; get; } bool ImplementLet { get; } bool ImplementSet { get; } bool IsReadOnly { set; get; } - string ParameterName { get; } + string ParameterName { set; get; } IValidateVBAIdentifiers NameValidator { set; get; } IEncapsulateFieldConflictFinder ConflictFinder { set; get; } bool TryValidateEncapsulationAttributes(out string errorMessage); @@ -37,11 +37,7 @@ public interface IEncapsulatableField : IEncapsulateFieldRefactoringElement IEnumerable PropertyAttributeSets { get; } } - public interface IUsingBackingField : IEncapsulatableField - { - } - - public class EncapsulateFieldCandidate : IEncapsulatableField + public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate { protected Declaration _target; protected QualifiedModuleName _qmn; @@ -65,13 +61,11 @@ public EncapsulateFieldCandidate(Declaration declaration, IValidateVBAIdentifier ImplementLet = true; ImplementSet = false; - if (_target.IsEnumField()) + if (_target.IsEnumField() && _target.AsTypeDeclaration.HasPrivateAccessibility()) { - //5.3.1 The declared type of a function declaration may not be a private enum name. - if (_target.AsTypeDeclaration.HasPrivateAccessibility()) - { - PropertyAsTypeName = Tokens.Long; - } + //5.3.1 The declared type of a function declaration + //may not be a private enum name. + PropertyAsTypeName = Tokens.Long; } else if (_target.AsTypeName.Equals(Tokens.Variant) && !_target.IsArray) @@ -113,12 +107,16 @@ public virtual bool EncapsulateFlag { set { + var valueChanged = _encapsulateFlag != value; + _encapsulateFlag = value; if (!_encapsulateFlag) { PropertyIdentifier = _fieldAndProperty.DefaultPropertyName; - ConflictFinder.AssignNoConflictIdentifier(this, DeclarationType.Property); - ConflictFinder.AssignNoConflictIdentifier(this, DeclarationType.Variable); + } + else if (valueChanged) + { + ConflictFinder.AssignNoConflictIdentifiers(this); } } get => _encapsulateFlag; @@ -130,7 +128,7 @@ public virtual bool EncapsulateFlag public override bool Equals(object obj) { return obj != null - && obj is IEncapsulatableField efc + && obj is IEncapsulateFieldCandidate efc && $"{efc.QualifiedModuleName.Name}.{efc.TargetID}" == $"{_qmn.Name}.{IdentifierName}"; } @@ -162,6 +160,8 @@ public string PropertyIdentifier _fieldAndProperty.Property = value; TryRestoreNewFieldNameAsOriginalFieldIdentifierName(); + + EncapsulateFieldValidationsProvider.AssignNoConflictParameter(this); } } @@ -200,7 +200,7 @@ public string IdentifierName public virtual string ReferenceQualifier { set; get; } - public string ParameterName => _fieldAndProperty.SetLetParameter; + public string ParameterName { set; get; } = EncapsulateFieldResources.DefaultPropertyParameter; private bool _implLet; public bool ImplementLet { get => !IsReadOnly && _implLet; set => _implLet = value; } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs index 4c44cb1c72..64dc3d0b28 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs @@ -56,7 +56,6 @@ public string Field set { _fieldAndProperty = new KeyValuePair(value, _fieldAndProperty.Value); - SetNonConflictParameterName(); } } @@ -66,23 +65,9 @@ public string Property set { _fieldAndProperty = new KeyValuePair(_fieldAndProperty.Key, value); - - SetNonConflictParameterName(); } } - public string SetLetParameter => _setLetParameter; - - private void SetNonConflictParameterName() - { - _setLetParameter = DEFAULT_WRITE_PARAMETER; - - var guard = 0; - while ( guard++ < 10 && (Field.IsEquivalentVBAIdentifierTo(_setLetParameter) - || Property.IsEquivalentVBAIdentifierTo(_setLetParameter))) - { - _setLetParameter = _setLetParameter.IncrementEncapsulationIdentifier(); - } - } + public string SetLetParameter => DEFAULT_WRITE_PARAMETER; } } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs index 9ac7882d12..47ecce352a 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs @@ -10,7 +10,7 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface IUserDefinedTypeCandidate : IEncapsulatableField + public interface IUserDefinedTypeCandidate : IEncapsulateFieldCandidate { IEnumerable Members { get; } void AddMember(IUserDefinedTypeMemberCandidate member); @@ -99,22 +99,11 @@ public override bool EncapsulateFlag foreach (var member in Members) { member.EncapsulateFlag = value; - if (!member.EncapsulateFlag || !ConflictFinder.HasConflictingIdentifier(member, DeclarationType.Property, out _)) - { - continue; - } - - //Reaching this line probably implies that there are multiple fields of the same User Defined - //Type within the module. - //Try to use a name involving the parent's identifier to make it unique/meaningful - //before giving up and creating incremented value(s). - member.PropertyIdentifier = $"{BackingIdentifier.CapitalizeFirstLetter()}{member.PropertyIdentifier.CapitalizeFirstLetter()}"; - ConflictFinder.AssignNoConflictIdentifier(member, DeclarationType.Property); } } base.EncapsulateFlag = value; } - get => _encapsulateFlag; + get => base.EncapsulateFlag; } protected override string AccessorInProperty diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs index c7e420d418..9f07766b01 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs @@ -9,7 +9,7 @@ namespace Rubberduck.Refactorings.EncapsulateField { - public interface IUserDefinedTypeMemberCandidate : IEncapsulatableField + public interface IUserDefinedTypeMemberCandidate : IEncapsulateFieldCandidate { IUserDefinedTypeCandidate Parent { get; } PropertyAttributeSet AsPropertyGeneratorSpec { get; } @@ -20,7 +20,7 @@ public class UserDefinedTypeMemberCandidate : IUserDefinedTypeMemberCandidate { private int _hashCode; private readonly string _uniqueID; - public UserDefinedTypeMemberCandidate(IEncapsulatableField candidate, IUserDefinedTypeCandidate udtVariable) + public UserDefinedTypeMemberCandidate(IEncapsulateFieldCandidate candidate, IUserDefinedTypeCandidate udtVariable) { _wrappedCandidate = candidate; Parent = udtVariable; @@ -30,11 +30,15 @@ public UserDefinedTypeMemberCandidate(IEncapsulatableField candidate, IUserDefin _hashCode = _uniqueID.GetHashCode(); } - private IEncapsulatableField _wrappedCandidate; + private IEncapsulateFieldCandidate _wrappedCandidate; public string AsTypeName => _wrappedCandidate.AsTypeName; - public string BackingIdentifier { get; set; } + public string BackingIdentifier + { + get => _wrappedCandidate.IdentifierName; + set { } + } public string BackingAsTypeName => Declaration.AsTypeName; @@ -89,9 +93,9 @@ public override bool Equals(object obj) public string PropertyIdentifier { set; get; } - private static string BuildUniqueID(IEncapsulatableField candidate) => $"{candidate.QualifiedModuleName.Name}.{candidate.IdentifierName}"; + private static string BuildUniqueID(IEncapsulateFieldCandidate candidate) => $"{candidate.QualifiedModuleName.Name}.{candidate.IdentifierName}"; - private static IEnumerable GetUDTMemberReferencesForField(IEncapsulatableField udtMember, IUserDefinedTypeCandidate field) + private static IEnumerable GetUDTMemberReferencesForField(IEncapsulateFieldCandidate udtMember, IUserDefinedTypeCandidate field) { var refs = new List(); foreach (var idRef in udtMember.Declaration.References) @@ -150,7 +154,26 @@ public bool IsReadOnly get => _wrappedCandidate.IsReadOnly; } - public bool EncapsulateFlag { set; get; } + private bool _encapsulateFlag; + public bool EncapsulateFlag + { + set + { + var valueChanged = _encapsulateFlag != value; + + _encapsulateFlag = value; + if (!_encapsulateFlag) + { + _wrappedCandidate.EncapsulateFlag = value; + PropertyIdentifier = _wrappedCandidate.PropertyIdentifier; + } + else if (valueChanged) + { + ConflictFinder.AssignNoConflictIdentifiers(this); + } + } + get => _encapsulateFlag; + } public bool CanBeReadWrite { @@ -164,9 +187,13 @@ public QualifiedModuleName QualifiedModuleName public string PropertyAsTypeName => _wrappedCandidate.PropertyAsTypeName; - public string ParameterName => _wrappedCandidate.ParameterName; + public string ParameterName + { + set => _wrappedCandidate.ParameterName = value; + get => _wrappedCandidate.ParameterName; + } - public bool ImplementLet => _wrappedCandidate.ImplementLet; + public bool ImplementLet => _wrappedCandidate.ImplementLet; public bool ImplementSet => _wrappedCandidate.ImplementSet; diff --git a/Rubberduck.Refactorings/EncapsulateField/Validations/ConvertFieldsToUDTMembersStrategyConflictFinder.cs b/Rubberduck.Refactorings/EncapsulateField/Validations/ConvertFieldsToUDTMembersStrategyConflictFinder.cs new file mode 100644 index 0000000000..841fd5abda --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/Validations/ConvertFieldsToUDTMembersStrategyConflictFinder.cs @@ -0,0 +1,83 @@ +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.Refactorings.EncapsulateField.Extensions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + public class ConvertFieldsToUDTMembersStrategyConflictFinder : EncapsulateFieldConflictFinderBase + { + private IEnumerable _objectStateUDTs; + public ConvertFieldsToUDTMembersStrategyConflictFinder(IDeclarationFinderProvider declarationFinderProvider, IEnumerable candidates, IEnumerable udtCandidates, IEnumerable objectStateUDTs) + : base(declarationFinderProvider, candidates, udtCandidates) + { + _objectStateUDTs = objectStateUDTs; + } + + public override bool TryValidateEncapsulationAttributes(IEncapsulateFieldCandidate field, out string errorMessage) + { + errorMessage = string.Empty; + if (!field.EncapsulateFlag) { return true; } + + if (!base.TryValidateEncapsulationAttributes(field, out errorMessage)) + { + return false; + } + + //Compare to existing members...they cannot change + var objectStateUDT = _objectStateUDTs.SingleOrDefault(os => os.IsSelected); + return !ConflictsWithExistingUDTMembers(objectStateUDT, field.BackingIdentifier); + } + + public override IEncapsulateFieldCandidate AssignNoConflictIdentifiers(IEncapsulateFieldCandidate candidate) + { + candidate = base.AssignNoConflictIdentifier(candidate, DeclarationType.Property); + + //Compare to existing members...they cannot change. + var objectStateUDT = _objectStateUDTs.SingleOrDefault(os => os.IsSelected); + var guard = 0; + while (guard++ < 10 && ConflictsWithExistingUDTMembers(objectStateUDT, candidate.PropertyIdentifier)) + { + candidate.PropertyIdentifier = candidate.PropertyIdentifier.IncrementEncapsulationIdentifier(); + } + return candidate; + } + + + protected override IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType) + { + candidate = base.AssignNoConflictIdentifier(candidate, declarationType); + + //Compare to existing members first...they cannot change + var objectStateUDT = _objectStateUDTs.SingleOrDefault(os => os.IsSelected); + var guard = 0; + while (guard++ < 10 && ConflictsWithExistingUDTMembers(objectStateUDT, candidate.BackingIdentifier)) + { + candidate.BackingIdentifier = candidate.BackingIdentifier.IncrementEncapsulationIdentifier(); + } + return candidate; + } + + private bool ConflictsWithExistingUDTMembers(IObjectStateUDT objectStateUDT, string identifier) + { + if (objectStateUDT is null) { return false; } + + return objectStateUDT.ExistingMembers.Any(nm => nm.IdentifierName.IsEquivalentVBAIdentifierTo(identifier)); + } + + protected override IEnumerable FindRelevantMembers(IEncapsulateFieldCandidate candidate) + { + var members = _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) + .Where(d => d != candidate.Declaration); + + var membersToRemove = _fieldCandidates.Where(fc => fc.EncapsulateFlag && fc.Declaration.DeclarationType.HasFlag(DeclarationType.Variable)) + .Select(fc => fc.Declaration); + + return members.Except(membersToRemove); + } + } +} diff --git a/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldConflictFinders.cs b/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldConflictFinderBase.cs similarity index 65% rename from Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldConflictFinders.cs rename to Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldConflictFinderBase.cs index 06967dba30..809933cdff 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldConflictFinders.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldConflictFinderBase.cs @@ -4,6 +4,7 @@ using Rubberduck.VBEditor; using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -12,54 +13,26 @@ namespace Rubberduck.Refactorings.EncapsulateField { public interface IEncapsulateFieldConflictFinder { - bool HasConflictingIdentifier(IEncapsulatableField field, DeclarationType declarationType, out string errorMessage); - IEncapsulatableField AssignNoConflictIdentifier(IEncapsulatableField candidate, DeclarationType declarationType); - string CreateNonConflictIdentifierForProposedType(string identifier, QualifiedModuleName qmn, DeclarationType declarationType); - bool IsConflictingProposedIdentifier(string fieldName, IEncapsulatableField candidate, DeclarationType declarationType); - bool TryValidateEncapsulationAttributes(IEncapsulatableField field, out string errorMessage); - } - - public class UseBackingFieldsConflictFinder : EncapsulateFieldConflictFinderBase - { - public UseBackingFieldsConflictFinder(IDeclarationFinderProvider declarationFinderProvider, IEnumerable candidates, IEnumerable udtCandidates) - : base(declarationFinderProvider, candidates, udtCandidates) { } - - protected override IEnumerable FindRelevantMembers(IEncapsulatableField candidate) - => _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) - .Where(d => d != candidate.Declaration); - } - - public class ConvertFieldsToUDTMembersConflictFinder : EncapsulateFieldConflictFinderBase - { - public ConvertFieldsToUDTMembersConflictFinder(IDeclarationFinderProvider declarationFinderProvider, IEnumerable candidates, IEnumerable udtCandidates) - : base(declarationFinderProvider, candidates, udtCandidates) { } - - protected override IEnumerable FindRelevantMembers(IEncapsulatableField candidate) - { - var members = _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) - .Where(d => d != candidate.Declaration); - - var membersToRemove = _fieldCandidates.Where(fc => fc.EncapsulateFlag && fc.Declaration.DeclarationType.HasFlag(DeclarationType.Variable)) - .Select(fc => fc.Declaration); - - return members.Except(membersToRemove); - } + bool HasConflictingIdentifier(IEncapsulateFieldCandidate field, DeclarationType declarationType, out string errorMessage); + IEncapsulateFieldCandidate AssignNoConflictIdentifiers(IEncapsulateFieldCandidate candidate); + bool IsConflictingProposedIdentifier(string fieldName, IEncapsulateFieldCandidate candidate, DeclarationType declarationType); + bool TryValidateEncapsulationAttributes(IEncapsulateFieldCandidate field, out string errorMessage); } public abstract class EncapsulateFieldConflictFinderBase : IEncapsulateFieldConflictFinder { protected readonly IDeclarationFinderProvider _declarationFinderProvider; - protected List _fieldCandidates { set; get; } = new List(); + protected List _fieldCandidates { set; get; } = new List(); protected List _udtMemberCandidates { set; get; } = new List(); - public EncapsulateFieldConflictFinderBase(IDeclarationFinderProvider declarationFinderProvider, IEnumerable candidates, IEnumerable udtCandidates) + public EncapsulateFieldConflictFinderBase(IDeclarationFinderProvider declarationFinderProvider, IEnumerable candidates, IEnumerable udtCandidates) { _declarationFinderProvider = declarationFinderProvider; _fieldCandidates.AddRange(candidates); _udtMemberCandidates.AddRange(udtCandidates); } - public bool TryValidateEncapsulationAttributes(IEncapsulatableField field, out string errorMessage) + public virtual bool TryValidateEncapsulationAttributes(IEncapsulateFieldCandidate field, out string errorMessage) { errorMessage = string.Empty; if (!field.EncapsulateFlag) { return true; } @@ -77,11 +50,24 @@ public bool TryValidateEncapsulationAttributes(IEncapsulatableField field, out s return true; } - public bool HasConflictingIdentifier(IEncapsulatableField field, DeclarationType declarationType, out string errorMessage) + public bool HasConflictingIdentifier(IEncapsulateFieldCandidate field, DeclarationType declarationType, out string errorMessage) => InternalHasConflictingIdentifier(field, declarationType, false, out errorMessage); - public IEncapsulatableField AssignNoConflictIdentifier(IEncapsulatableField candidate, DeclarationType declarationType) + public virtual IEncapsulateFieldCandidate AssignNoConflictIdentifiers(IEncapsulateFieldCandidate candidate) + { + candidate = AssignNoConflictIdentifier(candidate, DeclarationType.Property); + if (!(candidate is UserDefinedTypeMemberCandidate)) + { + candidate = AssignNoConflictIdentifier(candidate, DeclarationType.Variable); + } + return candidate; + } + + protected virtual IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType) { + Debug.Assert(declarationType.HasFlag(DeclarationType.Property) + || declarationType.HasFlag(DeclarationType.Variable)); + var isConflictingIdentifier = HasConflictingIdentifierIgnoreEncapsulationFlag(candidate, declarationType, out _); var guard = 0; while (guard++ < 10 && isConflictingIdentifier) @@ -98,26 +84,17 @@ public IEncapsulatableField AssignNoConflictIdentifier(IEncapsulatableField cand } isConflictingIdentifier = HasConflictingIdentifierIgnoreEncapsulationFlag(candidate, declarationType, out _); } - return candidate; - } - public string CreateNonConflictIdentifierForProposedType(string identifier, QualifiedModuleName qmn, DeclarationType declarationType) - { - var guard = 0; - while (guard++ < 10 && IsConflictIdentifier(identifier, qmn, declarationType)) - { - identifier = identifier.IncrementEncapsulationIdentifier(); - } - return identifier; + return EncapsulateFieldValidationsProvider.AssignNoConflictParameter(candidate); } - public bool IsConflictingProposedIdentifier(string fieldName, IEncapsulatableField candidate, DeclarationType declarationType) + public bool IsConflictingProposedIdentifier(string fieldName, IEncapsulateFieldCandidate candidate, DeclarationType declarationType) => PotentialConflictIdentifiers(candidate, declarationType) .Any(m => m.IsEquivalentVBAIdentifierTo(fieldName)); - protected abstract IEnumerable FindRelevantMembers(IEncapsulatableField candidate); + protected abstract IEnumerable FindRelevantMembers(IEncapsulateFieldCandidate candidate); - protected virtual bool InternalHasConflictingIdentifier(IEncapsulatableField field, DeclarationType declarationType, bool ignoreEncapsulationFlags, out string errorMessage) + protected virtual bool InternalHasConflictingIdentifier(IEncapsulateFieldCandidate field, DeclarationType declarationType, bool ignoreEncapsulationFlags, out string errorMessage) { errorMessage = string.Empty; @@ -126,14 +103,14 @@ protected virtual bool InternalHasConflictingIdentifier(IEncapsulatableField fie if (ignoreEncapsulationFlags) { - potentialDeclarationIdentifierConflicts.AddRange(_fieldCandidates.Where(fc => fc != field).Select(fc => fc.PropertyIdentifier)); + potentialDeclarationIdentifierConflicts.AddRange(_fieldCandidates.Where(fc => fc.TargetID != field.TargetID).Select(fc => fc.PropertyIdentifier)); } else { - potentialDeclarationIdentifierConflicts.AddRange(FlaggedCandidates.Where(fc => fc != field).Select(fc => fc.PropertyIdentifier)); + potentialDeclarationIdentifierConflicts.AddRange(FlaggedCandidates.Where(fc => fc.TargetID != field.TargetID).Select(fc => fc.PropertyIdentifier)); } - potentialDeclarationIdentifierConflicts.AddRange(_udtMemberCandidates.Where(udtm => udtm != field && udtm.EncapsulateFlag).Select(udtm => udtm.PropertyIdentifier)); + potentialDeclarationIdentifierConflicts.AddRange(_udtMemberCandidates.Where(udtm => udtm.TargetID != field.TargetID && udtm.EncapsulateFlag).Select(udtm => udtm.PropertyIdentifier)); var identifierToCompare = IdentifierToCompare(field, declarationType); @@ -145,19 +122,25 @@ protected virtual bool InternalHasConflictingIdentifier(IEncapsulatableField fie return false; } - protected string IdentifierToCompare(IEncapsulatableField field, DeclarationType declarationType) + protected string IdentifierToCompare(IEncapsulateFieldCandidate field, DeclarationType declarationType) { return declarationType.HasFlag(DeclarationType.Property) ? field.PropertyIdentifier : field.BackingIdentifier; } + protected bool HasConflictingIdentifierIgnoreEncapsulationFlag(IEncapsulateFieldCandidate field, DeclarationType declarationType, out string errorMessage) + => InternalHasConflictingIdentifier(field, declarationType, true, out errorMessage); + //The refactoring only inserts new code elements with the following Accessibilities: //Variables => Private //Properties => Public - //UDT => Private + //UDTs => Private private bool IsAlwaysIgnoreNameConflictType(Declaration d, DeclarationType toEnapsulateDeclarationType) { + //5.3.1.6 Each and must have a procedure + //name that is different from any other module variable name, module constant name, + //enum member name, or procedure name that is defined within the same module. var NeverCauseNameConflictTypes = new List() { DeclarationType.Project, @@ -182,9 +165,6 @@ private bool IsAlwaysIgnoreNameConflictType(Declaration d, DeclarationType toEna //UDT name cannot be the same as the enum name of any //or the UDT name of any other within the same NeverCauseNameConflictTypes.Remove(DeclarationType.UserDefinedType); - - //5.2.3.4 The enum name of a cannot be the same as the enum name of any other - // or as the UDT name of a within the same . NeverCauseNameConflictTypes.Remove(DeclarationType.Enumeration); } else if (toEnapsulateDeclarationType.HasFlag(DeclarationType.Property)) @@ -201,7 +181,7 @@ private bool IsAlwaysIgnoreNameConflictType(Declaration d, DeclarationType toEna || NeverCauseNameConflictTypes.Contains(d.DeclarationType); } - private List PotentialConflictIdentifiers(IEncapsulatableField candidate, DeclarationType declarationType) + private List PotentialConflictIdentifiers(IEncapsulateFieldCandidate candidate, DeclarationType declarationType) { var members = FindRelevantMembers(candidate); @@ -223,12 +203,9 @@ private List PotentialConflictIdentifiers(IEncapsulatableField candidate return nameConflictCandidates.Select(c => c.IdentifierName).ToList(); } - private List FlaggedCandidates + private List FlaggedCandidates => _fieldCandidates.Where(f => f.EncapsulateFlag).ToList(); - protected bool HasConflictingIdentifierIgnoreEncapsulationFlag(IEncapsulatableField field, DeclarationType declarationType, out string errorMessage) - => InternalHasConflictingIdentifier(field, declarationType, true, out errorMessage); - private bool IsConflictIdentifier(string fieldName, QualifiedModuleName qmn, DeclarationType declarationType) { var nameConflictCandidates = _declarationFinderProvider.DeclarationFinder.Members(qmn) diff --git a/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldValidationsProvider.cs b/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldValidationsProvider.cs index 7693ea6ab9..0f37531400 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldValidationsProvider.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldValidationsProvider.cs @@ -1,6 +1,7 @@ using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings.Common; +using Rubberduck.Refactorings.EncapsulateField.Extensions; using Rubberduck.VBEditor; using System; using System.Collections.Generic; @@ -20,54 +21,95 @@ public enum NameValidators public interface IEncapsulateFieldValidationsProvider { - IValidateVBAIdentifiers NameOnlyValidator(NameValidators validatorType); IEncapsulateFieldConflictFinder ConflictDetector(EncapsulateFieldStrategy strategy, IDeclarationFinderProvider declarationFinderProvider); - void RegisterCandidates(IEnumerable candidates); } public class EncapsulateFieldValidationsProvider : IEncapsulateFieldValidationsProvider { - private Dictionary _nameOnlyValidators; + private static Dictionary _nameOnlyValidators = new Dictionary() + { + [NameValidators.Default] = new IdentifierOnlyValidator(DeclarationType.Variable, false), + [NameValidators.UserDefinedType] = new IdentifierOnlyValidator(DeclarationType.UserDefinedType, false), + [NameValidators.UserDefinedTypeMember] = new IdentifierOnlyValidator(DeclarationType.UserDefinedTypeMember, false), + [NameValidators.UserDefinedTypeMemberArray] = new IdentifierOnlyValidator(DeclarationType.UserDefinedTypeMember, true), + }; + + private static DeclarationType[] _udtTypeIdentifierNonConflictTypes = new DeclarationType[] + { + DeclarationType.Project, + DeclarationType.Module, + DeclarationType.Property, + DeclarationType.Function, + DeclarationType.Procedure, + DeclarationType.Variable, + DeclarationType.Constant, + DeclarationType.UserDefinedTypeMember, + DeclarationType.EnumerationMember, + DeclarationType.Parameter + }; + - private List _candidates; + private List _candidates; private List _udtMemberCandidates; + private List _objectStateUDTs; - public EncapsulateFieldValidationsProvider() + public EncapsulateFieldValidationsProvider(IEnumerable candidates, IEnumerable objectStateUDTCandidates) { - _nameOnlyValidators = new Dictionary() - { - [NameValidators.Default] = new IdentifierOnlyValidator(DeclarationType.Variable, false), - [NameValidators.UserDefinedType] = new IdentifierOnlyValidator(DeclarationType.UserDefinedType, false), - [NameValidators.UserDefinedTypeMember] = new IdentifierOnlyValidator(DeclarationType.UserDefinedTypeMember, false), - [NameValidators.UserDefinedTypeMemberArray] = new IdentifierOnlyValidator(DeclarationType.UserDefinedTypeMember, true), - }; - - _candidates = new List(); _udtMemberCandidates = new List(); + _objectStateUDTs = objectStateUDTCandidates.ToList(); + _candidates = candidates.ToList(); + foreach (var udtCandidate in candidates.Where(c => c is IUserDefinedTypeCandidate).Cast()) + { + foreach (var member in udtCandidate.Members) + { + _udtMemberCandidates.Add(member); + } + } } - public IValidateVBAIdentifiers NameOnlyValidator(NameValidators validatorType) + public static IValidateVBAIdentifiers NameOnlyValidator(NameValidators validatorType) => _nameOnlyValidators[validatorType]; - public IEncapsulateFieldConflictFinder ConflictDetector(EncapsulateFieldStrategy strategy, IDeclarationFinderProvider declarationFinderProvider) + public static IEncapsulateFieldCandidate AssignNoConflictParameter(IEncapsulateFieldCandidate candidate) { - if (strategy == EncapsulateFieldStrategy.UseBackingFields) + candidate.ParameterName = EncapsulateFieldResources.DefaultPropertyParameter; + + var guard = 0; + while (guard++ < 10 && (candidate.BackingIdentifier.IsEquivalentVBAIdentifierTo(candidate.ParameterName) + || candidate.PropertyIdentifier.IsEquivalentVBAIdentifierTo(candidate.ParameterName))) { - return new UseBackingFieldsConflictFinder(declarationFinderProvider, _candidates, _udtMemberCandidates); + candidate.ParameterName = candidate.ParameterName.IncrementEncapsulationIdentifier(); } - return new ConvertFieldsToUDTMembersConflictFinder(declarationFinderProvider, _candidates, _udtMemberCandidates); + return candidate; } - public void RegisterCandidates(IEnumerable candidates) + public static IObjectStateUDT AssignNoConflictIdentifiers(IObjectStateUDT stateUDT, IDeclarationFinderProvider declarationFinderProvider) //, DeclarationType declarationType) { - _candidates.AddRange(candidates); - foreach (var udtCandidate in candidates.Where(c => c is IUserDefinedTypeCandidate).Cast()) + var members = declarationFinderProvider.DeclarationFinder.Members(stateUDT.QualifiedModuleName); + var guard = 0; + while (guard++ < 10 && members.Any(m => m.IdentifierName.IsEquivalentVBAIdentifierTo(stateUDT.FieldIdentifier))) { - foreach (var member in udtCandidate.Members) - { - _udtMemberCandidates.Add(member); - } + stateUDT.FieldIdentifier = stateUDT.FieldIdentifier.IncrementEncapsulationIdentifier(); + } + + members = declarationFinderProvider.DeclarationFinder.Members(stateUDT.QualifiedModuleName) + .Where(m => !_udtTypeIdentifierNonConflictTypes.Any(nct => m.DeclarationType.HasFlag(nct))); + + guard = 0; + while (guard++ < 10 && members.Any(m => m.IdentifierName.IsEquivalentVBAIdentifierTo(stateUDT.TypeIdentifier))) + { + stateUDT.TypeIdentifier = stateUDT.TypeIdentifier.IncrementEncapsulationIdentifier(); + } + return stateUDT; + } + + public IEncapsulateFieldConflictFinder ConflictDetector(EncapsulateFieldStrategy strategy, IDeclarationFinderProvider declarationFinderProvider) + { + if (strategy == EncapsulateFieldStrategy.UseBackingFields) + { + return new UseBackingFieldsStrategyConflictFinder(declarationFinderProvider, _candidates, _udtMemberCandidates); } + return new ConvertFieldsToUDTMembersStrategyConflictFinder(declarationFinderProvider, _candidates, _udtMemberCandidates, _objectStateUDTs); } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldNamesValidator.cs b/Rubberduck.Refactorings/EncapsulateField/Validations/IdentifierOnlyValidator.cs similarity index 100% rename from Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldNamesValidator.cs rename to Rubberduck.Refactorings/EncapsulateField/Validations/IdentifierOnlyValidator.cs diff --git a/Rubberduck.Refactorings/EncapsulateField/Validations/UseBackingFieldsStrategyConflictFinder.cs b/Rubberduck.Refactorings/EncapsulateField/Validations/UseBackingFieldsStrategyConflictFinder.cs new file mode 100644 index 0000000000..e324c401ca --- /dev/null +++ b/Rubberduck.Refactorings/EncapsulateField/Validations/UseBackingFieldsStrategyConflictFinder.cs @@ -0,0 +1,20 @@ +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Refactorings.EncapsulateField +{ + public class UseBackingFieldsStrategyConflictFinder : EncapsulateFieldConflictFinderBase + { + public UseBackingFieldsStrategyConflictFinder(IDeclarationFinderProvider declarationFinderProvider, IEnumerable candidates, IEnumerable udtCandidates) + : base(declarationFinderProvider, candidates, udtCandidates) { } + + protected override IEnumerable FindRelevantMembers(IEncapsulateFieldCandidate candidate) + => _declarationFinderProvider.DeclarationFinder.Members(candidate.QualifiedModuleName) + .Where(d => d != candidate.Declaration); + } +} diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs index 15a2713313..670e39beab 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs @@ -472,7 +472,7 @@ Sub Bar(ByVal name As Integer) var presenterAction = Support.SetParametersForSingleTarget("fizz", "Name"); - var validator = new EncapsulateFieldValidationsProvider().NameOnlyValidator(NameValidators.Default); + var validator = EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.Default); var enapsulationIdentifiers = new EncapsulationIdentifiers("fizz", validator/*(string name) => true*/) { Property = "Name" }; var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs index fcf97374f2..eed5c7b4c5 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldValidatorTests.cs @@ -33,9 +33,8 @@ public void VBAIdentifier_Property(string originalFieldName, string newPropertyN var encapsulatedField = Support.RetrieveEncapsulateFieldCandidate(inputCode, originalFieldName); - //encapsulatedField.PropertyName = newPropertyName; - encapsulatedField.PropertyIdentifier = newPropertyName; encapsulatedField.EncapsulateFlag = true; + encapsulatedField.PropertyIdentifier = newPropertyName; Assert.AreEqual(expectedResult, encapsulatedField.TryValidateEncapsulationAttributes(out _)); } @@ -102,7 +101,7 @@ Private Function First() As String End Function"; var candidate = Support.RetrieveEncapsulateFieldCandidate(inputCode, "myBar", DeclarationType.Variable); - var result = candidate.ConflictFinder/*NamesValidator*/.IsConflictingProposedIdentifier("First", candidate, DeclarationType.Property); + var result = candidate.ConflictFinder.IsConflictingProposedIdentifier("First", candidate, DeclarationType.Property); Assert.AreEqual(true, result); } @@ -580,6 +579,35 @@ Private foo As String Assert.AreEqual(true, model["seats"].TryValidateEncapsulationAttributes(out var errorMessage), errorMessage); } + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void AddedUDTMemberConflictsWithExistingName() + { + var fieldUT = "mFirstValue"; + string inputCode = + $@" + +Private Type MyType + FirstValue As Integer + SecondValue As Integer +End Type + +Private {fieldUT} As Double + +Private myType As MyType +"; + var userInput = new UserInputDataObject() + .UserSelectsField(fieldUT); + + userInput.EncapsulateUsingUDTField("myType"); + + var presenterAction = Support.SetParameters(userInput); + + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(inputCode, fieldUT, DeclarationType.Variable, presenterAction); + Assert.AreEqual(false, model[fieldUT].TryValidateEncapsulationAttributes(out var errorMessage), errorMessage); + } + protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) { return Support.SupportTestRefactoring(rewritingManager, state, factory, selectionService); diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs index e486286be9..668cc0f237 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs @@ -371,15 +371,12 @@ End Property StringAssert.Contains($" AnArray({dimensions}) As String", actualCode); } - [TestCase("Public Sub This_Type()\r\nEnd Sub", "This_Type_1")] - [TestCase("Private This_Type As Long\r\nPrivate This_Type_1 As String", "This_Type_2")] - [TestCase("Public Property Get This_Type() As Long\r\nEnd Property", "This_Type_1")] + [Test] [Category("Refactorings")] [Category("Encapsulate Field")] - public void UserDefinedTypeDefaultNameHasConflicts(string declaration, string expectedIdentifier) + public void UserDefinedTypeDefaultNameHasConflict() { - declaration = declaration.Replace("This_Type", $"{Support.StateUDTDefaultType}"); - expectedIdentifier = expectedIdentifier.Replace("This_Type", $"{Support.StateUDTDefaultType}"); + var expectedIdentifier = "TTestModule1_1"; string inputCode = $@" @@ -388,13 +385,16 @@ First As Long Second As String End Type +Private Type TTestModule1 + Bar As Long +End Type + Public fo|o As Long Public myBar As TBar - -{declaration} "; var userInput = new UserInputDataObject() + .UserSelectsField("foo") .UserSelectsField("myBar"); @@ -405,10 +405,11 @@ Public myBar As TBar StringAssert.Contains($"Private Type {expectedIdentifier}", actualCode); } - [Test] + [TestCase("Public", 1)] + [TestCase("Private", 2)] [Category("Refactorings")] [Category("Encapsulate Field")] - public void StateObjectCandidatesContent() + public void ObjectStateUDTs(string udtFieldAccessibility, int expectedCount) { string inputCode = $@" @@ -421,7 +422,7 @@ Public mFoo As String Public mBar As Long Private mFizz -Public myBar As TBar"; +{udtFieldAccessibility} myBar As TBar"; var userInput = new UserInputDataObject() .UserSelectsField("mFizz"); @@ -433,7 +434,7 @@ Private mFizz var model = Support.RetrieveUserModifiedModelPriorToRefactoring(inputCode, "mFizz", DeclarationType.Variable, presenterAction); var test = model.ObjectStateUDTCandidates; - Assert.AreEqual(2, model.ObjectStateUDTCandidates.Count()); + Assert.AreEqual(expectedCount, model.ObjectStateUDTCandidates.Count()); } protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs index 19fbeb9edc..cfb3a34e7f 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs @@ -64,7 +64,7 @@ End Type Public th|is As TBar Public that As TBar"; - var validator = new EncapsulateFieldValidationsProvider().NameOnlyValidator(NameValidators.Default); + var validator = EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.Default); var expectedThis = new EncapsulationIdentifiers("this", validator); var expectedThat = new EncapsulationIdentifiers("that", validator); @@ -85,12 +85,12 @@ Public th|is As TBar StringAssert.Contains($"Property Get Second", actualCode); StringAssert.Contains($"Private {expectedThat.TargetFieldName} As TBar", actualCode); - StringAssert.Contains($"ThatFirst = {expectedThat.TargetFieldName}.First", actualCode); - StringAssert.Contains($"ThatSecond = {expectedThat.TargetFieldName}.Second", actualCode); + StringAssert.Contains($"First_1 = {expectedThat.TargetFieldName}.First", actualCode); + StringAssert.Contains($"Second_1 = {expectedThat.TargetFieldName}.Second", actualCode); StringAssert.Contains($"{expectedThat.TargetFieldName}.First = value", actualCode); StringAssert.Contains($"{expectedThat.TargetFieldName}.Second = value", actualCode); - StringAssert.Contains($"Property Get ThatFirst", actualCode); - StringAssert.Contains($"Property Get ThatSecond", actualCode); + StringAssert.Contains($"Property Get First_1", actualCode); + StringAssert.Contains($"Property Get Second_1", actualCode); StringAssert.Contains($"Private {expectedThis.TargetFieldName} As TBar", actualCode); StringAssert.Contains($"Private {expectedThat.TargetFieldName} As TBar", actualCode); @@ -679,37 +679,6 @@ public void ClassModuleUDTFieldSelection_ExternalReferences_ClassModule() Public th|is As TBar"; -// var procedureModuleReferencingCode = -//$@"Option Explicit - -//Public Type TBar -// First As String -// Second As Long -//End Type - -//Private {sourceClassName} As {sourceModuleName} -//Private Const foo As String = ""Foo"" -//Private Const bar As Long = 7 - -//Public Sub Initialize() -// Set {sourceClassName} = New {sourceModuleName} -//End Sub - -//Public Sub Foo() -// {sourceClassName}.this.First = foo -//End Sub - -//Public Sub Bar() -// {sourceClassName}.this.Second = bar -//End Sub - -//Public Sub FooBar() -// With {sourceClassName} -// .this.First = foo -// .this.Second = bar -// End With -//End Sub -//"; string classModuleReferencingCode = $@"Option Explicit @@ -751,15 +720,9 @@ End Sub presenterAction, null, false, - //("StdModule", procedureModuleReferencingCode, ComponentType.StandardModule), ("ClassModule", classModuleReferencingCode, ComponentType.ClassModule), (sourceModuleName, sourceCodeString.Code, ComponentType.ClassModule)); - //var referencingModuleCode = actualModuleCode["StdModule"]; - //StringAssert.Contains($"{sourceClassName}.MyType.First = ", referencingModuleCode); - //StringAssert.Contains($"{sourceClassName}.MyType.Second = ", referencingModuleCode); - //StringAssert.Contains($" .MyType.Second = ", referencingModuleCode); - var referencingClassCode = actualModuleCode["ClassModule"]; StringAssert.Contains($"{sourceClassName}.MyType.First = ", referencingClassCode); StringAssert.Contains($"{sourceClassName}.MyType.Second = ", referencingClassCode); @@ -811,33 +774,6 @@ End With End Sub "; -// string classModuleReferencingCode = -//$@"Option Explicit - -//Private {sourceClassName} As {sourceModuleName} -//Private Const foo As String = ""Foo"" -//Private Const bar As Long = 7 - -//Private Sub Class_Initialize() -// Set {sourceClassName} = New {sourceModuleName} -//End Sub - -//Public Sub Foo() -// {sourceClassName}.this.First = foo -//End Sub - -//Public Sub Bar() -// {sourceClassName}.this.Second = bar -//End Sub - -//Public Sub FooBar() -// With {sourceClassName} -// .this.First = foo -// .this.Second = bar -// End With -//End Sub -//"; - var userInput = new UserInputDataObject() .UserSelectsField("this", "MyType"); @@ -852,18 +788,12 @@ End Sub null, false, ("StdModule", procedureModuleReferencingCode, ComponentType.StandardModule), - //("ClassModule", classModuleReferencingCode, ComponentType.ClassModule), (sourceModuleName, sourceCodeString.Code, ComponentType.ClassModule)); var referencingModuleCode = actualModuleCode["StdModule"]; StringAssert.Contains($"{sourceClassName}.MyType.First = ", referencingModuleCode); StringAssert.Contains($"{sourceClassName}.MyType.Second = ", referencingModuleCode); StringAssert.Contains($" .MyType.Second = ", referencingModuleCode); - - //var referencingClassCode = actualModuleCode["ClassModule"]; - //StringAssert.Contains($"{sourceClassName}.MyType.First = ", referencingClassCode); - //StringAssert.Contains($"{sourceClassName}.MyType.Second = ", referencingClassCode); - //StringAssert.Contains($" .MyType.Second = ", referencingClassCode); } [Test] @@ -955,7 +885,7 @@ Private Function First() As String var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); - StringAssert.Contains("Public Property Let MyBarFirst", actualCode); + StringAssert.Contains("Public Property Let First_1", actualCode); StringAssert.Contains("Public Property Let Second", actualCode); } diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs index 1fa6c92ab4..bee93fd54c 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulationIdentifiersTests.cs @@ -46,47 +46,37 @@ public void FieldNameValuesPerSequenceOfPropertyNameChanges() { string inputCode = "Public fizz As String"; - var encapsulatedField = Support.RetrieveEncapsulateFieldCandidate(inputCode, "fizz"); // as IUsingBackingField; + var encapsulatedField = Support.RetrieveEncapsulateFieldCandidate(inputCode, "fizz"); StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.BackingIdentifier); - //StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.FieldIdentifierOld); - //encapsulatedField.PropertyName = "Test"; encapsulatedField.PropertyIdentifier = "Test"; - //StringAssert.AreEqualIgnoringCase("fizz", encapsulatedField.FieldIdentifierOld); StringAssert.AreEqualIgnoringCase("fizz", encapsulatedField.BackingIdentifier); - //encapsulatedField.PropertyName = "Fizz"; encapsulatedField.PropertyIdentifier = "Fizz"; - //StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.FieldIdentifierOld); StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.BackingIdentifier); - //encapsulatedField.PropertyName = "Fiz"; encapsulatedField.PropertyIdentifier = "Fiz"; - //StringAssert.AreEqualIgnoringCase("fizz", encapsulatedField.FieldIdentifierOld); StringAssert.AreEqualIgnoringCase("fizz", encapsulatedField.BackingIdentifier); - //encapsulatedField.PropertyName = "Fizz"; encapsulatedField.PropertyIdentifier = "Fizz"; - //StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.FieldIdentifierOld); StringAssert.AreEqualIgnoringCase("fizz_1", encapsulatedField.BackingIdentifier); } - [Test] + [TestCase("Test", "value_1")] + [TestCase("Value", "value_2")] [Category("Refactorings")] [Category("Encapsulate Field")] - public void PropertyNameChange_UniqueParamName() + public void PropertyNameChange_UniqueParamName(string PropertyName, string expectedParameterName) { string inputCode = "Public value As String"; - var encapsulatedField = Support.RetrieveEncapsulateFieldCandidate(inputCode, "value"); + var fieldUT = "value"; - //encapsulatedField.PropertyName = "Test"; - encapsulatedField.PropertyIdentifier = "Test"; - StringAssert.AreEqualIgnoringCase("value_1", encapsulatedField.ParameterName); + var presenterAction = Support.SetParametersForSingleTarget(fieldUT, PropertyName); - //encapsulatedField.PropertyName = "Value"; - encapsulatedField.PropertyIdentifier = "Value"; - StringAssert.AreEqualIgnoringCase("value_2", encapsulatedField.ParameterName); + var model = Support.RetrieveUserModifiedModelPriorToRefactoring(inputCode, fieldUT, DeclarationType.Variable, presenterAction); + var encapsulatedField = model[fieldUT]; + StringAssert.AreEqualIgnoringCase(expectedParameterName, encapsulatedField.ParameterName); } [TestCase("strValue", "Value", "strValue")] @@ -96,7 +86,7 @@ public void PropertyNameChange_UniqueParamName() [Category("Encapsulate Field")] public void AccountsForHungarianNamesAndMemberPrefix(string inputName, string expectedPropertyName, string expectedFieldName) { - var validator = new EncapsulateFieldValidationsProvider().NameOnlyValidator(NameValidators.Default); + var validator = EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.Default); var sut = new EncapsulationIdentifiers(inputName, validator); Assert.AreEqual(expectedPropertyName, sut.DefaultPropertyName); diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs index beb49de560..1fd0cfc50d 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs @@ -36,7 +36,6 @@ public Func UserAcceptsDefaults(bo { return model => { - //model.ConvertFieldsToUDTMembers = convertFieldToUDTMember; model.EncapsulateFieldStrategy = convertFieldToUDTMember ? EncapsulateFieldStrategy.ConvertFieldsToUDTMembers : EncapsulateFieldStrategy.UseBackingFields; @@ -67,30 +66,28 @@ public Func SetParameters(UserInpu { return model => { - //model.ConvertFieldsToUDTMembers = userInput.ConvertFieldsToUDTMembers; - model.EncapsulateFieldStrategy = userInput.ConvertFieldsToUDTMembers - ? EncapsulateFieldStrategy.ConvertFieldsToUDTMembers - : EncapsulateFieldStrategy.UseBackingFields; - if (userInput.ConvertFieldsToUDTMembers) { - var stateUDT = model.EncapsulationCandidates.Where(sfc => sfc is IUserDefinedTypeCandidate udt && udt.TargetID == userInput.ObjectStateUDTTargetID) - .Select(sfc => sfc as IUserDefinedTypeCandidate).SingleOrDefault(); + model.EncapsulateFieldStrategy = EncapsulateFieldStrategy.ConvertFieldsToUDTMembers; + var stateUDT = model.ObjectStateUDTCandidates.Where(os => os.IdentifierName == userInput.ObjectStateUDTTargetID) + .Select(sfc => sfc).SingleOrDefault(); + if (stateUDT != null) { - stateUDT.EncapsulateFlag = false; - model.StateUDTField = new ObjectStateUDT(stateUDT); - model.StateUDTField.IsSelected = true; + model.StateUDTField = stateUDT; } } + else + { + model.EncapsulateFieldStrategy = EncapsulateFieldStrategy.UseBackingFields; + } foreach (var testModifiedAttribute in userInput.EncapsulateFieldAttributes) { var attrsInitializedByTheRefactoring = model[testModifiedAttribute.TargetFieldName]; - //attrsInitializedByTheRefactoring.PropertyName = testModifiedAttribute.PropertyName; - attrsInitializedByTheRefactoring.PropertyIdentifier = testModifiedAttribute.PropertyName; attrsInitializedByTheRefactoring.EncapsulateFlag = testModifiedAttribute.EncapsulateFlag; + attrsInitializedByTheRefactoring.PropertyIdentifier = testModifiedAttribute.PropertyName; attrsInitializedByTheRefactoring.IsReadOnly = testModifiedAttribute.IsReadOnly; } return model; @@ -101,16 +98,14 @@ public Func SetParameters(string o { return model => { - var encapsulatedField = model[originalField]; - //encapsulatedField.PropertyName = attrs.PropertyName; - encapsulatedField.PropertyIdentifier = attrs.PropertyName; - encapsulatedField.IsReadOnly = attrs.IsReadOnly; - encapsulatedField.EncapsulateFlag = attrs.EncapsulateFlag; - - //model.ConvertFieldsToUDTMembers = convertFieldsToUDTMembers; model.EncapsulateFieldStrategy = convertFieldsToUDTMembers ? EncapsulateFieldStrategy.ConvertFieldsToUDTMembers : EncapsulateFieldStrategy.UseBackingFields; + + var encapsulatedField = model[originalField]; + encapsulatedField.EncapsulateFlag = attrs.EncapsulateFlag; + encapsulatedField.PropertyIdentifier = attrs.PropertyName; + encapsulatedField.IsReadOnly = attrs.IsReadOnly; return model; }; } @@ -129,19 +124,19 @@ public IRefactoring SupportTestRefactoring(IRewritingManager rewritingManager, R return new EncapsulateFieldRefactoring(state, indenter, factory, rewritingManager, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); } - public IEncapsulatableField RetrieveEncapsulateFieldCandidate(string inputCode, string fieldName) + public IEncapsulateFieldCandidate RetrieveEncapsulateFieldCandidate(string inputCode, string fieldName) { var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; return RetrieveEncapsulateFieldCandidate(vbe, fieldName); } - public IEncapsulatableField RetrieveEncapsulateFieldCandidate(string inputCode, string fieldName, DeclarationType declarationType) + public IEncapsulateFieldCandidate RetrieveEncapsulateFieldCandidate(string inputCode, string fieldName, DeclarationType declarationType) { var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out _).Object; return RetrieveEncapsulateFieldCandidate(vbe, fieldName, declarationType); } - public IEncapsulatableField RetrieveEncapsulateFieldCandidate(IVBE vbe, string fieldName, DeclarationType declarationType = DeclarationType.Variable) + public IEncapsulateFieldCandidate RetrieveEncapsulateFieldCandidate(IVBE vbe, string fieldName, DeclarationType declarationType = DeclarationType.Variable) { var state = MockParser.CreateAndParse(vbe); using (state) @@ -150,7 +145,7 @@ public IEncapsulatableField RetrieveEncapsulateFieldCandidate(IVBE vbe, string f var builder = new EncapsulateFieldElementsBuilder(state, match.QualifiedModuleName); foreach (var candidate in builder.Candidates) { - candidate.NameValidator = builder.ValidationsProvider.NameOnlyValidator(NameValidators.Default); + candidate.NameValidator = EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.Default); } return builder.Candidates.First(); } @@ -195,7 +190,7 @@ public class TestEncapsulationAttributes { public TestEncapsulationAttributes(string fieldName, bool encapsulationFlag = true, bool isReadOnly = false) { - var validator = new EncapsulateFieldValidationsProvider().NameOnlyValidator(NameValidators.Default); + var validator = EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.Default); _identifiers = new EncapsulationIdentifiers(fieldName, validator); EncapsulateFlag = encapsulationFlag; IsReadOnly = isReadOnly; @@ -255,7 +250,7 @@ public void EncapsulateUsingUDTField(string targetID = null) public string StateUDT_FieldName { set; get; } - public TestEncapsulationAttributes this[string fieldName] + public TestEncapsulationAttributes this[string fieldName] => EncapsulateFieldAttributes.Where(efa => efa.TargetFieldName == fieldName).Single(); public IEnumerable EncapsulateFieldAttributes => _userInput; From 92efa3177e44a321d064bee6622755235cac5084 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sat, 11 Jan 2020 16:34:42 +0100 Subject: [PATCH 134/461] Amend identifier reference inspection base classes to allow providing additional properties for results Also moves more inspections to the base classes. --- ...ReferenceInspectionFromDeclarationsBase.cs | 43 ++++++ .../IdentifierReferenceInspectionBase.cs | 20 ++- ...ReferenceInspectionFromDeclarationsBase.cs | 22 ++- .../Abstract/InspectionResultBase.cs | 2 - .../Abstract/IsMissingInspectionBase.cs | 28 +--- .../SheetAccessedUsingStringInspection.cs | 135 +++++++++--------- ...issingOnInappropriateArgumentInspection.cs | 30 ++-- ...ssingWithNonArgumentParameterInspection.cs | 11 +- ...WithNonArgumentParameterInspectionTests.cs | 2 +- ...SheetAccessedUsingStringInspectionTests.cs | 48 +++++++ 10 files changed, 208 insertions(+), 133 deletions(-) create mode 100644 Rubberduck.CodeAnalysis/Inspections/Abstract/ArgumentReferenceInspectionFromDeclarationsBase.cs diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/ArgumentReferenceInspectionFromDeclarationsBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/ArgumentReferenceInspectionFromDeclarationsBase.cs new file mode 100644 index 0000000000..0e8b981748 --- /dev/null +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/ArgumentReferenceInspectionFromDeclarationsBase.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using System.Linq; +using Rubberduck.Inspections.Abstract; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; + +namespace Rubberduck.Inspections.Inspections.Abstract +{ + public abstract class ArgumentReferenceInspectionFromDeclarationsBase : IdentifierReferenceInspectionFromDeclarationsBase + { + protected ArgumentReferenceInspectionFromDeclarationsBase(RubberduckParserState state) + : base(state) { } + + protected abstract bool IsUnsuitableArgument(ArgumentReference reference, DeclarationFinder finder); + + protected virtual (bool isResult, object properties) IsUnsuitableArgumentWithAdditionalProperties(ArgumentReference reference, DeclarationFinder finder) + { + return (IsUnsuitableArgument(reference, finder), null); + } + + protected override IEnumerable<(IdentifierReference reference, object properties)> ObjectionableReferences(DeclarationFinder finder) + { + return ObjectionableDeclarations(finder) + .OfType() + .SelectMany(declaration => declaration.Parameters) + .SelectMany(parameter => parameter.ArgumentReferences) + .Select(reference => (reference, IsResultReferenceWithAdditionalProperties(reference, finder))) + .Where(tpl => tpl.Item2.isResult) + .Select(tpl => ((IdentifierReference) tpl.reference, tpl.Item2.properties)); ; + } + + protected override (bool isResult, object properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder) + { + if (!(reference is ArgumentReference argumentReference)) + { + return (false, null); + } + + return IsUnsuitableArgumentWithAdditionalProperties(argumentReference, finder); + } + } +} diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs index 60bc68a3f9..5ca69539ec 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs @@ -18,6 +18,11 @@ public IdentifierReferenceInspectionBase(RubberduckParserState state) protected abstract bool IsResultReference(IdentifierReference reference, DeclarationFinder finder); protected abstract string ResultDescription(IdentifierReference reference); + protected virtual (bool isResult, object properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder) + { + return (IsResultReference(reference, finder), null); + } + protected override IEnumerable DoGetInspectionResults() { var finder = DeclarationFinderProvider.DeclarationFinder; @@ -39,11 +44,13 @@ protected override IEnumerable DoGetInspectionResults() protected IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { - var objectionableReferences = ReferencesInModule(module, finder) - .Where(reference => IsResultReference(reference, finder)); + var objectionableReferencesWithProperties = ReferencesInModule(module, finder) + .Select(reference => (reference, IsResultReferenceWithAdditionalProperties(reference, finder))) + .Where(tpl => tpl.Item2.isResult) + .Select(tpl => (tpl.reference, tpl.Item2.properties)); - return objectionableReferences - .Select(reference => InspectionResult(reference, DeclarationFinderProvider)) + return objectionableReferencesWithProperties + .Select(tpl => InspectionResult(tpl.reference, DeclarationFinderProvider, tpl.properties)) .ToList(); } @@ -58,13 +65,14 @@ protected virtual IEnumerable ReferencesInModule(QualifiedM return finder.IdentifierReferences(module); } - protected virtual IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider) + protected virtual IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider, dynamic properties = null) { return new IdentifierReferenceInspectionResult( this, ResultDescription(reference), declarationFinderProvider, - reference); + reference, + properties); } } } \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs index c7ea463410..8ad64f1eab 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs @@ -23,37 +23,45 @@ protected override IEnumerable DoGetInspectionResults() var finder = DeclarationFinderProvider.DeclarationFinder; var objectionableReferences = ObjectionableReferences(finder); return objectionableReferences - .Select(reference => InspectionResult(reference, DeclarationFinderProvider)) + .Select(tpl => InspectionResult(tpl.reference, DeclarationFinderProvider, tpl.properties)) .ToList(); } - protected virtual IEnumerable ObjectionableReferences(DeclarationFinder finder) + protected virtual IEnumerable<(IdentifierReference reference, object properties)> ObjectionableReferences(DeclarationFinder finder) { var objectionableDeclarations = ObjectionableDeclarations(finder); return objectionableDeclarations .SelectMany(declaration => declaration.References) - .Where(reference => IsResultReference(reference, finder)); + .Select(reference => (reference, IsResultReferenceWithAdditionalProperties(reference, finder))) + .Where(tpl => tpl.Item2.isResult) + .Select(tpl => (tpl.reference, tpl.Item2.properties)); } protected virtual bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) => true; + protected virtual (bool isResult, object properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder) + { + return (IsResultReference(reference, finder), null); + } + protected IEnumerable DoGetInspectionResults(QualifiedModuleName module) { var finder = DeclarationFinderProvider.DeclarationFinder; var objectionableReferences = ObjectionableReferences(finder); return objectionableReferences - .Where(reference => reference.QualifiedModuleName.Equals(module)) - .Select(reference => InspectionResult(reference, DeclarationFinderProvider)) + .Where(tpl => tpl.reference.QualifiedModuleName.Equals(module)) + .Select(tpl => InspectionResult(tpl.reference, DeclarationFinderProvider, tpl.properties)) .ToList(); } - protected virtual IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider) + protected virtual IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider, dynamic properties = null) { return new IdentifierReferenceInspectionResult( this, ResultDescription(reference), declarationFinderProvider, - reference); + reference, + properties); } } } \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionResultBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionResultBase.cs index 499ca1760a..e57d6c1b15 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionResultBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionResultBase.cs @@ -1,10 +1,8 @@ using System.Collections.Generic; -using System.IO; using Antlr4.Runtime; using Rubberduck.Common; using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Inspections.Abstract; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.VBEditor; using Rubberduck.Interaction.Navigation; diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs index 813673522c..9bdf00fc3f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs @@ -1,10 +1,6 @@ using System.Collections.Generic; using System.Linq; -using Antlr4.Runtime; -using NLog; -using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; -using Rubberduck.Parsing.Binding; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; @@ -12,7 +8,7 @@ namespace Rubberduck.Inspections.Inspections.Abstract { - public abstract class IsMissingInspectionBase : IdentifierReferenceInspectionFromDeclarationsBase + public abstract class IsMissingInspectionBase : ArgumentReferenceInspectionFromDeclarationsBase { protected IsMissingInspectionBase(RubberduckParserState state) : base(state) { } @@ -23,9 +19,6 @@ protected IsMissingInspectionBase(RubberduckParserState state) "VBA6.DLL;VBA.Information.IsMissing" }; - protected abstract bool IsUnsuitableArgument(ArgumentReference reference, DeclarationFinder finder); - - protected override IEnumerable ObjectionableDeclarations(DeclarationFinder finder) { return IsMissingDeclarations(finder); @@ -34,7 +27,7 @@ protected override IEnumerable ObjectionableDeclarations(Declaratio protected IReadOnlyList IsMissingDeclarations(DeclarationFinder finder) { var vbaProjects = finder.Projects - .Where(project => project.IdentifierName == "VBA") + .Where(project => project.IdentifierName == "VBA" && !project.IsUserDefined) .ToList(); if (!vbaProjects.Any()) @@ -60,22 +53,7 @@ protected IReadOnlyList IsMissingDeclarations(DeclarationFinder fin return isMissing; } - protected override IEnumerable ObjectionableReferences(DeclarationFinder finder) - { - return ObjectionableDeclarations(finder) - .OfType() - .SelectMany(declaration => declaration.Parameters) - .SelectMany(parameter => parameter.ArgumentReferences) - .Where(reference => IsResultReference(reference, finder)); - } - - protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) - { - return reference is ArgumentReference argumentReference - && IsUnsuitableArgument(argumentReference, finder); - } - - protected ParameterDeclaration GetParameterForReference(ArgumentReference reference, DeclarationFinder finder) + protected ParameterDeclaration ParameterForReference(ArgumentReference reference, DeclarationFinder finder) { var argumentContext = reference.Context as VBAParser.LExprContext; if (!(argumentContext?.lExpression() is VBAParser.SimpleNameExprContext name)) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs index 6cf6b5b669..bed1115c65 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs @@ -1,16 +1,15 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.Common; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -45,9 +44,13 @@ namespace Rubberduck.Inspections.Concrete /// [RequiredHost("EXCEL.EXE")] [RequiredLibrary("Excel")] - public class SheetAccessedUsingStringInspection : InspectionBase + public class SheetAccessedUsingStringInspection : IdentifierReferenceInspectionFromDeclarationsBase { - public SheetAccessedUsingStringInspection(RubberduckParserState state) : base(state) { } + //TODO: revisit this and its tests after clarification of intended behaviour. + //This relates to the handling of implicit references to ActiveWorkbook. + + public SheetAccessedUsingStringInspection(RubberduckParserState state) + : base(state) { } private static readonly string[] InterestingMembers = { @@ -59,106 +62,108 @@ public SheetAccessedUsingStringInspection(RubberduckParserState state) : base(st "_Global", "_Application", "Global", "Application", "Workbook" }; - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable ObjectionableDeclarations(DeclarationFinder finder) { - var excel = State.DeclarationFinder.Projects.SingleOrDefault(item => !item.IsUserDefined && item.IdentifierName == "Excel"); + var excel = finder.Projects + .SingleOrDefault(project => project.IdentifierName == "Excel" && !project.IsUserDefined); if (excel == null) { - return Enumerable.Empty(); + return Enumerable.Empty(); } - var targetProperties = BuiltInDeclarations + var relevantClasses = InterestingClasses + .Select(className => finder.FindClassModule(className, excel, true)) + .OfType(); + + var relevantProperties = relevantClasses + .SelectMany(classDeclaration => classDeclaration.Members) .OfType() - .Where(x => InterestingMembers.Contains(x.IdentifierName) && InterestingClasses.Contains(x.ParentDeclaration?.IdentifierName)) - .ToList(); + .Where(member => InterestingMembers.Contains(member.IdentifierName)); - var references = targetProperties.SelectMany(declaration => declaration.References - .Where(reference => IsAccessedWithStringLiteralParameter(reference)) - .Select(reference => new IdentifierReferenceInspectionResult(this, - InspectionResults.SheetAccessedUsingStringInspection, State, reference))); + return relevantProperties; + } - var issues = new List(); + protected override (bool isResult, object properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder) + { + var sheetNameArgumentLiteralExpressionContext = SheetNameArgumentLiteralExpressionContext(reference); - foreach (var reference in references) + if (sheetNameArgumentLiteralExpressionContext?.STRINGLITERAL() == null) { - using (var component = GetVBComponentMatchingSheetName(reference)) - { - if (component == null) - { - continue; - } - using (var properties = component.Properties) - { - reference.Properties.CodeName = (string)properties.Single(property => property.Name == "CodeName").Value; - } - issues.Add(reference); - } + return (false, null); } - return issues; + + var projectId = reference.QualifiedModuleName.ProjectId; + var sheetName = sheetNameArgumentLiteralExpressionContext.GetText().UnQuote(); + var codeName = CodeNameOfVBComponentMatchingSheetName(projectId, sheetName); + + if (codeName == null) + { + return (false, null); + } + + dynamic properties = new PropertyBag(); + properties.CodeName = codeName; + return (true, properties); } - private static bool IsAccessedWithStringLiteralParameter(IdentifierReference reference) + private static VBAParser.LiteralExpressionContext SheetNameArgumentLiteralExpressionContext(IdentifierReference reference) { // Second case accounts for global modules var indexExprContext = reference.Context.Parent.Parent as VBAParser.IndexExprContext ?? reference.Context.Parent as VBAParser.IndexExprContext; - var literalExprContext = indexExprContext + return (indexExprContext ?.argumentList() ?.argument(0) ?.positionalArgument() - ?.argumentExpression().expression() as VBAParser.LiteralExprContext; - - return literalExprContext?.literalExpression().STRINGLITERAL() != null; + ?.argumentExpression() + ?.expression() as VBAParser.LiteralExprContext) + ?.literalExpression(); } - private IVBComponent GetVBComponentMatchingSheetName(IdentifierReferenceInspectionResult reference) + private string CodeNameOfVBComponentMatchingSheetName(string projectId, string sheetName) { - // Second case accounts for global modules - var indexExprContext = reference.Context.Parent.Parent as VBAParser.IndexExprContext ?? - reference.Context.Parent as VBAParser.IndexExprContext; + var components = State.ProjectsProvider.Components(projectId); - if (indexExprContext == null) + foreach (var (module, component) in components) { - return null; + if (component.Type != ComponentType.Document) + { + continue; + } + + var name = ComponentPropertyValue(component, "Name"); + if (sheetName.Equals(name)) + { + return ComponentPropertyValue(component, "CodeName"); + } } - var sheetArgumentContext = indexExprContext.argumentList().argument(0); - var sheetName = FormatSheetName(sheetArgumentContext.GetText()); - var project = State.ProjectsProvider.Project(reference.QualifiedName.ProjectId); + return null; + } - using (var components = project.VBComponents) + private static string ComponentPropertyValue(IVBComponent component, string propertyName) + { + using (var properties = component.Properties) { - foreach (var component in components) + foreach (var property in properties) { - using (var properties = component.Properties) + using (property) { - if (component.Type != ComponentType.Document) + if (property.Name == propertyName) { - component.Dispose(); - continue; - } - foreach (var property in properties) - { - var found = property.Name.Equals("Name") && ((string)property.Value).Equals(sheetName); - property.Dispose(); - if (found) - { - return component; - } + return (string)property.Value; } } - component.Dispose(); } - return null; } + + return null; } - private static string FormatSheetName(string sheetName) + protected override string ResultDescription(IdentifierReference reference) { - return sheetName.StartsWith("\"") && sheetName.EndsWith("\"") - ? sheetName.Substring(1, sheetName.Length - 2) - : sheetName; + return InspectionResults.SheetAccessedUsingStringInspection; } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs index c1a74c5bf6..eb0ddd336d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs @@ -40,30 +40,22 @@ public class IsMissingOnInappropriateArgumentInspection : IsMissingInspectionBas public IsMissingOnInappropriateArgumentInspection(RubberduckParserState state) : base(state) { } - protected override bool IsUnsuitableArgument(ArgumentReference reference, DeclarationFinder finder) + protected override (bool isResult, object properties) IsUnsuitableArgumentWithAdditionalProperties(ArgumentReference reference, DeclarationFinder finder) { - var parameter = GetParameterForReference(reference, finder); + var parameter = ParameterForReference(reference, finder); - return parameter != null - && (!parameter.IsOptional - || !parameter.AsTypeName.Equals(Tokens.Variant) - || !string.IsNullOrEmpty(parameter.DefaultValue) - || parameter.IsArray); + var isResult = parameter != null + && (!parameter.IsOptional + || !parameter.AsTypeName.Equals(Tokens.Variant) + || !string.IsNullOrEmpty(parameter.DefaultValue) + || parameter.IsArray); + return (isResult, parameter); } - protected override IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider) + protected override bool IsUnsuitableArgument(ArgumentReference reference, DeclarationFinder finder) { - //This is not ideal, put passing along the declaration finder used in the test itself or the parameter requires reimplementing half of the base class. - var argumentReference = reference as ArgumentReference; - var finder = declarationFinderProvider.DeclarationFinder; - var parameter = GetParameterForReference(argumentReference, finder); - - return new IdentifierReferenceInspectionResult( - this, - ResultDescription(reference), - declarationFinderProvider, - reference, - parameter); + //No need to implement this, since we override IsUnsuitableArgumentWithAdditionalProperties. + throw new System.NotImplementedException(); } protected override string ResultDescription(IdentifierReference reference) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs index 99597d0532..99dfeca2ef 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs @@ -1,15 +1,10 @@ -using System.Collections.Generic; -using System.Linq; -using Rubberduck.Inspections.Inspections.Abstract; -using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Inspections.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Inspections.Concrete +namespace Rubberduck.Inspections.Concrete { /// /// Identifies uses of 'IsMissing' involving a non-parameter argument. @@ -42,7 +37,7 @@ public IsMissingWithNonArgumentParameterInspection(RubberduckParserState state) protected override bool IsUnsuitableArgument(ArgumentReference reference, DeclarationFinder finder) { - var parameter = GetParameterForReference(reference, finder); + var parameter = ParameterForReference(reference, finder); return parameter == null; } diff --git a/RubberduckTests/Inspections/IsMissingWithNonArgumentParameterInspectionTests.cs b/RubberduckTests/Inspections/IsMissingWithNonArgumentParameterInspectionTests.cs index 120094b516..78d588e0ac 100644 --- a/RubberduckTests/Inspections/IsMissingWithNonArgumentParameterInspectionTests.cs +++ b/RubberduckTests/Inspections/IsMissingWithNonArgumentParameterInspectionTests.cs @@ -1,6 +1,6 @@ using System.Linq; using NUnit.Framework; -using Rubberduck.Inspections.Inspections.Concrete; +using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/Inspections/SheetAccessedUsingStringInspectionTests.cs b/RubberduckTests/Inspections/SheetAccessedUsingStringInspectionTests.cs index 95819c29b9..918901a1a2 100644 --- a/RubberduckTests/Inspections/SheetAccessedUsingStringInspectionTests.cs +++ b/RubberduckTests/Inspections/SheetAccessedUsingStringInspectionTests.cs @@ -66,6 +66,54 @@ public void SheetAccessedUsingString_DoesNotReturnResult_AccessingUsingWorkbooks Assert.AreEqual(0, ArrangeParserAndGetResults(inputCode).Count()); } + [Test] + [Ignore("Ref #4329")] + [Category("Inspections")] + public void SheetAccessedUsingString_DoesNotReturnResult_AccessingUsingWorkbookVariable() + { + const string inputCode = + @"Public Sub Foo() + Dim wkb As Excel.Workbook + Set wkb = Workbooks(""Foo"") + wkb.Worksheets(""Sheet1"").Range(""A1"") = ""Foo"" + wkb.Sheets(""Sheet1"").Range(""A1"") = ""Foo"" +End Sub"; + Assert.AreEqual(0, ArrangeParserAndGetResults(inputCode).Count()); + } + + [Test] + [Ignore("Ref #4329")] + [Category("Inspections")] + public void SheetAccessedUsingString_DoesNotReturnResult_AccessingUsingWorkbookProperty() + { + const string inputCode = + @" +Public Property Get MyWorkbook() As Excel.Workbook + Set MyWorkbook = Workbooks(""Foo"") +End Property + +Public Sub Foo() + MyWorkbook.Worksheets(""Sheet1"").Range(""A1"") = ""Foo"" + MyWorkbook.Sheets(""Sheet1"").Range(""A1"") = ""Foo"" +End Sub"; + Assert.AreEqual(0, ArrangeParserAndGetResults(inputCode).Count()); + } + + [Test] + [Ignore("Ref #4329")] + [Category("Inspections")] + public void SheetAccessedUsingString_DoesNotReturnResult_AccessingUsingWithBlockVariable() + { + const string inputCode = + @"Public Sub Foo() + With Workbooks(""Foo"") + .Worksheets(""Sheet1"").Range(""A1"") = ""Foo"" + .Sheets(""Sheet1"").Range(""A1"") = ""Foo"" + End With +End Sub"; + Assert.AreEqual(0, ArrangeParserAndGetResults(inputCode).Count()); + } + [Test] [Category("Inspections")] public void SheetAccessedUsingString_DoesNotReturnResult_NoSheetWithGivenNameExists() From 3ebe7c21036fbd1a4830c28a6bd5baecf5774693 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sat, 11 Jan 2020 18:48:09 +0100 Subject: [PATCH 135/461] Pass along result properties to the ResultDescription method of the identifier reference inspection base classes Also moves further inspections to the base classes. --- ...ReferenceInspectionFromDeclarationsBase.cs | 10 +-- .../IdentifierReferenceInspectionBase.cs | 4 +- ...ReferenceInspectionFromDeclarationsBase.cs | 27 ++++--- .../Abstract/IsMissingInspectionBase.cs | 6 +- ...berAccessMayReturnNothingInspectionBase.cs | 2 +- ...entWithIncompatibleObjectTypeInspection.cs | 69 +++++++---------- .../Concrete/AssignmentNotUsedInspection.cs | 2 +- .../DefaultMemberRequiredInspection.cs | 2 +- .../ApplicationWorksheetFunctionInspection.cs | 2 +- .../ImplicitActiveSheetReferenceInspection.cs | 2 +- .../SheetAccessedUsingStringInspection.cs | 14 +++- .../ImplicitDefaultMemberAccessInspection.cs | 2 +- ...tRecursiveDefaultMemberAccessInspection.cs | 2 +- ...citUnboundDefaultMemberAccessInspection.cs | 2 +- .../IndexedDefaultMemberAccessInspection.cs | 2 +- ...dRecursiveDefaultMemberAccessInspection.cs | 2 +- ...xedUnboundDefaultMemberAccessInspection.cs | 2 +- ...issingOnInappropriateArgumentInspection.cs | 2 +- ...ssingWithNonArgumentParameterInspection.cs | 2 +- .../ObjectVariableNotSetInspection.cs | 2 +- ...bjectWhereProcedureIsRequiredInspection.cs | 15 ++-- .../Concrete/ObsoleteMemberUsageInspection.cs | 2 +- .../Concrete/ProcedureRequiredInspection.cs | 2 +- ...entWithIncompatibleObjectTypeInspection.cs | 74 ++++++++----------- .../Concrete/UseOfBangNotationInspection.cs | 2 +- .../UseOfRecursiveBangNotationInspection.cs | 2 +- .../UseOfUnboundBangNotationInspection.cs | 2 +- .../Concrete/ValueRequiredInspection.cs | 2 +- .../Abstract/IParseTreeInspection.cs | 3 +- .../Inspections/InspectionTestsBase.cs | 3 +- ...SheetAccessedUsingStringInspectionTests.cs | 15 +++- .../AccessSheetUsingCodeNameQuickFixTests.cs | 24 +++--- 32 files changed, 149 insertions(+), 155 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/ArgumentReferenceInspectionFromDeclarationsBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/ArgumentReferenceInspectionFromDeclarationsBase.cs index 0e8b981748..fb1d6e76d0 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/ArgumentReferenceInspectionFromDeclarationsBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/ArgumentReferenceInspectionFromDeclarationsBase.cs @@ -19,15 +19,11 @@ protected virtual (bool isResult, object properties) IsUnsuitableArgumentWithAdd return (IsUnsuitableArgument(reference, finder), null); } - protected override IEnumerable<(IdentifierReference reference, object properties)> ObjectionableReferences(DeclarationFinder finder) + protected override IEnumerable ObjectionableReferences(DeclarationFinder finder) { return ObjectionableDeclarations(finder) - .OfType() - .SelectMany(declaration => declaration.Parameters) - .SelectMany(parameter => parameter.ArgumentReferences) - .Select(reference => (reference, IsResultReferenceWithAdditionalProperties(reference, finder))) - .Where(tpl => tpl.Item2.isResult) - .Select(tpl => ((IdentifierReference) tpl.reference, tpl.Item2.properties)); ; + .OfType() + .SelectMany(parameter => parameter.ArgumentReferences); } protected override (bool isResult, object properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs index 5ca69539ec..ed795a998a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs @@ -16,7 +16,7 @@ public IdentifierReferenceInspectionBase(RubberduckParserState state) {} protected abstract bool IsResultReference(IdentifierReference reference, DeclarationFinder finder); - protected abstract string ResultDescription(IdentifierReference reference); + protected abstract string ResultDescription(IdentifierReference reference, dynamic properties = null); protected virtual (bool isResult, object properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder) { @@ -69,7 +69,7 @@ protected virtual IInspectionResult InspectionResult(IdentifierReference referen { return new IdentifierReferenceInspectionResult( this, - ResultDescription(reference), + ResultDescription(reference, properties), declarationFinderProvider, reference, properties); diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs index 8ad64f1eab..d450ca8035 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs @@ -16,27 +16,33 @@ protected IdentifierReferenceInspectionFromDeclarationsBase(RubberduckParserStat {} protected abstract IEnumerable ObjectionableDeclarations(DeclarationFinder finder); - protected abstract string ResultDescription(IdentifierReference reference); + protected abstract string ResultDescription(IdentifierReference reference, dynamic properties = null); protected override IEnumerable DoGetInspectionResults() { var finder = DeclarationFinderProvider.DeclarationFinder; var objectionableReferences = ObjectionableReferences(finder); - return objectionableReferences + var resultReferences = ResultReferences(objectionableReferences, finder); + return resultReferences .Select(tpl => InspectionResult(tpl.reference, DeclarationFinderProvider, tpl.properties)) .ToList(); } - protected virtual IEnumerable<(IdentifierReference reference, object properties)> ObjectionableReferences(DeclarationFinder finder) + private IEnumerable<(IdentifierReference reference, object properties)> ResultReferences(IEnumerable potentialResultReferences, DeclarationFinder finder) { - var objectionableDeclarations = ObjectionableDeclarations(finder); - return objectionableDeclarations - .SelectMany(declaration => declaration.References) + return potentialResultReferences .Select(reference => (reference, IsResultReferenceWithAdditionalProperties(reference, finder))) .Where(tpl => tpl.Item2.isResult) .Select(tpl => (tpl.reference, tpl.Item2.properties)); } + protected virtual IEnumerable ObjectionableReferences(DeclarationFinder finder) + { + var objectionableDeclarations = ObjectionableDeclarations(finder); + return objectionableDeclarations + .SelectMany(declaration => declaration.References); + } + protected virtual bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) => true; protected virtual (bool isResult, object properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder) @@ -47,9 +53,10 @@ protected virtual (bool isResult, object properties) IsResultReferenceWithAdditi protected IEnumerable DoGetInspectionResults(QualifiedModuleName module) { var finder = DeclarationFinderProvider.DeclarationFinder; - var objectionableReferences = ObjectionableReferences(finder); - return objectionableReferences - .Where(tpl => tpl.reference.QualifiedModuleName.Equals(module)) + var objectionableReferences = ObjectionableReferences(finder) + .Where(reference => reference.QualifiedModuleName.Equals(module)); + var resultReferences = ResultReferences(objectionableReferences, finder); + return resultReferences .Select(tpl => InspectionResult(tpl.reference, DeclarationFinderProvider, tpl.properties)) .ToList(); } @@ -58,7 +65,7 @@ protected virtual IInspectionResult InspectionResult(IdentifierReference referen { return new IdentifierReferenceInspectionResult( this, - ResultDescription(reference), + ResultDescription(reference, properties), declarationFinderProvider, reference, properties); diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs index 9bdf00fc3f..1a9b1f4290 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs @@ -48,9 +48,11 @@ protected IReadOnlyList IsMissingDeclarations(DeclarationFinder fin var isMissing = informationModules .SelectMany(module => module.Members) .Where(decl => IsMissingQualifiedNames.Contains(decl.QualifiedName.ToString())) - .ToList(); + .OfType(); - return isMissing; + return isMissing + .SelectMany(declaration => declaration.Parameters) + .ToList(); } protected ParameterDeclaration ParameterForReference(ArgumentReference reference, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/MemberAccessMayReturnNothingInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/MemberAccessMayReturnNothingInspectionBase.cs index 0a197ad7ed..6365866923 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/MemberAccessMayReturnNothingInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/MemberAccessMayReturnNothingInspectionBase.cs @@ -100,7 +100,7 @@ private static IEnumerable GetReferenceNodes(INode node) } } - protected override string ResultDescription(IdentifierReference reference) + protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) { var semiQualifiedName = $"{reference.Declaration.ParentDeclaration.IdentifierName}.{reference.IdentifierName}"; return string.Format(ResultTemplate, semiQualifiedName); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs index da70c8076d..202c3cc876 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Linq; using Rubberduck.Inspections.Abstract; +using Rubberduck.Inspections.Inspections.Abstract; using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Grammar; @@ -77,53 +78,47 @@ namespace Rubberduck.CodeAnalysis.Inspections.Concrete /// End Sub /// ]]> /// - public class ArgumentWithIncompatibleObjectTypeInspection : InspectionBase + public class ArgumentWithIncompatibleObjectTypeInspection : ArgumentReferenceInspectionFromDeclarationsBase { - private readonly IDeclarationFinderProvider _declarationFinderProvider; private readonly ISetTypeResolver _setTypeResolver; public ArgumentWithIncompatibleObjectTypeInspection(RubberduckParserState state, ISetTypeResolver setTypeResolver) : base(state) { - _declarationFinderProvider = state; _setTypeResolver = setTypeResolver; //This will most likely cause a runtime error. The exceptions are rare and should be refactored or made explicit with an @Ignore annotation. Severity = CodeInspectionSeverity.Error; } - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable ObjectionableDeclarations(DeclarationFinder finder) { - var finder = _declarationFinderProvider.DeclarationFinder; - - var strictlyTypedObjectParameters = finder.DeclarationsWithType(DeclarationType.Parameter) - .Where(ToBeConsidered) - .OfType(); - - var offendingArguments = strictlyTypedObjectParameters - .SelectMany(param => param.ArgumentReferences) - .Select(argumentReference => ArgumentReferenceWithArgumentTypeName(argumentReference, finder)) - .Where(argumentReferenceWithTypeName => argumentReferenceWithTypeName.argumentTypeName != null - && !ArgumentPossiblyLegal( - argumentReferenceWithTypeName.argumentReference.Declaration, - argumentReferenceWithTypeName.argumentTypeName)); - - return offendingArguments - // Ignoring the Declaration disqualifies all assignments - .Where(argumentReferenceWithTypeName => !argumentReferenceWithTypeName.Item1.Declaration.IsIgnoringInspectionResultFor(AnnotationName)) - .Select(argumentReference => InspectionResult(argumentReference, _declarationFinderProvider)); + return finder.DeclarationsWithType(DeclarationType.Parameter) + .Where(ToBeConsidered); } private static bool ToBeConsidered(Declaration declaration) { - return declaration != null - && declaration.AsTypeDeclaration != null + return declaration?.AsTypeDeclaration != null && declaration.IsObject; } - private (IdentifierReference argumentReference, string argumentTypeName) ArgumentReferenceWithArgumentTypeName(IdentifierReference argumentReference, DeclarationFinder finder) + protected override (bool isResult, object properties) IsUnsuitableArgumentWithAdditionalProperties(ArgumentReference reference, DeclarationFinder finder) { - return (argumentReference, ArgumentSetTypeName(argumentReference, finder)); + var argumentSetTypeName = ArgumentSetTypeName(reference, finder); + + if (argumentSetTypeName == null || ArgumentPossiblyLegal(reference.Declaration, argumentSetTypeName)) + { + return (false, null); + } + + return (true, argumentSetTypeName); + } + + protected override bool IsUnsuitableArgument(ArgumentReference reference, DeclarationFinder finder) + { + //No need to implement this since we overwrite IsUnsuitableArgumentWithAdditionalProperties. + throw new System.NotImplementedException(); } private string ArgumentSetTypeName(IdentifierReference argumentReference, DeclarationFinder finder) @@ -146,7 +141,7 @@ private bool ArgumentPossiblyLegal(Declaration parameterDeclaration , string ass || HasSubType(parameterDeclaration, assignedTypeName); } - private bool HasBaseType(Declaration declaration, string typeName) + private static bool HasBaseType(Declaration declaration, string typeName) { var ownType = declaration.AsTypeDeclaration; if (ownType == null || !(ownType is ClassModuleDeclaration classType)) @@ -157,7 +152,7 @@ private bool HasBaseType(Declaration declaration, string typeName) return classType.Subtypes.Select(subtype => subtype.QualifiedModuleName.ToString()).Contains(typeName); } - private bool HasSubType(Declaration declaration, string typeName) + private static bool HasSubType(Declaration declaration, string typeName) { var ownType = declaration.AsTypeDeclaration; if (ownType == null || !(ownType is ClassModuleDeclaration classType)) @@ -168,20 +163,12 @@ private bool HasSubType(Declaration declaration, string typeName) return classType.Supertypes.Select(supertype => supertype.QualifiedModuleName.ToString()).Contains(typeName); } - private IInspectionResult InspectionResult((IdentifierReference argumentReference, string argumentTypeName) argumentReferenceWithTypeName, IDeclarationFinderProvider declarationFinderProvider) - { - var (argumentReference, argumentTypeName) = argumentReferenceWithTypeName; - return new IdentifierReferenceInspectionResult(this, - ResultDescription(argumentReference, argumentTypeName), - declarationFinderProvider, - argumentReference); - } - - private string ResultDescription(IdentifierReference argumentReference, string argumentTypeName) + protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) { - var parameterName = argumentReference.Declaration.IdentifierName; - var parameterTypeName = argumentReference.Declaration.FullAsTypeName; - var argumentExpression = argumentReference.Context.GetText(); + var parameterName = reference.Declaration.IdentifierName; + var parameterTypeName = reference.Declaration.FullAsTypeName; + var argumentExpression = reference.Context.GetText(); + var argumentTypeName = (string)properties; return string.Format(InspectionResults.SetAssignmentWithIncompatibleObjectTypeInspection, parameterName, parameterTypeName, argumentExpression, argumentTypeName); } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs index 1dd6c8312b..06c3c0e7d3 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs @@ -105,7 +105,7 @@ private static bool IsAssignmentOfNothing(IdentifierReference reference) && setStmtContext.expression().GetText().Equals(Tokens.Nothing); } - protected override string ResultDescription(IdentifierReference reference) + protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) { return Description; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs index 64bfe5c634..bca0d6ece6 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs @@ -73,7 +73,7 @@ protected override bool IsResultReference(IdentifierReference failedIndexedDefau return true; } - protected override string ResultDescription(IdentifierReference failedIndexedDefaultMemberAccess) + protected override string ResultDescription(IdentifierReference failedIndexedDefaultMemberAccess, dynamic properties = null) { var expression = failedIndexedDefaultMemberAccess.IdentifierName; var typeName = failedIndexedDefaultMemberAccess.Declaration?.FullAsTypeName; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs index b8bea5cb81..7cfc5223f9 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs @@ -88,7 +88,7 @@ protected override IEnumerable ObjectionableDeclarations(Declaratio .Where(decl => worksheetFunctionNames.Contains(decl.IdentifierName)); } - protected override string ResultDescription(IdentifierReference reference) + protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) { return string.Format(InspectionResults.ApplicationWorksheetFunctionInspection, reference.IdentifierName); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs index 7018921528..65a78b61f4 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs @@ -75,7 +75,7 @@ protected override IEnumerable ObjectionableDeclarations(Declaratio "Cells", "Range", "Columns", "Rows" }; - protected override string ResultDescription(IdentifierReference reference) + protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) { return string.Format( InspectionResults.ImplicitActiveSheetReferenceInspection, diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs index bed1115c65..be7dbfd40b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs @@ -10,6 +10,7 @@ using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.VBEditor.ComManagement; namespace Rubberduck.Inspections.Concrete { @@ -49,8 +50,13 @@ public class SheetAccessedUsingStringInspection : IdentifierReferenceInspectionF //TODO: revisit this and its tests after clarification of intended behaviour. //This relates to the handling of implicit references to ActiveWorkbook. - public SheetAccessedUsingStringInspection(RubberduckParserState state) - : base(state) { } + private readonly IProjectsProvider _projectsProvider; + + public SheetAccessedUsingStringInspection(RubberduckParserState state, IProjectsProvider projectsProvider) + : base(state) + { + _projectsProvider = projectsProvider; + } private static readonly string[] InterestingMembers = { @@ -123,7 +129,7 @@ private static VBAParser.LiteralExpressionContext SheetNameArgumentLiteralExpres private string CodeNameOfVBComponentMatchingSheetName(string projectId, string sheetName) { - var components = State.ProjectsProvider.Components(projectId); + var components = _projectsProvider.Components(projectId); foreach (var (module, component) in components) { @@ -161,7 +167,7 @@ private static string ComponentPropertyValue(IVBComponent component, string prop return null; } - protected override string ResultDescription(IdentifierReference reference) + protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) { return InspectionResults.SheetAccessedUsingStringInspection; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs index 4eb9538eb4..690a6fc2a6 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs @@ -64,7 +64,7 @@ protected override bool IsResultReference(IdentifierReference reference, Declara && !reference.IsIgnoringInspectionResultFor(AnnotationName); } - protected override string ResultDescription(IdentifierReference reference) + protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) { var expression = reference.IdentifierName; var defaultMember = reference.Declaration.QualifiedName.ToString(); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs index f2dae91a23..df4fbecbb9 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs @@ -84,7 +84,7 @@ protected override bool IsResultReference(IdentifierReference reference, Declara && !reference.IsIgnoringInspectionResultFor(AnnotationName); } - protected override string ResultDescription(IdentifierReference reference) + protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) { var expression = reference.IdentifierName; var defaultMember = reference.Declaration.QualifiedName.ToString(); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs index 230f79ae34..92df7f3220 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs @@ -71,7 +71,7 @@ protected override bool IsResultReference(IdentifierReference reference, Declara && !reference.IsIgnoringInspectionResultFor(AnnotationName); } - protected override string ResultDescription(IdentifierReference reference) + protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) { var expression = reference.IdentifierName; return string.Format(InspectionResults.ImplicitUnboundDefaultMemberAccessInspection, expression); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs index 66adec3eb6..6218ee64fa 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs @@ -47,7 +47,7 @@ protected override bool IsResultReference(IdentifierReference reference, Declara && !reference.IsIgnoringInspectionResultFor(AnnotationName); } - protected override string ResultDescription(IdentifierReference reference) + protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) { var expression = reference.IdentifierName; var defaultMember = reference.Declaration.QualifiedName.ToString(); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs index f37bb2305e..37244bec0a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs @@ -47,7 +47,7 @@ protected override bool IsResultReference(IdentifierReference reference, Declara && !reference.IsIgnoringInspectionResultFor(AnnotationName); } - protected override string ResultDescription(IdentifierReference reference) + protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) { var expression = reference.IdentifierName; var defaultMember = reference.Declaration.QualifiedName.ToString(); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs index 5fabddaf34..8f32c92d90 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs @@ -54,7 +54,7 @@ protected override bool IsResultReference(IdentifierReference reference, Declara && !reference.IsIgnoringInspectionResultFor(AnnotationName); } - protected override string ResultDescription(IdentifierReference reference) + protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) { var expression = reference.IdentifierName; return string.Format(InspectionResults.IndexedUnboundDefaultMemberAccessInspection, expression); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs index eb0ddd336d..625e474ed4 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs @@ -58,7 +58,7 @@ protected override bool IsUnsuitableArgument(ArgumentReference reference, Declar throw new System.NotImplementedException(); } - protected override string ResultDescription(IdentifierReference reference) + protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) { return InspectionResults.IsMissingOnInappropriateArgumentInspection; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs index 99dfeca2ef..d66455ace9 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs @@ -42,7 +42,7 @@ protected override bool IsUnsuitableArgument(ArgumentReference reference, Declar return parameter == null; } - protected override string ResultDescription(IdentifierReference reference) + protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) { return InspectionResults.IsMissingWithNonArgumentParameterInspection; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs index d8d811ea60..8c133debd9 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs @@ -98,7 +98,7 @@ protected override bool IsResultReference(IdentifierReference reference, Declara return true; } - protected override string ResultDescription(IdentifierReference reference) + protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) { return string.Format(InspectionResults.ObjectVariableNotSetInspection, reference.IdentifierName); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs index f39bd4d386..07ce23c3f0 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs @@ -55,12 +55,9 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ObjectWhereProcedureIsRequiredInspection : InspectionBase { - private readonly IDeclarationFinderProvider _declarationFinderProvider; - public ObjectWhereProcedureIsRequiredInspection(RubberduckParserState state) : base(state) { - _declarationFinderProvider = state; Severity = CodeInspectionSeverity.Warning; } @@ -83,7 +80,7 @@ protected override IEnumerable DoGetInspectionResults() private IEnumerable DoGetInspectionResults(QualifiedModuleName module) { - var finder = _declarationFinderProvider.DeclarationFinder; + var finder = DeclarationFinderProvider.DeclarationFinder; return BoundInspectionResults(module, finder) .Concat(UnboundInspectionResults(module, finder)); } @@ -95,11 +92,11 @@ private IEnumerable BoundInspectionResults(QualifiedModuleNam .Where(IsResultReference); return objectionableReferences - .Select(reference => BoundInspectionResult(reference, _declarationFinderProvider)) + .Select(reference => BoundInspectionResult(reference, DeclarationFinderProvider)) .ToList(); } - private bool IsResultReference(IdentifierReference reference) + private static bool IsResultReference(IdentifierReference reference) { return reference.IsProcedureCoercion; } @@ -113,7 +110,7 @@ private IInspectionResult BoundInspectionResult(IdentifierReference reference, I reference); } - private string BoundResultDescription(IdentifierReference reference) + private static string BoundResultDescription(IdentifierReference reference) { var expression = reference.IdentifierName; var defaultMember = reference.Declaration.QualifiedName.ToString(); @@ -127,7 +124,7 @@ private IEnumerable UnboundInspectionResults(QualifiedModuleN .Where(IsResultReference); return objectionableReferences - .Select(reference => UnboundInspectionResult(reference, _declarationFinderProvider)) + .Select(reference => UnboundInspectionResult(reference, DeclarationFinderProvider)) .ToList(); } @@ -142,7 +139,7 @@ private IInspectionResult UnboundInspectionResult(IdentifierReference reference, return result; } - private string UnboundResultDescription(IdentifierReference reference) + private static string UnboundResultDescription(IdentifierReference reference) { var expression = reference.IdentifierName; return string.Format(InspectionResults.ObjectWhereProcedureIsRequiredInspection_Unbound, expression); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs index 15881ffd29..b358ed5d2a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs @@ -64,7 +64,7 @@ protected override bool IsResultReference(IdentifierReference reference, Declara && declaration.Annotations.Any(pta => pta.Annotation is ObsoleteAnnotation); } - protected override string ResultDescription(IdentifierReference reference) + protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) { var replacementDocumentation = reference.Declaration.Annotations .First(pta => pta.Annotation is ObsoleteAnnotation) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs index a1d0f811b3..007e933d29 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs @@ -72,7 +72,7 @@ protected override bool IsResultReference(IdentifierReference failedCoercion, De return true; } - protected override string ResultDescription(IdentifierReference failedCoercion) + protected override string ResultDescription(IdentifierReference failedCoercion, dynamic properties = null) { var expression = failedCoercion.IdentifierName; var typeName = failedCoercion.Declaration?.FullAsTypeName; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs index e12dda932d..eee1ac8e6b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs @@ -1,12 +1,8 @@ -using System.Collections.Generic; -using System.Linq; +using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.TypeResolvers; using Rubberduck.Parsing.VBA; @@ -76,50 +72,57 @@ namespace Rubberduck.CodeAnalysis.Inspections.Concrete /// End Sub /// ]]> /// - public class SetAssignmentWithIncompatibleObjectTypeInspection : InspectionBase + public class SetAssignmentWithIncompatibleObjectTypeInspection : IdentifierReferenceInspectionBase { - private readonly IDeclarationFinderProvider _declarationFinderProvider; private readonly ISetTypeResolver _setTypeResolver; public SetAssignmentWithIncompatibleObjectTypeInspection(RubberduckParserState state, ISetTypeResolver setTypeResolver) : base(state) { - _declarationFinderProvider = state; _setTypeResolver = setTypeResolver; //This will most likely cause a runtime error. The exceptions are rare and should be refactored or made explicit with an @Ignore annotation. Severity = CodeInspectionSeverity.Error; } - protected override IEnumerable DoGetInspectionResults() + protected override (bool isResult, object properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder) { - var finder = _declarationFinderProvider.DeclarationFinder; + if (!ToBeConsidered(reference)) + { + return (false, null); + } - var setAssignments = finder.AllIdentifierReferences().Where(reference => reference.IsSetAssignment); + var assignedTypeName = AssignedTypeName(reference, finder); + + if(assignedTypeName == null || SetAssignmentPossiblyLegal(reference.Declaration, assignedTypeName)) + { + return (false, null); + } - var offendingAssignments = setAssignments - .Where(ToBeConsidered) - .Select(setAssignment => SetAssignmentWithAssignedTypeName(setAssignment, finder)) - .Where(setAssignmentWithAssignedTypeName => setAssignmentWithAssignedTypeName.assignedTypeName != null - && !SetAssignmentPossiblyLegal(setAssignmentWithAssignedTypeName)); + return (true, assignedTypeName); + } - return offendingAssignments - // Ignoring the Declaration disqualifies all assignments - .Where(setAssignmentWithAssignedTypeName => !setAssignmentWithAssignedTypeName.setAssignment.Declaration.IsIgnoringInspectionResultFor(AnnotationName)) - .Select(setAssignmentWithAssignedTypeName => InspectionResult(setAssignmentWithAssignedTypeName, _declarationFinderProvider)); + protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) + { + //No need to implement this since we override IsResultReferenceWithAdditionalProperties. + throw new System.NotImplementedException(); } private static bool ToBeConsidered(IdentifierReference reference) { + if (reference == null || !reference.IsSetAssignment) + { + return false; + } + var declaration = reference.Declaration; - return declaration != null - && declaration.AsTypeDeclaration != null + return declaration?.AsTypeDeclaration != null && declaration.IsObject; } - private (IdentifierReference setAssignment, string assignedTypeName) SetAssignmentWithAssignedTypeName(IdentifierReference setAssignment, DeclarationFinder finder) + private string AssignedTypeName(IdentifierReference setAssignment, DeclarationFinder finder) { - return (setAssignment, SetTypeNameOfExpression(RHS(setAssignment), setAssignment.QualifiedModuleName, finder)); + return SetTypeNameOfExpression(RHS(setAssignment), setAssignment.QualifiedModuleName, finder); } private VBAParser.ExpressionContext RHS(IdentifierReference setAssignment) @@ -131,13 +134,6 @@ private string SetTypeNameOfExpression(VBAParser.ExpressionContext expression, Q { return _setTypeResolver.SetTypeName(expression, containingModule); } - - private bool SetAssignmentPossiblyLegal((IdentifierReference setAssignment, string assignedTypeName) setAssignmentWithAssignedType) - { - var (setAssignment, assignedTypeName) = setAssignmentWithAssignedType; - - return SetAssignmentPossiblyLegal(setAssignment.Declaration, assignedTypeName); - } private bool SetAssignmentPossiblyLegal(Declaration declaration, string assignedTypeName) { @@ -170,19 +166,11 @@ private bool HasSubType(Declaration declaration, string typeName) return classType.Supertypes.Select(supertype => supertype.QualifiedModuleName.ToString()).Contains(typeName); } - private IInspectionResult InspectionResult((IdentifierReference setAssignment, string assignedTypeName) setAssignmentWithAssignedType, IDeclarationFinderProvider declarationFinderProvider) - { - var (setAssignment, assignedTypeName) = setAssignmentWithAssignedType; - return new IdentifierReferenceInspectionResult(this, - ResultDescription(setAssignment, assignedTypeName), - declarationFinderProvider, - setAssignment); - } - - private string ResultDescription(IdentifierReference setAssignment, string assignedTypeName) + protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) { - var declarationName = setAssignment.Declaration.IdentifierName; - var variableTypeName = setAssignment.Declaration.FullAsTypeName; + var declarationName = reference.Declaration.IdentifierName; + var variableTypeName = reference.Declaration.FullAsTypeName; + var assignedTypeName = (string)properties; return string.Format(InspectionResults.SetAssignmentWithIncompatibleObjectTypeInspection, declarationName, variableTypeName, assignedTypeName); } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfBangNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfBangNotationInspection.cs index 998e3a5ca4..7ce54dcf80 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfBangNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfBangNotationInspection.cs @@ -69,7 +69,7 @@ protected override bool IsResultReference(IdentifierReference reference, Declara && reference.Context is VBAParser.DictionaryAccessContext; } - protected override string ResultDescription(IdentifierReference reference) + protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) { var expression = reference.IdentifierName; return string.Format(InspectionResults.UseOfBangNotationInspection, expression); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs index a33860da11..091cffd053 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs @@ -77,7 +77,7 @@ protected override bool IsResultReference(IdentifierReference reference, Declara && reference.Context is VBAParser.DictionaryAccessContext; } - protected override string ResultDescription(IdentifierReference reference) + protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) { var expression = reference.IdentifierName; return string.Format(InspectionResults.UseOfRecursiveBangNotationInspection, expression); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs index a568cdfd40..b415224753 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs @@ -76,7 +76,7 @@ protected override bool IsResultReference(IdentifierReference reference, Declara && reference.Context is VBAParser.DictionaryAccessContext; } - protected override string ResultDescription(IdentifierReference reference) + protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) { var expression = reference.IdentifierName; return string.Format(InspectionResults.UseOfRecursiveBangNotationInspection, expression); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs index 7334e1cebf..5e29e43b76 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs @@ -75,7 +75,7 @@ protected override bool IsResultReference(IdentifierReference failedLetCoercion, return !failedLetCoercion.IsAssignment; } - protected override string ResultDescription(IdentifierReference failedLetCoercion) + protected override string ResultDescription(IdentifierReference failedLetCoercion, dynamic properties = null) { var expression = failedLetCoercion.IdentifierName; var typeName = failedLetCoercion.Declaration?.FullAsTypeName; diff --git a/Rubberduck.Parsing/Inspections/Abstract/IParseTreeInspection.cs b/Rubberduck.Parsing/Inspections/Abstract/IParseTreeInspection.cs index cc0a90953d..8aa530a0d2 100644 --- a/Rubberduck.Parsing/Inspections/Abstract/IParseTreeInspection.cs +++ b/Rubberduck.Parsing/Inspections/Abstract/IParseTreeInspection.cs @@ -1,5 +1,4 @@ -using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.VBA.Parsing; +using Rubberduck.Parsing.VBA.Parsing; namespace Rubberduck.Parsing.Inspections.Abstract { diff --git a/RubberduckTests/Inspections/InspectionTestsBase.cs b/RubberduckTests/Inspections/InspectionTestsBase.cs index 01868515fc..32b70660d9 100644 --- a/RubberduckTests/Inspections/InspectionTestsBase.cs +++ b/RubberduckTests/Inspections/InspectionTestsBase.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; diff --git a/RubberduckTests/Inspections/SheetAccessedUsingStringInspectionTests.cs b/RubberduckTests/Inspections/SheetAccessedUsingStringInspectionTests.cs index 918901a1a2..6250c5ac1f 100644 --- a/RubberduckTests/Inspections/SheetAccessedUsingStringInspectionTests.cs +++ b/RubberduckTests/Inspections/SheetAccessedUsingStringInspectionTests.cs @@ -53,6 +53,19 @@ public void SheetAccessedUsingString_ReturnsResult_AccessingUsingGlobalModule() Assert.AreEqual(2, ArrangeParserAndGetResults(inputCode).Count()); } + [Test] + [Ignore("Ref #4329")] + [Category("Inspections")] + public void SheetAccessedUsingString_DoesNotReturnResult_AccessingUsingActiveWorkbookProperty() + { + const string inputCode = + @"Public Sub Foo() + ActiveWorkbook.Worksheets(""Sheet1"").Range(""A1"") = ""Foo"" + ActiveWorkbook.Sheets(""Sheet1"").Range(""A1"") = ""Foo"" +End Sub"; + Assert.AreEqual(0, ArrangeParserAndGetResults(inputCode).Count()); + } + [Test] [Ignore("Ref #4329")] [Category("Inspections")] @@ -199,7 +212,7 @@ private static Mock CreateVBComponentPropertyMock(string propertyName protected override IInspection InspectionUnderTest(RubberduckParserState state) { - return new SheetAccessedUsingStringInspection(state); + return new SheetAccessedUsingStringInspection(state, state.ProjectsProvider); } } } diff --git a/RubberduckTests/QuickFixes/AccessSheetUsingCodeNameQuickFixTests.cs b/RubberduckTests/QuickFixes/AccessSheetUsingCodeNameQuickFixTests.cs index 2168bee3cf..859b31c38d 100644 --- a/RubberduckTests/QuickFixes/AccessSheetUsingCodeNameQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/AccessSheetUsingCodeNameQuickFixTests.cs @@ -27,7 +27,7 @@ Public Sub Foo() Sheet1.Range(""A1"") = ""foo"" End Sub"; - var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new SheetAccessedUsingStringInspection(state)); + var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new SheetAccessedUsingStringInspection(state, state.ProjectsProvider)); Assert.AreEqual(expectedCode, actualCode); } @@ -45,7 +45,7 @@ Public Sub Foo() Sheet1.Range(""A1"") = ""foo"" End Sub"; - var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new SheetAccessedUsingStringInspection(state)); + var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new SheetAccessedUsingStringInspection(state, state.ProjectsProvider)); Assert.AreEqual(expectedCode, actualCode); } @@ -63,7 +63,7 @@ Public Sub Foo() Sheet1.Range(""A1"") = ""foo"" End Sub"; - var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new SheetAccessedUsingStringInspection(state)); + var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new SheetAccessedUsingStringInspection(state, state.ProjectsProvider)); Assert.AreEqual(expectedCode, actualCode); } @@ -93,7 +93,7 @@ End Sub Public Sub Bar(ws As Worksheet) End Sub"; - var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new SheetAccessedUsingStringInspection(state)); + var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new SheetAccessedUsingStringInspection(state, state.ProjectsProvider)); Assert.AreEqual(expectedCode, actualCode); } @@ -113,7 +113,7 @@ Public Sub Foo() End Sub"; - var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new SheetAccessedUsingStringInspection(state)); + var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new SheetAccessedUsingStringInspection(state, state.ProjectsProvider)); Assert.AreEqual(expectedCode, actualCode); } @@ -135,7 +135,7 @@ Dim s As String Sheet1.Cells(1, 1) = ""foo"" End Sub"; - var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new SheetAccessedUsingStringInspection(state)); + var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new SheetAccessedUsingStringInspection(state, state.ProjectsProvider)); Assert.AreEqual(expectedCode, actualCode); } @@ -157,7 +157,7 @@ Dim s As String Sheet1.Cells(1, 1) = ""foo"" End Sub"; - var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new SheetAccessedUsingStringInspection(state)); + var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new SheetAccessedUsingStringInspection(state, state.ProjectsProvider)); Assert.AreEqual(expectedCode, actualCode); } @@ -187,7 +187,7 @@ Public Sub ws() Dim ws As Worksheet End Sub"; - var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new SheetAccessedUsingStringInspection(state)); + var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new SheetAccessedUsingStringInspection(state, state.ProjectsProvider)); Assert.AreEqual(expectedCode, actualCode); } @@ -217,7 +217,7 @@ Public Sub ws() Dim ws As Worksheet End Sub"; - var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new SheetAccessedUsingStringInspection(state)); + var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new SheetAccessedUsingStringInspection(state, state.ProjectsProvider)); Assert.AreEqual(expectedCode, actualCode); } @@ -239,7 +239,7 @@ Dim ws As Worksheet Debug.Print ws.Name End Sub"; - var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new SheetAccessedUsingStringInspection(state)); + var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new SheetAccessedUsingStringInspection(state, state.ProjectsProvider)); Assert.AreEqual(expectedCode, actualCode); } @@ -261,7 +261,7 @@ If Not Worksheets.Add(Sheet1) Is Nothing Then End If End Sub"; - var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new SheetAccessedUsingStringInspection(state)); + var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new SheetAccessedUsingStringInspection(state, state.ProjectsProvider)); Assert.AreEqual(expectedCode, actualCode); } @@ -281,7 +281,7 @@ Sub Test() Sheet1.Name = ""Foo"" End Sub"; - var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new SheetAccessedUsingStringInspection(state)); + var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new SheetAccessedUsingStringInspection(state, state.ProjectsProvider)); Assert.AreEqual(expectedCode, actualCode); } From c4c35f6aecb9d6211401654bb39611ca732dcb3f Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sat, 11 Jan 2020 19:17:29 +0100 Subject: [PATCH 136/461] Make constructor of IdentifierReference internal --- .../Inspections/Concrete/BooleanAssignedInIfElseInspection.cs | 1 - Rubberduck.Parsing/Symbols/ArgumentReference.cs | 2 +- Rubberduck.Parsing/Symbols/IdentifierReference.cs | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs index d3614c0116..7f6b2c93c7 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs @@ -9,7 +9,6 @@ using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor; -using Rubberduck.Inspections.Inspections.Extensions; namespace Rubberduck.Inspections.Concrete { diff --git a/Rubberduck.Parsing/Symbols/ArgumentReference.cs b/Rubberduck.Parsing/Symbols/ArgumentReference.cs index bb1e73e135..690b9b2585 100644 --- a/Rubberduck.Parsing/Symbols/ArgumentReference.cs +++ b/Rubberduck.Parsing/Symbols/ArgumentReference.cs @@ -9,7 +9,7 @@ namespace Rubberduck.Parsing.Symbols { public class ArgumentReference : IdentifierReference { - public ArgumentReference( + internal ArgumentReference( QualifiedModuleName qualifiedName, Declaration parentScopingDeclaration, Declaration parentNonScopingDeclaration, diff --git a/Rubberduck.Parsing/Symbols/IdentifierReference.cs b/Rubberduck.Parsing/Symbols/IdentifierReference.cs index 5613790ee3..31993145ec 100644 --- a/Rubberduck.Parsing/Symbols/IdentifierReference.cs +++ b/Rubberduck.Parsing/Symbols/IdentifierReference.cs @@ -12,7 +12,7 @@ namespace Rubberduck.Parsing.Symbols [DebuggerDisplay("({IdentifierName}) IsAss:{IsAssignment} | {Selection} ")] public class IdentifierReference : IEquatable { - public IdentifierReference( + internal IdentifierReference( QualifiedModuleName qualifiedName, Declaration parentScopingDeclaration, Declaration parentNonScopingDeclaration, From b61228039bb5a76a5081e8d9d7eaf16b25c998fe Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sun, 12 Jan 2020 00:49:00 +0100 Subject: [PATCH 137/461] Make the remaining identifier reference inspections use the base classes if apprpriate Some are left as-is because using the base classes would hurt readablity. --- ...plicitActiveWorkbookReferenceInspection.cs | 36 ++--- .../SuspiciousLetAssignmentInspection.cs | 13 +- .../UnassignedVariableUsageInspection.cs | 134 ++++++++++++------ .../UntypedFunctionUsageInspection.cs | 45 +++--- .../UnassignedVariableUsageInspectionTests.cs | 80 ++++++++++- 5 files changed, 206 insertions(+), 102 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveWorkbookReferenceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveWorkbookReferenceInspection.cs index 13b82617d9..80a775f030 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveWorkbookReferenceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveWorkbookReferenceInspection.cs @@ -1,13 +1,11 @@ using System.Collections.Generic; using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Inspections; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -38,7 +36,7 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [RequiredLibrary("Excel")] - public sealed class ImplicitActiveWorkbookReferenceInspection : InspectionBase + public sealed class ImplicitActiveWorkbookReferenceInspection : IdentifierReferenceInspectionFromDeclarationsBase { public ImplicitActiveWorkbookReferenceInspection(RubberduckParserState state) : base(state) { } @@ -53,27 +51,31 @@ public ImplicitActiveWorkbookReferenceInspection(RubberduckParserState state) "_Global", "_Application", "Global", "Application" }; - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable ObjectionableDeclarations(DeclarationFinder finder) { - var excel = State.DeclarationFinder.Projects.SingleOrDefault(item => !item.IsUserDefined && item.IdentifierName == "Excel"); + var excel = finder.Projects + .SingleOrDefault(project => project.IdentifierName == "Excel" && !project.IsUserDefined); if (excel == null) { - return Enumerable.Empty(); + return Enumerable.Empty(); } - var targetProperties = BuiltInDeclarations + var relevantClasses = InterestingClasses + .Select(className => finder.FindClassModule(className, excel, true)) + .OfType(); + + var relevantProperties = relevantClasses + .SelectMany(classDeclaration => classDeclaration.Members) .OfType() - .Where(x => InterestingMembers.Contains(x.IdentifierName) && InterestingClasses.Contains(x.ParentDeclaration?.IdentifierName)) - .ToList(); + .Where(member => InterestingMembers.Contains(member.IdentifierName)); - // only inspects references, must filter ignores manually, because default filtering doesn't work here - var members = targetProperties.SelectMany(item => - item.References.Where(reference => !reference.IsIgnoringInspectionResultFor(AnnotationName))); + return relevantProperties; + } - return members.Select(issue => new IdentifierReferenceInspectionResult(this, - string.Format(InspectionResults.ImplicitActiveWorkbookReferenceInspection, issue.Context.GetText()), - State, - issue)); + protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + { + var referenceText = reference.Context.GetText(); + return string.Format(InspectionResults.ImplicitActiveWorkbookReferenceInspection, referenceText); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs index 6464ed11c8..2a6392550c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs @@ -45,12 +45,9 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class SuspiciousLetAssignmentInspection : InspectionBase { - private readonly IDeclarationFinderProvider _declarationFinderProvider; - public SuspiciousLetAssignmentInspection(RubberduckParserState state) : base(state) { - _declarationFinderProvider = state; Severity = CodeInspectionSeverity.Warning; } @@ -73,7 +70,7 @@ protected override IEnumerable DoGetInspectionResults() private IEnumerable DoGetInspectionResults(QualifiedModuleName module) { - var finder = _declarationFinderProvider.DeclarationFinder; + var finder = DeclarationFinderProvider.DeclarationFinder; return BoundLhsInspectionResults(module, finder) .Concat(UnboundLhsInspectionResults(module, finder)); } @@ -92,7 +89,7 @@ private IEnumerable BoundLhsInspectionResults(QualifiedModule if (rhsDefaultMemberAccess != null) { - var result = InspectionResult(assignment, rhsDefaultMemberAccess, isUnbound, _declarationFinderProvider); + var result = InspectionResult(assignment, rhsDefaultMemberAccess, isUnbound); results.Add(result); } } @@ -133,12 +130,12 @@ private bool IsImplicitDefaultMemberAssignment(IdentifierReference reference) return (unboundRhsDefaultMemberAccess, true); } - private IInspectionResult InspectionResult(IdentifierReference lhsReference, IdentifierReference rhsReference, bool isUnbound, IDeclarationFinderProvider declarationFinderProvider) + private IInspectionResult InspectionResult(IdentifierReference lhsReference, IdentifierReference rhsReference, bool isUnbound) { var result = new IdentifierReferenceInspectionResult( this, ResultDescription(lhsReference, rhsReference), - declarationFinderProvider, + DeclarationFinderProvider, lhsReference); result.Properties.RhSReference = rhsReference; if (isUnbound) @@ -169,7 +166,7 @@ private IEnumerable UnboundLhsInspectionResults(QualifiedModu if (rhsDefaultMemberAccess != null) { - var result = InspectionResult(assignment, rhsDefaultMemberAccess, true, _declarationFinderProvider); + var result = InspectionResult(assignment, rhsDefaultMemberAccess, true); results.Add(result); } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs index 40537dc5c5..db42997b90 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs @@ -4,12 +4,15 @@ using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Results; +using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete { @@ -41,7 +44,7 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [SuppressMessage("ReSharper", "LoopCanBeConvertedToQuery")] - public sealed class UnassignedVariableUsageInspection : InspectionBase + public sealed class UnassignedVariableUsageInspection : IdentifierReferenceInspectionFromDeclarationsBase { public UnassignedVariableUsageInspection(RubberduckParserState state) : base(state) { } @@ -55,32 +58,97 @@ public UnassignedVariableUsageInspection(RubberduckParserState state) "VBA6.DLL;VBA.Strings.LenB" }; - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable ObjectionableDeclarations(DeclarationFinder finder) { - var declarations = State.DeclarationFinder.UserDeclarations(DeclarationType.Variable) - .Where(declaration => !declaration.IsArray && - State.DeclarationFinder.MatchName(declaration.AsTypeName) - .All(d => d.DeclarationType != DeclarationType.UserDefinedType) - && !declaration.IsSelfAssigned - && !declaration.References.Any(reference => reference.IsAssignment)); - - var excludedDeclarations = BuiltInDeclarations.Where(decl => IgnoredFunctions.Contains(decl.QualifiedName.ToString())).ToList(); - - return declarations - .Where(d => d.References.Any() && !excludedDeclarations.Any(excl => DeclarationReferencesContainsReference(excl, d))) - .SelectMany(d => d.References.Where(r => !IsAssignedByRefArgument(r.ParentScoping, r))) - .Distinct() - .Where(r => !r.Context.TryGetAncestor(out _) && !IsArraySubscriptAssignment(r)) - .Select(r => new IdentifierReferenceInspectionResult(this, - string.Format(InspectionResults.UnassignedVariableUsageInspection, r.IdentifierName), - State, - r)).ToList(); + return finder.UserDeclarations(DeclarationType.Variable) + .Where(declaration => !declaration.IsArray + && !declaration.IsSelfAssigned + && finder.MatchName(declaration.AsTypeName) + .All(d => d.DeclarationType != DeclarationType.UserDefinedType) + && !declaration.References + .Any(reference => reference.IsAssignment)); } - private bool IsAssignedByRefArgument(Declaration enclosingProcedure, IdentifierReference reference) + //We override this in order to look up the argument usage exclusion references only once. + protected override IEnumerable ObjectionableReferences(DeclarationFinder finder) + { + var excludedReferenceSelections = DeclarationsWithExcludedArgumentUsage(finder) + .SelectMany(SingleVariableArgumentSelections) + .ToHashSet(); + + return base.ObjectionableReferences(finder) + .Where(reference => !excludedReferenceSelections.Contains(reference.QualifiedSelection)); + } + + private IEnumerable DeclarationsWithExcludedArgumentUsage(DeclarationFinder finder) + { + var vbaProjects = finder.Projects + .Where(project => project.IdentifierName == "VBA" && !project.IsUserDefined) + .ToList(); + + if (!vbaProjects.Any()) + { + return new List(); + } + + var stringModules = vbaProjects + .Select(project => finder.FindStdModule("Strings", project, true)) + .OfType() + .ToList(); + + if (!stringModules.Any()) + { + return new List(); + } + + return stringModules + .SelectMany(module => module.Members) + .Where(decl => IgnoredFunctions.Contains(decl.QualifiedName.ToString())) + .OfType(); + } + + private static IEnumerable SingleVariableArgumentSelections(ModuleBodyElementDeclaration member) + { + return member.Parameters + .SelectMany(parameter => parameter.ArgumentReferences) + .Select(SingleVariableArgumentSelection) + .Where(maybeSelection => maybeSelection.HasValue) + .Select(selection => selection.Value); + } + + private static QualifiedSelection? SingleVariableArgumentSelection(ArgumentReference argumentReference) + { + var argumentContext = argumentReference.Context as VBAParser.LExprContext; + if (!(argumentContext?.lExpression() is VBAParser.SimpleNameExprContext name)) + { + return null; + } + + return new QualifiedSelection(argumentReference.QualifiedModuleName, name.GetSelection()); + } + + protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) + { + //FIXME: stop filtering out too many results. + return reference != null + && !IsAssignedByRefArgument(reference.ParentScoping, reference, finder) + && !IsArraySubscriptAssignment(reference) + && !reference.Context.TryGetAncestor(out _); + + } + + protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + { + var identifierName = reference.IdentifierName; + return string.Format( + InspectionResults.UnassignedVariableUsageInspection, + identifierName); + } + + private static bool IsAssignedByRefArgument(Declaration enclosingProcedure, IdentifierReference reference, DeclarationFinder finder) { var argExpression = reference.Context.GetAncestor(); - var parameter = State.DeclarationFinder.FindParameterOfNonDefaultMemberFromSimpleArgumentNotPassedByValExplicitly(argExpression, enclosingProcedure); + var parameter = finder.FindParameterOfNonDefaultMemberFromSimpleArgumentNotPassedByValExplicitly(argExpression, enclosingProcedure); // note: not recursive, by design. return parameter != null @@ -90,28 +158,12 @@ private bool IsAssignedByRefArgument(Declaration enclosingProcedure, IdentifierR private static bool IsArraySubscriptAssignment(IdentifierReference reference) { + //FIXME: stop returning true for too many cases. var isLetAssignment = reference.Context.TryGetAncestor(out var letStmt); var isSetAssignment = reference.Context.TryGetAncestor(out var setStmt); - return isLetAssignment && letStmt.lExpression() is VBAParser.IndexExprContext || - isSetAssignment && setStmt.lExpression() is VBAParser.IndexExprContext; - } - - private static bool DeclarationReferencesContainsReference(Declaration parentDeclaration, Declaration target) - { - foreach (var targetReference in target.References) - { - foreach (var reference in parentDeclaration.References) - { - var context = (ParserRuleContext)reference.Context.Parent; - if (context.GetSelection().Contains(targetReference.Selection)) - { - return true; - } - } - } - - return false; + return isLetAssignment && letStmt.lExpression() is VBAParser.IndexExprContext + || isSetAssignment && setStmt.lExpression() is VBAParser.IndexExprContext; } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UntypedFunctionUsageInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UntypedFunctionUsageInspection.cs index 0660c50c1e..d3aea5cfa3 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UntypedFunctionUsageInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UntypedFunctionUsageInspection.cs @@ -1,9 +1,7 @@ using System.Collections.Generic; using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.Symbols; @@ -32,7 +30,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class UntypedFunctionUsageInspection : InspectionBase + public sealed class UntypedFunctionUsageInspection : IdentifierReferenceInspectionFromDeclarationsBase { public UntypedFunctionUsageInspection(RubberduckParserState state) : base(state) { } @@ -63,48 +61,37 @@ public UntypedFunctionUsageInspection(RubberduckParserState state) Tokens.UCase }; - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable ObjectionableDeclarations(DeclarationFinder finder) { - var finder = State.DeclarationFinder; - - var declarationsToConsider = BuiltInVariantStringFunctionsWithStringTypedVersion(finder); - - return declarationsToConsider - .SelectMany(NonStringHintedReferences) - .Select(Result); + return BuiltInVariantStringFunctionsWithStringTypedVersion(finder); } private IEnumerable BuiltInVariantStringFunctionsWithStringTypedVersion(DeclarationFinder finder) { return finder .BuiltInDeclarations(DeclarationType.Member) - .Where(item => (_tokens.Contains(item.IdentifierName) - || item.IdentifierName.StartsWith("_B_var_") - && _tokens.Contains(item.IdentifierName.Substring("_B_var_".Length))) - && item.Scope.StartsWith("VBE7.DLL;")); + .Where(item => item.Scope.StartsWith("VBE7.DLL;") + && (_tokens.Contains(item.IdentifierName) + || item.IdentifierName.StartsWith("_B_var_") + && _tokens.Contains(item.IdentifierName.Substring("_B_var_".Length)))); } - private IEnumerable NonStringHintedReferences(Declaration declaration) + protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) { - return declaration.References - .Where(item => _tokens.Contains(item.IdentifierName)); + var declarationName = reference.Declaration.IdentifierName; + return string.Format( + InspectionResults.UntypedFunctionUsageInspection, + declarationName); } - private IInspectionResult Result(IdentifierReference reference) + protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) { - return new IdentifierReferenceInspectionResult( - this, - ResultDescription(reference), - State, - reference); + return IsNotStringHinted(reference); } - private static string ResultDescription(IdentifierReference reference) + private bool IsNotStringHinted(IdentifierReference reference) { - var declarationName = reference.Declaration.IdentifierName; - return string.Format( - InspectionResults.UntypedFunctionUsageInspection, - declarationName); + return _tokens.Contains(reference.IdentifierName); } } } diff --git a/RubberduckTests/Inspections/UnassignedVariableUsageInspectionTests.cs b/RubberduckTests/Inspections/UnassignedVariableUsageInspectionTests.cs index 17b974a841..019b2d0b42 100644 --- a/RubberduckTests/Inspections/UnassignedVariableUsageInspectionTests.cs +++ b/RubberduckTests/Inspections/UnassignedVariableUsageInspectionTests.cs @@ -3,6 +3,7 @@ using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; +using Rubberduck.VBEditor.SafeComWrappers; namespace RubberduckTests.Inspections { @@ -120,7 +121,8 @@ public void UnassignedVariableUsage_NoResultForAssignedByRefReference() Sub DoSomething() Dim foo AssignThing foo - Debug.Print foo + Dim bar As Variant + bar = foo End Sub Sub AssignThing(ByRef thing As Variant) @@ -143,31 +145,95 @@ End Sub } [Test] - [Ignore("Test concurrency issue. Only passes if run individually.")] [Category("Inspections")] public void UnassignedVariableUsage_NoResultForLenFunction() { const string code = @" Sub DoSomething() Dim foo As LongPtr - Debug.Print Len(foo) + Dim bar As Variant + bar = Len(foo) End Sub "; - Assert.AreEqual(0, InspectionResultsForStandardModule(code).Count()); + var inspectionResults = InspectionResultsForModules(("TestModule", code, ComponentType.StandardModule), "VBA"); + Assert.AreEqual(0, inspectionResults.Count()); } [Test] - [Ignore("Test concurrency issue. Only passes if run individually.")] [Category("Inspections")] public void UnassignedVariableUsage_NoResultForLenBFunction() { const string code = @" Sub DoSomething() Dim foo As LongPtr - Debug.Print LenB(foo) + Dim bar As Variant + bar = LenB(foo) End Sub "; - Assert.AreEqual(0, InspectionResultsForStandardModule(code).Count()); + var inspectionResults = InspectionResultsForModules(("TestModule", code, ComponentType.StandardModule), "VBA"); + Assert.AreEqual(0, inspectionResults.Count()); + } + + [Test] + [Category("Inspections")] + public void UnassignedVariableUsage_ResultForOthersIfLenFunctionIsUsed() + { + const string code = @" +Sub DoSomething() + Dim foo As Variant + Dim bar As Variant + bar = Len(foo) + bar = foo + 5 +End Sub +"; + var inspectionResults = InspectionResultsForModules(("TestModule", code, ComponentType.StandardModule), "VBA"); + Assert.AreEqual(1, inspectionResults.Count()); + } + + [Test] + [Category("Inspections")] + public void UnassignedVariableUsage_ResultForOthersIfLenBFunctionIsUsed() + { + const string code = @" +Sub DoSomething() + Dim foo As Variant + Dim bar As Variant + bar = LenB(foo) + bar = foo + 5 +End Sub +"; + var inspectionResults = InspectionResultsForModules(("TestModule", code, ComponentType.StandardModule), "VBA"); + Assert.AreEqual(1, inspectionResults.Count()); + } + + [Test] + [Category("Inspections")] + public void UnassignedVariableUsage_ResultForUsageInsideArgumentOfLen() + { + const string code = @" +Sub DoSomething() + Dim foo As Variant + Dim bar As Variant + bar = Len(foo + 5) +End Sub +"; + var inspectionResults = InspectionResultsForModules(("TestModule", code, ComponentType.StandardModule), "VBA"); + Assert.AreEqual(1, inspectionResults.Count()); + } + + [Test] + [Category("Inspections")] + public void UnassignedVariableUsage_ResultForUsageInsideArgumentOfLenB() + { + const string code = @" +Sub DoSomething() + Dim foo As Variant + Dim bar As Variant + bar = LenB(foo + 5) +End Sub +"; + var inspectionResults = InspectionResultsForModules(("TestModule", code, ComponentType.StandardModule), "VBA"); + Assert.AreEqual(1, inspectionResults.Count()); } [Test] From 535a8877d93a7a16eed5028139c5aa819002cf32 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sun, 12 Jan 2020 02:05:16 +0100 Subject: [PATCH 138/461] Fix false negatives for UnassignedVariableUsageInspection --- .../UnassignedVariableUsageInspection.cs | 31 +++- .../UnassignedVariableUsageInspectionTests.cs | 150 +++++++++++++++++- ...oveUnassignedVariableUsageQuickFixTests.cs | 22 ++- 3 files changed, 186 insertions(+), 17 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs index db42997b90..3715947792 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs @@ -129,12 +129,10 @@ private static IEnumerable SingleVariableArgumentSelections( protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) { - //FIXME: stop filtering out too many results. return reference != null && !IsAssignedByRefArgument(reference.ParentScoping, reference, finder) && !IsArraySubscriptAssignment(reference) - && !reference.Context.TryGetAncestor(out _); - + && !IsArrayReDim(reference); } protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) @@ -158,12 +156,29 @@ private static bool IsAssignedByRefArgument(Declaration enclosingProcedure, Iden private static bool IsArraySubscriptAssignment(IdentifierReference reference) { - //FIXME: stop returning true for too many cases. - var isLetAssignment = reference.Context.TryGetAncestor(out var letStmt); - var isSetAssignment = reference.Context.TryGetAncestor(out var setStmt); + var nameExpression = reference.Context; + if (!(nameExpression.Parent is VBAParser.IndexExprContext indexExpression)) + { + return false; + } + + var callingExpression = indexExpression.Parent; + + return callingExpression is VBAParser.SetStmtContext + || callingExpression is VBAParser.LetStmtContext; + } + + private static bool IsArrayReDim(IdentifierReference reference) + { + var nameExpression = reference.Context; + if (!(nameExpression.Parent is VBAParser.IndexExprContext indexExpression)) + { + return false; + } + + var reDimVariableStmt = indexExpression.Parent?.Parent; - return isLetAssignment && letStmt.lExpression() is VBAParser.IndexExprContext - || isSetAssignment && setStmt.lExpression() is VBAParser.IndexExprContext; + return reDimVariableStmt is VBAParser.RedimVariableDeclarationContext; } } } diff --git a/RubberduckTests/Inspections/UnassignedVariableUsageInspectionTests.cs b/RubberduckTests/Inspections/UnassignedVariableUsageInspectionTests.cs index 019b2d0b42..96e87cd41a 100644 --- a/RubberduckTests/Inspections/UnassignedVariableUsageInspectionTests.cs +++ b/RubberduckTests/Inspections/UnassignedVariableUsageInspectionTests.cs @@ -38,7 +38,22 @@ End Sub [Test] [Category("Inspections")] - public void IgnoresArraySubscripts() + public void DoNotIgnoresArrayReDimBounds() + { + const string code = @" +Sub Foo() + Dim bar As Variant + Dim baz As Variant + Dim foo As Variant + ReDim bar(baz To foo) +End Sub +"; + Assert.AreEqual(2, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + public void IgnoresArraySubscripts_Let() { const string code = @" Sub Foo() @@ -50,6 +65,139 @@ End Sub Assert.AreEqual(0, InspectionResultsForStandardModule(code).Count()); } + [Test] + [Category("Inspections")] + public void DoNotIgnoreArrayIndexes_Let() + { + const string code = @" +Sub Foo() + Dim bar As Variant + Dim foo As Variant + ReDim bar(1 To 10) + bar(foo) = 42 +End Sub +"; + Assert.AreEqual(1, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + public void DoNotIgnoreValuesAssignedToArraySubscripts_Let() + { + const string code = @" +Sub Foo() + Dim bar As Variant + Dim foo As Variant + ReDim bar(1 To 10) + bar(1) = foo +End Sub +"; + Assert.AreEqual(1, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + public void DoNotIgnoreIndexedPropertyAccess_Let() + { + const string code = @" +Sub Foo() + Dim foo As Variant + ReDim bar(1 To 10) + foo.Bar(1) = 42 +End Sub +"; + Assert.AreEqual(1, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + public void IgnoresArraySubscripts_Set() + { + const string code = @" +Sub Foo() + Dim bar As Variant + ReDim bar(1 To 10) + Set bar(1) = Nothing +End Sub +"; + Assert.AreEqual(0, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + public void DoNotIgnoreArrayIndexes_Set() + { + const string code = @" +Sub Foo() + Dim bar As Variant + Dim foo As Variant + ReDim bar(1 To 10) + Set bar(foo) = Nothing +End Sub +"; + Assert.AreEqual(1, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + public void DoNotIgnoreValuesAssignedToArraySubscripts_Set() + { + const string code = @" +Sub Foo() + Dim bar As Variant + Dim foo As Variant + ReDim bar(1 To 10) + Set bar(1) = foo +End Sub +"; + Assert.AreEqual(1, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + public void DoNotIgnoreIndexedPropertyAccess_Set() + { + const string code = @" +Sub Foo() + Dim foo As Variant + ReDim bar(1 To 10) + Set foo.Bar(1) = 42 +End Sub +"; + Assert.AreEqual(1, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + public void DoesNotIgnoreWithBlockVariableUse() + { + const string code = @" +Sub Foo() + Dim foo As Variant + With foo + End With +End Sub +"; + Assert.AreEqual(1, InspectionResultsForStandardModule(code).Count()); + } + + [Test] + [Category("Inspections")] + public void IgnoreUseViaWithBlockVariableInWithBlock() + { + const string code = @" +Sub Foo() + Dim foo As Variant + Dim bar As Variant + With foo + bar = .Baz + 23 + bar = .Baz + 42 + End With +End Sub +"; + Assert.AreEqual(1, InspectionResultsForStandardModule(code).Count()); + } + [Test] [Category("Inspections")] public void UnassignedVariableUsage_ReturnsResult() diff --git a/RubberduckTests/QuickFixes/RemoveUnassignedVariableUsageQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveUnassignedVariableUsageQuickFixTests.cs index 183f91c8bd..aef8e8cd05 100644 --- a/RubberduckTests/QuickFixes/RemoveUnassignedVariableUsageQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveUnassignedVariableUsageQuickFixTests.cs @@ -43,23 +43,29 @@ public void UnassignedVariableUsage_QuickFixWorksWithBlock() { const string inputCode = @"Sub test() - Dim wb As Workbook + Dim wb As Variant With wb - Debug.Print .Name - Debug.Print .Name - Debug.Print .Name + Bar .Name + Bar .Name + Bar .Name End With +End Sub + +Private Sub Bar(ByVal arg) End Sub"; const string expectedCode = @"Sub test() - Dim wb As Workbook + Dim wb As Variant 'TODO - {0} ' With wb -' Debug.Print .Name -' Debug.Print .Name -' Debug.Print .Name +' Bar .Name +' Bar .Name +' Bar .Name ' End With +End Sub + +Private Sub Bar(ByVal arg) End Sub"; var (actual, inspectionDescription) = From b969ddcd72465c304055d9ac7dcb84f67f5dfe8c Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Sun, 12 Jan 2020 16:17:13 -0500 Subject: [PATCH 139/461] add test for disabled SCP --- .../AutoComplete/SelfClosingPairHandlerTests.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/RubberduckTests/AutoComplete/SelfClosingPairHandlerTests.cs b/RubberduckTests/AutoComplete/SelfClosingPairHandlerTests.cs index e11d0659c6..8ba2156504 100644 --- a/RubberduckTests/AutoComplete/SelfClosingPairHandlerTests.cs +++ b/RubberduckTests/AutoComplete/SelfClosingPairHandlerTests.cs @@ -20,6 +20,18 @@ private bool Run(SelfClosingPairTestInfo info) return false; } + [Test] + public void GivenDisabledSelfClosingPairs_BailsOut() + { + var input = '"'; + var original = "DoSomething |".ToCodeString(); + var info = new SelfClosingPairTestInfo(original, input); + info.Settings.SelfClosingPairs.IsEnabled = false; + + Assert.IsFalse(Run(info)); + Assert.IsNull(info.Result); + } + [Test] public void GivenInvalidInput_ResultIsNull() { From d1badcc552e6324f54a550b904a29dbb0b69fe6a Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Mon, 13 Jan 2020 10:00:16 -0800 Subject: [PATCH 140/461] Fixed hiding UI detail display with empty list --- .../Refactorings/EncapsulateField/EncapsulateFieldView.xaml | 3 ++- .../EncapsulateField/EncapsulateFieldViewModel.cs | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml index 2faec19ce8..8b4fa16321 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml @@ -153,7 +153,8 @@ - EncapsulationFields orderedFields = Model.EncapsulationCandidates.Where(ec => !_selectedObjectStateUDT.FieldIdentifier.Equals(ec.IdentifierName)) .OrderBy(efd => efd.Declaration.Selection).ToList(); } + IsEmptyList = orderedFields.Count() == 0; foreach (var efd in orderedFields) { viewableFields.Add(new ViewableEncapsulatedField(efd)); @@ -116,6 +117,8 @@ public ObservableCollection EncapsulationFields } } + public bool IsEmptyList { set; get; } + public ObservableCollection UDTFields { get @@ -269,10 +272,9 @@ public bool IsReadOnly public bool ConvertFieldsToUDTMembers { - get => Model.EncapsulateFieldStrategy == EncapsulateFieldStrategy.ConvertFieldsToUDTMembers; // Model.ConvertFieldsToUDTMembers; + get => Model.EncapsulateFieldStrategy == EncapsulateFieldStrategy.ConvertFieldsToUDTMembers; set { - //Model.ConvertFieldsToUDTMembers = value; Model.EncapsulateFieldStrategy = value ? EncapsulateFieldStrategy.ConvertFieldsToUDTMembers : EncapsulateFieldStrategy.UseBackingFields; From 224a50521b4fd3ffcc4b6b5ed49ed2fc4dfa2186 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Mon, 13 Jan 2020 10:01:30 -0800 Subject: [PATCH 141/461] Handle nested UDTs --- .../EncapsulateFieldElementsBuilder.cs | 8 +- .../EncapsulateField/EncapsulateFieldModel.cs | 2 +- .../ConvertFieldsToUDTMembers.cs | 2 +- .../EncapsulateFieldStrategyBase.cs | 2 +- .../Extensions/DeclarationExtensions.cs | 12 +- .../ConvertToUDTMemberCandidate.cs | 51 ++-- .../EncapsulateFieldCandidate.cs | 9 +- .../EncapsulationIdentifiers.cs | 2 +- .../UserDefinedTypeCandidate.cs | 49 ++-- .../UserDefinedTypeMemberCandidate.cs | 72 ++++-- .../EncapsulateField/ObjectStateUDT.cs | 5 + ...ieldsToUDTMembersStrategyConflictFinder.cs | 2 - .../EncapsulateFieldValidationsProvider.cs | 17 +- ...port.cs => EncapsulateFIeldTestSupport.cs} | 4 +- .../EncapsulateField/EncapsulateFieldTests.cs | 2 +- .../EncapsulateUsingStateUDTTests.cs | 220 ++++++++++++++++++ .../EncapsulatedUDTFieldTests.cs | 90 +++++++ 17 files changed, 474 insertions(+), 75 deletions(-) rename RubberduckTests/Refactoring/EncapsulateField/{TestSupport.cs => EncapsulateFIeldTestSupport.cs} (98%) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementsBuilder.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementsBuilder.cs index fa845622fd..dd915b15c9 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementsBuilder.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementsBuilder.cs @@ -16,7 +16,7 @@ public class EncapsulateFieldElementsBuilder private readonly IDeclarationFinderProvider _declarationFinderProvider; private QualifiedModuleName _targetQMN; - public EncapsulateFieldElementsBuilder(IDeclarationFinderProvider declarationFinderProvider, QualifiedModuleName targetQMN)//, IEncapsulateFieldValidator validator ) + public EncapsulateFieldElementsBuilder(IDeclarationFinderProvider declarationFinderProvider, QualifiedModuleName targetQMN) { _declarationFinderProvider = declarationFinderProvider; _targetQMN = targetQMN; @@ -77,7 +77,7 @@ private void CreateRefactoringElements() } } - private IEnumerable BuildObjectStateUDTCandidates(IEnumerable candidates) //, IObjectStateUDT defaultObjectStateUDT) + private IEnumerable BuildObjectStateUDTCandidates(IEnumerable candidates) { var udtCandidates = candidates.Where(c => c is IUserDefinedTypeCandidate udt && udt.CanBeObjectStateUDT); @@ -105,9 +105,9 @@ private IObjectStateUDT CreateStateUDTField() return stateUDT; } - private IEncapsulateFieldCandidate CreateCandidate(Declaration target, IValidateVBAIdentifiers validator)// Predicate nameValidator) + private IEncapsulateFieldCandidate CreateCandidate(Declaration target, IValidateVBAIdentifiers validator) { - if (target.IsUserDefinedTypeField()) + if (target.IsUserDefinedType()) { var udtValidator = EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedType); var udtField = new UserDefinedTypeCandidate(target, udtValidator) as IUserDefinedTypeCandidate; diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index 7b3956cd59..477286522b 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -92,7 +92,7 @@ private void ChangeSettingsToConvertFieldsToUDTMembersStrategy() { foreach (var candidate in EncapsulationCandidates) { - candidate.ConflictFinder = _validationsProvider.ConflictDetector(EncapsulateFieldStrategy , _declarationFinderProvider);// ConflictDetector; + candidate.ConflictFinder = _validationsProvider.ConflictDetector(EncapsulateFieldStrategy , _declarationFinderProvider); candidate.NameValidator = candidate.Declaration.IsArray ? EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMemberArray) : EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMember); diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs index a30231a101..e0375c1903 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs @@ -82,7 +82,7 @@ protected override void LoadFieldReferenceContextReplacements(IEncapsulateFieldC { foreach (var member in udt.Members) { - foreach (var idRef in member.ParentContextReferences) + foreach (var idRef in member.FieldContextReferences) { var replacementText = member.ReferenceAccessor(idRef); if (IsExternalReferenceRequiringModuleQualification(idRef)) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs index 4bfb961ba2..e5ffc4ed8e 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs @@ -129,7 +129,7 @@ protected virtual void LoadFieldReferenceContextReplacements(IEncapsulateFieldCa { foreach (var member in udt.Members) { - foreach (var idRef in member.ParentContextReferences) + foreach (var idRef in member.FieldContextReferences) { var replacementText = member.ReferenceAccessor(idRef); SetUDTMemberReferenceRewriteContent(idRef, replacementText); diff --git a/Rubberduck.Refactorings/EncapsulateField/Extensions/DeclarationExtensions.cs b/Rubberduck.Refactorings/EncapsulateField/Extensions/DeclarationExtensions.cs index 47510f387f..be86893515 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Extensions/DeclarationExtensions.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Extensions/DeclarationExtensions.cs @@ -30,7 +30,10 @@ public static bool IsConstant(this Declaration declaration) => declaration.DeclarationType.HasFlag(DeclarationType.Constant); public static bool IsUserDefinedTypeField(this Declaration declaration) - => declaration.IsMemberVariable() && (declaration.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.UserDefinedType) ?? false); + => declaration.IsMemberVariable() && IsUserDefinedType(declaration); + + public static bool IsUserDefinedType(this Declaration declaration) + => (declaration.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.UserDefinedType) ?? false); public static bool IsEnumField(this Declaration declaration) => declaration.IsMemberVariable() && (declaration.AsTypeDeclaration?.DeclarationType.Equals(DeclarationType.Enumeration) ?? false); @@ -40,12 +43,5 @@ public static bool IsDeclaredInList(this Declaration declaration) return declaration.Context.TryGetAncestor(out var varList) && varList.ChildCount > 1; } - - public static IEnumerable AllReferences(this IEnumerable declarations) - { - return from dec in declarations - from reference in dec.References - select reference; - } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs index b9ac57e645..1b241b0ee4 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs @@ -4,6 +4,7 @@ using System.Text; using System.Threading.Tasks; using Antlr4.Runtime; +using Rubberduck.Common; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.VBEditor; @@ -14,18 +15,21 @@ namespace Rubberduck.Refactorings.EncapsulateField public interface IConvertToUDTMember : IEncapsulateFieldCandidate { string UDTMemberDeclaration { get; } - IObjectStateUDT ObjectStateUDT { set; get; } IEncapsulateFieldCandidate WrappedCandidate { get; } } public class ConvertToUDTMember : IConvertToUDTMember { + private int _hashCode; + private readonly string _uniqueID; private readonly IEncapsulateFieldCandidate _wrapped; public ConvertToUDTMember(IEncapsulateFieldCandidate candidate, IObjectStateUDT objStateUDT) { _wrapped = candidate; PropertyIdentifier = _wrapped.PropertyIdentifier; ObjectStateUDT = objStateUDT; + _uniqueID = BuildUniqueID(candidate, objStateUDT); + _hashCode = _uniqueID.GetHashCode(); } public virtual string UDTMemberDeclaration @@ -42,7 +46,7 @@ public virtual string UDTMemberDeclaration public IEncapsulateFieldCandidate WrappedCandidate => _wrapped; - public IObjectStateUDT ObjectStateUDT { set; get; } + public IObjectStateUDT ObjectStateUDT { private set; get; } public string TargetID => _wrapped.TargetID; @@ -91,7 +95,7 @@ public string ParameterName get => _wrapped.ParameterName; } - public IValidateVBAIdentifiers NameValidator + public IValidateVBAIdentifiers NameValidator { set => _wrapped.NameValidator = value; get => _wrapped.NameValidator; @@ -109,7 +113,7 @@ private string AccessorInProperty { if (_wrapped is IUserDefinedTypeMemberCandidate udtm) { - return $"{ObjectStateUDT.FieldIdentifier}.{udtm.Parent.PropertyIdentifier}.{BackingIdentifier}"; + return $"{ObjectStateUDT.FieldIdentifier}.{udtm.UDTField.PropertyIdentifier}.{BackingIdentifier}"; } return $"{ObjectStateUDT.FieldIdentifier}.{BackingIdentifier}"; } @@ -119,9 +123,9 @@ public string ReferenceAccessor(IdentifierReference idRef) { if (idRef.QualifiedModuleName != QualifiedModuleName) { - return $"{QualifiedModuleName.ComponentName}.{PropertyIdentifier}"; + return PropertyIdentifier; } - return $"{BackingIdentifier}"; + return BackingIdentifier; } public string IdentifierName => _wrapped.IdentifierName; @@ -139,31 +143,46 @@ public IEnumerable PropertyAttributeSets { get { - if (_wrapped is IUserDefinedTypeCandidate udt && udt.TypeDeclarationIsPrivate) + var modifiedSets = new List(); + var sets = _wrapped.PropertyAttributeSets; + for (var idx = 0; idx < sets.Count(); idx++) { - var sets = new List(); - foreach (var member in udt.Members) - { - sets.Add(CreateMemberPropertyAttributeSet(member)); - } - return sets; + var attributeSet = sets.ElementAt(idx); + var fields = attributeSet.BackingField.Split(new char[] { '.' }); + + attributeSet.BackingField = fields.Count() > 1 + ? $"{ObjectStateUDT.FieldIdentifier}.{attributeSet.BackingField.CapitalizeFirstLetter()}" + : $"{ObjectStateUDT.FieldIdentifier}.{attributeSet.PropertyName.CapitalizeFirstLetter()}"; + + modifiedSets.Add(attributeSet); } - return new List() { AsPropertyAttributeSet }; + return modifiedSets; } } + public override bool Equals(object obj) + { + return obj != null + && obj is ConvertToUDTMember convertWrapper + && BuildUniqueID(convertWrapper, convertWrapper.ObjectStateUDT) == _uniqueID; + } + + public override int GetHashCode() => _hashCode; + + private static string BuildUniqueID(IEncapsulateFieldCandidate candidate, IObjectStateUDT field) => $"{candidate.QualifiedModuleName.Name}.{field.IdentifierName}.{candidate.IdentifierName}"; + private PropertyAttributeSet CreateMemberPropertyAttributeSet (IUserDefinedTypeMemberCandidate udtMember) { return new PropertyAttributeSet() { PropertyName = udtMember.PropertyIdentifier, - BackingField = $"{ObjectStateUDT.FieldIdentifier}.{udtMember.Parent.PropertyIdentifier}.{udtMember.BackingIdentifier}", + BackingField = $"{ObjectStateUDT.FieldIdentifier}.{udtMember.UDTField.PropertyIdentifier}.{udtMember.BackingIdentifier}", AsTypeName = udtMember.PropertyAsTypeName, ParameterName = udtMember.ParameterName, GenerateLetter = udtMember.ImplementLet, GenerateSetter = udtMember.ImplementSet, UsesSetAssignment = udtMember.Declaration.IsObject, - IsUDTProperty = false //TODO: If udtMember is a UDT, this needs to be true + IsUDTProperty = (udtMember.Declaration.AsTypeDeclaration?.DeclarationType ?? DeclarationType.Variable) == DeclarationType.UserDefinedType }; } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs index c5b615a2a3..47a8b71768 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs @@ -41,6 +41,7 @@ public class EncapsulateFieldCandidate : IEncapsulateFieldCandidate { protected Declaration _target; protected QualifiedModuleName _qmn; + protected readonly string _uniqueID; protected int _hashCode; private string _identifierName; protected EncapsulationIdentifiers _fieldAndProperty; @@ -57,7 +58,8 @@ public EncapsulateFieldCandidate(Declaration declaration, IValidateVBAIdentifier CanBeReadWrite = true; - _hashCode = ($"{_qmn.Name}.{declaration.IdentifierName}").GetHashCode(); + _uniqueID = $"{_qmn.Name}.{declaration.IdentifierName}"; + _hashCode = _uniqueID.GetHashCode(); ImplementLet = true; ImplementSet = false; @@ -129,11 +131,14 @@ public override bool Equals(object obj) { return obj != null && obj is IEncapsulateFieldCandidate efc - && $"{efc.QualifiedModuleName.Name}.{efc.TargetID}" == $"{_qmn.Name}.{IdentifierName}"; + && $"{efc.QualifiedModuleName.Name}.{efc.IdentifierName}" == _uniqueID; } public override int GetHashCode() => _hashCode; + public override string ToString() + =>$"({TargetID}){Declaration.ToString()}"; + protected virtual string AccessorInProperty => $"{BackingIdentifier}"; diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs index 64dc3d0b28..8f60f475f3 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs @@ -15,7 +15,7 @@ public class EncapsulationIdentifiers private string _targetIdentifier; private string _setLetParameter; - public EncapsulationIdentifiers(string field, IValidateVBAIdentifiers identifierValidator) // Predicate IsValidPropertyName) + public EncapsulationIdentifiers(string field, IValidateVBAIdentifiers identifierValidator) { _targetIdentifier = field; diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs index 47ecce352a..ff89c84d87 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs @@ -16,6 +16,7 @@ public interface IUserDefinedTypeCandidate : IEncapsulateFieldCandidate void AddMember(IUserDefinedTypeMemberCandidate member); bool TypeDeclarationIsPrivate { set; get; } bool CanBeObjectStateUDT { set; get; } + bool IsSelectedObjectStateUDT { set; get; } } public class UserDefinedTypeCandidate : EncapsulateFieldCandidate, IUserDefinedTypeCandidate @@ -33,7 +34,14 @@ public void AddMember(IUserDefinedTypeMemberCandidate member) private List _udtMembers = new List(); public IEnumerable Members => _udtMembers; - public bool TypeDeclarationIsPrivate { set; get; } + private bool _isPrivate; + public bool TypeDeclarationIsPrivate + { + set => _isPrivate = value; + get => Declaration.AsTypeDeclaration?.HasPrivateAccessibility() ?? false; + } + + public bool IsSelectedObjectStateUDT { set; get; } private bool _canBeObjectStateUDT; public bool CanBeObjectStateUDT @@ -119,6 +127,20 @@ protected override string AccessorLocalReference(IdentifierReference idRef) return TypeDeclarationIsPrivate ? $"{BackingIdentifier}" : $"{PropertyIdentifier}"; } + public override bool Equals(object obj) + { + if (obj is IUserDefinedTypeCandidate udt) + { + return udt.TargetID.Equals(TargetID); + } + return false; + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + public override IEnumerable PropertyAttributeSets { get @@ -128,7 +150,16 @@ public override IEnumerable PropertyAttributeSets var specs = new List(); foreach (var member in Members) { - specs.Add(member.AsPropertyGeneratorSpec); + var sets = member.PropertyAttributeSets; + var modifiedSets = new List(); + PropertyAttributeSet newSet; + foreach (var set in sets) + { + newSet = set; + newSet.BackingField = $"{BackingIdentifier}.{set.BackingField}"; + modifiedSets.Add(newSet); + } + specs.AddRange(modifiedSets); } return specs; } @@ -136,20 +167,6 @@ public override IEnumerable PropertyAttributeSets } } - public override bool Equals(object obj) - { - if (obj is IUserDefinedTypeCandidate udt) - { - return udt.TargetID.Equals(TargetID); - } - return false; - } - - public override int GetHashCode() - { - return base.GetHashCode(); - } - protected override PropertyAttributeSet AsPropertyAttributeSet { get diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs index 9f07766b01..16dced30e7 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs @@ -2,6 +2,7 @@ using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; +using Rubberduck.Refactorings.EncapsulateField.Extensions; using Rubberduck.VBEditor; using System.Collections.Generic; using System.Diagnostics; @@ -11,38 +12,44 @@ namespace Rubberduck.Refactorings.EncapsulateField { public interface IUserDefinedTypeMemberCandidate : IEncapsulateFieldCandidate { - IUserDefinedTypeCandidate Parent { get; } + IUserDefinedTypeCandidate UDTField { get; } PropertyAttributeSet AsPropertyGeneratorSpec { get; } - IEnumerable ParentContextReferences { get; } + IEnumerable FieldContextReferences { get; } + IEncapsulateFieldCandidate WrappedCandidate { get; } } public class UserDefinedTypeMemberCandidate : IUserDefinedTypeMemberCandidate { private int _hashCode; private readonly string _uniqueID; - public UserDefinedTypeMemberCandidate(IEncapsulateFieldCandidate candidate, IUserDefinedTypeCandidate udtVariable) + public UserDefinedTypeMemberCandidate(IEncapsulateFieldCandidate candidate, IUserDefinedTypeCandidate udtField) { _wrappedCandidate = candidate; - Parent = udtVariable; + UDTField = udtField; PropertyIdentifier = IdentifierName; BackingIdentifier = IdentifierName; - _uniqueID = BuildUniqueID(candidate); + _uniqueID = BuildUniqueID(candidate, UDTField); _hashCode = _uniqueID.GetHashCode(); } private IEncapsulateFieldCandidate _wrappedCandidate; + public IEncapsulateFieldCandidate WrappedCandidate => _wrappedCandidate; + public string AsTypeName => _wrappedCandidate.AsTypeName; public string BackingIdentifier { - get => _wrappedCandidate.IdentifierName; + get + { + return _wrappedCandidate.IdentifierName; + } set { } } public string BackingAsTypeName => Declaration.AsTypeName; - public IUserDefinedTypeCandidate Parent { private set; get; } + public IUserDefinedTypeCandidate UDTField { private set; get; } public IValidateVBAIdentifiers NameValidator { @@ -56,10 +63,10 @@ public IEncapsulateFieldConflictFinder ConflictFinder get => _wrappedCandidate.ConflictFinder; } - public string TargetID => $"{Parent.IdentifierName}.{IdentifierName}"; + public string TargetID => $"{UDTField.IdentifierName}.{IdentifierName}"; - public IEnumerable ParentContextReferences - => GetUDTMemberReferencesForField(this, Parent); + public IEnumerable FieldContextReferences + => GetUDTMemberReferencesForField(this, UDTField); public string ReferenceAccessor(IdentifierReference idRef) => PropertyIdentifier; @@ -71,13 +78,13 @@ public PropertyAttributeSet AsPropertyGeneratorSpec return new PropertyAttributeSet() { PropertyName = PropertyIdentifier, - BackingField = $"{Parent.BackingIdentifier}.{BackingIdentifier}", + BackingField = BackingIdentifier, AsTypeName = PropertyAsTypeName, ParameterName = ParameterName, GenerateLetter = ImplementLet, GenerateSetter = ImplementSet, UsesSetAssignment = Declaration.IsObject, - IsUDTProperty = false //TODO: If udtMember is a UDT, this needs to be true + IsUDTProperty = Declaration.DeclarationType == DeclarationType.UserDefinedType }; } } @@ -86,14 +93,14 @@ public override bool Equals(object obj) { return obj != null && obj is IUserDefinedTypeMemberCandidate udtMember - && BuildUniqueID(udtMember) == _uniqueID; + && BuildUniqueID(udtMember, udtMember.UDTField) == _uniqueID; } public override int GetHashCode() => _hashCode; public string PropertyIdentifier { set; get; } - private static string BuildUniqueID(IEncapsulateFieldCandidate candidate) => $"{candidate.QualifiedModuleName.Name}.{candidate.IdentifierName}"; + private static string BuildUniqueID(IEncapsulateFieldCandidate candidate, IEncapsulateFieldCandidate field) => $"{candidate.QualifiedModuleName.Name}.{field.IdentifierName}.{candidate.IdentifierName}"; private static IEnumerable GetUDTMemberReferencesForField(IEncapsulateFieldCandidate udtMember, IUserDefinedTypeCandidate field) { @@ -159,6 +166,14 @@ public bool EncapsulateFlag { set { + if (_wrappedCandidate is IUserDefinedTypeCandidate udt && udt.TypeDeclarationIsPrivate) + { + foreach (var member in udt.Members) + { + member.EncapsulateFlag = value; + } + return; + } var valueChanged = _encapsulateFlag != value; _encapsulateFlag = value; @@ -182,7 +197,7 @@ public bool CanBeReadWrite } public bool HasValidEncapsulationAttributes => true; - public QualifiedModuleName QualifiedModuleName + public QualifiedModuleName QualifiedModuleName => _wrappedCandidate.QualifiedModuleName; public string PropertyAsTypeName => _wrappedCandidate.PropertyAsTypeName; @@ -193,10 +208,33 @@ public string ParameterName get => _wrappedCandidate.ParameterName; } - public bool ImplementLet => _wrappedCandidate.ImplementLet; + public bool ImplementLet => _wrappedCandidate.ImplementLet; public bool ImplementSet => _wrappedCandidate.ImplementSet; - public IEnumerable PropertyAttributeSets => _wrappedCandidate.PropertyAttributeSets; + public IEnumerable PropertyAttributeSets + { + get + { + if (!(_wrappedCandidate is IUserDefinedTypeCandidate udt)) + { + return new List() { AsPropertyGeneratorSpec }; + } + + var sets = _wrappedCandidate.PropertyAttributeSets; + if (udt.TypeDeclarationIsPrivate) + { + return sets; + } + var modifiedSets = new List(); + for(var idx = 0; idx < sets.Count(); idx++) + { + var attr = sets.ElementAt(idx); + attr.BackingField = attr.PropertyName; + modifiedSets.Add(attr); + } + return modifiedSets; + } + } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/ObjectStateUDT.cs b/Rubberduck.Refactorings/EncapsulateField/ObjectStateUDT.cs index 81e420941a..7bb12298fc 100644 --- a/Rubberduck.Refactorings/EncapsulateField/ObjectStateUDT.cs +++ b/Rubberduck.Refactorings/EncapsulateField/ObjectStateUDT.cs @@ -71,6 +71,11 @@ public bool IsSelected set { _isSelected = value; + if (_wrappedUDT != null) + { + _wrappedUDT.IsSelectedObjectStateUDT = value; + } + if (_isSelected && IsExistingDeclaration) { _wrappedUDT.EncapsulateFlag = false; diff --git a/Rubberduck.Refactorings/EncapsulateField/Validations/ConvertFieldsToUDTMembersStrategyConflictFinder.cs b/Rubberduck.Refactorings/EncapsulateField/Validations/ConvertFieldsToUDTMembersStrategyConflictFinder.cs index 841fd5abda..893471bd7a 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Validations/ConvertFieldsToUDTMembersStrategyConflictFinder.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Validations/ConvertFieldsToUDTMembersStrategyConflictFinder.cs @@ -37,7 +37,6 @@ public override IEncapsulateFieldCandidate AssignNoConflictIdentifiers(IEncapsul { candidate = base.AssignNoConflictIdentifier(candidate, DeclarationType.Property); - //Compare to existing members...they cannot change. var objectStateUDT = _objectStateUDTs.SingleOrDefault(os => os.IsSelected); var guard = 0; while (guard++ < 10 && ConflictsWithExistingUDTMembers(objectStateUDT, candidate.PropertyIdentifier)) @@ -52,7 +51,6 @@ protected override IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncaps { candidate = base.AssignNoConflictIdentifier(candidate, declarationType); - //Compare to existing members first...they cannot change var objectStateUDT = _objectStateUDTs.SingleOrDefault(os => os.IsSelected); var guard = 0; while (guard++ < 10 && ConflictsWithExistingUDTMembers(objectStateUDT, candidate.BackingIdentifier)) diff --git a/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldValidationsProvider.cs b/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldValidationsProvider.cs index 0f37531400..c4ec6604ab 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldValidationsProvider.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldValidationsProvider.cs @@ -58,12 +58,23 @@ public EncapsulateFieldValidationsProvider(IEnumerable(); _objectStateUDTs = objectStateUDTCandidates.ToList(); _candidates = candidates.ToList(); + var udtCandidates = candidates.Where(c => c is IUserDefinedTypeCandidate).Cast(); + foreach (var udtCandidate in candidates.Where(c => c is IUserDefinedTypeCandidate).Cast()) { - foreach (var member in udtCandidate.Members) + LoadUDTMemberCandidates(udtCandidate); + } + } + + private void LoadUDTMemberCandidates(IUserDefinedTypeCandidate udtCandidate) + { + foreach (var member in udtCandidate.Members) + { + if (member.WrappedCandidate is IUserDefinedTypeCandidate udt) { - _udtMemberCandidates.Add(member); + LoadUDTMemberCandidates(udt); } + _udtMemberCandidates.Add(member); } } @@ -83,7 +94,7 @@ public static IEncapsulateFieldCandidate AssignNoConflictParameter(IEncapsulateF return candidate; } - public static IObjectStateUDT AssignNoConflictIdentifiers(IObjectStateUDT stateUDT, IDeclarationFinderProvider declarationFinderProvider) //, DeclarationType declarationType) + public static IObjectStateUDT AssignNoConflictIdentifiers(IObjectStateUDT stateUDT, IDeclarationFinderProvider declarationFinderProvider) { var members = declarationFinderProvider.DeclarationFinder.Members(stateUDT.QualifiedModuleName); var guard = 0; diff --git a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFIeldTestSupport.cs similarity index 98% rename from RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs rename to RubberduckTests/Refactoring/EncapsulateField/EncapsulateFIeldTestSupport.cs index 1fd0cfc50d..acd35a8ab8 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/TestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFIeldTestSupport.cs @@ -115,7 +115,7 @@ public string RefactoredCode(CodeString codeString, Func(); uiDispatcherMock @@ -220,7 +220,7 @@ public class UserInputDataObject public UserInputDataObject() { } - public UserInputDataObject UserSelectsField(string fieldName, string propertyName = null/*, bool encapsulationFlag = true*/, bool isReadOnly = false) + public UserInputDataObject UserSelectsField(string fieldName, string propertyName = null, bool isReadOnly = false) { return AddUserInputSet(fieldName, propertyName, true, isReadOnly); } diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs index 670e39beab..0d4dc223fa 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFieldTests.cs @@ -473,7 +473,7 @@ Sub Bar(ByVal name As Integer) var presenterAction = Support.SetParametersForSingleTarget("fizz", "Name"); var validator = EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.Default); - var enapsulationIdentifiers = new EncapsulationIdentifiers("fizz", validator/*(string name) => true*/) { Property = "Name" }; + var enapsulationIdentifiers = new EncapsulationIdentifiers("fizz", validator) { Property = "Name" }; var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); StringAssert.AreEqualIgnoringCase(enapsulationIdentifiers.TargetFieldName, "fizz"); diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs index 668cc0f237..21143e3a6c 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs @@ -437,6 +437,226 @@ Private mFizz Assert.AreEqual(expectedCount, model.ObjectStateUDTCandidates.Count()); } + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UDTMemberIsPrivateUDT() + { + string inputCode = +$@" + +Private Type TFoo + Foo As Integer + Bar As Byte +End Type + +Private Type TBar + FooBar As TFoo +End Type + +Private my|Bar As TBar +"; + + var userInput = new UserInputDataObject(); + + userInput.EncapsulateUsingUDTField(); + + var presenterAction = Support.SetParameters(userInput); + + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + + StringAssert.Contains("Public Property Let Foo(", actualCode); + StringAssert.Contains("Public Property Let Bar(", actualCode); + StringAssert.Contains("this.MyBar.FooBar.Foo = value", actualCode); + } + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UDTMemberIsPublicUDT() + { + string inputCode = +$@" + +Public Type TFoo + Foo As Integer + Bar As Byte +End Type + +Private Type TBar + FooBar As TFoo +End Type + +Private my|Bar As TBar +"; + + var userInput = new UserInputDataObject(); + + userInput.EncapsulateUsingUDTField(); + + var presenterAction = Support.SetParameters(userInput); + + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + + StringAssert.Contains("Public Property Let FooBar(", actualCode); + StringAssert.Contains("this.MyBar.FooBar = value", actualCode); + } + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UDTMemberIsPrivateUDT_RepeatedType() + { + string inputCode = +$@" + +Private Type TFoo + Foo As Integer + Bar As Byte +End Type + +Private Type TBar + FooBar As TFoo + ReBar As TFoo +End Type + +Private my|Bar As TBar +"; + + var userInput = new UserInputDataObject(); + + userInput.EncapsulateUsingUDTField(); + + var presenterAction = Support.SetParameters(userInput); + + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + + StringAssert.Contains("Public Property Let Foo(", actualCode); + StringAssert.Contains("Public Property Let Bar(", actualCode); + StringAssert.Contains("Public Property Let Foo_1(", actualCode); + StringAssert.Contains("Public Property Let Bar_1(", actualCode); + StringAssert.Contains("this.MyBar.FooBar.Foo = value", actualCode); + StringAssert.Contains("this.MyBar.ReBar.Foo = value", actualCode); + } + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void GivenReferencedPublicField_UpdatesReferenceToNewProperty() + { + const string codeClass1 = + @"|Public fizz As Integer + +Sub Foo() + fizz = 1 +End Sub"; + const string codeClass2 = +@"Sub Foo() + Dim theClass As Class1 + theClass.fizz = 0 + Bar theClass.fizz +End Sub + +Sub Bar(ByVal v As Integer) +End Sub"; + + var userInput = new UserInputDataObject() + .AddUserInputSet("fizz", "Name"); + + userInput.EncapsulateUsingUDTField(); + + var presenterAction = Support.SetParameters(userInput); + + var class1CodeString = codeClass1.ToCodeString(); + var actualCode = RefactoredCode( + "Class1", + class1CodeString.CaretPosition.ToOneBased(), + presenterAction, + null, + false, + ("Class1", class1CodeString.Code, ComponentType.ClassModule), + ("Class2", codeClass2, ComponentType.ClassModule)); + + StringAssert.Contains("Name = 1", actualCode["Class1"]); + StringAssert.Contains("theClass.Name = 0", actualCode["Class2"]); + StringAssert.Contains("Bar theClass.Name", actualCode["Class2"]); + StringAssert.DoesNotContain("fizz", actualCode["Class2"]); + } + + [TestCase(false)] + [TestCase(true)] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void StandardModuleSource_ExternalReferences(bool moduleResolve) + { + var sourceModuleName = "SourceModule"; + var referenceExpression = moduleResolve ? $"{sourceModuleName}." : string.Empty; + var sourceModuleCode = +$@" + +Public th|is As Long"; + + var procedureModuleReferencingCode = +$@"Option Explicit + +Private Const bar As Long = 7 + +Public Sub Bar() + {referenceExpression}this = bar +End Sub + +Public Sub Foo() + With {sourceModuleName} + .this = bar + End With +End Sub +"; + + string classModuleReferencingCode = +$@"Option Explicit + +Private Const bar As Long = 7 + +Public Sub Bar() + {referenceExpression}this = bar +End Sub + +Public Sub Foo() + With {sourceModuleName} + .this = bar + End With +End Sub +"; + + var userInput = new UserInputDataObject() + .UserSelectsField("this", "MyProperty"); + + userInput.EncapsulateUsingUDTField(); + + var presenterAction = Support.SetParameters(userInput); + + var sourceCodeString = sourceModuleCode.ToCodeString(); + var actualModuleCode = RefactoredCode( + sourceModuleName, + sourceCodeString.CaretPosition.ToOneBased(), + presenterAction, + null, + false, + ("StdModule", procedureModuleReferencingCode, ComponentType.StandardModule), + ("ClassModule", classModuleReferencingCode, ComponentType.ClassModule), + (sourceModuleName, sourceCodeString.Code, ComponentType.StandardModule)); + + var referencingModuleCode = actualModuleCode["StdModule"]; + StringAssert.Contains($"{sourceModuleName}.MyProperty = ", referencingModuleCode); + StringAssert.DoesNotContain($"{sourceModuleName}.{sourceModuleName}.MyProperty = ", referencingModuleCode); + StringAssert.Contains($" .MyProperty = bar", referencingModuleCode); + + var referencingClassCode = actualModuleCode["ClassModule"]; + StringAssert.Contains($"{sourceModuleName}.MyProperty = ", referencingClassCode); + StringAssert.DoesNotContain($"{sourceModuleName}.{sourceModuleName}.MyProperty = ", referencingClassCode); + StringAssert.Contains($" .MyProperty = bar", referencingClassCode); + } + protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) { return Support.SupportTestRefactoring(rewritingManager, state, factory, selectionService); diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs index cfb3a34e7f..8dbd2f64a8 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulatedUDTFieldTests.cs @@ -889,6 +889,96 @@ Private Function First() As String StringAssert.Contains("Public Property Let Second", actualCode); } + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UDTMemberIsPrivateUDT() + { + string inputCode = +$@" + +Private Type TFoo + Foo As Integer + Bar As Byte +End Type + +Private Type TBar + FooBar As TFoo +End Type + +Private my|Bar As TBar +"; + + var presenterAction = Support.UserAcceptsDefaults(); + + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + + StringAssert.Contains("Public Property Let Foo(", actualCode); + StringAssert.Contains("Public Property Let Bar(", actualCode); + StringAssert.Contains("myBar.FooBar.Foo = value", actualCode); + } + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UDTMemberIsPrivateUDT_RepeatedType() + { + string inputCode = +$@" + +Private Type TFoo + Foo As Integer + Bar As Byte +End Type + +Private Type TBar + FooBar As TFoo + ReBar As TFoo +End Type + +Private my|Bar As TBar +"; + + var presenterAction = Support.UserAcceptsDefaults(); + + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + + StringAssert.Contains("Public Property Let Foo(", actualCode); + StringAssert.Contains("Public Property Let Bar(", actualCode); + StringAssert.Contains("Public Property Let Foo_1(", actualCode); + StringAssert.Contains("Public Property Let Bar_1(", actualCode); + StringAssert.Contains("myBar.FooBar.Foo = value", actualCode); + StringAssert.Contains("myBar.ReBar.Foo = value", actualCode); + } + + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void UDTMemberIsPublicUDT() + { + string inputCode = +$@" + +Public Type TFoo + Foo As Integer + Bar As Byte +End Type + +Private Type TBar + FooBar As TFoo +End Type + +Private my|Bar As TBar +"; + + var presenterAction = Support.UserAcceptsDefaults(); + + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + + StringAssert.Contains("Public Property Let FooBar(", actualCode); + StringAssert.Contains("myBar.FooBar = value", actualCode); + } + protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) { return Support.SupportTestRefactoring(rewritingManager, state, factory, selectionService); From dce7b5ef9d39164ef8013a33ab2d5f4f8d497048 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Mon, 13 Jan 2020 14:34:09 -0800 Subject: [PATCH 142/461] ResourceFile changes --- Rubberduck.Resources/RubberduckUI.Designer.cs | 74 ++++++++++++++++++- Rubberduck.Resources/RubberduckUI.cs.resx | 6 -- Rubberduck.Resources/RubberduckUI.de.resx | 6 -- Rubberduck.Resources/RubberduckUI.es.resx | 6 -- Rubberduck.Resources/RubberduckUI.fr.resx | 6 -- Rubberduck.Resources/RubberduckUI.resx | 27 ++++++- 6 files changed, 99 insertions(+), 26 deletions(-) diff --git a/Rubberduck.Resources/RubberduckUI.Designer.cs b/Rubberduck.Resources/RubberduckUI.Designer.cs index 171761f190..395640373f 100644 --- a/Rubberduck.Resources/RubberduckUI.Designer.cs +++ b/Rubberduck.Resources/RubberduckUI.Designer.cs @@ -1211,6 +1211,15 @@ public static string EmptyUIRefreshMessage_Title { } } + /// + /// Looks up a localized string similar to Unable to encapsulate {0}. Redim({0}) statement(s) exist in other modules. + /// + public static string EncapsulateField_ArrayHasExternalRedimFormat { + get { + return ResourceManager.GetString("EncapsulateField_ArrayHasExternalRedimFormat", resourceCulture); + } + } + /// /// Looks up a localized string similar to Rubberduck - Encapsulate Field. /// @@ -1221,7 +1230,25 @@ public static string EncapsulateField_Caption { } /// - /// Looks up a localized string similar to Please specify property name, parameter accessibility, and setter type.. + /// Looks up a localized string similar to this. + /// + public static string EncapsulateField_DefaultObjectStateUDTFieldName { + get { + return ResourceManager.GetString("EncapsulateField_DefaultObjectStateUDTFieldName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to value. + /// + public static string EncapsulateField_DefaultPropertyParameter { + get { + return ResourceManager.GetString("EncapsulateField_DefaultPropertyParameter", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Select one or more fields to encapsulate. Accept the default values or edit property names. /// public static string EncapsulateField_InstructionText { get { @@ -1229,6 +1256,15 @@ public static string EncapsulateField_InstructionText { } } + /// + /// Looks up a localized string similar to Name Conflict Detected. + /// + public static string EncapsulateField_NameConflictDetected { + get { + return ResourceManager.GetString("EncapsulateField_NameConflictDetected", resourceCulture); + } + } + /// /// Looks up a localized string similar to Parameter Name:. /// @@ -1247,6 +1283,24 @@ public static string EncapsulateField_Preview { } } + /// + /// Looks up a localized string similar to '<===== Property and Declaration changes above this line =====>. + /// + public static string EncapsulateField_PreviewMarker { + get { + return ResourceManager.GetString("EncapsulateField_PreviewMarker", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Creates a Property for each UDT Member. + /// + public static string EncapsulateField_PrivateUDTPropertyText { + get { + return ResourceManager.GetString("EncapsulateField_PrivateUDTPropertyText", resourceCulture); + } + } + /// /// Looks up a localized string similar to Property Name:. /// @@ -1256,6 +1310,15 @@ public static string EncapsulateField_PropertyName { } } + /// + /// Looks up a localized string similar to Read Only. + /// + public static string EncapsulateField_ReadOnlyCheckBoxContent { + get { + return ResourceManager.GetString("EncapsulateField_ReadOnlyCheckBoxContent", resourceCulture); + } + } + /// /// Looks up a localized string similar to Setter Type:. /// @@ -1274,6 +1337,15 @@ public static string EncapsulateField_TitleText { } } + /// + /// Looks up a localized string similar to Wrap Fields in Private Type. + /// + public static string EncapsulateField_WrapFieldsInPrivateType { + get { + return ResourceManager.GetString("EncapsulateField_WrapFieldsInPrivateType", resourceCulture); + } + } + /// /// Looks up a localized string similar to Absolute. /// diff --git a/Rubberduck.Resources/RubberduckUI.cs.resx b/Rubberduck.Resources/RubberduckUI.cs.resx index e0ff6965ff..9d4590e2a9 100644 --- a/Rubberduck.Resources/RubberduckUI.cs.resx +++ b/Rubberduck.Resources/RubberduckUI.cs.resx @@ -623,15 +623,9 @@ Jste si jisti, že chcete pokračovat s tímto přejmenováním? Jméno Property: - - Typ Setteru: - Zapouzdřit Pole - - Jméno Vlastnosti: - Rubberduck - Přesuň na Místo Použití diff --git a/Rubberduck.Resources/RubberduckUI.de.resx b/Rubberduck.Resources/RubberduckUI.de.resx index 22c1cf3210..2630b38666 100644 --- a/Rubberduck.Resources/RubberduckUI.de.resx +++ b/Rubberduck.Resources/RubberduckUI.de.resx @@ -575,12 +575,6 @@ Wollen Sie trotzdem fortfahren? Feld Kapseln - - Eigenschaftsname - - - Typ für 'Set': - '{0}' hat keine Referenzen. diff --git a/Rubberduck.Resources/RubberduckUI.es.resx b/Rubberduck.Resources/RubberduckUI.es.resx index b45d0e3f68..a3352c0841 100644 --- a/Rubberduck.Resources/RubberduckUI.es.resx +++ b/Rubberduck.Resources/RubberduckUI.es.resx @@ -577,15 +577,9 @@ Advertencia: Se perderán todos los ajustes personalizados. Su archivo anterior Nombre de la propiedad: - - Tipo de conjuntos: - Campo encapsulado - - Nombre del parámetro: - Rubberduck - Acercar al uso diff --git a/Rubberduck.Resources/RubberduckUI.fr.resx b/Rubberduck.Resources/RubberduckUI.fr.resx index b357a9bb67..2d54f147b8 100644 --- a/Rubberduck.Resources/RubberduckUI.fr.resx +++ b/Rubberduck.Resources/RubberduckUI.fr.resx @@ -507,9 +507,6 @@ Attention: les valeurs personnalisées seront perdues. Le fichier original se Allemand - - Nom du paramètre: - Référer explicitement au classeur actif @@ -612,9 +609,6 @@ Attention: les valeurs personnalisées seront perdues. Le fichier original se Remplacer tout - - Mutateur: - Sélection invalide diff --git a/Rubberduck.Resources/RubberduckUI.resx b/Rubberduck.Resources/RubberduckUI.resx index a28f453774..da901ff542 100644 --- a/Rubberduck.Resources/RubberduckUI.resx +++ b/Rubberduck.Resources/RubberduckUI.resx @@ -572,7 +572,7 @@ Do you want to proceed with this rename? Rubberduck - Encapsulate Field - Please specify property name, parameter accessibility, and setter type. + Select one or more fields to encapsulate. Accept the default values or edit property names Preview: @@ -1754,4 +1754,29 @@ Import aborted. VB Form + + Unable to encapsulate {0}. Redim({0}) statement(s) exist in other modules + {0} = selected field IdentifierName + + + this + + + value + + + Name Conflict Detected + + + '<===== Property and Declaration changes above this line =====> + + + Creates a Property for each UDT Member + + + Read Only + + + Wrap Fields in Private Type + \ No newline at end of file From 115735dd1b213d5afe47e8299e52a6f219dd9fee Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Mon, 13 Jan 2020 14:34:44 -0800 Subject: [PATCH 143/461] UI uses UI resources --- .../EncapsulateFieldView.xaml | 16 +++--- .../EncapsulateFieldViewModel.cs | 57 +++++++------------ 2 files changed, 29 insertions(+), 44 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml index 8b4fa16321..97cdd8a6d8 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml @@ -33,9 +33,9 @@ - @@ -169,7 +169,7 @@ Margin="10,5,0,5" Height="22" VerticalAlignment="Center" - Text="{Binding Path=PrivateUDTPropertyText}" + Text="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=EncapsulateField_PrivateUDTPropertyText}" MinWidth="80" /> - ef.EncapsulateFlag).ToList(); - _masterDetail = new MasterDetailSelectionManager(model.SelectedFieldCandidates.SingleOrDefault()); + _masterDetailManager = new MasterDetailSelectionManager(model.SelectedFieldCandidates.SingleOrDefault()); ManageEncapsulationFlagsAndSelectedItem(); @@ -177,18 +177,18 @@ public IEncapsulatedFieldViewData SelectedField { if (value is null) { return; } - _masterDetail.SelectionTargetID = value.TargetID; + _masterDetailManager.SelectionTargetID = value.TargetID; OnPropertyChanged(nameof(SelectedField)); - if (_masterDetail.DetailUpdateRequired) + if (_masterDetailManager.DetailUpdateRequired) { - _masterDetail.DetailField = SelectedField; + _masterDetailManager.DetailField = SelectedField; UpdateDetailForSelection(); } OnPropertyChanged(nameof(PropertiesPreview)); } - get => EncapsulationFields.FirstOrDefault(f => f.TargetID.Equals(_masterDetail.SelectionTargetID)); + get => EncapsulationFields.FirstOrDefault(f => f.TargetID.Equals(_masterDetailManager.SelectionTargetID)); } private void UpdateDetailForSelection() @@ -216,26 +216,26 @@ public string PropertyName { if (SelectedField is null || value is null) { return; } - _masterDetail.DetailField.PropertyName = value; + _masterDetailManager.DetailField.PropertyName = value; UpdateDetailForSelection(); } - get => _masterDetail.DetailField?.PropertyName ?? SelectedField?.PropertyName ?? string.Empty; + get => _masterDetailManager.DetailField?.PropertyName ?? SelectedField?.PropertyName ?? string.Empty; } public bool SelectedFieldIsNotFlagged - => !(_masterDetail.DetailField?.EncapsulateFlag ?? false); + => !(_masterDetailManager.DetailField?.EncapsulateFlag ?? false); public bool SelectedFieldIsPrivateUDT - => (_masterDetail.DetailField?.IsPrivateUserDefinedType ?? false); + => (_masterDetailManager.DetailField?.IsPrivateUserDefinedType ?? false); public bool SelectedFieldHasEditablePropertyName => !SelectedFieldIsPrivateUDT; public bool EnableReadOnlyOption - => !(_masterDetail.DetailField?.IsRequiredToBeReadOnly ?? false); + => !(_masterDetailManager.DetailField?.IsRequiredToBeReadOnly ?? false); - public string GroupBoxHeaderContent - => $"{_masterDetail.DetailField?.TargetID ?? string.Empty} {EncapsulateFieldResources.GroupBoxHeaderSuffix} "; + public string GroupBoxHeaderContent + => $"{_masterDetailManager.DetailField?.TargetID ?? string.Empty} {RubberduckUI.EncapsulateField_PropertyName} "; private string _validationErrorMessage; public string ValidationErrorMessage => _validationErrorMessage; @@ -265,9 +265,9 @@ public bool IsReadOnly { set { - _masterDetail.DetailField.IsReadOnly = value; + _masterDetailManager.DetailField.IsReadOnly = value; } - get => _masterDetail.DetailField?.IsReadOnly ?? SelectedField?.IsReadOnly ?? false; + get => _masterDetailManager.DetailField?.IsReadOnly ?? SelectedField?.IsReadOnly ?? false; } public bool ConvertFieldsToUDTMembers @@ -308,7 +308,7 @@ private void RefreshValidationResults() } _hasValidNames = !_failedValidationResults.Any(); - if (_failedValidationResults.TryGetValue(_masterDetail.SelectionTargetID, out var errorMsg)) + if (_failedValidationResults.TryGetValue(_masterDetailManager.SelectionTargetID, out var errorMsg)) { _validationErrorMessage = errorMsg; _selectionHasValidEncapsulationAttributes = false; @@ -333,7 +333,7 @@ private void ToggleSelection(bool value) } else { - _masterDetail.DetailField = null; + _masterDetailManager.DetailField = null; } ReloadListAndPreview(); RefreshValidationResults(); @@ -346,26 +346,11 @@ private void ToggleSelection(bool value) public CommandBase EncapsulateFlagChangeCommand { get; } public CommandBase ReadOnlyChangeCommand { get; } - public string Caption - => EncapsulateFieldResources.Caption; - - public string InstructionText - => EncapsulateFieldResources.InstructionText; - - public string Preview - => EncapsulateFieldResources.Preview; - - public string TitleText - => EncapsulateFieldResources.TitleText; - - public string PrivateUDTPropertyText - => EncapsulateFieldResources.PrivateUDTPropertyText; - private void ChangeIsReadOnlyFlag(object param) { if (SelectedField is null) { return; } - _masterDetail.DetailField.IsReadOnly = SelectedField.IsReadOnly; + _masterDetailManager.DetailField.IsReadOnly = SelectedField.IsReadOnly; OnPropertyChanged(nameof(IsReadOnly)); OnPropertyChanged(nameof(PropertiesPreview)); } @@ -412,11 +397,11 @@ private void ManageEncapsulationFlagsAndSelectedItem(object param = null) private void SetSelectedField(IEncapsulatedFieldViewData selected) { - _masterDetail.SelectionTargetID = selected?.TargetID ?? null; + _masterDetailManager.SelectionTargetID = selected?.TargetID ?? null; OnPropertyChanged(nameof(SelectedField)); - if (_masterDetail.DetailUpdateRequired) + if (_masterDetailManager.DetailUpdateRequired) { - _masterDetail.DetailField = SelectedField; + _masterDetailManager.DetailField = SelectedField; UpdateDetailForSelection(); } } From 50e4b675065bd2669adb6146a0e54e435ac104a9 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Mon, 13 Jan 2020 14:41:50 -0800 Subject: [PATCH 144/461] Modified to use RubberduckUI resources --- .../EncapsulateFIeldResources.cs | 42 ------------------- .../EncapsulateFieldStrategyBase.cs | 3 +- .../FieldCandidates/ArrayCandidate.cs | 14 +++++++ .../ConvertToUDTMemberCandidate.cs | 22 +++------- .../EncapsulateFieldCandidate.cs | 5 ++- .../EncapsulationIdentifiers.cs | 3 +- .../EncapsulateField/ObjectStateUDT.cs | 3 +- .../EncapsulateFieldConflictFinderBase.cs | 3 +- .../EncapsulateFieldValidationsProvider.cs | 3 +- .../EncapsulateArrayFieldTests.cs | 9 +++- 10 files changed, 40 insertions(+), 67 deletions(-) delete mode 100644 Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs deleted file mode 100644 index 7146628ae2..0000000000 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFIeldResources.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Rubberduck.Resources; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Rubberduck.Refactorings.EncapsulateField -{ - //TODO: All the raw strings here will be assigned keys in RubberduckUI.resx - //just before the 'WIP' annotation is removed - public class EncapsulateFieldResources - { - public static string PreviewMarker - => "'<===== Property and Declaration changes above this line =====>"; - - public static string DefaultPropertyParameter => "value"; - - public static string DefaultStateUDTFieldName => "this"; - - public static string GroupBoxHeaderSuffix = "Property Name"; - - public static string Caption - => RubberduckUI.EncapsulateField_Caption; - - public static string InstructionText /* => RubberduckUI.EncapsulateField_InstructionText*/ - => "Select one or more fields to encapsulate. Accept the default values or edit property names"; - - public static string Preview - => RubberduckUI.EncapsulateField_Preview; - - public static string TitleText - => RubberduckUI.EncapsulateField_TitleText; - - public static string PrivateUDTPropertyText - => "Creates a Property for Each UDT Member"; - - public static string NameConflictDetected => "Name Conflict Detected"; - - public static string ArrayHasExternalRedimFormat => "Storage space for {0} is reallocated external to module '{1}'"; - } -} diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs index e5ffc4ed8e..f5f5b3ccab 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs @@ -4,6 +4,7 @@ using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings.EncapsulateField.Extensions; +using Rubberduck.Resources; using Rubberduck.SmartIndenter; using Rubberduck.VBEditor; using System; @@ -91,7 +92,7 @@ private void InsertNewContent(EncapsulateFieldModel model, IEncapsulateFieldRewr if (isPreview) { - AddContentBlock(NewContentTypes.PostContentMessage, EncapsulateFieldResources.PreviewMarker); + AddContentBlock(NewContentTypes.PostContentMessage, RubberduckUI.EncapsulateField_PreviewMarker); } var newContentBlock = string.Join(DoubleSpace, diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs index 04bf5cb2dd..d00327a57e 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs @@ -2,6 +2,7 @@ using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; +using Rubberduck.Resources; using System; using System.Linq; @@ -31,6 +32,19 @@ public ArrayCandidate(Declaration declaration, IValidateVBAIdentifiers validator } } + public override bool TryValidateEncapsulationAttributes(out string errorMessage) + { + errorMessage = string.Empty; + if (!EncapsulateFlag) { return true; } + + if (HasExternalRedimOperation) + { + errorMessage = string.Format(RubberduckUI.EncapsulateField_ArrayHasExternalRedimFormat, IdentifierName); + return false; + } + return ConflictFinder.TryValidateEncapsulationAttributes(this, out errorMessage); + } + public string UDTMemberDeclaration => $"{PropertyIdentifier}({_subscripts}) {Tokens.As} {Declaration.AsTypeName}"; diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs index 1b241b0ee4..503f539482 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs @@ -136,6 +136,10 @@ public string ReferenceAccessor(IdentifierReference idRef) public bool TryValidateEncapsulationAttributes(out string errorMessage) { + if (_wrapped is IArrayCandidate ac) + { + return ac.TryValidateEncapsulationAttributes(out errorMessage); + } return ConflictFinder.TryValidateEncapsulationAttributes(this, out errorMessage); } @@ -169,22 +173,8 @@ public override bool Equals(object obj) public override int GetHashCode() => _hashCode; - private static string BuildUniqueID(IEncapsulateFieldCandidate candidate, IObjectStateUDT field) => $"{candidate.QualifiedModuleName.Name}.{field.IdentifierName}.{candidate.IdentifierName}"; - - private PropertyAttributeSet CreateMemberPropertyAttributeSet (IUserDefinedTypeMemberCandidate udtMember) - { - return new PropertyAttributeSet() - { - PropertyName = udtMember.PropertyIdentifier, - BackingField = $"{ObjectStateUDT.FieldIdentifier}.{udtMember.UDTField.PropertyIdentifier}.{udtMember.BackingIdentifier}", - AsTypeName = udtMember.PropertyAsTypeName, - ParameterName = udtMember.ParameterName, - GenerateLetter = udtMember.ImplementLet, - GenerateSetter = udtMember.ImplementSet, - UsesSetAssignment = udtMember.Declaration.IsObject, - IsUDTProperty = (udtMember.Declaration.AsTypeDeclaration?.DeclarationType ?? DeclarationType.Variable) == DeclarationType.UserDefinedType - }; - } + private static string BuildUniqueID(IEncapsulateFieldCandidate candidate, IObjectStateUDT field) + => $"{candidate.QualifiedModuleName.Name}.{field.IdentifierName}.{candidate.IdentifierName}"; private PropertyAttributeSet AsPropertyAttributeSet { diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs index 47a8b71768..f257230dd2 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs @@ -2,6 +2,7 @@ using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.Refactorings.EncapsulateField.Extensions; +using Rubberduck.Resources; using Rubberduck.VBEditor; using Rubberduck.VBEditor.SafeComWrappers; using System; @@ -99,7 +100,7 @@ public virtual string BackingIdentifier public virtual IEncapsulateFieldConflictFinder ConflictFinder { set; get; } - public bool TryValidateEncapsulationAttributes(out string errorMessage) + public virtual bool TryValidateEncapsulationAttributes(out string errorMessage) => ConflictFinder.TryValidateEncapsulationAttributes(this, out errorMessage); public virtual string TargetID => _target?.IdentifierName ?? IdentifierName; @@ -205,7 +206,7 @@ public string IdentifierName public virtual string ReferenceQualifier { set; get; } - public string ParameterName { set; get; } = EncapsulateFieldResources.DefaultPropertyParameter; + public string ParameterName { set; get; } = RubberduckUI.EncapsulateField_DefaultPropertyParameter; private bool _implLet; public bool ImplementLet { get => !IsReadOnly && _implLet; set => _implLet = value; } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs index 8f60f475f3..a5e096d8cb 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulationIdentifiers.cs @@ -4,12 +4,13 @@ using System.Collections.Generic; using Rubberduck.Refactorings.EncapsulateField.Extensions; using System; +using Rubberduck.Resources; namespace Rubberduck.Refactorings.EncapsulateField { public class EncapsulationIdentifiers { - private static string DEFAULT_WRITE_PARAMETER = EncapsulateFieldResources.DefaultPropertyParameter; + private static string DEFAULT_WRITE_PARAMETER = RubberduckUI.EncapsulateField_DefaultPropertyParameter; private KeyValuePair _fieldAndProperty; private string _targetIdentifier; diff --git a/Rubberduck.Refactorings/EncapsulateField/ObjectStateUDT.cs b/Rubberduck.Refactorings/EncapsulateField/ObjectStateUDT.cs index 7bb12298fc..e714a9ef9c 100644 --- a/Rubberduck.Refactorings/EncapsulateField/ObjectStateUDT.cs +++ b/Rubberduck.Refactorings/EncapsulateField/ObjectStateUDT.cs @@ -9,6 +9,7 @@ using System.Text; using System.Threading.Tasks; using Rubberduck.Refactorings.EncapsulateField.Extensions; +using Rubberduck.Resources; namespace Rubberduck.Refactorings.EncapsulateField { @@ -29,7 +30,7 @@ public interface IObjectStateUDT : IEncapsulateFieldRefactoringElement //newly inserted declaration public class ObjectStateUDT : IObjectStateUDT { - private static string _defaultNewFieldName = EncapsulateFieldResources.DefaultStateUDTFieldName; + private static string _defaultNewFieldName = RubberduckUI.EncapsulateField_DefaultObjectStateUDTFieldName; // EncapsulateFieldResources.DefaultStateUDTFieldName; private List _convertedMembers; private readonly IUserDefinedTypeCandidate _wrappedUDT; diff --git a/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldConflictFinderBase.cs b/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldConflictFinderBase.cs index 809933cdff..0093293b69 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldConflictFinderBase.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldConflictFinderBase.cs @@ -1,6 +1,7 @@ using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings.EncapsulateField.Extensions; +using Rubberduck.Resources; using Rubberduck.VBEditor; using System; using System.Collections.Generic; @@ -116,7 +117,7 @@ protected virtual bool InternalHasConflictingIdentifier(IEncapsulateFieldCandida if (potentialDeclarationIdentifierConflicts.Any(m => m.IsEquivalentVBAIdentifierTo(identifierToCompare))) { - errorMessage = EncapsulateFieldResources.NameConflictDetected; + errorMessage = RubberduckUI.EncapsulateField_NameConflictDetected; return true; } return false; diff --git a/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldValidationsProvider.cs b/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldValidationsProvider.cs index c4ec6604ab..1ec9987cfe 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldValidationsProvider.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Validations/EncapsulateFieldValidationsProvider.cs @@ -2,6 +2,7 @@ using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings.Common; using Rubberduck.Refactorings.EncapsulateField.Extensions; +using Rubberduck.Resources; using Rubberduck.VBEditor; using System; using System.Collections.Generic; @@ -83,7 +84,7 @@ public static IValidateVBAIdentifiers NameOnlyValidator(NameValidators validator public static IEncapsulateFieldCandidate AssignNoConflictParameter(IEncapsulateFieldCandidate candidate) { - candidate.ParameterName = EncapsulateFieldResources.DefaultPropertyParameter; + candidate.ParameterName = RubberduckUI.EncapsulateField_DefaultPropertyParameter; var guard = 0; while (guard++ < 10 && (candidate.BackingIdentifier.IsEquivalentVBAIdentifierTo(candidate.ParameterName) diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateArrayFieldTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateArrayFieldTests.cs index 93aa8b1c5d..b4a3abac9a 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateArrayFieldTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateArrayFieldTests.cs @@ -4,6 +4,7 @@ using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings; using Rubberduck.Refactorings.EncapsulateField; +using Rubberduck.Resources; using Rubberduck.VBEditor; using Rubberduck.VBEditor.Utility; using RubberduckTests.Mocks; @@ -204,9 +205,13 @@ End Sub var vbe = MockVbeBuilder.BuildFromStdModules(("SourceModule", inputCode), ("ClientModule", redimCode)); var model = Support.RetrieveUserModifiedModelPriorToRefactoring(vbe.Object, fieldUT, DeclarationType.Variable, presenterAction); - model[fieldUT].TryValidateEncapsulationAttributes(out var errorMessage); + var field = model[fieldUT]; - StringAssert.AreNotEqualIgnoringCase(EncapsulateFieldResources.ArrayHasExternalRedimFormat, errorMessage); + field.TryValidateEncapsulationAttributes(out var errorMessage); + + var expectedError = string.Format(RubberduckUI.EncapsulateField_ArrayHasExternalRedimFormat, field.IdentifierName); + + StringAssert.AreEqualIgnoringCase(expectedError, errorMessage); } protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) From cc99a0b71be10f8c59729ce91a6f7e2477176f27 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Tue, 14 Jan 2020 00:17:24 +0100 Subject: [PATCH 145/461] Make reporting of unhandled exceptions more useful --- Rubberduck.Main/Extension.cs | 43 ++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/Rubberduck.Main/Extension.cs b/Rubberduck.Main/Extension.cs index feee0fc3da..fb4a27d29d 100644 --- a/Rubberduck.Main/Extension.cs +++ b/Rubberduck.Main/Extension.cs @@ -232,7 +232,7 @@ private void Startup() try { var currentDomain = AppDomain.CurrentDomain; - currentDomain.UnhandledException += HandlAppDomainException; + currentDomain.UnhandledException += HandleAppDomainException; currentDomain.AssemblyResolve += LoadFromSameFolder; _container = new WindsorContainer().Install(new RubberduckIoCInstaller(_vbe, _addin, _initialSettings, _vbeNativeApi, _beepInterceptor)); @@ -244,14 +244,25 @@ private void Startup() } catch (Exception e) { - _logger.Log(LogLevel.Fatal, e, "Startup sequence threw an unexpected exception."); + _logger.Fatal(e, "Startup sequence threw an unexpected exception."); throw new Exception("Rubberduck's startup sequence threw an unexpected exception. Please check the Rubberduck logs for more information and report an issue if necessary", e); } } - private void HandlAppDomainException(object sender, UnhandledExceptionEventArgs e) + private void HandleAppDomainException(object sender, UnhandledExceptionEventArgs e) { - _logger.Log(LogLevel.Fatal, e); + var message = e.IsTerminating + ? "An unhandled exception occurred. The runtime is shutting down." + : "An unhandled exception occurred. The runtime continues running."; + if (e.ExceptionObject is Exception exception) + { + _logger.Fatal(exception, message); + + } + else + { + _logger.Fatal(message); + } } private void ShutdownAddIn() @@ -259,12 +270,12 @@ private void ShutdownAddIn() var currentDomain = AppDomain.CurrentDomain; try { - _logger.Log(LogLevel.Info, "Rubberduck is shutting down."); - _logger.Log(LogLevel.Trace, "Unhooking VBENativeServices events..."); + _logger.Info("Rubberduck is shutting down."); + _logger.Trace("Unhooking VBENativeServices events..."); VbeNativeServices.UnhookEvents(); VbeProvider.Terminate(); - _logger.Log(LogLevel.Trace, "Releasing dockable hosts..."); + _logger.Trace("Releasing dockable hosts..."); using (var windows = _vbe.Windows) { @@ -273,14 +284,14 @@ private void ShutdownAddIn() if (_app != null) { - _logger.Log(LogLevel.Trace, "Initiating App.Shutdown..."); + _logger.Trace("Initiating App.Shutdown..."); _app.Shutdown(); _app = null; } if (_container != null) { - _logger.Log(LogLevel.Trace, "Disposing IoC container..."); + _logger.Trace("Disposing IoC container..."); _container.Dispose(); _container = null; } @@ -288,33 +299,33 @@ private void ShutdownAddIn() catch (Exception e) { _logger.Error(e); - _logger.Log(LogLevel.Warn, "Exception is swallowed."); + _logger.Warn("Exception is swallowed."); //throw; // <<~ uncomment to crash the process } finally { try { - _logger.Log(LogLevel.Trace, "Disposing COM safe..."); + _logger.Trace("Disposing COM safe..."); ComSafeManager.DisposeAndResetComSafe(); _addin = null; _vbe = null; _isInitialized = false; - _logger.Log(LogLevel.Info, "No exceptions were thrown."); + _logger.Info("No exceptions were thrown."); } catch (Exception e) { _logger.Error(e); - _logger.Log(LogLevel.Warn, "Exception disposing the ComSafe has been swallowed."); + _logger.Warn("Exception disposing the ComSafe has been swallowed."); //throw; // <<~ uncomment to crash the process } finally { - _logger.Log(LogLevel.Trace, "Unregistering AppDomain handlers...."); + _logger.Trace("Unregistering AppDomain handlers...."); currentDomain.AssemblyResolve -= LoadFromSameFolder; - currentDomain.UnhandledException -= HandlAppDomainException; - _logger.Log(LogLevel.Trace, "Done. Main Shutdown completed. Toolwindows follow. Quack!"); + currentDomain.UnhandledException -= HandleAppDomainException; + _logger.Trace( "Done. Main Shutdown completed. Toolwindows follow. Quack!"); _isInitialized = false; } } From 34a80c7dc6c60bb70a3997b5eb1355d9c63e0404 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Mon, 13 Jan 2020 19:13:04 -0800 Subject: [PATCH 146/461] Reorganizing of UI support classes --- .../EncapsulateFieldViewModel.cs | 181 ++++++------------ .../MasterDetailSelectionManager.cs | 69 +++++++ .../ViewableEncapsulatedField.cs | 4 - 3 files changed, 130 insertions(+), 124 deletions(-) create mode 100644 Rubberduck.Core/UI/Refactorings/EncapsulateField/MasterDetailSelectionManager.cs diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs index 9db31a203a..e6c657e90a 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs @@ -12,72 +12,10 @@ namespace Rubberduck.UI.Refactorings.EncapsulateField { public class EncapsulateFieldViewModel : RefactoringViewModelBase { - private class MasterDetailSelectionManager - { - private const string _neverATargetID = "_Never_a_TargetID_"; - private bool _detailFieldIsFlagged; - - public MasterDetailSelectionManager(IEncapsulateFieldCandidate selected) - : this(selected?.TargetID) - { - if (selected != null) - { - DetailField = new ViewableEncapsulatedField(selected); - } - } - - private MasterDetailSelectionManager(string targetID) - { - SelectionTargetID = targetID; - DetailField = null; - _detailFieldIsFlagged = false; - } - - - private IEncapsulatedFieldViewData _detailField; - public IEncapsulatedFieldViewData DetailField - { - set - { - _detailField = value; - _detailFieldIsFlagged = _detailField?.EncapsulateFlag ?? false; - } - get => _detailField; - } - - private string _selectionTargetID; - public string SelectionTargetID - { - set => _selectionTargetID = value; - get => _selectionTargetID ?? _neverATargetID; - } - - public bool DetailUpdateRequired - { - get - { - if (DetailField is null) - { - return true; - } - - if (_detailFieldIsFlagged != DetailField.EncapsulateFlag) - { - _detailFieldIsFlagged = !_detailFieldIsFlagged; - return true; - } - return SelectionTargetID != DetailField?.TargetID; - } - } - } - private MasterDetailSelectionManager _masterDetailManager; - public RubberduckParserState State { get; } - public EncapsulateFieldViewModel(EncapsulateFieldModel model, RubberduckParserState state) : base(model) + public EncapsulateFieldViewModel(EncapsulateFieldModel model) : base(model) { - State = state; - SelectAllCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), _ => ToggleSelection(true)); DeselectAllCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), _ => ToggleSelection(false)); @@ -159,18 +97,6 @@ public IObjectStateUDT SelectedObjectStateUDT } } - private void SetObjectStateUDT() - { - foreach (var field in UDTFields) - { - field.IsSelected = _selectedObjectStateUDT == field; - } - OnPropertyChanged(nameof(SelectedObjectStateUDT)); - OnPropertyChanged(nameof(EncapsulationFields)); - OnPropertyChanged(nameof(PropertiesPreview)); - } - - public IEncapsulatedFieldViewData SelectedField { set @@ -191,25 +117,6 @@ public IEncapsulatedFieldViewData SelectedField get => EncapsulationFields.FirstOrDefault(f => f.TargetID.Equals(_masterDetailManager.SelectionTargetID)); } - private void UpdateDetailForSelection() - { - - RefreshValidationResults(); - - OnPropertyChanged(nameof(SelectedFieldIsNotFlagged)); - OnPropertyChanged(nameof(GroupBoxHeaderContent)); - OnPropertyChanged(nameof(PropertyName)); - OnPropertyChanged(nameof(IsReadOnly)); - OnPropertyChanged(nameof(HasValidNames)); - OnPropertyChanged(nameof(EnableReadOnlyOption)); - OnPropertyChanged(nameof(SelectedFieldIsPrivateUDT)); - OnPropertyChanged(nameof(SelectedFieldHasEditablePropertyName)); - OnPropertyChanged(nameof(SelectionHasValidEncapsulationAttributes)); - OnPropertyChanged(nameof(PropertiesPreview)); - OnPropertyChanged(nameof(EncapsulationFields)); - OnPropertyChanged(nameof(ValidationErrorMessage)); - } - public string PropertyName { set @@ -291,34 +198,31 @@ public bool ConvertFieldsToUDTMembers private bool _selectionHasValidEncapsulationAttributes; public bool SelectionHasValidEncapsulationAttributes => _selectionHasValidEncapsulationAttributes; - private Dictionary _failedValidationResults = new Dictionary(); - private void RefreshValidationResults() - { - _failedValidationResults.Clear(); - _hasValidNames = true; - _selectionHasValidEncapsulationAttributes = true; - _validationErrorMessage = string.Empty; + public string PropertiesPreview => Model.PreviewRefactoring(); - foreach (var field in EncapsulationFields.Where(ef => ef.EncapsulateFlag)) - { - if (!field.TryValidateEncapsulationAttributes(out var errorMessage)) - { - _failedValidationResults.Add(field.TargetID, errorMessage); - } - } + public CommandBase SelectAllCommand { get; } - _hasValidNames = !_failedValidationResults.Any(); - if (_failedValidationResults.TryGetValue(_masterDetailManager.SelectionTargetID, out var errorMsg)) + public CommandBase DeselectAllCommand { get; } + + public CommandBase IsReadOnlyCommand { get; } + + public CommandBase PropertyChangeCommand { get; } + + public CommandBase EncapsulateFlagChangeCommand { get; } + + public CommandBase ReadOnlyChangeCommand { get; } + + private void SetObjectStateUDT() + { + foreach (var field in UDTFields) { - _validationErrorMessage = errorMsg; - _selectionHasValidEncapsulationAttributes = false; + field.IsSelected = _selectedObjectStateUDT == field; } + OnPropertyChanged(nameof(SelectedObjectStateUDT)); + OnPropertyChanged(nameof(EncapsulationFields)); + OnPropertyChanged(nameof(PropertiesPreview)); } - public string PropertiesPreview => Model.PreviewRefactoring(); - - public CommandBase SelectAllCommand { get; } - public CommandBase DeselectAllCommand { get; } private void ToggleSelection(bool value) { _lastCheckedBoxes.Clear(); @@ -340,11 +244,48 @@ private void ToggleSelection(bool value) UpdateDetailForSelection(); } - public CommandBase IsReadOnlyCommand { get; } - public CommandBase PropertyChangeCommand { get; } + private Dictionary _failedValidationResults = new Dictionary(); + private void RefreshValidationResults() + { + _failedValidationResults.Clear(); + _hasValidNames = true; + _selectionHasValidEncapsulationAttributes = true; + _validationErrorMessage = string.Empty; - public CommandBase EncapsulateFlagChangeCommand { get; } - public CommandBase ReadOnlyChangeCommand { get; } + foreach (var field in EncapsulationFields.Where(ef => ef.EncapsulateFlag)) + { + if (!field.TryValidateEncapsulationAttributes(out var errorMessage)) + { + _failedValidationResults.Add(field.TargetID, errorMessage); + } + } + + _hasValidNames = !_failedValidationResults.Any(); + if (_failedValidationResults.TryGetValue(_masterDetailManager.SelectionTargetID, out var errorMsg)) + { + _validationErrorMessage = errorMsg; + _selectionHasValidEncapsulationAttributes = false; + } + } + + private void UpdateDetailForSelection() + { + + RefreshValidationResults(); + + OnPropertyChanged(nameof(SelectedFieldIsNotFlagged)); + OnPropertyChanged(nameof(GroupBoxHeaderContent)); + OnPropertyChanged(nameof(PropertyName)); + OnPropertyChanged(nameof(IsReadOnly)); + OnPropertyChanged(nameof(HasValidNames)); + OnPropertyChanged(nameof(EnableReadOnlyOption)); + OnPropertyChanged(nameof(SelectedFieldIsPrivateUDT)); + OnPropertyChanged(nameof(SelectedFieldHasEditablePropertyName)); + OnPropertyChanged(nameof(SelectionHasValidEncapsulationAttributes)); + OnPropertyChanged(nameof(PropertiesPreview)); + OnPropertyChanged(nameof(EncapsulationFields)); + OnPropertyChanged(nameof(ValidationErrorMessage)); + } private void ChangeIsReadOnlyFlag(object param) { diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/MasterDetailSelectionManager.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/MasterDetailSelectionManager.cs new file mode 100644 index 0000000000..9b02aac200 --- /dev/null +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/MasterDetailSelectionManager.cs @@ -0,0 +1,69 @@ +using Rubberduck.Refactorings.EncapsulateField; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.UI.Refactorings.EncapsulateField +{ + public class MasterDetailSelectionManager + { + private const string _neverATargetID = "_Never_a_TargetID_"; + private bool _detailFieldIsFlagged; + + public MasterDetailSelectionManager(IEncapsulateFieldCandidate selected) + : this(selected?.TargetID) + { + if (selected != null) + { + DetailField = new ViewableEncapsulatedField(selected); + } + } + + private MasterDetailSelectionManager(string targetID) + { + SelectionTargetID = targetID; + DetailField = null; + _detailFieldIsFlagged = false; + } + + + private IEncapsulatedFieldViewData _detailField; + public IEncapsulatedFieldViewData DetailField + { + set + { + _detailField = value; + _detailFieldIsFlagged = _detailField?.EncapsulateFlag ?? false; + } + get => _detailField; + } + + private string _selectionTargetID; + public string SelectionTargetID + { + set => _selectionTargetID = value; + get => _selectionTargetID ?? _neverATargetID; + } + + public bool DetailUpdateRequired + { + get + { + if (DetailField is null) + { + return true; + } + + if (_detailFieldIsFlagged != DetailField.EncapsulateFlag) + { + _detailFieldIsFlagged = !_detailFieldIsFlagged; + return true; + } + return SelectionTargetID != DetailField?.TargetID; + } + } + } + +} diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs index 23fad97b7c..e1496dae0d 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/ViewableEncapsulatedField.cs @@ -57,10 +57,6 @@ public bool HasValidEncapsulationAttributes public bool TryValidateEncapsulationAttributes(out string errorMessage) { errorMessage = string.Empty; - if (IsPrivateUserDefinedType) - { - return true; - } return _efd.TryValidateEncapsulationAttributes(out errorMessage); } From 9e44ec4136345179bdacda39ac0328229c01c91b Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Mon, 13 Jan 2020 19:15:02 -0800 Subject: [PATCH 147/461] Removal of un-ref'd model parameter --- .../EncapsulateFieldRefactoring.cs | 2 +- .../ConvertFieldsToUDTMembers.cs | 20 +++++++------- .../EncapsulateFieldStrategyBase.cs | 26 +++++++++---------- .../UseBackingFields.cs | 8 +++--- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 51ca92c175..e6c9cd906b 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -126,7 +126,7 @@ private IEncapsulateFieldRewriteSession RefactorRewrite(EncapsulateFieldModel mo ? new ConvertFieldsToUDTMembers(_declarationFinderProvider, model, _indenter) as IEncapsulateStrategy : new UseBackingFields(_declarationFinderProvider, model, _indenter) as IEncapsulateStrategy; - return strategy.RefactorRewrite(model, refactorRewriteSession, asPreview); + return strategy.RefactorRewrite(refactorRewriteSession, asPreview); } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs index e0375c1903..d14e320714 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs @@ -23,38 +23,38 @@ public ConvertFieldsToUDTMembers(IDeclarationFinderProvider declarationFinderPro _stateUDTField = model.StateUDTField; } - protected override void ModifyFields(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) + protected override void ModifyFields(IEncapsulateFieldRewriteSession refactorRewriteSession) { var rewriter = refactorRewriteSession.CheckOutModuleRewriter(_targetQMN); - foreach (var field in model.SelectedFieldCandidates) + foreach (var field in SelectedFields) { refactorRewriteSession.Remove(field.Declaration, rewriter); } if (_stateUDTField.IsExistingDeclaration) { - _stateUDTField.AddMembers(model.SelectedFieldCandidates.Cast()); + _stateUDTField.AddMembers(SelectedFields.Cast()); rewriter.Replace(_stateUDTField.AsTypeDeclaration, _stateUDTField.TypeDeclarationBlock(_indenter)); } } - protected override void ModifyReferences(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) + protected override void ModifyReferences(IEncapsulateFieldRewriteSession refactorRewriteSession) { - foreach (var field in model.SelectedFieldCandidates) + foreach (var field in SelectedFields) { LoadFieldReferenceContextReplacements(field); } - RewriteReferences(model, refactorRewriteSession); + RewriteReferences(refactorRewriteSession); } - protected override void LoadNewDeclarationBlocks(EncapsulateFieldModel model) + protected override void LoadNewDeclarationBlocks() { if (_stateUDTField.IsExistingDeclaration) { return; } - _stateUDTField.AddMembers(model.SelectedFieldCandidates.Cast()); + _stateUDTField.AddMembers(SelectedFields.Cast()); AddContentBlock(NewContentTypes.TypeDeclarationBlock, _stateUDTField.TypeDeclarationBlock(_indenter)); @@ -62,9 +62,9 @@ protected override void LoadNewDeclarationBlocks(EncapsulateFieldModel model) return; } - protected override void LoadNewPropertyBlocks(EncapsulateFieldModel model) + protected override void LoadNewPropertyBlocks(/*EncapsulateFieldModel model*/) { - var propertyGenerationSpecs = model.SelectedFieldCandidates.SelectMany(f => f.PropertyAttributeSets); + var propertyGenerationSpecs = /*model.SelectedFieldCandidates*/SelectedFields.SelectMany(f => f.PropertyAttributeSets); var generator = new PropertyGenerator(); foreach (var spec in propertyGenerationSpecs) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs index f5f5b3ccab..c6e80a1cee 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs @@ -17,7 +17,7 @@ namespace Rubberduck.Refactorings.EncapsulateField { public interface IEncapsulateStrategy { - IEncapsulateFieldRewriteSession RefactorRewrite(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession, bool asPreview); + IEncapsulateFieldRewriteSession RefactorRewrite(IEncapsulateFieldRewriteSession refactorRewriteSession, bool asPreview); } public abstract class EncapsulateFieldStrategyBase : IEncapsulateStrategy @@ -46,24 +46,24 @@ public EncapsulateFieldStrategyBase(IDeclarationFinderProvider declarationFinder .FirstOrDefault()?.Context.Start.TokenIndex ?? null; } - public IEncapsulateFieldRewriteSession RefactorRewrite(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession, bool asPreview) + public IEncapsulateFieldRewriteSession RefactorRewrite(IEncapsulateFieldRewriteSession refactorRewriteSession, bool asPreview) { - ModifyFields(model, refactorRewriteSession); + ModifyFields(refactorRewriteSession); - ModifyReferences(model, refactorRewriteSession); + ModifyReferences(refactorRewriteSession); - InsertNewContent(model, refactorRewriteSession, asPreview); + InsertNewContent(refactorRewriteSession, asPreview); return refactorRewriteSession; } - protected abstract void ModifyFields(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession rewriteSession); + protected abstract void ModifyFields(IEncapsulateFieldRewriteSession rewriteSession); - protected abstract void ModifyReferences(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession); + protected abstract void ModifyReferences(IEncapsulateFieldRewriteSession refactorRewriteSession); - protected abstract void LoadNewDeclarationBlocks(EncapsulateFieldModel model); + protected abstract void LoadNewDeclarationBlocks(); - protected void RewriteReferences(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) + protected void RewriteReferences(IEncapsulateFieldRewriteSession refactorRewriteSession) { foreach (var replacement in IdentifierReplacements) { @@ -76,7 +76,7 @@ protected void RewriteReferences(EncapsulateFieldModel model, IEncapsulateFieldR protected void AddContentBlock(NewContentTypes contentType, string block) => _newContent[contentType].Add(block); - private void InsertNewContent(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession, bool isPreview = false) + private void InsertNewContent(IEncapsulateFieldRewriteSession refactorRewriteSession, bool isPreview = false) { _newContent = new Dictionary> { @@ -86,9 +86,9 @@ private void InsertNewContent(EncapsulateFieldModel model, IEncapsulateFieldRewr { NewContentTypes.TypeDeclarationBlock, new List() } }; - LoadNewDeclarationBlocks(model); + LoadNewDeclarationBlocks(); - LoadNewPropertyBlocks(model); + LoadNewPropertyBlocks(); if (isPreview) { @@ -113,7 +113,7 @@ private void InsertNewContent(EncapsulateFieldModel model, IEncapsulateFieldRewr } } - protected virtual void LoadNewPropertyBlocks(EncapsulateFieldModel model) + protected virtual void LoadNewPropertyBlocks() { var propertyGenerationSpecs = SelectedFields.SelectMany(f => f.PropertyAttributeSets); diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/UseBackingFields.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/UseBackingFields.cs index 3cdedf0191..3304555297 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/UseBackingFields.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/UseBackingFields.cs @@ -18,7 +18,7 @@ public class UseBackingFields : EncapsulateFieldStrategyBase public UseBackingFields(IDeclarationFinderProvider declarationFinderProvider, EncapsulateFieldModel model, IIndenter indenter) : base(declarationFinderProvider, model, indenter){ } - protected override void ModifyFields(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) + protected override void ModifyFields(IEncapsulateFieldRewriteSession refactorRewriteSession) { var rewriter = refactorRewriteSession.CheckOutModuleRewriter(_targetQMN); @@ -42,17 +42,17 @@ protected override void ModifyFields(EncapsulateFieldModel model, IEncapsulateFi } } - protected override void ModifyReferences(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession) + protected override void ModifyReferences(IEncapsulateFieldRewriteSession refactorRewriteSession) { foreach (var field in SelectedFields) { LoadFieldReferenceContextReplacements(field); } - RewriteReferences(model, refactorRewriteSession); + RewriteReferences(refactorRewriteSession); } - protected override void LoadNewDeclarationBlocks(EncapsulateFieldModel model) + protected override void LoadNewDeclarationBlocks() { //New field declarations created here were removed from their list within ModifyFields(...) var fieldsRequiringNewDeclaration = SelectedFields From 4f6197844e78c6d9b783ffcc4c44dac06ccf3af7 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Mon, 13 Jan 2020 19:15:30 -0800 Subject: [PATCH 148/461] Reorganizing --- .../EncapsulateField/EncapsulateFieldModel.cs | 85 +++++++++---------- 1 file changed, 42 insertions(+), 43 deletions(-) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index 477286522b..72f8c849d6 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -46,6 +46,10 @@ public EncapsulateFieldModel( public QualifiedModuleName QualifiedModuleName => _targetQMN; + public string PreviewRefactoring() => _previewDelegate(this); + + public IEnumerable ObjectStateUDTCandidates => _objStateCandidates; + private EncapsulateFieldStrategy _encapsulationFieldStategy; public EncapsulateFieldStrategy EncapsulateFieldStrategy { @@ -58,49 +62,13 @@ public EncapsulateFieldStrategy EncapsulateFieldStrategy if (_encapsulationFieldStategy == EncapsulateFieldStrategy.UseBackingFields) { - ChangeSettingToUseBackingFieldsStrategy(); + UpdateFieldCandidatesForUseBackingFieldsStrategy(); return; } - ChangeSettingsToConvertFieldsToUDTMembersStrategy(); + UpdateFieldCandidatesForConvertFieldsToUDTMembersStrategy(); } } - private void ChangeSettingToUseBackingFieldsStrategy() - { - foreach (var candidate in EncapsulationCandidates) - { - candidate.ConflictFinder = _validationsProvider.ConflictDetector(EncapsulateFieldStrategy, _declarationFinderProvider); - switch (candidate) - { - case IUserDefinedTypeCandidate udt: - candidate.NameValidator = EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedType); - break; - case IUserDefinedTypeMemberCandidate udtm: - candidate.NameValidator = candidate.Declaration.IsArray - ? EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMemberArray) - : EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMember); - break; - default: - candidate.NameValidator = EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.Default); - break; - } - EditIdentifiersAsRequired(); - } - } - - private void ChangeSettingsToConvertFieldsToUDTMembersStrategy() - { - foreach (var candidate in EncapsulationCandidates) - { - candidate.ConflictFinder = _validationsProvider.ConflictDetector(EncapsulateFieldStrategy , _declarationFinderProvider); - candidate.NameValidator = candidate.Declaration.IsArray - ? EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMemberArray) - : EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMember); - - EditIdentifiersAsRequired(); - } - } - public IEncapsulateFieldValidationsProvider ValidationsProvider => _validationsProvider; private List _useBackingFieldCandidates; @@ -175,21 +143,52 @@ public IObjectStateUDT StateUDTField if (EncapsulateFieldStrategy == EncapsulateFieldStrategy.ConvertFieldsToUDTMembers) { - EditIdentifiersAsRequired(); + AssignNoConflictIdentifiers(); } } } - private void EditIdentifiersAsRequired() + private void UpdateFieldCandidatesForUseBackingFieldsStrategy() { foreach (var candidate in EncapsulationCandidates) { - candidate.ConflictFinder.AssignNoConflictIdentifiers(candidate); + switch (candidate) + { + case IUserDefinedTypeCandidate udt: + candidate.NameValidator = EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedType); + break; + case IUserDefinedTypeMemberCandidate udtm: + candidate.NameValidator = candidate.Declaration.IsArray + ? EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMemberArray) + : EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMember); + break; + default: + candidate.NameValidator = EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.Default); + break; + } + AssignNoConflictIdentifiers(); } } - public string PreviewRefactoring() => _previewDelegate(this); + private void UpdateFieldCandidatesForConvertFieldsToUDTMembersStrategy() + { + foreach (var candidate in EncapsulationCandidates) + { + candidate.NameValidator = candidate.Declaration.IsArray + ? EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMemberArray) + : EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMember); - public IEnumerable ObjectStateUDTCandidates => _objStateCandidates; + AssignNoConflictIdentifiers(); + } + } + + private void AssignNoConflictIdentifiers() + { + foreach (var candidate in EncapsulationCandidates) + { + candidate.ConflictFinder = _validationsProvider.ConflictDetector(EncapsulateFieldStrategy, _declarationFinderProvider); + candidate.ConflictFinder.AssignNoConflictIdentifiers(candidate); + } + } } } From 28cfd6b1f790b87f44df8eefbc9ce20a9c74b3df Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Mon, 13 Jan 2020 20:20:14 -0800 Subject: [PATCH 149/461] Miscellaneous updates renaming --- .../EncapsulateFieldElementsBuilder.cs | 8 +++--- .../ConvertFieldsToUDTMembers.cs | 4 +-- .../EncapsulateFieldStrategyBase.cs | 4 +-- .../FieldCandidates/ArrayCandidate.cs | 25 +++++++++++-------- .../ConvertToUDTMemberCandidate.cs | 10 ++++++-- .../EncapsulateFieldCandidate.cs | 19 ++++++-------- .../UserDefinedTypeCandidate.cs | 9 +++---- .../UserDefinedTypeMemberCandidate.cs | 2 +- ...ieldsToUDTMembersStrategyConflictFinder.cs | 1 - 9 files changed, 43 insertions(+), 39 deletions(-) diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementsBuilder.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementsBuilder.cs index dd915b15c9..723ddd78c2 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementsBuilder.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldElementsBuilder.cs @@ -15,11 +15,13 @@ public class EncapsulateFieldElementsBuilder { private readonly IDeclarationFinderProvider _declarationFinderProvider; private QualifiedModuleName _targetQMN; + private string _defaultObjectStateUDTTypeName; public EncapsulateFieldElementsBuilder(IDeclarationFinderProvider declarationFinderProvider, QualifiedModuleName targetQMN) { _declarationFinderProvider = declarationFinderProvider; _targetQMN = targetQMN; + _defaultObjectStateUDTTypeName = $"T{_targetQMN.ComponentName}"; CreateRefactoringElements(); } @@ -55,8 +57,7 @@ private void CreateRefactoringElements() ObjectStateUDTCandidates = BuildObjectStateUDTCandidates(candidates).ToList(); - var objectStateUDTIdentifier = $"T{_targetQMN.ComponentName}"; - ObjectStateUDT = ObjectStateUDTCandidates.FirstOrDefault(os => os.AsTypeDeclaration.IdentifierName.StartsWith(objectStateUDTIdentifier, StringComparison.InvariantCultureIgnoreCase)); + ObjectStateUDT = ObjectStateUDTCandidates.FirstOrDefault(os => os.AsTypeDeclaration.IdentifierName.StartsWith(_defaultObjectStateUDTTypeName, StringComparison.InvariantCultureIgnoreCase)); DefaultObjectStateUDT = CreateStateUDTField(); DefaultObjectStateUDT.IsSelected = true; @@ -88,8 +89,7 @@ private IEnumerable BuildObjectStateUDTCandidates(IEnumerable os.AsTypeDeclaration.IdentifierName.StartsWith(objectStateUDTIdentifier, StringComparison.InvariantCultureIgnoreCase)); + var objectStateUDT = objectStateUDTs.FirstOrDefault(os => os.AsTypeDeclaration.IdentifierName.StartsWith(_defaultObjectStateUDTTypeName, StringComparison.InvariantCultureIgnoreCase)); return objectStateUDTs; } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs index d14e320714..880e2608f9 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs @@ -84,7 +84,7 @@ protected override void LoadFieldReferenceContextReplacements(IEncapsulateFieldC { foreach (var idRef in member.FieldContextReferences) { - var replacementText = member.ReferenceAccessor(idRef); + var replacementText = member.IdentifierForReference(idRef); if (IsExternalReferenceRequiringModuleQualification(idRef)) { replacementText = $"{udt.QualifiedModuleName.ComponentName}.{replacementText}"; @@ -98,7 +98,7 @@ protected override void LoadFieldReferenceContextReplacements(IEncapsulateFieldC { foreach (var idRef in field.Declaration.References) { - var replacementText = converted.ReferenceAccessor(idRef); + var replacementText = converted.IdentifierForReference(idRef); if (IsExternalReferenceRequiringModuleQualification(idRef)) { diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs index c6e80a1cee..4826fd69a2 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/EncapsulateFieldStrategyBase.cs @@ -132,7 +132,7 @@ protected virtual void LoadFieldReferenceContextReplacements(IEncapsulateFieldCa { foreach (var idRef in member.FieldContextReferences) { - var replacementText = member.ReferenceAccessor(idRef); + var replacementText = member.IdentifierForReference(idRef); SetUDTMemberReferenceRewriteContent(idRef, replacementText); } } @@ -141,7 +141,7 @@ protected virtual void LoadFieldReferenceContextReplacements(IEncapsulateFieldCa { foreach (var idRef in field.Declaration.References) { - var replacementText = field.ReferenceAccessor(idRef); + var replacementText = field.IdentifierForReference(idRef); if (IsExternalReferenceRequiringModuleQualification(idRef)) { replacementText = $"{field.QualifiedModuleName.ComponentName}.{replacementText}"; diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs index d00327a57e..b9dd90744e 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ArrayCandidate.cs @@ -11,6 +11,7 @@ namespace Rubberduck.Refactorings.EncapsulateField public interface IArrayCandidate : IEncapsulateFieldCandidate { string UDTMemberDeclaration { get;} + bool HasExternalRedimOperation(out string errorMessage); } public class ArrayCandidate : EncapsulateFieldCandidate, IArrayCandidate @@ -37,9 +38,8 @@ public override bool TryValidateEncapsulationAttributes(out string errorMessage) errorMessage = string.Empty; if (!EncapsulateFlag) { return true; } - if (HasExternalRedimOperation) + if (HasExternalRedimOperation(out errorMessage)) { - errorMessage = string.Format(RubberduckUI.EncapsulateField_ArrayHasExternalRedimFormat, IdentifierName); return false; } return ConflictFinder.TryValidateEncapsulationAttributes(this, out errorMessage); @@ -48,14 +48,19 @@ public override bool TryValidateEncapsulationAttributes(out string errorMessage) public string UDTMemberDeclaration => $"{PropertyIdentifier}({_subscripts}) {Tokens.As} {Declaration.AsTypeName}"; - protected override string AccessorInProperty - => $"{BackingIdentifier}"; - - protected override string AccessorLocalReference(IdentifierReference idRef) - => $"{BackingIdentifier}"; + protected override string IdentifierForLocalReferences(IdentifierReference idRef) + => BackingIdentifier; - private bool HasExternalRedimOperation - => Declaration.References.Any(rf => rf.QualifiedModuleName != QualifiedModuleName - && rf.Context.TryGetAncestor(out _)); + public bool HasExternalRedimOperation(out string errorMessage) + { + errorMessage = string.Empty; + if (Declaration.References.Any(rf => rf.QualifiedModuleName != QualifiedModuleName + && rf.Context.TryGetAncestor(out _))) + { + errorMessage = string.Format(RubberduckUI.EncapsulateField_ArrayHasExternalRedimFormat, IdentifierName); + return true; + } + return false; + } } } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs index 503f539482..0251d1adc4 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs @@ -119,7 +119,7 @@ private string AccessorInProperty } } - public string ReferenceAccessor(IdentifierReference idRef) + public string IdentifierForReference(IdentifierReference idRef) { if (idRef.QualifiedModuleName != QualifiedModuleName) { @@ -136,9 +136,15 @@ public string ReferenceAccessor(IdentifierReference idRef) public bool TryValidateEncapsulationAttributes(out string errorMessage) { + errorMessage = string.Empty; + if (!_wrapped.EncapsulateFlag) { return true; } + if (_wrapped is IArrayCandidate ac) { - return ac.TryValidateEncapsulationAttributes(out errorMessage); + if (ac.HasExternalRedimOperation(out errorMessage)) + { + return false; + } } return ConflictFinder.TryValidateEncapsulationAttributes(this, out errorMessage); } diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs index f257230dd2..089532c16d 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/EncapsulateFieldCandidate.cs @@ -34,7 +34,7 @@ public interface IEncapsulateFieldCandidate : IEncapsulateFieldRefactoringElemen IValidateVBAIdentifiers NameValidator { set; get; } IEncapsulateFieldConflictFinder ConflictFinder { set; get; } bool TryValidateEncapsulationAttributes(out string errorMessage); - string ReferenceAccessor(IdentifierReference idRef); + string IdentifierForReference(IdentifierReference idRef); IEnumerable PropertyAttributeSets { get; } } @@ -140,22 +140,19 @@ public override bool Equals(object obj) public override string ToString() =>$"({TargetID}){Declaration.ToString()}"; - protected virtual string AccessorInProperty - => $"{BackingIdentifier}"; + protected string IdentifierInNewProperties + => BackingIdentifier; - public string ReferenceAccessor(IdentifierReference idRef) + public string IdentifierForReference(IdentifierReference idRef) { if (idRef.QualifiedModuleName != QualifiedModuleName) { - return AccessorExternalReference(idRef); + return PropertyIdentifier; } - return AccessorLocalReference(idRef); + return IdentifierForLocalReferences(idRef); } - protected virtual string AccessorLocalReference(IdentifierReference idRef) - => PropertyIdentifier; - - protected virtual string AccessorExternalReference(IdentifierReference idRef) + protected virtual string IdentifierForLocalReferences(IdentifierReference idRef) => PropertyIdentifier; public string PropertyIdentifier @@ -226,7 +223,7 @@ protected virtual PropertyAttributeSet AsPropertyAttributeSet return new PropertyAttributeSet() { PropertyName = PropertyIdentifier, - BackingField = AccessorInProperty, + BackingField = IdentifierInNewProperties, AsTypeName = PropertyAsTypeName, ParameterName = ParameterName, GenerateLetter = ImplementLet, diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs index ff89c84d87..a8d03aa1ea 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeCandidate.cs @@ -114,17 +114,14 @@ public override bool EncapsulateFlag get => base.EncapsulateFlag; } - protected override string AccessorInProperty - => $"{BackingIdentifier}"; - - protected override string AccessorLocalReference(IdentifierReference idRef) + protected override string IdentifierForLocalReferences(IdentifierReference idRef) { if (idRef.Context.Parent.Parent is VBAParser.WithStmtContext wsc) { return BackingIdentifier; } - return TypeDeclarationIsPrivate ? $"{BackingIdentifier}" : $"{PropertyIdentifier}"; + return TypeDeclarationIsPrivate ? BackingIdentifier : PropertyIdentifier; } public override bool Equals(object obj) @@ -174,7 +171,7 @@ protected override PropertyAttributeSet AsPropertyAttributeSet return new PropertyAttributeSet() { PropertyName = PropertyIdentifier, - BackingField = AccessorInProperty, + BackingField = IdentifierInNewProperties, AsTypeName = PropertyAsTypeName, ParameterName = ParameterName, GenerateLetter = ImplementLet, diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs index 16dced30e7..63b525dc68 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/UserDefinedTypeMemberCandidate.cs @@ -68,7 +68,7 @@ public IEncapsulateFieldConflictFinder ConflictFinder public IEnumerable FieldContextReferences => GetUDTMemberReferencesForField(this, UDTField); - public string ReferenceAccessor(IdentifierReference idRef) + public string IdentifierForReference(IdentifierReference idRef) => PropertyIdentifier; public PropertyAttributeSet AsPropertyGeneratorSpec diff --git a/Rubberduck.Refactorings/EncapsulateField/Validations/ConvertFieldsToUDTMembersStrategyConflictFinder.cs b/Rubberduck.Refactorings/EncapsulateField/Validations/ConvertFieldsToUDTMembersStrategyConflictFinder.cs index 893471bd7a..b6c6b0ee5d 100644 --- a/Rubberduck.Refactorings/EncapsulateField/Validations/ConvertFieldsToUDTMembersStrategyConflictFinder.cs +++ b/Rubberduck.Refactorings/EncapsulateField/Validations/ConvertFieldsToUDTMembersStrategyConflictFinder.cs @@ -46,7 +46,6 @@ public override IEncapsulateFieldCandidate AssignNoConflictIdentifiers(IEncapsul return candidate; } - protected override IEncapsulateFieldCandidate AssignNoConflictIdentifier(IEncapsulateFieldCandidate candidate, DeclarationType declarationType) { candidate = base.AssignNoConflictIdentifier(candidate, declarationType); From 830a34912d2754977fa393d4dce1ba30d8d4b2e5 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Tue, 14 Jan 2020 15:58:43 -0800 Subject: [PATCH 150/461] Found failing scenario...added test and resolution --- .../EncapsulateFieldViewModel.cs | 2 +- .../EncapsulateField/EncapsulateFieldModel.cs | 32 ++++++------ .../EncapsulateFieldRefactoring.cs | 2 +- .../ConvertFieldsToUDTMembers.cs | 6 +-- .../ConvertToUDTMemberCandidate.cs | 3 +- .../EncapsulateField/ObjectStateUDT.cs | 3 +- .../EncapsulateFIeldTestSupport.cs | 2 +- .../EncapsulateUsingStateUDTTests.cs | 50 +++++++++++++++++++ 8 files changed, 77 insertions(+), 23 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs index e6c657e90a..5275c21590 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldViewModel.cs @@ -92,7 +92,7 @@ public IObjectStateUDT SelectedObjectStateUDT set { _selectedObjectStateUDT = value; - Model.StateUDTField = _selectedObjectStateUDT; + Model.ObjectStateUDTField = _selectedObjectStateUDT; SetObjectStateUDT(); } } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index 72f8c849d6..53ea4f2a76 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; @@ -41,7 +42,7 @@ public EncapsulateFieldModel( _objStateCandidates.Add(_newObjectStateUDT); EncapsulateFieldStrategy = EncapsulateFieldStrategy.UseBackingFields; - _activeObjectStateUDT = StateUDTField; + _activeObjectStateUDT = ObjectStateUDTField; } public QualifiedModuleName QualifiedModuleName => _targetQMN; @@ -86,10 +87,9 @@ public List EncapsulationCandidates _convertedFields = new List(); foreach (var field in _useBackingFieldCandidates) { - _convertedFields.Add(new ConvertToUDTMember(field, StateUDTField)); + _convertedFields.Add(new ConvertToUDTMember(field, ObjectStateUDTField)); } } - return _convertedFields; } } @@ -114,7 +114,7 @@ public IEncapsulateFieldCandidate this[Declaration fieldDeclaration] => EncapsulationCandidates.Where(c => c.Declaration == fieldDeclaration).Single(); private IObjectStateUDT _activeObjectStateUDT; - public IObjectStateUDT StateUDTField + public IObjectStateUDT ObjectStateUDTField { get { @@ -143,7 +143,15 @@ public IObjectStateUDT StateUDTField if (EncapsulateFieldStrategy == EncapsulateFieldStrategy.ConvertFieldsToUDTMembers) { - AssignNoConflictIdentifiers(); + foreach (var field in EncapsulationCandidates) + { + if (field is IConvertToUDTMember convertedField) + { + convertedField.ObjectStateUDT = _activeObjectStateUDT; + convertedField.ConflictFinder = _validationsProvider.ConflictDetector(EncapsulateFieldStrategy, _declarationFinderProvider); + convertedField.ConflictFinder.AssignNoConflictIdentifiers(convertedField); + } + } } } } @@ -166,26 +174,20 @@ private void UpdateFieldCandidatesForUseBackingFieldsStrategy() candidate.NameValidator = EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.Default); break; } - AssignNoConflictIdentifiers(); + candidate.ConflictFinder = _validationsProvider.ConflictDetector(EncapsulateFieldStrategy, _declarationFinderProvider); + candidate.ConflictFinder.AssignNoConflictIdentifiers(candidate); } } private void UpdateFieldCandidatesForConvertFieldsToUDTMembersStrategy() { - foreach (var candidate in EncapsulationCandidates) + foreach (var candidate in EncapsulationCandidates.Cast()) { + candidate.ObjectStateUDT = ObjectStateUDTField; candidate.NameValidator = candidate.Declaration.IsArray ? EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMemberArray) : EncapsulateFieldValidationsProvider.NameOnlyValidator(NameValidators.UserDefinedTypeMember); - AssignNoConflictIdentifiers(); - } - } - - private void AssignNoConflictIdentifiers() - { - foreach (var candidate in EncapsulationCandidates) - { candidate.ConflictFinder = _validationsProvider.ConflictDetector(EncapsulateFieldStrategy, _declarationFinderProvider); candidate.ConflictFinder.AssignNoConflictIdentifiers(candidate); } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index e6c9cd906b..b9c754c43b 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -91,7 +91,7 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) if (builder.ObjectStateUDT != null) { model.EncapsulateFieldStrategy = EncapsulateFieldStrategy.ConvertFieldsToUDTMembers; - model.StateUDTField = builder.ObjectStateUDT; + model.ObjectStateUDTField = builder.ObjectStateUDT; } return model; diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs index 880e2608f9..b55bd17dc5 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulationStrategies/ConvertFieldsToUDTMembers.cs @@ -20,7 +20,7 @@ public class ConvertFieldsToUDTMembers : EncapsulateFieldStrategyBase public ConvertFieldsToUDTMembers(IDeclarationFinderProvider declarationFinderProvider, EncapsulateFieldModel model, IIndenter indenter) : base(declarationFinderProvider, model, indenter) { - _stateUDTField = model.StateUDTField; + _stateUDTField = model.ObjectStateUDTField; } protected override void ModifyFields(IEncapsulateFieldRewriteSession refactorRewriteSession) @@ -62,9 +62,9 @@ protected override void LoadNewDeclarationBlocks() return; } - protected override void LoadNewPropertyBlocks(/*EncapsulateFieldModel model*/) + protected override void LoadNewPropertyBlocks() { - var propertyGenerationSpecs = /*model.SelectedFieldCandidates*/SelectedFields.SelectMany(f => f.PropertyAttributeSets); + var propertyGenerationSpecs = SelectedFields.SelectMany(f => f.PropertyAttributeSets); var generator = new PropertyGenerator(); foreach (var spec in propertyGenerationSpecs) diff --git a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs index 0251d1adc4..21cfd3e5a9 100644 --- a/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs +++ b/Rubberduck.Refactorings/EncapsulateField/FieldCandidates/ConvertToUDTMemberCandidate.cs @@ -16,6 +16,7 @@ public interface IConvertToUDTMember : IEncapsulateFieldCandidate { string UDTMemberDeclaration { get; } IEncapsulateFieldCandidate WrappedCandidate { get; } + IObjectStateUDT ObjectStateUDT { set; get; } } public class ConvertToUDTMember : IConvertToUDTMember @@ -46,7 +47,7 @@ public virtual string UDTMemberDeclaration public IEncapsulateFieldCandidate WrappedCandidate => _wrapped; - public IObjectStateUDT ObjectStateUDT { private set; get; } + public IObjectStateUDT ObjectStateUDT { set; get; } public string TargetID => _wrapped.TargetID; diff --git a/Rubberduck.Refactorings/EncapsulateField/ObjectStateUDT.cs b/Rubberduck.Refactorings/EncapsulateField/ObjectStateUDT.cs index e714a9ef9c..611fd72b37 100644 --- a/Rubberduck.Refactorings/EncapsulateField/ObjectStateUDT.cs +++ b/Rubberduck.Refactorings/EncapsulateField/ObjectStateUDT.cs @@ -120,7 +120,8 @@ public void AddMembers(IEnumerable fields) { foreach (var member in _wrappedUDT.Members) { - _convertedMembers.Add(new ConvertToUDTMember(member, this)); + var convertedMember = new ConvertToUDTMember(member, this) { EncapsulateFlag = false }; + _convertedMembers.Add(convertedMember); } } _convertedMembers.AddRange(fields); diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFIeldTestSupport.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFIeldTestSupport.cs index acd35a8ab8..6e91c24114 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFIeldTestSupport.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateFIeldTestSupport.cs @@ -74,7 +74,7 @@ public Func SetParameters(UserInpu if (stateUDT != null) { - model.StateUDTField = stateUDT; + model.ObjectStateUDTField = stateUDT; } } else diff --git a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs index 21143e3a6c..71e4f87d1d 100644 --- a/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs +++ b/RubberduckTests/Refactoring/EncapsulateField/EncapsulateUsingStateUDTTests.cs @@ -657,6 +657,56 @@ End Sub StringAssert.Contains($" .MyProperty = bar", referencingClassCode); } + [Test] + [Category("Refactorings")] + [Category("Encapsulate Field")] + public void PrivateUDT_SelectedOtherThanObjectStateUDT() + { + string inputCode = +$@" + +Private Type TTest + TestValue As String + TestNumber As Long +End Type + +Private Type TTestModule1 + SomeValue As Long +End Type + +Private mTest As TTest + +Private this As TTestModule1 + +Private the|Target As Variant + +Public Property Get SomeValue() As Long + SomeValue = this.SomeValue +End Property + +Public Property Let SomeValue(ByVal value As Long) + this.SomeValue = value +End Property + +Public Sub Foo(arg As Long) + SomeValue = arg * 4 +End Sub +"; + + var userInput = new UserInputDataObject() + .UserSelectsField("theTarget"); + + userInput.EncapsulateUsingUDTField("mTest"); + + var presenterAction = Support.SetParameters(userInput); + + var actualCode = Support.RefactoredCode(inputCode.ToCodeString(), presenterAction); + + StringAssert.DoesNotContain("TheTarget = this.TheTarget", actualCode); + StringAssert.Contains("TheTarget = mTest.TheTarget", actualCode); + StringAssert.Contains("TheTarget As Variant", actualCode); + } + protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) { return Support.SupportTestRefactoring(rewritingManager, state, factory, selectionService); From 2384e2892ce22c94149e4971b3e74e3cd9cda87d Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Wed, 15 Jan 2020 01:00:54 +0100 Subject: [PATCH 151/461] Rename inspections and adjust resources according to comments to PR #5338 --- ...ionReturnValueAlwaysDiscardedInspection.cs | 156 +++++++++ ...FunctionReturnValueDiscardedInspection.cs} | 19 +- .../FunctionReturnValueNeverUsedInspection.cs | 311 ------------------ .../QuickFixes/ConvertToProcedureQuickFix.cs | 2 +- .../Inspections/InspectionInfo.Designer.cs | 12 +- .../Inspections/InspectionInfo.cs.resx | 3 - .../Inspections/InspectionInfo.de.resx | 8 +- .../Inspections/InspectionInfo.es.resx | 3 - .../Inspections/InspectionInfo.fr.resx | 3 - .../Inspections/InspectionInfo.resx | 8 +- .../Inspections/InspectionNames.Designer.cs | 12 +- .../Inspections/InspectionNames.cs.resx | 3 - .../Inspections/InspectionNames.de.resx | 8 +- .../Inspections/InspectionNames.es.resx | 3 - .../Inspections/InspectionNames.fr.resx | 3 - .../Inspections/InspectionNames.resx | 8 +- .../Inspections/InspectionResults.Designer.cs | 10 +- .../Inspections/InspectionResults.cs.resx | 3 - .../Inspections/InspectionResults.de.resx | 8 +- .../Inspections/InspectionResults.es.resx | 3 - .../Inspections/InspectionResults.fr.resx | 3 - .../Inspections/InspectionResults.resx | 8 +- ...urnValueAlwaysDiscardedInspectionTests.cs} | 10 +- ...ionReturnValueDiscardedInspectionTests.cs} | 42 +-- .../ConvertToProcedureQuickFixTests.cs | 8 +- .../QuickFixes/IgnoreOnceQuickFixTests.cs | 12 +- 26 files changed, 243 insertions(+), 426 deletions(-) create mode 100644 Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueAlwaysDiscardedInspection.cs rename Rubberduck.CodeAnalysis/Inspections/Concrete/{FunctionReturnValueNotUsedInspection.cs => FunctionReturnValueDiscardedInspection.cs} (86%) delete mode 100644 Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueNeverUsedInspection.cs rename RubberduckTests/Inspections/{FunctionReturnValueNeverUsedInspectionTests.cs => FunctionReturnValueAlwaysDiscardedInspectionTests.cs} (96%) rename RubberduckTests/Inspections/{FunctionReturnValueNotUsedInspectionTests.cs => FunctionReturnValueDiscardedInspectionTests.cs} (85%) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueAlwaysDiscardedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueAlwaysDiscardedInspection.cs new file mode 100644 index 0000000000..b3bfa0cbdc --- /dev/null +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueAlwaysDiscardedInspection.cs @@ -0,0 +1,156 @@ +using System.Collections.Generic; +using System.Linq; +using Antlr4.Runtime; +using Rubberduck.Inspections.Abstract; +using Rubberduck.JunkDrawer.Extensions; +using Rubberduck.Parsing; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Resources.Inspections; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; + +namespace Rubberduck.Inspections.Concrete +{ + /// + /// Warns when a user function's return value is discarded at all its call sites. + /// + /// + /// A 'Function' procedure normally means its return value to be captured and consumed by the calling code. + /// It's possible that not all call sites need the return value, but if the value is systematically discarded then this + /// means the function is side-effecting, and thus should probably be a 'Sub' procedure instead. + /// + /// + /// + /// + /// + /// + /// + public sealed class FunctionReturnValueAlwaysDiscardedInspection : DeclarationInspectionBase + { + public FunctionReturnValueAlwaysDiscardedInspection(RubberduckParserState state) + :base(state, DeclarationType.Function) + {} + + protected override bool IsResultDeclaration(Declaration declaration) + { + if (!(declaration is ModuleBodyElementDeclaration moduleBodyElementDeclaration)) + { + return false; + } + + //We only report the interface itself. + if (moduleBodyElementDeclaration.IsInterfaceImplementation) + { + return false; + } + + var finder = DeclarationFinderProvider.DeclarationFinder; + + if (moduleBodyElementDeclaration.IsInterfaceMember) + { + return IsInterfaceIssue(moduleBodyElementDeclaration, finder); + } + + return IsIssueItself(moduleBodyElementDeclaration); + } + + private bool IsIssueItself(ModuleBodyElementDeclaration declaration) + { + var procedureCallReferences = ProcedureCallReferences(declaration).ToHashSet(); + if (!procedureCallReferences.Any()) + { + return false; + } + + return declaration.References + .All(reference => procedureCallReferences.Contains(reference) + || reference.IsAssignment && IsReturnStatement(declaration, reference)); + } + + private bool IsReturnStatement(Declaration function, IdentifierReference assignment) + { + return assignment.ParentScoping.Equals(function) && assignment.Declaration.Equals(function); + } + + private bool IsInterfaceIssue(ModuleBodyElementDeclaration declaration, DeclarationFinder finder) + { + if (!IsIssueItself(declaration)) + { + return false; + } + + var implementations = finder.FindInterfaceImplementationMembers(declaration); + return implementations.All(implementation => IsIssueItself(implementation) + || implementation.References.All(reference => + reference.IsAssignment + && IsReturnStatement(implementation, reference))); + } + + private static IEnumerable ProcedureCallReferences(Declaration declaration) + { + return declaration.References + .Where(IsProcedureCallReference); + } + + private static bool IsProcedureCallReference(IdentifierReference reference) + { + return reference?.Declaration != null + && !reference.IsAssignment + && !reference.IsArrayAccess + && !reference.IsInnerRecursiveDefaultMemberAccess + && IsCalledAsProcedure(reference.Context); + } + + private static bool IsCalledAsProcedure(ParserRuleContext context) + { + var callStmt = context.GetAncestor(); + if (callStmt == null) + { + return false; + } + + //If we are in an argument list, the value is used somewhere in defining the argument. + var argumentListParent = context.GetAncestor(); + if (argumentListParent != null) + { + return false; + } + + //Member accesses are parsed right-to-left, e.g. 'foo.Bar' is the parent of 'foo'. + //Thus, having a member access parent means that the return value is used somehow. + var ownFunctionCallExpression = context.Parent is VBAParser.MemberAccessExprContext methodCall + ? methodCall + : context; + var memberAccessParent = ownFunctionCallExpression.GetAncestor(); + return memberAccessParent == null; + } + + protected override string ResultDescription(Declaration declaration) + { + var functionName = declaration.QualifiedName.ToString(); + return string.Format(InspectionResults.FunctionReturnValueAlwaysDiscardedInspection, functionName); + } + } +} diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueDiscardedInspection.cs similarity index 86% rename from Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueNotUsedInspection.cs rename to Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueDiscardedInspection.cs index 7de41640f0..e4c91a4bcc 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueDiscardedInspection.cs @@ -1,17 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Antlr4.Runtime; +using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete { @@ -44,10 +38,13 @@ namespace Rubberduck.Inspections.Concrete /// End Function /// ]]> /// - public sealed class FunctionReturnValueNotUsedInspection : IdentifierReferenceInspectionBase + public sealed class FunctionReturnValueDiscardedInspection : IdentifierReferenceInspectionBase { - public FunctionReturnValueNotUsedInspection(RubberduckParserState state) - : base(state) { } + public FunctionReturnValueDiscardedInspection(RubberduckParserState state) + : base(state) + { + Severity = CodeInspectionSeverity.Suggestion; + } protected override bool IsResultReference(IdentifierReference reference) { @@ -91,7 +88,7 @@ private static bool IsCalledAsProcedure(ParserRuleContext context) protected override string ResultDescription(IdentifierReference reference) { var functionName = reference.Declaration.QualifiedName.ToString(); - return string.Format(InspectionResults.FunctionReturnValueNotUsedInspection, functionName); + return string.Format(InspectionResults.FunctionReturnValueDiscardedInspection, functionName); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueNeverUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueNeverUsedInspection.cs deleted file mode 100644 index 36218fa548..0000000000 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueNeverUsedInspection.cs +++ /dev/null @@ -1,311 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Antlr4.Runtime; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; -using Rubberduck.JunkDrawer.Extensions; -using Rubberduck.Parsing; -using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections; -using Rubberduck.Parsing.Inspections.Abstract; -using Rubberduck.Resources.Inspections; -using Rubberduck.Parsing.Symbols; -using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.VBA.DeclarationCaching; -using Rubberduck.VBEditor; - -namespace Rubberduck.Inspections.Concrete -{ - /// - /// Warns when a user function's return value is never used, at any of its call sites. - /// - /// - /// A 'Function' procedure normally means its return value to be captured and consumed by the calling code. - /// It's possible that not all call sites need the return value, but if the value is systematically discarded then this - /// means the function is side-effecting, and thus should probably be a 'Sub' procedure instead. - /// - /// - /// - /// - /// - /// - /// - public sealed class FunctionReturnValueNeverUsedInspection : DeclarationInspectionBase - { - public FunctionReturnValueNeverUsedInspection(RubberduckParserState state) - :base(state, DeclarationType.Function) - {} - - protected override bool IsResultDeclaration(Declaration declaration) - { - if (!(declaration is ModuleBodyElementDeclaration moduleBodyElementDeclaration)) - { - return false; - } - - //We only report the interface itself. - if (moduleBodyElementDeclaration.IsInterfaceImplementation) - { - return false; - } - - var finder = DeclarationFinderProvider.DeclarationFinder; - - if (moduleBodyElementDeclaration.IsInterfaceMember) - { - return IsInterfaceIssue(moduleBodyElementDeclaration, finder); - } - - return IsIssueItself(moduleBodyElementDeclaration); - } - - private bool IsIssueItself(ModuleBodyElementDeclaration declaration) - { - var procedureCallReferences = ProcedureCallReferences(declaration).ToHashSet(); - if (!procedureCallReferences.Any()) - { - return false; - } - - return declaration.References - .All(reference => procedureCallReferences.Contains(reference) - || reference.IsAssignment && IsReturnStatement(declaration, reference)); - } - - private bool IsReturnStatement(Declaration function, IdentifierReference assignment) - { - return assignment.ParentScoping.Equals(function) && assignment.Declaration.Equals(function); - } - - private bool IsInterfaceIssue(ModuleBodyElementDeclaration declaration, DeclarationFinder finder) - { - if (!IsIssueItself(declaration)) - { - return false; - } - - var implementations = finder.FindInterfaceImplementationMembers(declaration); - return implementations.All(implementation => IsIssueItself(implementation) - || implementation.References.All(reference => - reference.IsAssignment - && IsReturnStatement(implementation, reference))); - } - - private static IEnumerable ProcedureCallReferences(Declaration declaration) - { - return declaration.References - .Where(IsProcedureCallReference); - } - - private static bool IsProcedureCallReference(IdentifierReference reference) - { - return reference?.Declaration != null - && !reference.IsAssignment - && !reference.IsArrayAccess - && !reference.IsInnerRecursiveDefaultMemberAccess - && IsCalledAsProcedure(reference.Context); - } - - private static bool IsCalledAsProcedure(ParserRuleContext context) - { - var callStmt = context.GetAncestor(); - if (callStmt == null) - { - return false; - } - - //If we are in an argument list, the value is used somewhere in defining the argument. - var argumentListParent = context.GetAncestor(); - if (argumentListParent != null) - { - return false; - } - - //Member accesses are parsed right-to-left, e.g. 'foo.Bar' is the parent of 'foo'. - //Thus, having a member access parent means that the return value is used somehow. - var ownFunctionCallExpression = context.Parent is VBAParser.MemberAccessExprContext methodCall - ? methodCall - : context; - var memberAccessParent = ownFunctionCallExpression.GetAncestor(); - if (memberAccessParent != null) - { - return false; - } - - return true; - } - - protected override string ResultDescription(Declaration declaration) - { - var functionName = declaration.QualifiedName.ToString(); - return string.Format(InspectionResults.FunctionReturnValueNeverUsedInspection, functionName); - } - - //protected override IEnumerable DoGetInspectionResults() - //{ - // var interfaceMembers = State.DeclarationFinder.FindAllInterfaceMembers().ToList(); - // var interfaceImplementationMembers = State.DeclarationFinder.FindAllInterfaceImplementingMembers(); - // var functions = State.DeclarationFinder - // .UserDeclarations(DeclarationType.Function) - // .Where(item => item.References.Any(r => !IsReturnStatement(item, r) && !r.IsAssignment)) - // .ToList(); - // var interfaceMemberIssues = GetInterfaceMemberIssues(interfaceMembers); - // var nonInterfaceFunctions = functions.Except(interfaceMembers.Union(interfaceImplementationMembers)); - // var nonInterfaceIssues = GetNonInterfaceIssues(nonInterfaceFunctions); - // return interfaceMemberIssues.Union(nonInterfaceIssues); - //} - - private IEnumerable GetInterfaceMemberIssues(IEnumerable interfaceMembers) - { - return from interfaceMember in interfaceMembers - let implementationMembers = - State.DeclarationFinder.FindInterfaceImplementationMembers(interfaceMember).ToList() - where interfaceMember.DeclarationType == DeclarationType.Function && - !IsReturnValueUsed(interfaceMember) && - implementationMembers.All(member => !IsReturnValueUsed(member)) - let implementationMemberIssues = - implementationMembers.Select( - implementationMember => - Tuple.Create(implementationMember.Context, - new QualifiedSelection(implementationMember.QualifiedName.QualifiedModuleName, - implementationMember.Selection), implementationMember)) - select CreateInspectionResult(this, interfaceMember); - - } - - private IEnumerable GetNonInterfaceIssues(IEnumerable nonInterfaceFunctions) - { - var returnValueNotUsedFunctions = nonInterfaceFunctions.Where(function => function.DeclarationType == DeclarationType.Function && !IsReturnValueUsed(function)); - var nonInterfaceIssues = returnValueNotUsedFunctions - .Where(function => !IsRecursive(function)) - .Select(function => - new DeclarationInspectionResult( - this, - string.Format(InspectionResults.FunctionReturnValueNeverUsedInspection, function.IdentifierName), - function)); - return nonInterfaceIssues; - } - - private bool IsRecursive(Declaration function) - { - return function.References.Any(usage => usage.ParentScoping.Equals(function) && IsIndexExprOrCallStmt(usage)); - } - - private bool IsReturnValueUsed(Declaration function) - { - // TODO: This is O(MG) at work here. Need to refactor the whole shebang. - return (from usage in function.References - where !IsLet(usage) - where !IsSet(usage) - where !IsCallStmt(usage) - where !IsTypeOfExpression(usage) - where !IsAddressOfCall(usage) - select usage).Any(usage => !IsReturnStatement(function, usage)); - } - - private bool IsAddressOfCall(IdentifierReference usage) - { - return usage.Context.IsDescendentOf(); - } - - private bool IsTypeOfExpression(IdentifierReference usage) - { - return usage.Context.IsDescendentOf(); - } - - private bool IsIndexExprOrCallStmt(IdentifierReference usage) - { - return IsCallStmt(usage) || IsIndexExprContext(usage); - } - - private bool IsCallStmt(IdentifierReference usage) - { - var callStmt = usage.Context.GetAncestor(); - if (callStmt == null) - { - return false; - } - - var indexExpr = usage.Context.GetAncestor(); - if (indexExpr != null) - { - var memberAccessStmt = usage.Context.GetAncestor(); - if (memberAccessStmt != null && - callStmt.SourceInterval.ProperlyContains(memberAccessStmt.SourceInterval) && - memberAccessStmt.SourceInterval.ProperlyContains(indexExpr.SourceInterval)) - { - return false; - } - } - - var argumentList = CallStatement.GetArgumentList(callStmt); - if (argumentList == null) - { - return true; - } - return !usage.Context.IsDescendentOf(argumentList); - } - - private bool IsIndexExprContext(IdentifierReference usage) - { - var indexExpr = usage.Context.GetAncestor(); - if (indexExpr == null) - { - return false; - } - var argumentList = indexExpr.argumentList(); - if (argumentList == null) - { - return true; - } - return !usage.Context.IsDescendentOf(argumentList); - } - - private bool IsLet(IdentifierReference usage) - { - var letStmt = usage.Context.GetAncestor(); - - return letStmt != null && letStmt == usage.Context; - } - - private bool IsSet(IdentifierReference usage) - { - var setStmt = usage.Context.GetAncestor(); - - return setStmt != null && setStmt == usage.Context; - } - - private DeclarationInspectionResult CreateInspectionResult(IInspection inspection, Declaration interfaceMember) - { - dynamic properties = new PropertyBag(); - properties.DisableFixes = nameof(QuickFixes.ConvertToProcedureQuickFix); - - return new DeclarationInspectionResult(inspection, - string.Format(InspectionResults.FunctionReturnValueNeverUsedInspection, - interfaceMember.IdentifierName), - interfaceMember, properties: properties); - } - } -} diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ConvertToProcedureQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/ConvertToProcedureQuickFix.cs index 572854f0c5..1634cf401a 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ConvertToProcedureQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/ConvertToProcedureQuickFix.cs @@ -53,7 +53,7 @@ public sealed class ConvertToProcedureQuickFix : QuickFixBase private readonly IDeclarationFinderProvider _declarationFinderProvider; public ConvertToProcedureQuickFix(IDeclarationFinderProvider declarationFinderProvider) - : base(typeof(NonReturningFunctionInspection), typeof(FunctionReturnValueNeverUsedInspection)) + : base(typeof(NonReturningFunctionInspection), typeof(FunctionReturnValueAlwaysDiscardedInspection)) { _declarationFinderProvider = declarationFinderProvider; } diff --git a/Rubberduck.Resources/Inspections/InspectionInfo.Designer.cs b/Rubberduck.Resources/Inspections/InspectionInfo.Designer.cs index 03ef56de47..cac418b8ab 100644 --- a/Rubberduck.Resources/Inspections/InspectionInfo.Designer.cs +++ b/Rubberduck.Resources/Inspections/InspectionInfo.Designer.cs @@ -277,20 +277,20 @@ public static string ExcelUdfNameIsValidCellReferenceInspection { } /// - /// Looks up a localized string similar to A member is written as a function, but used as a procedure. Unless the function is recursive, consider converting the 'Function' into a 'Sub'. If the function is recursive, none of its external callers are using the returned value.. + /// Looks up a localized string similar to A member is written as a function, but always used as a procedure. Consider converting the 'Function' into a 'Sub'.. /// - public static string FunctionReturnValueNeverUsedInspection { + public static string FunctionReturnValueAlwaysDiscardedInspection { get { - return ResourceManager.GetString("FunctionReturnValueNeverUsedInspection", resourceCulture); + return ResourceManager.GetString("FunctionReturnValueAlwaysDiscardedInspection", resourceCulture); } } /// - /// Looks up a localized string similar to The return value of a function is not used, i.e. it is used like a procedure. This is either an oversight or the function is used for its side-effects, whose existence would also be a code smell.. + /// Looks up a localized string similar to The return value of a function gets discarded, i.e. the function is used like a procedure. This is either an oversight or the function is used for its side-effects, whose existence would also be a code smell.. /// - public static string FunctionReturnValueNotUsedInspection { + public static string FunctionReturnValueDiscardedInspection { get { - return ResourceManager.GetString("FunctionReturnValueNotUsedInspection", resourceCulture); + return ResourceManager.GetString("FunctionReturnValueDiscardedInspection", resourceCulture); } } diff --git a/Rubberduck.Resources/Inspections/InspectionInfo.cs.resx b/Rubberduck.Resources/Inspections/InspectionInfo.cs.resx index 675311048a..cd5589847d 100644 --- a/Rubberduck.Resources/Inspections/InspectionInfo.cs.resx +++ b/Rubberduck.Resources/Inspections/InspectionInfo.cs.resx @@ -247,9 +247,6 @@ Jestliže může být parametr prázdný, ignorujte výsledek této inspekce; p Deklarace proměnné objektu s automatickým instancí v rozsahu procedur mění, jak funguje nulling reference, což může vést k neočekávanému chování. - - Člen je definován jako funkce, ale používá se jako procedura. Pokud nejde o rekurzivní funkci, zvažte zapsání 'Function' jako 'Sub'. Pokud je funkce rekurzivní, žádný z jejich externích voláních nepoužívá její návratnou hodnotu. - Rubberduck rozeznává tuto proměnnou jako proměnnou objektu, která je definována bez klíčového slova 'Set'. Tato skutečnost způsobuje run-time chybu 91 'Object or With block variable not set'. diff --git a/Rubberduck.Resources/Inspections/InspectionInfo.de.resx b/Rubberduck.Resources/Inspections/InspectionInfo.de.resx index 91ef02eb7f..5befb5f592 100644 --- a/Rubberduck.Resources/Inspections/InspectionInfo.de.resx +++ b/Rubberduck.Resources/Inspections/InspectionInfo.de.resx @@ -226,8 +226,8 @@ Falls der Parameter 'null' sein kann, bitte dieses Auftreten ignorieren. 'null' Das Schlüsselwort 'Public' kann nur auf Modulebene verwendet werden; Sein Konterpart 'Private' kann auch nur auf Modulebene verwendet werden. 'Dim' jedoch kann verwendet werden, um sowohl modulweite als auch prozedurweite Variablen zu deklarieren. Um der Konsistenz Willen ist es besser, 'Dim' nur für lokale Variablen zu verwenden, also 'Private' statt 'Dim' auf Modulebene zu verwenden. - - Ein Member ist als Funktion geschrieben, wird aber wie eine Prozedur verwendet. Falls die Funktion nicht rekursiv ist, sollten Sie in Erwägung ziehen, die 'Function' in ein 'Sub' zu konvertieren. Falls die Funktion rekursiv ist, verwendet keiner der externen Aufrufer den Rückgabewert. + + Ein Member ist als Funktion geschrieben, wird aber überall wie eine Prozedur verwendet. Sie sollten in Erwägung ziehen die 'Function' in ein 'Sub' zu konvertieren. Es wird ein Memberzugriff verwendet, der vom Interface des Objektes nicht deklariert wird. Dies ist höchstwahrscheinlich ein Fehler. Falls der Memberzugriff das erweiterbare Interface des Objektes verwendet, erwägen Sie ein nicht erweiterbares Äquivalent zu verwenden um Prüfungen zur Kompilierzeit zu ermöglichen und das Auftreten von Laufzeitfehler 438 zu verhindern. @@ -433,7 +433,7 @@ Falls der Parameter 'null' sein kann, bitte dieses Auftreten ignorieren. 'null' Eine Bedingung in einem Case-Ausdruck ist entweder nie erfüllt, verursacht einen Laufzeitfehler oder kann nicht erfüllt werden, da die vorherigen Case-Ausdrücke bereits alle zulässigen Werte abdecken. Infolgedessen wird der Code in dem Case-Zweig nie ausgeführt und stellt "toten Code" dar oder der Case-Ausdruck stellt sogar einen Laufzeitfehler dar, der nur darauf wartet irgendwann aufzutreten. Der Case-Zweig sollte entweder gelöscht, verändert oder an eine andere Stelle verschoben werden. - - Der Rückgabewert einer Funktion wird nicht verwendet, d.h. die wird wie eine Prozedur verwendet. Dies ist entweder ein Versäumnis oder die Funktion wird wegen ihrer Nebenwirkungen verwendet, deren Existenz in der Regel selber problematisch wäre. + + Der Rückgabewert einer Funktion wird verworfen, d.h. die Funktion wird wie eine Prozedur verwendet. Dies ist entweder ein Versäumnis oder die Funktion wird wegen ihrer Nebenwirkungen verwendet, deren Existenz in der Regel selber problematisch wäre. \ No newline at end of file diff --git a/Rubberduck.Resources/Inspections/InspectionInfo.es.resx b/Rubberduck.Resources/Inspections/InspectionInfo.es.resx index e0886eea32..1536768850 100644 --- a/Rubberduck.Resources/Inspections/InspectionInfo.es.resx +++ b/Rubberduck.Resources/Inspections/InspectionInfo.es.resx @@ -217,9 +217,6 @@ Si el parámetro puede ser nulo, ignore el resultado de esta inspección; pasar Una declaración de variable de objeto auto-instanciada en el ámbito del procedimiento cambia cómo funciona la anulación de la referencia, lo que puede llevar a un comportamiento inesperado. - - Un miembro se escribe como una función, pero se usa como un procedimiento. A menos que la función sea recursiva, considere convertir la 'Función' en un 'Sub'. Si la función es recursiva, ninguno de sus llamadores externos está utilizando el valor devuelto. - Por lo que Rubberduck puede decir, esta variable es una variable de objeto, asignada sin la palabra clave 'Set'. Esto causa el error 91 en tiempo de ejecución 'Objeto o variable de bloque no establecida'. diff --git a/Rubberduck.Resources/Inspections/InspectionInfo.fr.resx b/Rubberduck.Resources/Inspections/InspectionInfo.fr.resx index 005726c001..27d14e6da4 100644 --- a/Rubberduck.Resources/Inspections/InspectionInfo.fr.resx +++ b/Rubberduck.Resources/Inspections/InspectionInfo.fr.resx @@ -210,9 +210,6 @@ Une variable objet assignée lors de sa déclaration dans une procédure, modifie comment VBA gère cet objet, ce qui peut mener à un comportement inattendu. - - Un membre est implémenté comme une fonction, mais utilisé comme une procédure. À moins que la fonction soit récursive, considérez la convertir en procédure. Si la fonction est récursive, aucun appelant externe n'utilise sa valeur de retour. - Rubberduck voit cette variable comme étant une référence à un objet, assignée sans le mot-clé 'Set'. Ceci cause une erreur d'exécution (#91 'Object or With block variable not set'). diff --git a/Rubberduck.Resources/Inspections/InspectionInfo.resx b/Rubberduck.Resources/Inspections/InspectionInfo.resx index 6863b2338e..c4c605cdd2 100644 --- a/Rubberduck.Resources/Inspections/InspectionInfo.resx +++ b/Rubberduck.Resources/Inspections/InspectionInfo.resx @@ -217,8 +217,8 @@ If the parameter can be null, ignore this inspection result; passing a null valu An auto-instantiated object variable declaration at procedure scope changes how nulling the reference works, which can lead to unexpected behavior. - - A member is written as a function, but used as a procedure. Unless the function is recursive, consider converting the 'Function' into a 'Sub'. If the function is recursive, none of its external callers are using the returned value. + + A member is written as a function, but always used as a procedure. Consider converting the 'Function' into a 'Sub'. As far as Rubberduck can tell, this variable is an object variable, assigned without the 'Set' keyword. This causes run-time error 91 'Object or With block variable not set' or 438 'Object doesn't support this property or method' depending on whether the variable has the value 'Nothing' or not. @@ -433,7 +433,7 @@ If the parameter can be null, ignore this inspection result; passing a null valu Whenever both sides of an assignment without Set are objects, there is an assignment from the default member of the RHS to the one on the LHS. Although this might be intentional, in many situations it will just mask an erroneously forgotten Set. - - The return value of a function is not used, i.e. it is used like a procedure. This is either an oversight or the function is used for its side-effects, whose existence would also be a code smell. + + The return value of a function gets discarded, i.e. the function is used like a procedure. This is either an oversight or the function is used for its side-effects, whose existence would also be a code smell. \ No newline at end of file diff --git a/Rubberduck.Resources/Inspections/InspectionNames.Designer.cs b/Rubberduck.Resources/Inspections/InspectionNames.Designer.cs index 8ccc5e21d3..5dfd52ef11 100644 --- a/Rubberduck.Resources/Inspections/InspectionNames.Designer.cs +++ b/Rubberduck.Resources/Inspections/InspectionNames.Designer.cs @@ -277,20 +277,20 @@ public static string ExcelUdfNameIsValidCellReferenceInspection { } /// - /// Looks up a localized string similar to Function return value is never used. + /// Looks up a localized string similar to Function return value is always discarded. /// - public static string FunctionReturnValueNeverUsedInspection { + public static string FunctionReturnValueAlwaysDiscardedInspection { get { - return ResourceManager.GetString("FunctionReturnValueNeverUsedInspection", resourceCulture); + return ResourceManager.GetString("FunctionReturnValueAlwaysDiscardedInspection", resourceCulture); } } /// - /// Looks up a localized string similar to Function return value is not used. + /// Looks up a localized string similar to Function return value gets discarded. /// - public static string FunctionReturnValueNotUsedInspection { + public static string FunctionReturnValueDiscardedInspection { get { - return ResourceManager.GetString("FunctionReturnValueNotUsedInspection", resourceCulture); + return ResourceManager.GetString("FunctionReturnValueDiscardedInspection", resourceCulture); } } diff --git a/Rubberduck.Resources/Inspections/InspectionNames.cs.resx b/Rubberduck.Resources/Inspections/InspectionNames.cs.resx index 652990593b..eea4e426a6 100644 --- a/Rubberduck.Resources/Inspections/InspectionNames.cs.resx +++ b/Rubberduck.Resources/Inspections/InspectionNames.cs.resx @@ -213,9 +213,6 @@ Reference k objektu proměnné je automaticky instancovaná - - Vratná hodnota funkce není nikdy použita - Funkce, která nic nevrací, nebo property getter diff --git a/Rubberduck.Resources/Inspections/InspectionNames.de.resx b/Rubberduck.Resources/Inspections/InspectionNames.de.resx index 7a959a9ba9..873134722a 100644 --- a/Rubberduck.Resources/Inspections/InspectionNames.de.resx +++ b/Rubberduck.Resources/Inspections/InspectionNames.de.resx @@ -213,8 +213,8 @@ Objektvariable ist selbstzugewiesen. - - Der Rückgabewert der Funktion wird nie genutzt. + + Der Rückgabewert einer Funktion wird immer verworfen. Zuweisung in eine Objektvariable benötigt das 'Set'-Schlüsselwort. @@ -417,7 +417,7 @@ Verdächtige Let-Zuweisung - - Der Rückgabewert der Funktion wird nicht genutzt. + + Der Rückgabewert einer Funktion wird verworfen. \ No newline at end of file diff --git a/Rubberduck.Resources/Inspections/InspectionNames.es.resx b/Rubberduck.Resources/Inspections/InspectionNames.es.resx index 415cf8f326..c26872c7a4 100644 --- a/Rubberduck.Resources/Inspections/InspectionNames.es.resx +++ b/Rubberduck.Resources/Inspections/InspectionNames.es.resx @@ -216,9 +216,6 @@ La referencia de la variable de objeto es una instancia automática - - El valor de retorno de la función nunca se usa - La asignación de variables de objeto requiere la palabra clave 'Set' diff --git a/Rubberduck.Resources/Inspections/InspectionNames.fr.resx b/Rubberduck.Resources/Inspections/InspectionNames.fr.resx index 325202f775..1089b087d2 100644 --- a/Rubberduck.Resources/Inspections/InspectionNames.fr.resx +++ b/Rubberduck.Resources/Inspections/InspectionNames.fr.resx @@ -213,9 +213,6 @@ La variable objet est assignée lors de sa déclaration - - La valeur de retour de la fonction n'est jamais utilisée. - L'assignation d'une référence d'objet requiert le mot-clé 'Set' diff --git a/Rubberduck.Resources/Inspections/InspectionNames.resx b/Rubberduck.Resources/Inspections/InspectionNames.resx index 1324f267a6..0295a35351 100644 --- a/Rubberduck.Resources/Inspections/InspectionNames.resx +++ b/Rubberduck.Resources/Inspections/InspectionNames.resx @@ -216,8 +216,8 @@ Object variable reference is auto-instantiated - - Function return value is never used + + Function return value is always discarded Object variable assignment requires 'Set' keyword @@ -437,7 +437,7 @@ Suspicious Let assignment - - Function return value is not used + + Function return value gets discarded \ No newline at end of file diff --git a/Rubberduck.Resources/Inspections/InspectionResults.Designer.cs b/Rubberduck.Resources/Inspections/InspectionResults.Designer.cs index 1df0fe53d2..0d2ad75771 100644 --- a/Rubberduck.Resources/Inspections/InspectionResults.Designer.cs +++ b/Rubberduck.Resources/Inspections/InspectionResults.Designer.cs @@ -279,18 +279,18 @@ public static string ExcelUdfNameIsValidCellReferenceInspection { /// /// Looks up a localized string similar to Return value of function '{0}' is never used.. /// - public static string FunctionReturnValueNeverUsedInspection { + public static string FunctionReturnValueAlwaysDiscardedInspection { get { - return ResourceManager.GetString("FunctionReturnValueNeverUsedInspection", resourceCulture); + return ResourceManager.GetString("FunctionReturnValueAlwaysDiscardedInspection", resourceCulture); } } /// - /// Looks up a localized string similar to Return value of function '{0}' is not used.. + /// Looks up a localized string similar to Return value of function '{0}' gets discarded.. /// - public static string FunctionReturnValueNotUsedInspection { + public static string FunctionReturnValueDiscardedInspection { get { - return ResourceManager.GetString("FunctionReturnValueNotUsedInspection", resourceCulture); + return ResourceManager.GetString("FunctionReturnValueDiscardedInspection", resourceCulture); } } diff --git a/Rubberduck.Resources/Inspections/InspectionResults.cs.resx b/Rubberduck.Resources/Inspections/InspectionResults.cs.resx index 61927a1c6c..dd094ce4ac 100644 --- a/Rubberduck.Resources/Inspections/InspectionResults.cs.resx +++ b/Rubberduck.Resources/Inspections/InspectionResults.cs.resx @@ -195,9 +195,6 @@ Reference '{0}' objektu je automaticky instancovaná - - Návratná hodnota funkce '{0}' není nikdy použita. - Parametr '{0}' je předán pomocí ByVal a je mu přiřazena hodnota diff --git a/Rubberduck.Resources/Inspections/InspectionResults.de.resx b/Rubberduck.Resources/Inspections/InspectionResults.de.resx index 2817e62f0f..b9160db11b 100644 --- a/Rubberduck.Resources/Inspections/InspectionResults.de.resx +++ b/Rubberduck.Resources/Inspections/InspectionResults.de.resx @@ -137,8 +137,8 @@ Objekt-Referenz '{0}' ist sebstzugewiesen. - - Der Rückgabewert der Funktion '{0}' wird nie verwendet. + + Der Rückgabewert der Funktion '{0}' wird immer verworfen. Der Parameter '{0}' wird als byVal übergeben und bekommt ienen Wert zugesiesen. @@ -458,7 +458,7 @@ In Memoriam, 1972-2018 Bereichsbedingungen in Case-Ausdrücken müssen von der Form '[x] T [y]' sein, wobei [x] kleiner oder gleich [y] ist. - - Der Rückgabewert der Funktion '{0}' wird nicht verwendet. + + Der Rückgabewert der Funktion '{0}' wird verworfen. \ No newline at end of file diff --git a/Rubberduck.Resources/Inspections/InspectionResults.es.resx b/Rubberduck.Resources/Inspections/InspectionResults.es.resx index 93daaa7ad7..8d0bb5d990 100644 --- a/Rubberduck.Resources/Inspections/InspectionResults.es.resx +++ b/Rubberduck.Resources/Inspections/InspectionResults.es.resx @@ -138,9 +138,6 @@ La referencia de objeto '{0}' se crea automáticamente. - - El valor de retorno de la función '{0}' nunca se usa. - El parámetro '{0}' se pasa 'ByVal' y se le asigna un valor. diff --git a/Rubberduck.Resources/Inspections/InspectionResults.fr.resx b/Rubberduck.Resources/Inspections/InspectionResults.fr.resx index b988fa43e6..85974dc529 100644 --- a/Rubberduck.Resources/Inspections/InspectionResults.fr.resx +++ b/Rubberduck.Resources/Inspections/InspectionResults.fr.resx @@ -137,9 +137,6 @@ La variable '{0}' est assignée lors de sa déclaration - - La valeur de retour de la fonction '{0}' n'est jamais utilisée. - Le paramètre '{0}' passé par valeur est assigné diff --git a/Rubberduck.Resources/Inspections/InspectionResults.resx b/Rubberduck.Resources/Inspections/InspectionResults.resx index 7990692d3f..e4c4a98561 100644 --- a/Rubberduck.Resources/Inspections/InspectionResults.resx +++ b/Rubberduck.Resources/Inspections/InspectionResults.resx @@ -141,8 +141,9 @@ Object reference '{0}' is auto-instantiated. - + Return value of function '{0}' is never used. + {0} function name Parameter '{0}' is passed 'ByVal' and assigned a value. @@ -498,7 +499,8 @@ In memoriam, 1972-2018 There is an assignment from the default member of the result of expression '{1}' to that of the expression '{0}'. {0} lhsExpression; {1} rhsExpression - - Return value of function '{0}' is not used. + + Return value of function '{0}' gets discarded. + {0} function name \ No newline at end of file diff --git a/RubberduckTests/Inspections/FunctionReturnValueNeverUsedInspectionTests.cs b/RubberduckTests/Inspections/FunctionReturnValueAlwaysDiscardedInspectionTests.cs similarity index 96% rename from RubberduckTests/Inspections/FunctionReturnValueNeverUsedInspectionTests.cs rename to RubberduckTests/Inspections/FunctionReturnValueAlwaysDiscardedInspectionTests.cs index 8890af5594..cfcbb9d92f 100644 --- a/RubberduckTests/Inspections/FunctionReturnValueNeverUsedInspectionTests.cs +++ b/RubberduckTests/Inspections/FunctionReturnValueAlwaysDiscardedInspectionTests.cs @@ -8,7 +8,7 @@ namespace RubberduckTests.Inspections { [TestFixture] - public class FunctionReturnValueNeverUsedInspectionTests : InspectionTestsBase + public class FunctionReturnValueAlwaysDiscardedInspectionTests : InspectionTestsBase { [Test] [Category("Inspections")] @@ -120,7 +120,7 @@ End Sub [Test] [Category("Inspections")] [Category("Unused Value")] - public void AdressOfAndCallWithoutAssignment_NoResult() + public void AddressOfAndCallWithoutAssignment_NoResult() { const string code = @" Public Function Foo(ByVal bar As String) As Integer @@ -177,7 +177,7 @@ End Sub public void Ignored_DoesNotReturnResult() { const string code = @" -'@Ignore FunctionReturnValueNeverUsed +'@Ignore FunctionReturnValueAlwaysDiscarded Public Function Foo() As Integer End Function @@ -477,12 +477,12 @@ public void InspectionName() { var inspection = InspectionUnderTest(null); - Assert.AreEqual(nameof(FunctionReturnValueNeverUsedInspection), inspection.Name); + Assert.AreEqual(nameof(FunctionReturnValueAlwaysDiscardedInspection), inspection.Name); } protected override IInspection InspectionUnderTest(RubberduckParserState state) { - return new FunctionReturnValueNeverUsedInspection(state); + return new FunctionReturnValueAlwaysDiscardedInspection(state); } } } diff --git a/RubberduckTests/Inspections/FunctionReturnValueNotUsedInspectionTests.cs b/RubberduckTests/Inspections/FunctionReturnValueDiscardedInspectionTests.cs similarity index 85% rename from RubberduckTests/Inspections/FunctionReturnValueNotUsedInspectionTests.cs rename to RubberduckTests/Inspections/FunctionReturnValueDiscardedInspectionTests.cs index 0d37e3faf5..20a4eae77a 100644 --- a/RubberduckTests/Inspections/FunctionReturnValueNotUsedInspectionTests.cs +++ b/RubberduckTests/Inspections/FunctionReturnValueDiscardedInspectionTests.cs @@ -8,12 +8,12 @@ namespace RubberduckTests.Inspections { [TestFixture] - public class FunctionReturnValueNotUsedInspectionTests : InspectionTestsBase + public class FunctionReturnValueDiscardedInspectionTests : InspectionTestsBase { [Test] [Category("Inspections")] [Category("Unused Value")] - public void FunctionReturnValueNotUsed_IgnoresUnusedFunction() + public void FunctionReturnValueDiscarded_IgnoresUnusedFunction() { const string code = @" Public Function Foo() As Long @@ -26,7 +26,7 @@ End Function [Test] [Category("Inspections")] [Category("Unused Value")] - public void FunctionReturnValueNotUsed_ReturnsResult_ExplicitCallWithoutAssignment() + public void FunctionReturnValueDiscarded_ReturnsResult_ExplicitCallWithoutAssignment() { const string code = @" Public Function Foo(ByVal bar As String) As Integer @@ -43,7 +43,7 @@ End Sub [Test] [Category("Inspections")] [Category("Unused Value")] - public void FunctionReturnValueNotUsed_ReturnsResult_CallWithoutAssignment() + public void FunctionReturnValueDiscarded_ReturnsResult_CallWithoutAssignment() { const string code = @" Public Function Foo(ByVal bar As String) As Integer @@ -60,7 +60,7 @@ End Sub [Test] [Category("Inspections")] [Category("Unused Value")] - public void FunctionReturnValueNotUsed_TwoUses_TwoResults() + public void FunctionReturnValueDiscarded_TwoUses_TwoResults() { const string code = @" Public Function Foo(ByVal bar As String) As Integer @@ -98,7 +98,7 @@ End Sub [Test] [Category("Inspections")] [Category("Unused Value")] - public void FunctionReturnValueNotUsed_ReturnsResult_NoReturnValueAssignment() + public void FunctionReturnValueDiscarded_ReturnsResult_NoReturnValueAssignment() { const string code = @" Public Function Foo() As Integer @@ -114,10 +114,10 @@ End Sub [Test] [Category("Inspections")] [Category("Unused Value")] - public void FunctionReturnValueNotUsed_Ignored_DoesNotReturnResult_AddressOf() + public void FunctionReturnValueDiscarded_Ignored_DoesNotReturnResult_AddressOf() { const string code = @" -'@Ignore FunctionReturnValueNotUsed +'@Ignore FunctionReturnValueDiscarded Public Function Foo(ByVal bar As String) As Integer Foo = 42 End Function @@ -132,7 +132,7 @@ End Sub [Test] [Category("Inspections")] [Category("Unused Value")] - public void FunctionReturnValueNotUsed_MultipleConsecutiveCalls_returnsOneResult() + public void FunctionReturnValueDiscarded_MultipleConsecutiveCalls_returnsOneResult() { const string code = @" Public Function Foo(ByVal bar As String) As Integer @@ -149,7 +149,7 @@ End Sub [Test] [Category("Inspections")] [Category("Unused Value")] - public void FunctionReturnValueNotUsed_DoesNotReturnResult_IfStatement() + public void FunctionReturnValueDiscarded_DoesNotReturnResult_IfStatement() { const string code = @" Public Function Foo(ByVal bar As String) As Integer @@ -167,7 +167,7 @@ End Sub [Test] [Category("Inspections")] [Category("Unused Value")] - public void FunctionReturnValueNotUsed_DoesNotReturnResult_ForEachStatement() + public void FunctionReturnValueDiscarded_DoesNotReturnResult_ForEachStatement() { const string code = @" Public Function Foo(ByVal bar As String) As Integer @@ -188,7 +188,7 @@ End Sub [Test] [Category("Inspections")] [Category("Unused Value")] - public void FunctionReturnValueNotUsed_DoesNotReturnResult_WhileStatement() + public void FunctionReturnValueDiscarded_DoesNotReturnResult_WhileStatement() { const string code = @" Public Function Foo(ByVal bar As String) As Integer @@ -209,7 +209,7 @@ End Sub [Test] [Category("Inspections")] [Category("Unused Value")] - public void FunctionReturnValueNotUsed_DoesNotReturnResult_DoUntilStatement() + public void FunctionReturnValueDiscarded_DoesNotReturnResult_DoUntilStatement() { const string code = @" Public Function Foo(ByVal bar As String) As Integer @@ -230,7 +230,7 @@ End Sub [Test] [Category("Inspections")] [Category("Unused Value")] - public void FunctionReturnValueNotUsed_DoesNotReturnResult_ReturnValueAssignment() + public void FunctionReturnValueDiscarded_DoesNotReturnResult_ReturnValueAssignment() { const string code = @" Public Function Foo(ByVal bar As String) As Integer @@ -247,7 +247,7 @@ End Sub [Test] [Category("Inspections")] [Category("Unused Value")] - public void FunctionReturnValueNotUsed_DoesNotReturnResult_RecursiveFunction() + public void FunctionReturnValueDiscarded_DoesNotReturnResult_RecursiveFunction() { const string code = @" Public Function Factorial(ByVal n As Long) As Long @@ -264,7 +264,7 @@ End Function [Test] [Category("Inspections")] [Category("Unused Value")] - public void FunctionReturnValueNotUsed_DoesNotReturnResult_ArgumentFunctionCall() + public void FunctionReturnValueDiscarded_DoesNotReturnResult_ArgumentFunctionCall() { const string code = @" Public Function Foo(ByVal bar As String) As Integer @@ -284,7 +284,7 @@ End Sub [Test] [Category("Inspections")] [Category("Unused Value")] - public void FunctionReturnValueNotUsed_DoesNotReturnResult_IgnoresBuiltInFunctions() + public void FunctionReturnValueDiscarded_DoesNotReturnResult_IgnoresBuiltInFunctions() { const string code = @" Public Sub Dummy() @@ -347,7 +347,7 @@ Public Sub Baz() [Test] [Category("Inspections")] [Category("Unused Value")] - public void FunctionReturnValueNotUsed_ReturnsResult_InterfaceMember() + public void FunctionReturnValueDiscarded_ReturnsResult_InterfaceMember() { const string interfaceCode = @" Public Function Test() As Integer @@ -433,14 +433,14 @@ End Function [Category("Unused Value")] public void InspectionName() { - var inspection = new FunctionReturnValueNotUsedInspection(null); + var inspection = new FunctionReturnValueDiscardedInspection(null); - Assert.AreEqual(nameof(FunctionReturnValueNotUsedInspection), inspection.Name); + Assert.AreEqual(nameof(FunctionReturnValueDiscardedInspection), inspection.Name); } protected override IInspection InspectionUnderTest(RubberduckParserState state) { - return new FunctionReturnValueNotUsedInspection(state); + return new FunctionReturnValueDiscardedInspection(state); } } } diff --git a/RubberduckTests/QuickFixes/ConvertToProcedureQuickFixTests.cs b/RubberduckTests/QuickFixes/ConvertToProcedureQuickFixTests.cs index cadc1d1d55..a3958c7ff8 100644 --- a/RubberduckTests/QuickFixes/ConvertToProcedureQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ConvertToProcedureQuickFixTests.cs @@ -46,7 +46,7 @@ Public Sub Test() End Sub "; - var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new FunctionReturnValueNeverUsedInspection(state)); + var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new FunctionReturnValueAlwaysDiscardedInspection(state)); Assert.AreEqual(expectedCode, actualCode); } @@ -86,13 +86,13 @@ Public Sub Test() End Sub "; - var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new FunctionReturnValueNeverUsedInspection(state)); + var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new FunctionReturnValueAlwaysDiscardedInspection(state)); Assert.AreEqual(expectedCode, actualCode); } [Test] [Category("QuickFixes")] - public void FunctionReturnValueNeverUsed_QuickFixWorks_Interface() + public void FunctionReturnValueAlwaysDiscarded_QuickFixWorks_Interface() { const string inputInterfaceCode = @"Public Function Test() As Integer @@ -146,7 +146,7 @@ Dim testObj As IFoo using (state) { - var inspection = new FunctionReturnValueNeverUsedInspection(state); + var inspection = new FunctionReturnValueAlwaysDiscardedInspection(state); var inspectionResults = inspection.GetInspectionResults(CancellationToken.None); var rewriteSession = rewritingManager.CheckOutCodePaneSession(); diff --git a/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs b/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs index 278f77e779..16935aa575 100644 --- a/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs @@ -114,7 +114,7 @@ public void EncapsulatePublicField_IgnoreQuickFixWorks() [Test] [Category("QuickFixes")] [Category("Unused Value")] - public void FunctionReturnValueNotUsed_IgnoreQuickFixWorks() + public void FunctionReturnValueDiscarded_IgnoreQuickFixWorks() { const string inputCode = @"Public Function Foo(ByVal bar As String) As Boolean @@ -129,18 +129,18 @@ Public Sub Goo() End Function Public Sub Goo() - '@Ignore FunctionReturnValueNotUsed + '@Ignore FunctionReturnValueDiscarded Foo ""test"" End Sub"; - var actualCode = ApplyIgnoreOnceToFirstResult(inputCode, state => new FunctionReturnValueNotUsedInspection(state), TestStandardModuleVbeSetup); + var actualCode = ApplyIgnoreOnceToFirstResult(inputCode, state => new FunctionReturnValueDiscardedInspection(state), TestStandardModuleVbeSetup); Assert.AreEqual(expectedCode, actualCode); } [Test] [Category("QuickFixes")] [Category("Unused Value")] - public void FunctionReturnValueNeverUsed_IgnoreQuickFixWorks() + public void FunctionReturnValueAlwaysDiscarded_IgnoreQuickFixWorks() { const string inputCode = @"Public Function Foo(ByVal bar As String) As Boolean @@ -151,7 +151,7 @@ Public Sub Goo() End Sub"; const string expectedCode = - @"'@Ignore FunctionReturnValueNeverUsed + @"'@Ignore FunctionReturnValueAlwaysDiscarded Public Function Foo(ByVal bar As String) As Boolean End Function @@ -159,7 +159,7 @@ Public Sub Goo() Foo ""test"" End Sub"; - var actualCode = ApplyIgnoreOnceToFirstResult(inputCode, state => new FunctionReturnValueNeverUsedInspection(state), TestStandardModuleVbeSetup); + var actualCode = ApplyIgnoreOnceToFirstResult(inputCode, state => new FunctionReturnValueAlwaysDiscardedInspection(state), TestStandardModuleVbeSetup); Assert.AreEqual(expectedCode, actualCode); } From 681fc3d8b0e8d83fe7eac277687cd59e0f9fb092 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Wed, 15 Jan 2020 01:22:59 +0100 Subject: [PATCH 152/461] Alignment of punctuation at end of inspection resources Also includes some German translations. --- .../Inspections/InspectionInfo.Designer.cs | 4 +- .../Inspections/InspectionInfo.de.resx | 3 + .../Inspections/InspectionInfo.resx | 4 +- .../Inspections/InspectionNames.Designer.cs | 34 ++++---- .../Inspections/InspectionNames.de.resx | 9 +- .../Inspections/InspectionNames.resx | 34 ++++---- .../Inspections/InspectionResults.Designer.cs | 18 ++-- .../Inspections/InspectionResults.de.resx | 83 ++++++++++--------- .../Inspections/InspectionResults.resx | 20 +++-- 9 files changed, 110 insertions(+), 99 deletions(-) diff --git a/Rubberduck.Resources/Inspections/InspectionInfo.Designer.cs b/Rubberduck.Resources/Inspections/InspectionInfo.Designer.cs index 5ce479fe2f..29273a1de8 100644 --- a/Rubberduck.Resources/Inspections/InspectionInfo.Designer.cs +++ b/Rubberduck.Resources/Inspections/InspectionInfo.Designer.cs @@ -367,7 +367,7 @@ public static string ImplicitDefaultMemberAccessInspection { } /// - /// Looks up a localized string similar to If the type clause for a Const isn't included it is implicitly typed. Include an explicit ' As <Type>' replacing '<Type>' with the correct data type to explicitly type your const value.. + /// Looks up a localized string similar to If the as type clause for a Const isn't included it is implicitly typed. Include an explicit ' As <Type>' replacing '<Type>' with the correct data type to explicitly type your const value.. /// public static string ImplicitlyTypedConstInspection { get { @@ -547,7 +547,7 @@ public static string ModuleScopeDimKeywordInspection { } /// - /// Looks up a localized string similar to Modules without the '@Folder' annotation cannot receive custom groupings in the Code Explorer. . + /// Looks up a localized string similar to Modules without the '@Folder' annotation cannot receive custom groupings in the Code Explorer.. /// public static string ModuleWithoutFolderInspection { get { diff --git a/Rubberduck.Resources/Inspections/InspectionInfo.de.resx b/Rubberduck.Resources/Inspections/InspectionInfo.de.resx index 5befb5f592..e028a267ed 100644 --- a/Rubberduck.Resources/Inspections/InspectionInfo.de.resx +++ b/Rubberduck.Resources/Inspections/InspectionInfo.de.resx @@ -436,4 +436,7 @@ Falls der Parameter 'null' sein kann, bitte dieses Auftreten ignorieren. 'null' Der Rückgabewert einer Funktion wird verworfen, d.h. die Funktion wird wie eine Prozedur verwendet. Dies ist entweder ein Versäumnis oder die Funktion wird wegen ihrer Nebenwirkungen verwendet, deren Existenz in der Regel selber problematisch wäre. + + Wird keine Typdeklaration verwendet wird der Datentyp einer Konstante implizit bestimmt. Erwägen Sie eine explizite 'As <Datentyp>'-Deklaration zu verwenden um die Lesbarkeit zu verbessern, wobei '<Datentyp>' der erwünschte Datentyp der Konstante ist. + \ No newline at end of file diff --git a/Rubberduck.Resources/Inspections/InspectionInfo.resx b/Rubberduck.Resources/Inspections/InspectionInfo.resx index 7128cb7653..ecfe565c9c 100644 --- a/Rubberduck.Resources/Inspections/InspectionInfo.resx +++ b/Rubberduck.Resources/Inspections/InspectionInfo.resx @@ -329,7 +329,7 @@ If the parameter can be null, ignore this inspection result; passing a null valu An annotation is specified multiple times, but is intended to be specified only once. - Modules without the '@Folder' annotation cannot receive custom groupings in the Code Explorer. + Modules without the '@Folder' annotation cannot receive custom groupings in the Code Explorer. On Local Error exists only for compatibility with previous versions of Visual Basic, and all Errors are treated as Local regardless of the On Local Error statement. Use of this keyword inaccurately gives the impression that there is a distinction between types of error handling when there is not. @@ -437,6 +437,6 @@ If the parameter can be null, ignore this inspection result; passing a null valu The return value of a function gets discarded, i.e. the function is used like a procedure. This is either an oversight or the function is used for its side-effects, whose existence would also be a code smell. - If the type clause for a Const isn't included it is implicitly typed. Include an explicit ' As <Type>' replacing '<Type>' with the correct data type to explicitly type your const value. + If the as type clause for a Const isn't included it is implicitly typed. Include an explicit ' As <Type>' replacing '<Type>' with the correct data type to explicitly type your const value. \ No newline at end of file diff --git a/Rubberduck.Resources/Inspections/InspectionNames.Designer.cs b/Rubberduck.Resources/Inspections/InspectionNames.Designer.cs index 304f558868..415c6b6001 100644 --- a/Rubberduck.Resources/Inspections/InspectionNames.Designer.cs +++ b/Rubberduck.Resources/Inspections/InspectionNames.Designer.cs @@ -133,7 +133,7 @@ public static string DefaultMemberRequiredInspection { } /// - /// Looks up a localized string similar to Project name is not specified. + /// Looks up a localized string similar to Project name is not specified.. /// public static string DefaultProjectNameInspection { get { @@ -277,7 +277,7 @@ public static string ExcelUdfNameIsValidCellReferenceInspection { } /// - /// Looks up a localized string similar to Function return value is always discarded. + /// Looks up a localized string similar to Function return value is always discarded.. /// public static string FunctionReturnValueAlwaysDiscardedInspection { get { @@ -286,7 +286,7 @@ public static string FunctionReturnValueAlwaysDiscardedInspection { } /// - /// Looks up a localized string similar to Function return value gets discarded. + /// Looks up a localized string similar to Function return value gets discarded.. /// public static string FunctionReturnValueDiscardedInspection { get { @@ -556,7 +556,7 @@ public static string ModuleWithoutFolderInspection { } /// - /// Looks up a localized string similar to Scope of variable is broader than it needs to be. + /// Looks up a localized string similar to Scope of variable is broader than it needs to be.. /// public static string MoveFieldCloserToUsageInspection { get { @@ -565,7 +565,7 @@ public static string MoveFieldCloserToUsageInspection { } /// - /// Looks up a localized string similar to Parameter declaration is split on multiple lines. + /// Looks up a localized string similar to Parameter declaration is split on multiple lines.. /// public static string MultilineParameterInspection { get { @@ -610,7 +610,7 @@ public static string NonReturningFunctionInspection { } /// - /// Looks up a localized string similar to Object variable assignment requires 'Set' keyword. + /// Looks up a localized string similar to Object variable assignment requires 'Set' keyword.. /// public static string ObjectVariableNotSetInspection { get { @@ -727,7 +727,7 @@ public static string OnLocalErrorInspection { } /// - /// Looks up a localized string similar to 'Option Base 1' is specified. + /// Looks up a localized string similar to 'Option Base 1' is specified.. /// public static string OptionBaseInspection { get { @@ -745,7 +745,7 @@ public static string OptionBaseZeroInspection { } /// - /// Looks up a localized string similar to 'Option Explicit' is not specified. + /// Looks up a localized string similar to 'Option Explicit' is not specified.. /// public static string OptionExplicitInspection { get { @@ -754,7 +754,7 @@ public static string OptionExplicitInspection { } /// - /// Looks up a localized string similar to Parameter can be passed by value. + /// Looks up a localized string similar to Parameter can be passed by value.. /// public static string ParameterCanBeByValInspection { get { @@ -763,7 +763,7 @@ public static string ParameterCanBeByValInspection { } /// - /// Looks up a localized string similar to Parameter is not referred to. + /// Looks up a localized string similar to Parameter is not referred to.. /// public static string ParameterNotUsedInspection { get { @@ -772,7 +772,7 @@ public static string ParameterNotUsedInspection { } /// - /// Looks up a localized string similar to Procedure can be written as a function. + /// Looks up a localized string similar to Procedure can be written as a function.. /// public static string ProcedureCanBeWrittenAsFunctionInspection { get { @@ -781,7 +781,7 @@ public static string ProcedureCanBeWrittenAsFunctionInspection { } /// - /// Looks up a localized string similar to Procedure is not referred to. + /// Looks up a localized string similar to Procedure is not referred to.. /// public static string ProcedureNotUsedInspection { get { @@ -817,7 +817,7 @@ public static string RedundantOptionInspection { } /// - /// Looks up a localized string similar to Object variable reference is auto-instantiated. + /// Looks up a localized string similar to Object variable reference is auto-instantiated.. /// public static string SelfAssignedDeclarationInspection { get { @@ -889,7 +889,7 @@ public static string SuspiciousLetAssignmentInspection { } /// - /// Looks up a localized string similar to Variable is used but not assigned. + /// Looks up a localized string similar to Variable is used but not assigned.. /// public static string UnassignedVariableUsageInspection { get { @@ -925,7 +925,7 @@ public static string UnhandledOnErrorResumeNextInspection { } /// - /// Looks up a localized string similar to Case Clause(s) cannot be reached. + /// Looks up a localized string similar to Case Clause(s) cannot be reached.. /// public static string UnreachableCaseInspection { get { @@ -988,7 +988,7 @@ public static string ValueRequiredInspection { } /// - /// Looks up a localized string similar to Variable is not assigned. + /// Looks up a localized string similar to Variable is not assigned.. /// public static string VariableNotAssignedInspection { get { @@ -997,7 +997,7 @@ public static string VariableNotAssignedInspection { } /// - /// Looks up a localized string similar to Variable is not referred to. + /// Looks up a localized string similar to Variable is not referred to.. /// public static string VariableNotUsedInspection { get { diff --git a/Rubberduck.Resources/Inspections/InspectionNames.de.resx b/Rubberduck.Resources/Inspections/InspectionNames.de.resx index 873134722a..06e9add69d 100644 --- a/Rubberduck.Resources/Inspections/InspectionNames.de.resx +++ b/Rubberduck.Resources/Inspections/InspectionNames.de.resx @@ -229,13 +229,13 @@ Verwendung von 'Dim' auf Modulebene - Laufzeitgebundener Aufruf an WorksheetFunction + Laufzeitgebundener Aufruf an WorksheetFunction. Hostspezifischer geklammerter Ausdruck wird nur zur Laufzeit ausgewertet - Variable verwendet 'Ungarische Notation' + Variable verwendet 'Ungarische Notation'. Member existiert auf dem Interface nicht @@ -322,7 +322,7 @@ Verwendung eines als '@Obsolete' markierten Members - Verwendung der 'CDecl' Aufrufkonvention unter Windows + Verwendung der 'CDecl' Aufrufkonvention unter Windows Annotation ist dupliziert @@ -420,4 +420,7 @@ Der Rückgabewert einer Funktion wird verworfen. + + Konstante mit implizit bestimmtem Datentyp + \ No newline at end of file diff --git a/Rubberduck.Resources/Inspections/InspectionNames.resx b/Rubberduck.Resources/Inspections/InspectionNames.resx index 0460531ad2..d1ded96ad5 100644 --- a/Rubberduck.Resources/Inspections/InspectionNames.resx +++ b/Rubberduck.Resources/Inspections/InspectionNames.resx @@ -124,7 +124,7 @@ Constant is not used - Project name is not specified + Project name is not specified. Empty string literal @@ -148,10 +148,10 @@ Member return type is implicitly 'Variant' - Scope of variable is broader than it needs to be + Scope of variable is broader than it needs to be. - Parameter declaration is split on multiple lines + Parameter declaration is split on multiple lines. Multiple declarations in single instruction @@ -175,22 +175,22 @@ Obsolete Type hint usage - 'Option Base 1' is specified + 'Option Base 1' is specified. - 'Option Explicit' is not specified + 'Option Explicit' is not specified. - Parameter can be passed by value + Parameter can be passed by value. - Parameter is not referred to + Parameter is not referred to. - Procedure is not referred to + Procedure is not referred to. - Variable is used but not assigned + Variable is used but not assigned. Use of variant-returning string function @@ -199,10 +199,10 @@ Use meaningful names - Variable is not assigned + Variable is not assigned. - Variable is not referred to + Variable is not referred to. Implicitly 'Variant' variable @@ -211,16 +211,16 @@ Write-only property - Procedure can be written as a function + Procedure can be written as a function. - Object variable reference is auto-instantiated + Object variable reference is auto-instantiated. - Function return value is always discarded + Function return value is always discarded. - Object variable assignment requires 'Set' keyword + Object variable assignment requires 'Set' keyword. Missing annotation parameter @@ -301,7 +301,7 @@ Use of obsolete 'Error' statement - Case Clause(s) cannot be reached + Case Clause(s) cannot be reached. Unhandled 'On Error Resume Next' @@ -438,7 +438,7 @@ Suspicious Let assignment - Function return value gets discarded + Function return value gets discarded. Implicitly typed Const diff --git a/Rubberduck.Resources/Inspections/InspectionResults.Designer.cs b/Rubberduck.Resources/Inspections/InspectionResults.Designer.cs index dd055863b6..3eb1f8de2c 100644 --- a/Rubberduck.Resources/Inspections/InspectionResults.Designer.cs +++ b/Rubberduck.Resources/Inspections/InspectionResults.Designer.cs @@ -106,7 +106,7 @@ public static string AssignmentNotUsedInspection { } /// - /// Looks up a localized string similar to The attribute value(s) for attribute {0} ({1}) are out of sync with the {2} annotation. . + /// Looks up a localized string similar to The attribute value(s) for attribute {0} ({1}) are out of sync with the {2} annotation.. /// public static string AttributeValueOutOfSyncInspection { get { @@ -484,7 +484,7 @@ public static string IsMissingWithNonArgumentParameterInspection { } /// - /// Looks up a localized string similar to Keyword used as an identifier for the member '{0}'. + /// Looks up a localized string similar to Keyword used as an identifier for the member '{0}'.. /// public static string KeywordsUsedAsMemberInspection { get { @@ -493,7 +493,7 @@ public static string KeywordsUsedAsMemberInspection { } /// - /// Looks up a localized string similar to Line continuation(s) in unexpected places. . + /// Looks up a localized string similar to Line continuation(s) in unexpected places.. /// public static string LineContinuationBetweenKeywordsInspection { get { @@ -565,7 +565,7 @@ public static string ModuleScopeDimKeywordInspection { } /// - /// Looks up a localized string similar to Module '{0}' has no '@Folder' annotation. + /// Looks up a localized string similar to Module '{0}' has no '@Folder' annotation.. /// public static string ModuleWithoutFolderInspection { get { @@ -610,7 +610,7 @@ public static string NegativeLineNumberInspection { } /// - /// Looks up a localized string similar to Non-breaking space encountered in identifier '{0}'. + /// Looks up a localized string similar to Non-breaking space encountered in identifier '{0}'.. /// public static string NonBreakingSpaceIdentifierInspection { get { @@ -853,7 +853,7 @@ public static string SelfAssignedDeclarationInspection { } /// - /// Looks up a localized string similar to To the variable '{0}' of declared type '{1}' a value is set assigned with the incompatible declared type '{2}'. . + /// Looks up a localized string similar to To the variable '{0}' of declared type '{1}' a value is set assigned with the incompatible declared type '{2}'.. /// public static string SetAssignmentWithIncompatibleObjectTypeInspection { get { @@ -973,7 +973,7 @@ public static string UnreachableCaseInspection { } /// - /// Looks up a localized string similar to 'Case Else' statement is unreachable. + /// Looks up a localized string similar to 'Case Else' statement is unreachable.. /// public static string UnreachableCaseInspection_CaseElse { get { @@ -991,7 +991,7 @@ public static string UnreachableCaseInspection_InherentlyUnreachable { } /// - /// Looks up a localized string similar to 'Case' statement will cause run-time error 6 (Overflow). + /// Looks up a localized string similar to 'Case' statement will cause run-time error 6 (Overflow).. /// public static string UnreachableCaseInspection_Overflow { get { @@ -1009,7 +1009,7 @@ public static string UnreachableCaseInspection_TypeMismatch { } /// - /// Looks up a localized string similar to 'Case' statement is unreachable. + /// Looks up a localized string similar to 'Case' statement is unreachable.. /// public static string UnreachableCaseInspection_Unreachable { get { diff --git a/Rubberduck.Resources/Inspections/InspectionResults.de.resx b/Rubberduck.Resources/Inspections/InspectionResults.de.resx index b9160db11b..8608bb9ed7 100644 --- a/Rubberduck.Resources/Inspections/InspectionResults.de.resx +++ b/Rubberduck.Resources/Inspections/InspectionResults.de.resx @@ -118,7 +118,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Das öffentliche Feld '{0}' bricht die Kapselung + Das öffentliche Feld '{0}' bricht die Kapselung. Veringere die den Geltungsbereich der Modulvariable '{0}'. @@ -144,28 +144,28 @@ Der Parameter '{0}' wird als byVal übergeben und bekommt ienen Wert zugesiesen. - {0} '{1}' wird nicht genutzt + {0} '{1}' wird nicht genutzt. - Methode '{0}' ist implizit 'Public' + Methode '{0}' ist implizit 'Public'. - {0} '{1}' ist implizit 'Variant' + {0} '{1}' ist implizit 'Variant'. Der Rückgabewert der Methode '{0}' ist implizit 'Variant'. - Der Parameter '{0}' wird über mehrere Zeilen angegeben + Der Parameter '{0}' wird über mehrere Zeilen angegeben. - Der Rückgabewert der Methode '{0}' wird nicht zugewiesen + Der Rückgabewert der Methode '{0}' wird nicht zugewiesen. - {0} '{1}' verwendet die veraltete 'Global' Zugriffsdeklaration + {0} '{1}' verwendet die veraltete 'Global' Zugriffsdeklaration. - Der Parameter '{0}' kann als Wert übergeben werden + Der Parameter '{0}' kann als Wert übergeben werden. Der Parameter '{0}' wird nicht verwendet. @@ -174,7 +174,7 @@ Die Prozedur '{0}' kann als Funktion geschrieben werden. - Die Variable '{0}' wird verwendet ohne ihr einen Wert zuzuweisen + Die Variable '{0}' wird verwendet ohne ihr einen Wert zuzuweisen. 'Option Explicit' ist für '{0}' nicht angegeben. @@ -186,52 +186,52 @@ vbNullString' sollte statt einem leeren String-Literal verwendet werden. - Objektvariable '{0}' wird ohne das 'Set'-Schlüsselwort zugewiesen + Objektvariable '{0}' wird ohne das 'Set'-Schlüsselwort zugewiesen. - {0} '{1}' ist implizit 'Variant' + {0} '{1}' ist implizit 'Variant'. - Kommentar verwendet die obsolete 'REM'-Markierung + Kommentar verwendet die obsolete 'REM'-Markierung. - Projekt '{0}' hat den Standardnamen + Projekt '{0}' hat den Standardnamen. - Verwendung der veralteten 'Call'-Anweisung + Verwendung der veralteten 'Call'-Anweisung. - Verwendung der veralteten 'Let'-Anweisung + Verwendung der veralteten 'Let'-Anweisung. - Member '{0}' referenziert implizit auf 'ActiveSheet' + Member '{0}' referenziert implizit auf 'ActiveSheet'. - Member '{0}' referenziert implizit auf 'ActiveWorkbook' + Member '{0}' referenziert implizit auf 'ActiveWorkbook'. - Ersetze Funktion {0} mit der existierenden typisierten Funktion + Ersetze Funktion {0} mit der existierenden typisierten Funktion. - Komponente '{0}' verwendet 'Option Base 1' + Komponente '{0}' verwendet 'Option Base 1'. - {0} von {1} '{2}' verwendet einen obsoleten Typenhinweis + {0} von {1} '{2}' verwendet einen obsoleten Typenhinweis. - Instruktion enthält Mehrfachdeklaration + Instruktion enthält Mehrfachdeklaration. Ausdruck '{0}' sollte einen Parameter enthalten, es wurde aber keiner angegeben. - Die lokale Variable '{0}' wurde nicht deklariert + Die lokale Variable '{0}' wurde nicht deklariert. Die Modulvariable '{0}' ist mit dem 'Dim'-Schlüsselwort deklariert. - {0} ({1} Ergebnisse) + {0} ({1} Ergebnisse). Laufzeitgebundene Nutzung des Application.{0} Members. @@ -243,19 +243,19 @@ Member '{0}' ist auf dem Interface für '{1}' nicht deklariert. - Komponente '{0}' verwendet 'Option Base 0' + Komponente '{0}' verwendet 'Option Base 0'. Der Parameter '{0}' wird implizit als Referenz übergeben. - Die Zeilenbezeichnung '{0}' wird nicht verwendet + Die Zeilenbezeichnung '{0}' wird nicht verwendet. - Der Parameter '{0}' hat eine redundante 'ByRef'-Markierung + Der Parameter '{0}' hat eine redundante 'ByRef'-Markierung. - 'If'-Block enthält keine ausführbaren Anweisungen + 'If'-Block enthält keine ausführbaren Anweisungen. Die Annotation '{0}' ist in diesem Kontext nicht erlaubt. @@ -267,37 +267,37 @@ Modul oder Element '{0}' hat eine '{1}' Annotation, aber das zugehörige Attribut fehlt. - 'Case'-Block enthält keine ausführbaren Anweisungen + 'Case'-Block enthält keine ausführbaren Anweisungen. - Das Schlüsselwort 'Stop' unterbricht die Ausführung + Das Schlüsselwort 'Stop' unterbricht die Ausführung. - {0} '{1}' überschattet {2} '{3}' + {0} '{1}' überschattet {2} '{3}'. - Ein Laufzeitfehler wird mit der veralteten 'Error'-Anweisung ausgelöst + Ein Laufzeitfehler wird mit der veralteten 'Error'-Anweisung ausgelöst. - 'For Each…Next'-Schleife enthält keine ausführbaren Anweisungen + 'For Each…Next'-Schleife enthält keine ausführbaren Anweisungen. - 'Else'-Block enthält keine ausführbaren Anweisungen + 'Else'-Block enthält keine ausführbaren Anweisungen. 'For…Next'-Schleife enthält keine ausführbaren Anweisungen. - {0} '{1}' ist als Integer deklariert + {0} '{1}' ist als Integer deklariert. - 'While…Wend'-Schleife enthält keine ausführbaren Anweisungen + 'While…Wend'-Schleife enthält keine ausführbaren Anweisungen. - 'Do…While'-Schleife enthält keine ausführbaren Anweisungen + 'Do…While'-Schleife enthält keine ausführbaren Anweisungen. - Boolean Ausdruck '{0}' wurde in einer trivialen If/Else-Verzweigung zugewiesen + Boolean Ausdruck '{0}' wurde in einer trivialen If/Else-Verzweigung zugewiesen. Modul/Klasse {0} ist leer. @@ -306,13 +306,13 @@ Fehler werden ignoriert aber nie wieder behandelt. - Statt '{1}' explizit 'as {0}' verwenden + Statt '{1}' explizit 'As {0}' verwenden. 1 ist der Standardwert für 'Step' in einer 'For-Next'-Schleife und daher redundant. - Step ist nicht angegeben + Step ist nicht angegeben. Statisch erreichbares Tabellenblatt kann mit dem Code-Namen referenziert werden. @@ -363,7 +363,7 @@ Der Name des Elements '{0}' ist ein Schlüsselwort. - Zeilenfortsetzungszeichen an unerwarteten Orten + Zeilenfortsetzungszeichen an unerwarteten Orten. Der Bezeichner '{0}' enthält eine geschütztes Leerzeichen. @@ -461,4 +461,7 @@ In Memoriam, 1972-2018 Der Rückgabewert der Funktion '{0}' wird verworfen. + + Der Datentyp der Konstante '{0}' ist implizit bestimmt. + \ No newline at end of file diff --git a/Rubberduck.Resources/Inspections/InspectionResults.resx b/Rubberduck.Resources/Inspections/InspectionResults.resx index a34f882381..a675ca3eee 100644 --- a/Rubberduck.Resources/Inspections/InspectionResults.resx +++ b/Rubberduck.Resources/Inspections/InspectionResults.resx @@ -208,9 +208,11 @@ Member '{0}' implicitly references 'ActiveSheet'. + {0} member name Member '{0}' implicitly references 'ActiveWorkbook'. + {0} member name Instruction contains multiple declarations. @@ -318,13 +320,13 @@ Case clause '{0}' cannot be reached. - 'Case Else' statement is unreachable + 'Case Else' statement is unreachable. 'Case' statement will cause run-time error 13 (type mismatch). - 'Case' statement is unreachable + 'Case' statement is unreachable. Errors are ignored but never handled again. @@ -353,13 +355,13 @@ 'Case' statement Range Clauses must be expressed '[x] To [y]' where [x] is less than or equal to [y]'. - 'Case' statement will cause run-time error 6 (Overflow) + 'Case' statement will cause run-time error 6 (Overflow). Annotation '{0}' is duplicated. - Module '{0}' has no '@Folder' annotation + Module '{0}' has no '@Folder' annotation. 'On Local Error' statement detected. @@ -385,7 +387,7 @@ {0} Function name - The attribute value(s) for attribute {0} ({1}) are out of sync with the {2} annotation. + The attribute value(s) for attribute {0} ({1}) are out of sync with the {2} annotation. {0} attribute name, {1} attribute values, {2} annotation name @@ -397,14 +399,14 @@ {0} module; {1} specified attribute; {2} specified values - Keyword used as an identifier for the member '{0}' + Keyword used as an identifier for the member '{0}'. {0} Member name - Line continuation(s) in unexpected places. + Line continuation(s) in unexpected places. - Non-breaking space encountered in identifier '{0}' + Non-breaking space encountered in identifier '{0}'. {0} Identifier @@ -424,7 +426,7 @@ In memoriam, 1972-2018 'While...Wend' conditional loop can be written as a 'Do While...Loop' block. - To the variable '{0}' of declared type '{1}' a value is set assigned with the incompatible declared type '{2}'. + To the variable '{0}' of declared type '{1}' a value is set assigned with the incompatible declared type '{2}'. {0} variable name, {1} variable declared type, {2} rhs declared type From 534f7f752440c16b01a40bf8e1cfb8efd6c02f65 Mon Sep 17 00:00:00 2001 From: IvenBach Date: Wed, 15 Jan 2020 13:28:45 -0800 Subject: [PATCH 153/461] Simplify default expression --- .../UI/Command/MenuItems/ParentMenus/ParentMenuItemBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rubberduck.Core/UI/Command/MenuItems/ParentMenus/ParentMenuItemBase.cs b/Rubberduck.Core/UI/Command/MenuItems/ParentMenus/ParentMenuItemBase.cs index 713a256f24..5047c33265 100644 --- a/Rubberduck.Core/UI/Command/MenuItems/ParentMenus/ParentMenuItemBase.cs +++ b/Rubberduck.Core/UI/Command/MenuItems/ParentMenus/ParentMenuItemBase.cs @@ -62,7 +62,7 @@ public virtual Func ToolTipText } public virtual bool BeginGroup => false; - public virtual int DisplayOrder => default(int); + public virtual int DisplayOrder => default; public void Localize() { From 52a04e9bedec256a888aeda6a5f388837ea485f2 Mon Sep 17 00:00:00 2001 From: IvenBach Date: Wed, 15 Jan 2020 13:31:36 -0800 Subject: [PATCH 154/461] Add instancing for Extract Interface Declaration's aren't correctly reflecting the exposed attribute. Need to work out *why*, when PublicNotCreatable is chosen in the IDE, it isn't reflected in Declaration.Attributes.ExposedAttributes.Values --- .../ExtractInterfaceView.xaml | 368 +++++++++--------- .../ExtractInterfaceViewModel.cs | 16 +- .../ExtractInterfaceRefactoring.cs | 6 + .../InteractiveRefactoringBase.cs | 3 +- Rubberduck.Resources/RubberduckUI.Designer.cs | 27 ++ Rubberduck.Resources/RubberduckUI.resx | 9 + .../Office/CommandBarButton.cs | 1 - 7 files changed, 248 insertions(+), 182 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceView.xaml b/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceView.xaml index bb476c0667..75b9cb3ae7 100644 --- a/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceView.xaml +++ b/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceView.xaml @@ -1,179 +1,189 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceViewModel.cs b/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceViewModel.cs index a5960dd92f..734172d181 100644 --- a/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceViewModel.cs @@ -5,7 +5,6 @@ using NLog; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; -using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings.ExtractInterface; using Rubberduck.UI.Command; @@ -62,6 +61,21 @@ public bool IsValidInterfaceName } } + public bool IsInterfacePublicNotCreateable + { + get + { + try + { + return Convert.ToBoolean(Model.TargetDeclaration.Attributes.ExposedAttribute.Values.First()); + } + catch (FormatException) + { + return false; + } + } + } + private void ToggleSelection(bool value) { foreach (var item in Members) diff --git a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs index 6745a264e8..98c2ee5f4d 100644 --- a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs +++ b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs @@ -140,6 +140,12 @@ private void AddInterfaceClass(Declaration implementingClass, string interfaceNa private void AddInterfaceMembersToClass(ExtractInterfaceModel model, IModuleRewriter rewriter) { _implementInterfaceRefactoring.Refactor(model.SelectedMembers.Select(m => m.Member).ToList(), rewriter, model.InterfaceName); + + var classIsExposed = Convert.ToBoolean(model.TargetDeclaration.Attributes.ExposedAttribute.Values.First()); + if (classIsExposed) + { + model.TargetDeclaration.Attributes.AddExposedClassAttribute(); + } } private string GetInterfaceModuleBody(ExtractInterfaceModel model) diff --git a/Rubberduck.Refactorings/InteractiveRefactoringBase.cs b/Rubberduck.Refactorings/InteractiveRefactoringBase.cs index e8939954c8..d27dc94200 100644 --- a/Rubberduck.Refactorings/InteractiveRefactoringBase.cs +++ b/Rubberduck.Refactorings/InteractiveRefactoringBase.cs @@ -26,7 +26,8 @@ protected InteractiveRefactoringBase( public override void Refactor(Declaration target) { - Refactor(InitializeModel(target)); + var model = InitializeModel(target); + Refactor(model); } protected void Refactor(TModel initialModel) diff --git a/Rubberduck.Resources/RubberduckUI.Designer.cs b/Rubberduck.Resources/RubberduckUI.Designer.cs index 171761f190..735c1b7314 100644 --- a/Rubberduck.Resources/RubberduckUI.Designer.cs +++ b/Rubberduck.Resources/RubberduckUI.Designer.cs @@ -1348,6 +1348,15 @@ public static string ExtractInterface_Caption { } } + /// + /// Looks up a localized string similar to Instancing. + /// + public static string ExtractInterface_InstancingGroupBox { + get { + return ResourceManager.GetString("ExtractInterface_InstancingGroupBox", resourceCulture); + } + } + /// /// Looks up a localized string similar to Please specify interface name and members.. /// @@ -1366,6 +1375,24 @@ public static string ExtractInterface_MembersGroupBox { } } + /// + /// Looks up a localized string similar to Private. + /// + public static string ExtractInterface_PrivateRadioButton { + get { + return ResourceManager.GetString("ExtractInterface_PrivateRadioButton", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Public Not Creatable. + /// + public static string ExtractInterface_PublicNotCreatableRadioButton { + get { + return ResourceManager.GetString("ExtractInterface_PublicNotCreatableRadioButton", resourceCulture); + } + } + /// /// Looks up a localized string similar to Extract Interface. /// diff --git a/Rubberduck.Resources/RubberduckUI.resx b/Rubberduck.Resources/RubberduckUI.resx index a28f453774..f5b2c96354 100644 --- a/Rubberduck.Resources/RubberduckUI.resx +++ b/Rubberduck.Resources/RubberduckUI.resx @@ -1754,4 +1754,13 @@ Import aborted. VB Form + + Instancing + + + Private + + + Public Not Creatable + \ No newline at end of file diff --git a/Rubberduck.VBEditor.VBA/SafeComWrappers/Office/CommandBarButton.cs b/Rubberduck.VBEditor.VBA/SafeComWrappers/Office/CommandBarButton.cs index a35f769281..c9b56b4b7c 100644 --- a/Rubberduck.VBEditor.VBA/SafeComWrappers/Office/CommandBarButton.cs +++ b/Rubberduck.VBEditor.VBA/SafeComWrappers/Office/CommandBarButton.cs @@ -3,7 +3,6 @@ using System.Runtime.InteropServices; using System.Windows.Forms; using Microsoft.CSharp.RuntimeBinder; -using NLog; using Rubberduck.VBEditor.SafeComWrappers.Abstract; using MSO = Microsoft.Office.Core; From 00922e1179307034f7ae58988bcf5b8d53932db2 Mon Sep 17 00:00:00 2001 From: IvenBach Date: Wed, 15 Jan 2020 15:20:57 -0800 Subject: [PATCH 155/461] Make property assignment explicit --- .../ExtractInterface/InterfaceMember.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Rubberduck.Refactorings/ExtractInterface/InterfaceMember.cs b/Rubberduck.Refactorings/ExtractInterface/InterfaceMember.cs index 3817516ebe..4deb49b8b2 100644 --- a/Rubberduck.Refactorings/ExtractInterface/InterfaceMember.cs +++ b/Rubberduck.Refactorings/ExtractInterface/InterfaceMember.cs @@ -56,7 +56,7 @@ public InterfaceMember(Declaration member) Identifier = member.IdentifierName; Type = member.AsTypeName; - GetMethodType(); + MemberType = GetMethodType(Member.Context); if (member is IParameterizedDeclaration memberWithParams) { @@ -83,34 +83,34 @@ public InterfaceMember(Declaration member) } } - private void GetMethodType() + private string GetMethodType(Antlr4.Runtime.ParserRuleContext context) { - var context = Member.Context; - if (context is VBAParser.SubStmtContext) { - MemberType = Tokens.Sub; + return Tokens.Sub; } if (context is VBAParser.FunctionStmtContext) { - MemberType = Tokens.Function; + return Tokens.Function; } if (context is VBAParser.PropertyGetStmtContext) { - MemberType = $"{Tokens.Property} {Tokens.Get}"; + return $"{Tokens.Property} {Tokens.Get}"; } if (context is VBAParser.PropertyLetStmtContext) { - MemberType = $"{Tokens.Property} {Tokens.Let}"; + return $"{Tokens.Property} {Tokens.Let}"; } if (context is VBAParser.PropertySetStmtContext) { - MemberType = $"{Tokens.Property} {Tokens.Set}"; + return $"{Tokens.Property} {Tokens.Set}"; } + + return null; } public string Body => string.Format("Public {0}{1}End {2}{1}", FullMemberSignature, Environment.NewLine, MemberType.Split(' ').First()); From 5b09c23c667ac0a29564399be933864807509400 Mon Sep 17 00:00:00 2001 From: IvenBach Date: Wed, 15 Jan 2020 16:28:09 -0800 Subject: [PATCH 156/461] Add converter and use it --- .../ClassInstancingToBooleanConverter.cs | 26 +++++++++++++++++++ .../ExtractInterfaceView.xaml | 8 +++--- .../ExtractInterfaceViewModel.cs | 25 +++++++++++++++++- 3 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 Rubberduck.Core/UI/Converters/ClassInstancingToBooleanConverter.cs diff --git a/Rubberduck.Core/UI/Converters/ClassInstancingToBooleanConverter.cs b/Rubberduck.Core/UI/Converters/ClassInstancingToBooleanConverter.cs new file mode 100644 index 0000000000..209aa0e519 --- /dev/null +++ b/Rubberduck.Core/UI/Converters/ClassInstancingToBooleanConverter.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; +using Rubberduck.UI.Refactorings; + +namespace Rubberduck.UI.Converters +{ + class ClassInstancingToBooleanConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return (ClassInstancing)value == ClassInstancing.Private; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return (bool)value + ? ClassInstancing.Private + : ClassInstancing.PublicNotCreatable; + } + } +} diff --git a/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceView.xaml b/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceView.xaml index 75b9cb3ae7..04da0e6aa2 100644 --- a/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceView.xaml +++ b/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceView.xaml @@ -7,6 +7,7 @@ mc:Ignorable="d" Height="378" Width="372"> + @@ -93,10 +94,11 @@ - + + IsEnabled="{Binding IsInterfacePublicNotCreateableEnabled}" /> diff --git a/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceViewModel.cs b/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceViewModel.cs index 734172d181..4409601157 100644 --- a/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceViewModel.cs @@ -10,6 +10,12 @@ namespace Rubberduck.UI.Refactorings { + public enum ClassInstancing + { + Private = 0, + PublicNotCreatable, + } + public class ExtractInterfaceViewModel : RefactoringViewModelBase { public ExtractInterfaceViewModel(ExtractInterfaceModel model) : base(model) @@ -61,7 +67,7 @@ public bool IsValidInterfaceName } } - public bool IsInterfacePublicNotCreateable + public bool IsInterfacePublicNotCreateableEnabled { get { @@ -76,6 +82,23 @@ public bool IsInterfacePublicNotCreateable } } + private ClassInstancing classInstancing = ClassInstancing.Private; + public ClassInstancing ClassInstancing + { + get => classInstancing; + set + { + if (value == classInstancing) + { + return; + } + + classInstancing = value; + OnPropertyChanged(); + } + } + + private void ToggleSelection(bool value) { foreach (var item in Members) From 38d4399901f941928b6f61752efb257680a0ee74 Mon Sep 17 00:00:00 2001 From: IvenBach Date: Thu, 16 Jan 2020 13:34:57 -0800 Subject: [PATCH 157/461] Enable adding exposed attribute to interface Presently the choice is PublicNotCreatable if the implementing class is exposed. Next step is to connect view model RadioButton choice to determine the instacing. --- .../ClassInstancingToBooleanConverter.cs | 6 +-- .../ExtractInterfaceViewModel.cs | 6 --- .../ExtractInterface/ExtractInterfaceModel.cs | 7 ++++ .../ExtractInterfaceRefactoring.cs | 38 ++++++++++++++++--- 4 files changed, 40 insertions(+), 17 deletions(-) diff --git a/Rubberduck.Core/UI/Converters/ClassInstancingToBooleanConverter.cs b/Rubberduck.Core/UI/Converters/ClassInstancingToBooleanConverter.cs index 209aa0e519..f977865b9f 100644 --- a/Rubberduck.Core/UI/Converters/ClassInstancingToBooleanConverter.cs +++ b/Rubberduck.Core/UI/Converters/ClassInstancingToBooleanConverter.cs @@ -1,11 +1,7 @@ using System; -using System.Collections.Generic; using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using System.Windows.Data; -using Rubberduck.UI.Refactorings; +using Rubberduck.Refactorings.ExtractInterface; namespace Rubberduck.UI.Converters { diff --git a/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceViewModel.cs b/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceViewModel.cs index 4409601157..302ce36026 100644 --- a/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceViewModel.cs @@ -10,12 +10,6 @@ namespace Rubberduck.UI.Refactorings { - public enum ClassInstancing - { - Private = 0, - PublicNotCreatable, - } - public class ExtractInterfaceViewModel : RefactoringViewModelBase { public ExtractInterfaceViewModel(ExtractInterfaceModel model) : base(model) diff --git a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceModel.cs b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceModel.cs index 4ccd4cca88..d7bed42a7d 100644 --- a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceModel.cs +++ b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceModel.cs @@ -6,6 +6,12 @@ namespace Rubberduck.Refactorings.ExtractInterface { + public enum ClassInstancing + { + Private = 0, + PublicNotCreatable, + } + public class ExtractInterfaceModel : IRefactoringModel { public IDeclarationFinderProvider DeclarationFinderProvider { get; } @@ -14,6 +20,7 @@ public class ExtractInterfaceModel : IRefactoringModel public string InterfaceName { get; set; } public ObservableCollection Members { get; set; } = new ObservableCollection(); public IEnumerable SelectedMembers => Members.Where(m => m.IsSelected); + public ClassInstancing ClassInstancing { get; set; } public static readonly DeclarationType[] MemberTypes = { diff --git a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs index 98c2ee5f4d..0cf1715e74 100644 --- a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs +++ b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs @@ -13,6 +13,7 @@ using Rubberduck.VBEditor; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.Utility; +using Rubberduck.VBEditor.SafeComWrappers.Abstract; namespace Rubberduck.Refactorings.ExtractInterface { @@ -127,27 +128,52 @@ private void AddInterfaceClass(Declaration implementingClass, string interfaceNa interfaceComponent.Name = interfaceName; var optionPresent = interfaceModule.CountOfLines > 1; + var optionExplicit = $"{Tokens.Option} {Tokens.Explicit}{Environment.NewLine}"; if (!optionPresent) { - interfaceModule.InsertLines(1, $"{Tokens.Option} {Tokens.Explicit}{Environment.NewLine}"); + interfaceModule.InsertLines(1, optionExplicit); } + interfaceModule.InsertLines(3, interfaceBody); + + var classIsExposed = Convert.ToBoolean(implementingClass.Attributes.ExposedAttribute.Values.First()); + if (classIsExposed) + { + AddExposedAttribute(components, interfaceComponent); + } } } } } - private void AddInterfaceMembersToClass(ExtractInterfaceModel model, IModuleRewriter rewriter) + private void AddExposedAttribute(IVBComponents components, IVBComponent interfaceComponent) { - _implementInterfaceRefactoring.Refactor(model.SelectedMembers.Select(m => m.Member).ToList(), rewriter, model.InterfaceName); + try + { + var tempExportDirectory = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + System.IO.Path.DirectorySeparatorChar + "Rubberduck" + System.IO.Path.DirectorySeparatorChar; + var tempFile = interfaceComponent.ExportAsSourceFile(tempExportDirectory + interfaceComponent.Name); + + var text = System.IO.File.ReadAllText(tempFile); + var sb = new System.Text.StringBuilder(text); + sb.Replace("Attribute VB_Exposed = False", "Attribute VB_Exposed = True"); + System.IO.File.WriteAllText(tempFile, sb.ToString()); - var classIsExposed = Convert.ToBoolean(model.TargetDeclaration.Attributes.ExposedAttribute.Values.First()); - if (classIsExposed) + components.Remove(interfaceComponent); + components.ImportSourceFile(tempFile); + + System.IO.File.Delete(tempFile); + } + catch (Exception) { - model.TargetDeclaration.Attributes.AddExposedClassAttribute(); + throw; } } + private void AddInterfaceMembersToClass(ExtractInterfaceModel model, IModuleRewriter rewriter) + { + _implementInterfaceRefactoring.Refactor(model.SelectedMembers.Select(m => m.Member).ToList(), rewriter, model.InterfaceName); + } + private string GetInterfaceModuleBody(ExtractInterfaceModel model) { return string.Join(Environment.NewLine, model.SelectedMembers.Select(m => m.Body)); From d44c74b29a10600246933a1c831142a969f06730 Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Fri, 17 Jan 2020 00:15:03 -0500 Subject: [PATCH 158/461] UI tweaks --- .../EncapsulateFieldView.xaml | 350 +++++++----------- Rubberduck.Resources/RubberduckUI.Designer.cs | 8 +- Rubberduck.Resources/RubberduckUI.resx | 8 +- 3 files changed, 149 insertions(+), 217 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml index 97cdd8a6d8..b122b70561 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml @@ -6,8 +6,9 @@ xmlns:controls="clr-namespace:Rubberduck.UI.Controls" xmlns:converters="clr-namespace:Rubberduck.UI.Converters" mc:Ignorable="d" - d:DesignHeight="800" - d:DesignWidth="900"> + MinHeight="600" + d:DesignHeight="600" + d:DesignWidth="600" Background="AliceBlue"> @@ -16,13 +17,13 @@ @@ -38,227 +39,158 @@ - - - - - + + + + + + + + + + + + + + - - + + - + - - - - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + Command="{Binding Path=DataContext.EncapsulateFlagChangeCommand, RelativeSource={RelativeSource AncestorType=ListBox}}" + CommandParameter="{Binding ElementName=EncapsulationFields, Path=SelectedField}"> + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + - - + + + - + Style="{StaticResource CommandButtonStyle}" + Command="{Binding CancelButtonCommand}"/> diff --git a/Rubberduck.Resources/RubberduckUI.Designer.cs b/Rubberduck.Resources/RubberduckUI.Designer.cs index 395640373f..e9dde5383b 100644 --- a/Rubberduck.Resources/RubberduckUI.Designer.cs +++ b/Rubberduck.Resources/RubberduckUI.Designer.cs @@ -1257,7 +1257,7 @@ public static string EncapsulateField_InstructionText { } /// - /// Looks up a localized string similar to Name Conflict Detected. + /// Looks up a localized string similar to Name conflict. /// public static string EncapsulateField_NameConflictDetected { get { @@ -1284,7 +1284,7 @@ public static string EncapsulateField_Preview { } /// - /// Looks up a localized string similar to '<===== Property and Declaration changes above this line =====>. + /// Looks up a localized string similar to '<===== Property and declaration changes above this line =====>. /// public static string EncapsulateField_PreviewMarker { get { @@ -1293,7 +1293,7 @@ public static string EncapsulateField_PreviewMarker { } /// - /// Looks up a localized string similar to Creates a Property for each UDT Member. + /// Looks up a localized string similar to Creates a property for each UDT Member. /// public static string EncapsulateField_PrivateUDTPropertyText { get { @@ -1403,7 +1403,7 @@ public static System.Drawing.Bitmap exclamation_pinned { } /// - /// Looks up a localized string similar to Choose a folder to export the source of {0} to:. + /// Looks up a localized string similar to Select a folder to export the source of {0} to:. /// public static string ExportAllCommand_SaveAsDialog_Title { get { diff --git a/Rubberduck.Resources/RubberduckUI.resx b/Rubberduck.Resources/RubberduckUI.resx index da901ff542..5c86158903 100644 --- a/Rubberduck.Resources/RubberduckUI.resx +++ b/Rubberduck.Resources/RubberduckUI.resx @@ -1095,7 +1095,7 @@ This dialog is showing because version checks are enabled. You can turn off this Experimental Features (Requires a restart to take effect): - Choose a folder to export the source of {0} to: + Select a folder to export the source of {0} to: {0} VBProject.Name @@ -1765,13 +1765,13 @@ Import aborted. value - Name Conflict Detected + Name conflict - '<===== Property and Declaration changes above this line =====> + '<===== Property and declaration changes above this line =====> - Creates a Property for each UDT Member + Creates a property for each UDT Member Read Only From 93156c584bced4bfd11dfcef91951afacc42e930 Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Fri, 17 Jan 2020 00:18:32 -0500 Subject: [PATCH 159/461] removed background --- .../Refactorings/EncapsulateField/EncapsulateFieldView.xaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml index b122b70561..e296537e2f 100644 --- a/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml +++ b/Rubberduck.Core/UI/Refactorings/EncapsulateField/EncapsulateFieldView.xaml @@ -8,12 +8,11 @@ mc:Ignorable="d" MinHeight="600" d:DesignHeight="600" - d:DesignWidth="600" Background="AliceBlue"> + d:DesignWidth="600"> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Rubberduck.Core/UI/Controls/ToolBar.xaml b/Rubberduck.Core/UI/Controls/ToolBar.xaml index ab587d106a..edc4c2ff23 100644 --- a/Rubberduck.Core/UI/Controls/ToolBar.xaml +++ b/Rubberduck.Core/UI/Controls/ToolBar.xaml @@ -2,7 +2,10 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" xmlns:converters="clr-namespace:Rubberduck.UI.Converters"> - + + + + @@ -23,15 +26,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Rubberduck.Core/UI/Refactorings/ReorderParameters/ReorderParametersView.xaml b/Rubberduck.Core/UI/Refactorings/ReorderParameters/ReorderParametersView.xaml index 82c4d02cf5..3260c727f3 100644 --- a/Rubberduck.Core/UI/Refactorings/ReorderParameters/ReorderParametersView.xaml +++ b/Rubberduck.Core/UI/Refactorings/ReorderParameters/ReorderParametersView.xaml @@ -8,88 +8,83 @@ mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> - - + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Rubberduck.Core/UI/RegexAssistant/RegexAssistant.xaml b/Rubberduck.Core/UI/RegexAssistant/RegexAssistant.xaml index 8202a40dd0..79259e9780 100644 --- a/Rubberduck.Core/UI/RegexAssistant/RegexAssistant.xaml +++ b/Rubberduck.Core/UI/RegexAssistant/RegexAssistant.xaml @@ -8,50 +8,41 @@ d:DataContext="{d:DesignInstance {x:Type assistant:RegexAssistantViewModel}, IsDesignTimeCreatable=False}" Height="302"> - - - - - - - - - - - - - + + + + - - - + + + - - - + + diff --git a/Rubberduck.Core/UI/Settings/AddRemoveReferencesUserSettings.xaml b/Rubberduck.Core/UI/Settings/AddRemoveReferencesUserSettings.xaml index 0ec37152e9..f4865e46aa 100644 --- a/Rubberduck.Core/UI/Settings/AddRemoveReferencesUserSettings.xaml +++ b/Rubberduck.Core/UI/Settings/AddRemoveReferencesUserSettings.xaml @@ -10,26 +10,22 @@ d:DesignHeight="350" d:DataContext="{d:DesignInstance {x:Type settings:AddRemoveReferencesUserSettingsViewModel}, IsDesignTimeCreatable=False}"> - - + + + + - + + - - - - - - - - - - - + + + + diff --git a/Rubberduck.Core/UI/Settings/GeneralSettings.xaml b/Rubberduck.Core/UI/Settings/GeneralSettings.xaml index ec9bf2670c..a48a4562de 100644 --- a/Rubberduck.Core/UI/Settings/GeneralSettings.xaml +++ b/Rubberduck.Core/UI/Settings/GeneralSettings.xaml @@ -12,68 +12,63 @@ d:DesignWidth="300" d:DataContext="{d:DesignInstance {x:Type settings:GeneralSettingsViewModel}, IsDesignTimeCreatable=False}"> - - - - - + + + + - - - - - - - - - - + + + + + - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Rubberduck.Core/UI/Settings/InspectionSettings.xaml b/Rubberduck.Core/UI/Settings/InspectionSettings.xaml index b4410e92bc..ebab6ad638 100644 --- a/Rubberduck.Core/UI/Settings/InspectionSettings.xaml +++ b/Rubberduck.Core/UI/Settings/InspectionSettings.xaml @@ -13,263 +13,250 @@ d:DesignWidth="700" d:DataContext="{d:DesignInstance {x:Type settings:InspectionSettingsViewModel}, IsDesignTimeCreatable=False}"> - - - + + + + + + + + - - - + + + - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + - + + diff --git a/Rubberduck.Core/UI/Settings/SettingsControl.xaml b/Rubberduck.Core/UI/Settings/SettingsControl.xaml index c5e035fcba..0daf9fe7b8 100644 --- a/Rubberduck.Core/UI/Settings/SettingsControl.xaml +++ b/Rubberduck.Core/UI/Settings/SettingsControl.xaml @@ -12,84 +12,78 @@ - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Rubberduck.Core/UI/Settings/TodoSettings.xaml b/Rubberduck.Core/UI/Settings/TodoSettings.xaml index d48630db29..127cdd1077 100644 --- a/Rubberduck.Core/UI/Settings/TodoSettings.xaml +++ b/Rubberduck.Core/UI/Settings/TodoSettings.xaml @@ -11,238 +11,229 @@ d:DesignHeight="300" d:DesignWidth="300" d:DataContext="{d:DesignInstance {x:Type settings:TodoSettingsViewModel}, IsDesignTimeCreatable=False}"> - - - - - - - - - - + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Rubberduck.Core/UI/Styles/DefaultStyle.xaml b/Rubberduck.Core/UI/Styles/DefaultStyle.xaml new file mode 100644 index 0000000000..afa26788aa --- /dev/null +++ b/Rubberduck.Core/UI/Styles/DefaultStyle.xaml @@ -0,0 +1,48 @@ + + + + + + + + + + + + #FFD9F4FF + #FF9BDDFB + #FFEEEDED + #FFDDDDDD + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Rubberduck.Core/UI/ToDoItems/ToDoExplorerControl.xaml b/Rubberduck.Core/UI/ToDoItems/ToDoExplorerControl.xaml index 18c7df1f31..03072b7002 100644 --- a/Rubberduck.Core/UI/ToDoItems/ToDoExplorerControl.xaml +++ b/Rubberduck.Core/UI/ToDoItems/ToDoExplorerControl.xaml @@ -13,226 +13,212 @@ d:DesignHeight="300" d:DesignWidth="400" d:DataContext="{d:DesignInstance {x:Type toDoItems:ToDoExplorerViewModel}, IsDesignTimeCreatable=False}"> - + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + diff --git a/Rubberduck.Interaction/Rubberduck.Interaction.csproj b/Rubberduck.Interaction/Rubberduck.Interaction.csproj index 862bddc8c1..5138b9cfd3 100644 --- a/Rubberduck.Interaction/Rubberduck.Interaction.csproj +++ b/Rubberduck.Interaction/Rubberduck.Interaction.csproj @@ -24,8 +24,6 @@ - - Form - + \ No newline at end of file From 3b63eb9c311a4cc4d3bf4580b127cb9791a800c4 Mon Sep 17 00:00:00 2001 From: IvenBach Date: Fri, 17 Jan 2020 12:52:10 -0800 Subject: [PATCH 161/461] Update extract public interface A private class can have a (public | private) interface extracted. The default option is public. When an implementing class is public the newly created interface must also too be public. As such the private option for the extracted interface is disabled. Need to get the Public.Checked = true on private implementing classes. Once that's done I can merge the following commits together and edit this commit. --- .../ClassInstancingToBooleanConverter.cs | 6 ++-- .../ExtractInterfaceView.xaml | 11 ++++---- .../ExtractInterfaceViewModel.cs | 28 ++++++++----------- .../ExtractInterface/ExtractInterfaceModel.cs | 5 +++- .../ExtractInterfaceRefactoring.cs | 14 +++++----- Rubberduck.Resources/RubberduckUI.Designer.cs | 2 +- Rubberduck.Resources/RubberduckUI.resx | 2 +- 7 files changed, 34 insertions(+), 34 deletions(-) diff --git a/Rubberduck.Core/UI/Converters/ClassInstancingToBooleanConverter.cs b/Rubberduck.Core/UI/Converters/ClassInstancingToBooleanConverter.cs index f977865b9f..25f3fcb6ba 100644 --- a/Rubberduck.Core/UI/Converters/ClassInstancingToBooleanConverter.cs +++ b/Rubberduck.Core/UI/Converters/ClassInstancingToBooleanConverter.cs @@ -9,14 +9,14 @@ class ClassInstancingToBooleanConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - return (ClassInstancing)value == ClassInstancing.Private; + return (ClassInstancing)value == ClassInstancing.PublicNotCreatable; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return (bool)value - ? ClassInstancing.Private - : ClassInstancing.PublicNotCreatable; + ? ClassInstancing.PublicNotCreatable + : ClassInstancing.Private; } } } diff --git a/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceView.xaml b/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceView.xaml index 04da0e6aa2..cfc0292cc1 100644 --- a/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceView.xaml +++ b/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceView.xaml @@ -8,6 +8,7 @@ + @@ -93,12 +94,12 @@ - - + + + IsChecked="{Binding IsPublicInterfaceChecked, Mode=TwoWay}" /> diff --git a/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceViewModel.cs b/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceViewModel.cs index 302ce36026..2ff79ac9d6 100644 --- a/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceViewModel.cs @@ -7,6 +7,7 @@ using Rubberduck.Parsing.Symbols; using Rubberduck.Refactorings.ExtractInterface; using Rubberduck.UI.Command; +using System.Windows.Data; namespace Rubberduck.UI.Refactorings { @@ -61,38 +62,33 @@ public bool IsValidInterfaceName } } - public bool IsInterfacePublicNotCreateableEnabled + public bool IsPrivateInterfaceEnabled { get { - try - { - return Convert.ToBoolean(Model.TargetDeclaration.Attributes.ExposedAttribute.Values.First()); - } - catch (FormatException) - { - return false; - } + return Model.ImplementingClassInstancing != ClassInstancing.PublicNotCreatable; } } - private ClassInstancing classInstancing = ClassInstancing.Private; - public ClassInstancing ClassInstancing + private readonly IValueConverter classInstancingConverter = new Converters.ClassInstancingToBooleanConverter(); + + private bool isPublicInterfaceChecked = true; + public bool IsPublicInterfaceChecked { - get => classInstancing; + get => isPublicInterfaceChecked; set { - if (value == classInstancing) + if (value == isPublicInterfaceChecked) { return; } - classInstancing = value; - OnPropertyChanged(); + Model.ImplementingClassInstancing = (ClassInstancing)classInstancingConverter.ConvertBack(value, null, null, null); + isPublicInterfaceChecked = value; + OnPropertyChanged(); } } - private void ToggleSelection(bool value) { foreach (var item in Members) diff --git a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceModel.cs b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceModel.cs index d7bed42a7d..a40272af48 100644 --- a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceModel.cs +++ b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceModel.cs @@ -20,7 +20,7 @@ public class ExtractInterfaceModel : IRefactoringModel public string InterfaceName { get; set; } public ObservableCollection Members { get; set; } = new ObservableCollection(); public IEnumerable SelectedMembers => Members.Where(m => m.IsSelected); - public ClassInstancing ClassInstancing { get; set; } + public ClassInstancing ImplementingClassInstancing { get; set; } public static readonly DeclarationType[] MemberTypes = { @@ -35,6 +35,9 @@ public ExtractInterfaceModel(IDeclarationFinderProvider declarationFinderProvide { TargetDeclaration = target; DeclarationFinderProvider = declarationFinderProvider; + ImplementingClassInstancing = System.Convert.ToBoolean(target.Attributes.ExposedAttribute.Values.First()) + ? ClassInstancing.PublicNotCreatable + : ClassInstancing.Private; if (TargetDeclaration == null) { diff --git a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs index 0cf1715e74..f723fdbb4d 100644 --- a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs +++ b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs @@ -98,7 +98,7 @@ private void AddInterface(ExtractInterfaceModel model) return; //The target project is not available. } - AddInterfaceClass(model.TargetDeclaration, model.InterfaceName, GetInterfaceModuleBody(model)); + AddInterfaceClass(model.TargetDeclaration, model.InterfaceName, GetInterfaceModuleBody(model), model.ImplementingClassInstancing); var rewriteSession = RewritingManager.CheckOutCodePaneSession(); var rewriter = rewriteSession.CheckOutModuleRewriter(model.TargetDeclaration.QualifiedModuleName); @@ -116,7 +116,7 @@ private void AddInterface(ExtractInterfaceModel model) } } - private void AddInterfaceClass(Declaration implementingClass, string interfaceName, string interfaceBody) + private void AddInterfaceClass(Declaration implementingClass, string interfaceName, string interfaceBody, ClassInstancing interfaceInstancing) { var targetProject = implementingClass.Project; using (var components = targetProject.VBComponents) @@ -128,16 +128,15 @@ private void AddInterfaceClass(Declaration implementingClass, string interfaceNa interfaceComponent.Name = interfaceName; var optionPresent = interfaceModule.CountOfLines > 1; - var optionExplicit = $"{Tokens.Option} {Tokens.Explicit}{Environment.NewLine}"; if (!optionPresent) { - interfaceModule.InsertLines(1, optionExplicit); + interfaceModule.InsertLines(1, "Option Explicit" + Environment.NewLine); } - interfaceModule.InsertLines(3, interfaceBody); + interfaceModule.InsertLines(1, "'@Interface"); + interfaceModule.InsertLines(4, interfaceBody); - var classIsExposed = Convert.ToBoolean(implementingClass.Attributes.ExposedAttribute.Values.First()); - if (classIsExposed) + if (interfaceInstancing == ClassInstancing.PublicNotCreatable) { AddExposedAttribute(components, interfaceComponent); } @@ -155,6 +154,7 @@ private void AddExposedAttribute(IVBComponents components, IVBComponent interfac var text = System.IO.File.ReadAllText(tempFile); var sb = new System.Text.StringBuilder(text); + sb.Insert(text.IndexOf("Option Explicit"), "'@Exposed" + Environment.NewLine); sb.Replace("Attribute VB_Exposed = False", "Attribute VB_Exposed = True"); System.IO.File.WriteAllText(tempFile, sb.ToString()); diff --git a/Rubberduck.Resources/RubberduckUI.Designer.cs b/Rubberduck.Resources/RubberduckUI.Designer.cs index 735c1b7314..c6bf02ae9b 100644 --- a/Rubberduck.Resources/RubberduckUI.Designer.cs +++ b/Rubberduck.Resources/RubberduckUI.Designer.cs @@ -1385,7 +1385,7 @@ public static string ExtractInterface_PrivateRadioButton { } /// - /// Looks up a localized string similar to Public Not Creatable. + /// Looks up a localized string similar to Public (Not Creatable). /// public static string ExtractInterface_PublicNotCreatableRadioButton { get { diff --git a/Rubberduck.Resources/RubberduckUI.resx b/Rubberduck.Resources/RubberduckUI.resx index f5b2c96354..54aa6cedd7 100644 --- a/Rubberduck.Resources/RubberduckUI.resx +++ b/Rubberduck.Resources/RubberduckUI.resx @@ -1761,6 +1761,6 @@ Import aborted. Private - Public Not Creatable + Public (Not Creatable) \ No newline at end of file From e8fd5737feb1b146a0d2d4267ed20f7976c60611 Mon Sep 17 00:00:00 2001 From: IvenBach Date: Fri, 17 Jan 2020 13:57:12 -0800 Subject: [PATCH 162/461] Opportunistic updates Use pattern matching Simplify default expression Use auto property Use IEnumerable. ToList() removed as ubsequent calls use IEnumerable. --- .../UI/Command/MenuItems/CommandMenuItemBase.cs | 2 +- .../MenuItems/ParentMenus/ParentMenuItemBase.cs | 3 +-- Rubberduck.Parsing/VBA/RubberduckParserState.cs | 15 +++++++-------- .../ExtractInterfaceRefactoring.cs | 2 +- .../ImplementInterfaceRefactoring.cs | 2 +- 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/Rubberduck.Core/UI/Command/MenuItems/CommandMenuItemBase.cs b/Rubberduck.Core/UI/Command/MenuItems/CommandMenuItemBase.cs index 6271d4ae8a..d2acfb9fb7 100644 --- a/Rubberduck.Core/UI/Command/MenuItems/CommandMenuItemBase.cs +++ b/Rubberduck.Core/UI/Command/MenuItems/CommandMenuItemBase.cs @@ -54,7 +54,7 @@ public virtual bool EvaluateCanExecute(RubberduckParserState state) public virtual bool HiddenWhenDisabled => false; public virtual bool IsVisible => true; public virtual bool BeginGroup => false; - public virtual int DisplayOrder => default(int); + public virtual int DisplayOrder => default; public virtual Image Image => null; public virtual Image Mask => null; } diff --git a/Rubberduck.Core/UI/Command/MenuItems/ParentMenus/ParentMenuItemBase.cs b/Rubberduck.Core/UI/Command/MenuItems/ParentMenus/ParentMenuItemBase.cs index 5047c33265..9e231ebb4e 100644 --- a/Rubberduck.Core/UI/Command/MenuItems/ParentMenus/ParentMenuItemBase.cs +++ b/Rubberduck.Core/UI/Command/MenuItems/ParentMenus/ParentMenuItemBase.cs @@ -201,8 +201,7 @@ private ICommandBarControl InitializeChildControl(ICommandMenuItem item) private void child_Click(object sender, CommandBarButtonClickEventArgs e) { - var item = _items.Select(kvp => kvp.Key).SingleOrDefault(menu => e.Tag.EndsWith(menu.GetType().Name)) as ICommandMenuItem; - if (item == null) + if (!(_items.Select(kvp => kvp.Key).SingleOrDefault(menu => e.Tag.EndsWith(menu.GetType().Name)) is ICommandMenuItem item)) { return; } diff --git a/Rubberduck.Parsing/VBA/RubberduckParserState.cs b/Rubberduck.Parsing/VBA/RubberduckParserState.cs index fcb54a2871..d80d4de17a 100644 --- a/Rubberduck.Parsing/VBA/RubberduckParserState.cs +++ b/Rubberduck.Parsing/VBA/RubberduckParserState.cs @@ -581,17 +581,16 @@ public ParserState GetModuleState(QualifiedModuleName module) return _moduleStates.GetOrAdd(module, new ModuleState(ParserState.Pending)).State; } - private readonly object _statusLockObject = new object(); - private ParserState _status; - public ParserState Status => _status; + private readonly object _statusLockObject = new object(); + public ParserState Status { get; private set; } private void SetStatusWithCancellation(ParserState value, CancellationToken token) { - if (_status != value) + if (Status != value) { - var oldStatus = _status; - _status = value; - OnStateChanged(this, token, _status, oldStatus); + var oldStatus = Status; + Status = value; + OnStateChanged(this, token, Status, oldStatus); } } @@ -599,7 +598,7 @@ public void SetStatusAndFireStateChanged(object requestor, ParserState status, C { if (Status == status) { - OnStateChanged(requestor, token, status, _status); + OnStateChanged(requestor, token, status, Status); } else { diff --git a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs index f723fdbb4d..0d00e4b03b 100644 --- a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs +++ b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs @@ -171,7 +171,7 @@ private void AddExposedAttribute(IVBComponents components, IVBComponent interfac private void AddInterfaceMembersToClass(ExtractInterfaceModel model, IModuleRewriter rewriter) { - _implementInterfaceRefactoring.Refactor(model.SelectedMembers.Select(m => m.Member).ToList(), rewriter, model.InterfaceName); + _implementInterfaceRefactoring.Refactor(model.SelectedMembers.Select(m => m.Member), rewriter, model.InterfaceName); } private string GetInterfaceModuleBody(ExtractInterfaceModel model) diff --git a/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceRefactoring.cs b/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceRefactoring.cs index 0a80552b8b..a24a003d38 100644 --- a/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceRefactoring.cs +++ b/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceRefactoring.cs @@ -79,7 +79,7 @@ public override void Refactor(Declaration target) throw new NotSupportedException(); } - internal void Refactor(List members, IModuleRewriter rewriter, string interfaceName) + internal void Refactor(IEnumerable members, IModuleRewriter rewriter, string interfaceName) { AddItems(members, rewriter, interfaceName); } From 664c7d995e1c4de12e07e4a30696bc6f50eed19c Mon Sep 17 00:00:00 2001 From: IvenBach Date: Fri, 17 Jan 2020 14:47:05 -0800 Subject: [PATCH 163/461] Correct default public interface extraction --- .../ExtractInterface/ExtractInterfaceViewModel.cs | 7 +++---- .../ExtractInterface/ExtractInterfaceModel.cs | 8 ++++---- .../ExtractInterface/ExtractInterfaceRefactoring.cs | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceViewModel.cs b/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceViewModel.cs index 2ff79ac9d6..599ffbb8a9 100644 --- a/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceViewModel.cs +++ b/Rubberduck.Core/UI/Refactorings/ExtractInterface/ExtractInterfaceViewModel.cs @@ -7,7 +7,6 @@ using Rubberduck.Parsing.Symbols; using Rubberduck.Refactorings.ExtractInterface; using Rubberduck.UI.Command; -using System.Windows.Data; namespace Rubberduck.UI.Refactorings { @@ -70,8 +69,6 @@ public bool IsPrivateInterfaceEnabled } } - private readonly IValueConverter classInstancingConverter = new Converters.ClassInstancingToBooleanConverter(); - private bool isPublicInterfaceChecked = true; public bool IsPublicInterfaceChecked { @@ -83,7 +80,9 @@ public bool IsPublicInterfaceChecked return; } - Model.ImplementingClassInstancing = (ClassInstancing)classInstancingConverter.ConvertBack(value, null, null, null); + Model.InterfaceInstancing = value + ? ClassInstancing.PublicNotCreatable + : ClassInstancing.Private; isPublicInterfaceChecked = value; OnPropertyChanged(); } diff --git a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceModel.cs b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceModel.cs index a40272af48..32da869aeb 100644 --- a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceModel.cs +++ b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceModel.cs @@ -20,7 +20,10 @@ public class ExtractInterfaceModel : IRefactoringModel public string InterfaceName { get; set; } public ObservableCollection Members { get; set; } = new ObservableCollection(); public IEnumerable SelectedMembers => Members.Where(m => m.IsSelected); - public ClassInstancing ImplementingClassInstancing { get; set; } + public ClassInstancing ImplementingClassInstancing => System.Convert.ToBoolean(TargetDeclaration.Attributes.ExposedAttribute.Values.First()) + ? ClassInstancing.PublicNotCreatable + : ClassInstancing.Private; + public ClassInstancing InterfaceInstancing { get; set; } = ClassInstancing.PublicNotCreatable; public static readonly DeclarationType[] MemberTypes = { @@ -35,9 +38,6 @@ public ExtractInterfaceModel(IDeclarationFinderProvider declarationFinderProvide { TargetDeclaration = target; DeclarationFinderProvider = declarationFinderProvider; - ImplementingClassInstancing = System.Convert.ToBoolean(target.Attributes.ExposedAttribute.Values.First()) - ? ClassInstancing.PublicNotCreatable - : ClassInstancing.Private; if (TargetDeclaration == null) { diff --git a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs index 0d00e4b03b..4e0f95e0b0 100644 --- a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs +++ b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs @@ -98,7 +98,7 @@ private void AddInterface(ExtractInterfaceModel model) return; //The target project is not available. } - AddInterfaceClass(model.TargetDeclaration, model.InterfaceName, GetInterfaceModuleBody(model), model.ImplementingClassInstancing); + AddInterfaceClass(model.TargetDeclaration, model.InterfaceName, GetInterfaceModuleBody(model), model.InterfaceInstancing); var rewriteSession = RewritingManager.CheckOutCodePaneSession(); var rewriter = rewriteSession.CheckOutModuleRewriter(model.TargetDeclaration.QualifiedModuleName); From f012d164c47e6759ee306c531640b067d73be12f Mon Sep 17 00:00:00 2001 From: bclothier Date: Fri, 17 Jan 2020 20:28:39 -0600 Subject: [PATCH 164/461] Consolidate all hard-coded hexcodes into references to the style XAML --- Rubberduck.Core/UI/About/AboutControl.xaml | 105 ++++++------ .../AddRemoveReferencesWindow.xaml | 150 +++++++++--------- .../UI/CodeExplorer/CodeExplorerControl.xaml | 2 +- Rubberduck.Core/UI/Controls/ToolBar.xaml | 48 +++--- .../Inspections/InspectionResultsControl.xaml | 2 +- .../EncapsulateFieldView.xaml | 14 +- .../ExtractInterfaceView.xaml | 83 +++++----- .../RemoveParametersView.xaml | 4 +- .../ReorderParametersView.xaml | 4 +- .../UI/Settings/IndenterSettings.xaml | 72 +++++---- .../UI/Settings/InspectionSettings.xaml | 2 +- Rubberduck.Core/UI/Settings/TodoSettings.xaml | 8 +- Rubberduck.Core/UI/Styles/DefaultStyle.xaml | 46 +++++- .../UI/ToDoItems/ToDoExplorerControl.xaml | 2 +- .../UI/UnitTesting/TestExplorerControl.xaml | 2 +- 15 files changed, 297 insertions(+), 247 deletions(-) diff --git a/Rubberduck.Core/UI/About/AboutControl.xaml b/Rubberduck.Core/UI/About/AboutControl.xaml index 3ecb097acf..aa5f47ad22 100644 --- a/Rubberduck.Core/UI/About/AboutControl.xaml +++ b/Rubberduck.Core/UI/About/AboutControl.xaml @@ -8,56 +8,61 @@ d:DataContext="{d:DesignInstance {x:Type about:AboutControlViewModel}, IsDesignTimeCreatable=False}" KeyDown="OnKeyDownHandler"> - - - - - - - + + + + + + + + + + + + diff --git a/Rubberduck.Core/UI/AddRemoveReferences/AddRemoveReferencesWindow.xaml b/Rubberduck.Core/UI/AddRemoveReferences/AddRemoveReferencesWindow.xaml index 6a3212cc32..c82c18f3f8 100644 --- a/Rubberduck.Core/UI/AddRemoveReferences/AddRemoveReferencesWindow.xaml +++ b/Rubberduck.Core/UI/AddRemoveReferences/AddRemoveReferencesWindow.xaml @@ -13,56 +13,61 @@ d:DesignHeight="380" d:DesignWidth="600" d:DataContext="{d:DesignInstance local:AddRemoveReferencesViewModel}"> - 2000 + + + + - - - - - - - + 2000 - - - - - + + + + + + + - - - + + - - + + + + + + + + + + + @@ -257,7 +263,7 @@ - - + /// The reference library's enum. + /// Returns the instance. + public MockProjectBuilder AddReference(ReferenceLibrary referenceLibrary) + { + var (name, path, versionMajor, versionMinor, isBuiltIn) = MockVbeBuilder.ReferenceLibraries[referenceLibrary]; + return AddReference(name, path, versionMajor, versionMinor, isBuiltIn); + } + /// /// Adds a mock reference to the project. /// diff --git a/RubberduckTests/Mocks/MockVbeBuilder.cs b/RubberduckTests/Mocks/MockVbeBuilder.cs index acad78aa93..65c0d63c89 100644 --- a/RubberduckTests/Mocks/MockVbeBuilder.cs +++ b/RubberduckTests/Mocks/MockVbeBuilder.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Linq; using Moq; @@ -11,6 +12,28 @@ namespace RubberduckTests.Mocks { + public enum ReferenceLibrary + { + VBA, + Excel, + MsOffice, + StdOle, + MsForms, + VBIDE, + Scripting, + Regex, + MsXml, + ShDoc, + AdoDb, + AdoRecordset, + } + + public static class ReferenceLibraryExtensions + { + public static string Name(this ReferenceLibrary val) => MockVbeBuilder.ReferenceLibraryIdentifiers[val].Name; + public static string Path(this ReferenceLibrary val) => MockVbeBuilder.ReferenceLibraryIdentifiers[val].Path; + } + /// /// Builds a mock . /// @@ -22,45 +45,31 @@ public class MockVbeBuilder private readonly Mock _vbe; private readonly Mock _vbeEvents; - #region standard library paths (referenced in all VBA projects hosted in Microsoft Excel) - public static readonly string LibraryPathVBA = @"C:\PROGRA~1\COMMON~1\MICROS~1\VBA\VBA7.1\VBE7.DLL"; // standard library, priority locked - public static readonly string LibraryPathMsExcel = @"C:\Program Files\Microsoft Office\Office15\EXCEL.EXE"; // mock host application, priority locked - public static readonly string LibraryPathMsOffice = @"C:\Program Files\Common Files\Microsoft Shared\OFFICE15\MSO.DLL"; - public static readonly string LibraryPathStdOle = @"C:\Windows\System32\stdole2.tlb"; - public static readonly string LibraryPathMsForms = @"C:\Windows\system32\FM20.DLL"; // standard in projects with a UserForm module - #endregion - - public static readonly string LibraryPathVBIDE = @"C:\Program Files (x86)\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.OLB"; - public static readonly string LibraryPathScripting = @"C:\Windows\System32\scrrun.dll"; - public static readonly string LibraryPathRegex = @"C:\Windows\System32\vbscript.dll\3"; - public static readonly string LibraryPathMsXml = @"C:\Windows\System32\msxml6.dll"; - public static readonly string LibraryPathShDoc = @"C:\Windows\System32\ieframe.dll"; - public static readonly string LibraryPathAdoDb = @"C:\Program Files\Common Files\System\ado\msado15.dll"; - public static readonly string LibraryPathAdoRecordset = @"C:\Program Files\Common Files\System\ado\msador15.dll"; - - public static readonly Dictionary LibraryPaths = new Dictionary + public static Dictionary ReferenceLibraryIdentifiers = new Dictionary() { - ["VBA"] = LibraryPathVBA, - ["Excel"] = LibraryPathMsExcel, - ["Office"] = LibraryPathMsOffice, - ["stdole"] = LibraryPathStdOle, - ["MSForms"] = LibraryPathMsForms, - ["VBIDE"] = LibraryPathVBIDE, - ["Scripting"] = LibraryPathScripting, - ["VBScript_RegExp_55"] = LibraryPathRegex, - ["MSXML2"] = LibraryPathMsXml, - ["SHDocVw"] = LibraryPathShDoc, - ["ADODB"] = LibraryPathAdoDb, - ["ADOR"] = LibraryPathAdoRecordset + //standard library paths (referenced in all VBA projects hosted in Microsoft Excel) + [ReferenceLibrary.VBA] = ("VBA", @"C:\PROGRA~1\COMMON~1\MICROS~1\VBA\VBA7.1\VBE7.DLL"), //standard library, priority locked" + [ReferenceLibrary.Excel] = ("Excel", @"C:\Program Files\Microsoft Office\Office15\EXCEL.EXE"), // mock host application, priority locked + [ReferenceLibrary.MsOffice] = ("Office", @"C:\Program Files\Common Files\Microsoft Shared\OFFICE15\MSO.DLL"), + [ReferenceLibrary.StdOle] = ("stdole", @"C:\Windows\System32\stdole2.tlb"), + [ReferenceLibrary.MsForms] = ("MSForms", @"C:\Windows\system32\FM20.DLL"), // standard in projects with a UserForm module + //end standard library paths + [ReferenceLibrary.VBIDE] = ("VBIDE", @"C:\Program Files (x86)\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.OLB"), + [ReferenceLibrary.Scripting] = ("Scripting", @"C:\Windows\System32\scrrun.dll"), + [ReferenceLibrary.Regex] = ("VBScript_RegExp_55", @"C:\Windows\System32\vbscript.dll\3"), + [ReferenceLibrary.MsXml] = ("MSXML2", @"C:\Windows\System32\msxml6.dll"), + [ReferenceLibrary.ShDoc] = ("SHDocVw", @"C:\Windows\System32\ieframe.dll"), + [ReferenceLibrary.AdoDb] = ("ADODB", @"C:\Program Files\Common Files\System\ado\msado15.dll"), + [ReferenceLibrary.AdoRecordset] = ("ADOR", @"C:\Program Files\Common Files\System\ado\msador15.dll"), }; - private static readonly Dictionary> AddReference = new Dictionary> + internal static readonly Dictionary ReferenceLibraries = new Dictionary { - ["Excel"] = (MockProjectBuilder builder) => builder.AddReference("Excel", LibraryPathMsExcel, 1, 8, true), - ["VBA"] = (MockProjectBuilder builder) => builder.AddReference("VBA", LibraryPathVBA, 4, 2, true), - ["Scripting"] = (MockProjectBuilder builder) => builder.AddReference("Scripting", LibraryPathScripting, 1, 0, true), - ["ADODB"] = (MockProjectBuilder builder) => builder.AddReference("ADODB", LibraryPathAdoDb, 6, 1, false), - ["MSForms"] = (MockProjectBuilder builder) => builder.AddReference("MSForms", LibraryPathMsForms, 2, 0, true), + [ReferenceLibrary.VBA] = (ReferenceLibrary.VBA.Name(), ReferenceLibrary.VBA.Path(), 4, 2, true), + [ReferenceLibrary.Excel] = (ReferenceLibrary.Excel.Name(), ReferenceLibrary.Excel.Path(), 1, 8, true), + [ReferenceLibrary.Scripting] = (ReferenceLibrary.Scripting.Name(), ReferenceLibrary.Scripting.Path(), 1, 0, true), + [ReferenceLibrary.AdoDb] = (ReferenceLibrary.AdoDb.Name(), ReferenceLibrary.AdoDb.Path(), 6, 1, false), + [ReferenceLibrary.MsForms] = (ReferenceLibrary.MsForms.Name(), ReferenceLibrary.MsForms.Path(), 2, 0, true), }; //private Mock _vbWindows; @@ -160,7 +169,7 @@ public static Mock BuildFromSingleModule(string content, string name, Comp if (referenceStdLibs) { - builder.AddReference("VBA", LibraryPathVBA, 4, 2, true); + builder.AddReference(ReferenceLibrary.VBA); } var project = builder.Build(); @@ -194,24 +203,24 @@ public static Mock BuildFromModules(params (string name, string content, C /// Builds a mock VBE containing a single "TestProject1" with multiple modules. /// public static Mock BuildFromModules(IEnumerable<(string name, string content, ComponentType componentType)> modules) - => BuildFromModules(modules, Enumerable.Empty()); + => BuildFromModules(modules, Enumerable.Empty()); /// /// Builds a mock VBE containing a single "TestProject1" with one module and one or more libraries. /// - public static Mock BuildFromModules((string name, string content, ComponentType componentType) module, params string[] libraries) - => BuildFromModules(new (string, string, ComponentType)[] { module }, libraries); + public static Mock BuildFromModules((string name, string content, ComponentType componentType) module, params ReferenceLibrary[] libraries) + => BuildFromModules(new(string, string, ComponentType)[] { module }, libraries); /// /// Builds a mock VBE containing a single "TestProject1" with multiple modules and libraries. /// - public static Mock BuildFromModules(IEnumerable<(string name, string content, ComponentType componentType)> modules, IEnumerable libraryNames) - => BuildFromModules(TestProjectName, modules, libraryNames); + public static Mock BuildFromModules(IEnumerable<(string name, string content, ComponentType componentType)> modules, IEnumerable libraries) + => BuildFromModules(TestProjectName, modules, libraries); /// /// Builds a mock VBE containing one project with multiple modules and libraries. /// - public static Mock BuildFromModules(string projectName, IEnumerable<(string name, string content, ComponentType componentType)> modules, IEnumerable libraryNames) + public static Mock BuildFromModules(string projectName, IEnumerable<(string name, string content, ComponentType componentType)> modules, IEnumerable referenceLibraries) { var vbeBuilder = new MockVbeBuilder(); @@ -221,9 +230,10 @@ public static Mock BuildFromModules(string projectName, IEnumerable<(strin builder.AddComponent(name, componentType, content); } - foreach (var name in libraryNames) + foreach (var refLibrary in referenceLibraries) { - AddReference[name](builder); + var (name, path, versionMajor, versionMinor, isBuiltIn) = ReferenceLibraries[refLibrary]; + builder.AddReference(name, path, versionMajor, versionMinor, isBuiltIn); } var project = builder.Build(); diff --git a/RubberduckTests/QuickFixes/AccessSheetUsingCodeNameQuickFixTests.cs b/RubberduckTests/QuickFixes/AccessSheetUsingCodeNameQuickFixTests.cs index 2168bee3cf..5a115bdce8 100644 --- a/RubberduckTests/QuickFixes/AccessSheetUsingCodeNameQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/AccessSheetUsingCodeNameQuickFixTests.cs @@ -307,7 +307,7 @@ protected override IVBE TestVbe(string code, out IVBComponent component) CreateVBComponentPropertyMock("Name", "Name").Object, CreateVBComponentPropertyMock("CodeName", "CodeName").Object }) - .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) + .AddReference(ReferenceLibrary.Excel) .Build(); component = project.Object.VBComponents[0]; diff --git a/RubberduckTests/QuickFixes/ApplicationWorksheetFunctionQuickFixTests.cs b/RubberduckTests/QuickFixes/ApplicationWorksheetFunctionQuickFixTests.cs index d005c6a09c..f7ff8c175d 100644 --- a/RubberduckTests/QuickFixes/ApplicationWorksheetFunctionQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ApplicationWorksheetFunctionQuickFixTests.cs @@ -93,7 +93,7 @@ protected override IVBE TestVbe(string code, out IVBComponent component) var builder = new MockVbeBuilder(); var project = builder.ProjectBuilder("VBAProject", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, code) - .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) + .AddReference(ReferenceLibrary.Excel) .Build(); var vbe = builder.AddProject(project).Build().Object; diff --git a/RubberduckTests/QuickFixes/ExpandBangNotationQuickFixTests.cs b/RubberduckTests/QuickFixes/ExpandBangNotationQuickFixTests.cs index f94feb9399..25103f5f24 100644 --- a/RubberduckTests/QuickFixes/ExpandBangNotationQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ExpandBangNotationQuickFixTests.cs @@ -193,7 +193,7 @@ End Sub var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) + .AddReference(ReferenceLibrary.Excel) .AddProjectToVbeBuilder() .Build(); @@ -224,7 +224,7 @@ End Sub var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) + .AddReference(ReferenceLibrary.Excel) .AddProjectToVbeBuilder() .Build(); diff --git a/RubberduckTests/QuickFixes/ExpandDefaultMemberQuickFixTests.cs b/RubberduckTests/QuickFixes/ExpandDefaultMemberQuickFixTests.cs index 309a9ca5d6..4668bebe40 100644 --- a/RubberduckTests/QuickFixes/ExpandDefaultMemberQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ExpandDefaultMemberQuickFixTests.cs @@ -667,7 +667,7 @@ End Sub var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) + .AddReference(ReferenceLibrary.Excel) .AddProjectToVbeBuilder() .Build(); @@ -700,7 +700,7 @@ End Sub var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) + .AddReference(ReferenceLibrary.Excel) .AddProjectToVbeBuilder() .Build(); @@ -731,7 +731,7 @@ End Sub var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) + .AddReference(ReferenceLibrary.Excel) .AddProjectToVbeBuilder() .Build(); diff --git a/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs b/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs index 01771d522e..13a1fdf2b3 100644 --- a/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs @@ -738,7 +738,7 @@ Dim str As String var builder = new MockVbeBuilder(); var project = builder.ProjectBuilder("VBAProject", ProjectProtection.Unprotected) .AddComponent("MyClass", ComponentType.ClassModule, inputCode) - .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) + .AddReference(ReferenceLibrary.VBA) .Build(); var vbe = builder.AddProject(project).Build(); @@ -1152,7 +1152,7 @@ private IEnumerable InspectionResults(IInspection inspection, var builder = new MockVbeBuilder(); var project = builder.ProjectBuilder("TestProject1", "TestProject1", ProjectProtection.Unprotected) .AddComponent("Class1", ComponentType.ClassModule, inputCode) - .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) + .AddReference(ReferenceLibrary.Excel) .Build(); var component = project.Object.VBComponents[0]; var vbe = builder.AddProject(project).Build(); @@ -1165,7 +1165,7 @@ private IEnumerable InspectionResults(IInspection inspection, var builder = new MockVbeBuilder(); var project = builder.ProjectBuilder("VBAProject", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, inputCode) - .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) + .AddReference(ReferenceLibrary.Excel) .Build(); var vbe = builder.AddProject(project).Build(); diff --git a/RubberduckTests/QuickFixes/IsMissingOnInappropriateArgumentQuickFixTests.cs b/RubberduckTests/QuickFixes/IsMissingOnInappropriateArgumentQuickFixTests.cs index d65dfb22ef..c0fd3ad76d 100644 --- a/RubberduckTests/QuickFixes/IsMissingOnInappropriateArgumentQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/IsMissingOnInappropriateArgumentQuickFixTests.cs @@ -448,7 +448,7 @@ protected override IVBE TestVbe(string code, out IVBComponent component) var builder = new MockVbeBuilder(); var project = builder.ProjectBuilder("TestProject1", "TestProject1", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, code) - .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) + .AddReference(ReferenceLibrary.VBA) .Build(); var vbe = builder.AddProject(project).Build(); component = project.Object.VBComponents.First(); diff --git a/RubberduckTests/QuickFixes/UntypedFunctionUsageQuickFixTests.cs b/RubberduckTests/QuickFixes/UntypedFunctionUsageQuickFixTests.cs index 6a73594103..f1cfe72333 100644 --- a/RubberduckTests/QuickFixes/UntypedFunctionUsageQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/UntypedFunctionUsageQuickFixTests.cs @@ -33,7 +33,7 @@ Dim str As String var builder = new MockVbeBuilder(); var project = builder.ProjectBuilder("VBAProject", ProjectProtection.Unprotected) .AddComponent("MyClass", ComponentType.ClassModule, inputCode) - .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) + .AddReference(ReferenceLibrary.VBA) .Build(); var vbe = builder.AddProject(project).Build(); diff --git a/RubberduckTests/QuickFixes/UseSetKeywordForObjectAssignmentQuickFixTests.cs b/RubberduckTests/QuickFixes/UseSetKeywordForObjectAssignmentQuickFixTests.cs index 8398e54891..82568fad75 100644 --- a/RubberduckTests/QuickFixes/UseSetKeywordForObjectAssignmentQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/UseSetKeywordForObjectAssignmentQuickFixTests.cs @@ -149,7 +149,7 @@ protected override IVBE TestVbe(string code, out IVBComponent component) var builder = new MockVbeBuilder(); var project = builder.ProjectBuilder("VBAProject", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, code) - .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) + .AddReference(ReferenceLibrary.Excel) .Build(); var vbe = builder.AddProject(project).Build().Object; diff --git a/RubberduckTests/Refactoring/MoveCloserToUsageTests.cs b/RubberduckTests/Refactoring/MoveCloserToUsageTests.cs index 53b09e1643..6de5d2ddb2 100644 --- a/RubberduckTests/Refactoring/MoveCloserToUsageTests.cs +++ b/RubberduckTests/Refactoring/MoveCloserToUsageTests.cs @@ -824,7 +824,7 @@ Dim baz As Excel.Range var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Module", ComponentType.StandardModule, inputCode) - .AddReference("EXCEL", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) + .AddReference(ReferenceLibrary.Excel) .AddProjectToVbeBuilder() .Build() .Object; diff --git a/RubberduckTests/Refactoring/Rename/RenameTests.cs b/RubberduckTests/Refactoring/Rename/RenameTests.cs index 2547b18287..02701260b9 100644 --- a/RubberduckTests/Refactoring/Rename/RenameTests.cs +++ b/RubberduckTests/Refactoring/Rename/RenameTests.cs @@ -3205,8 +3205,8 @@ private static IVBE BuildProject(string projectName, IEnumerable Date: Tue, 21 Jan 2020 18:16:37 -0800 Subject: [PATCH 196/461] Some clearnup unused elements --- RubberduckTests/Mocks/MockVbeBuilder.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/RubberduckTests/Mocks/MockVbeBuilder.cs b/RubberduckTests/Mocks/MockVbeBuilder.cs index 65c0d63c89..5bdeda3c78 100644 --- a/RubberduckTests/Mocks/MockVbeBuilder.cs +++ b/RubberduckTests/Mocks/MockVbeBuilder.cs @@ -1,7 +1,5 @@ -using System; using System.Collections; using System.Collections.Generic; -using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Linq; using Moq; @@ -43,7 +41,6 @@ public class MockVbeBuilder public const string TestProjectName = "TestProject1"; public const string TestModuleName = "TestModule1"; private readonly Mock _vbe; - private readonly Mock _vbeEvents; public static Dictionary ReferenceLibraryIdentifiers = new Dictionary() { @@ -72,7 +69,6 @@ public class MockVbeBuilder [ReferenceLibrary.MsForms] = (ReferenceLibrary.MsForms.Name(), ReferenceLibrary.MsForms.Path(), 2, 0, true), }; - //private Mock _vbWindows; private readonly Windows _windows = new Windows(); private readonly ICollection _projects = new List(); From c38ddae034f603f56e7ea16431873f8e810da359 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Wed, 22 Jan 2020 23:33:27 +0100 Subject: [PATCH 197/461] Minor refactoring to address review to PR #5347 --- .../Inspections/Concrete/ObsoleteTypeHintInspection.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs index 6b1100e654..d2c3526d7b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs @@ -48,7 +48,7 @@ protected override IEnumerable DoGetInspectionResults() var finder = _declarationFinderProvider.DeclarationFinder; var results = new List(); - foreach (var moduleDeclaration in State.DeclarationFinder.UserDeclarations(DeclarationType.Module)) + foreach (var moduleDeclaration in finder.UserDeclarations(DeclarationType.Module)) { if (moduleDeclaration == null) { @@ -91,7 +91,7 @@ private IInspectionResult InspectionResult(Declaration declaration) declaration); } - private string ResultDescription(Declaration declaration) + private static string ResultDescription(Declaration declaration) { var declarationTypeName = declaration.DeclarationType.ToString().ToLower(); var identifierName = declaration.IdentifierName; From bd58d297802b787bcc4e1fc27c3fdcf383226ca6 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Thu, 23 Jan 2020 20:16:58 +0100 Subject: [PATCH 198/461] Adjust codecov.yml to avoid bogus failed messages Previously, it reported failure no change was tracked. --- codecov.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/codecov.yml b/codecov.yml index da8dd5a659..6c9da3c662 100644 --- a/codecov.yml +++ b/codecov.yml @@ -16,17 +16,19 @@ coverage: precision: 2 range: 40..80 status: - # don't block mindlessly on coverage failures - informational: true # status information for PRs only only_pulls: true patch: default: + # don't block mindlessly on coverage failures + informational: true # strongly suggest more than 60% of changes be covered target: 60 threshold: 10 project: default: + # don't block mindlessly on coverage failures + informational: true target: 0 # don't force a minimum coverage # allow decrease by up to 5 % threshold: 5 From 286b55cbd0ad4becd3f9c00d2b7eb2a436c1ddbb Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sat, 25 Jan 2020 14:58:48 +0100 Subject: [PATCH 199/461] Add more high level exception handling The async void responsible for refreshing the inspection results now has a to level exception handler swallowing all exceptions. This is necessary since bubbling out of there will likely take down the host. Moreover, we now log and swallow COM exceptions coming from the process of changing the status label of the refresh button. This means that COM registration issues for the command bar controls will no abort the calling process. The only effect will be that the label does not change. --- .../CommandBars/RubberduckCommandBar.cs | 58 +++++++++++++------ .../Inspections/InspectionResultsViewModel.cs | 14 +++++ 2 files changed, 53 insertions(+), 19 deletions(-) diff --git a/Rubberduck.Core/UI/Command/MenuItems/CommandBars/RubberduckCommandBar.cs b/Rubberduck.Core/UI/Command/MenuItems/CommandBars/RubberduckCommandBar.cs index 8bdd6c9510..9f757f4773 100644 --- a/Rubberduck.Core/UI/Command/MenuItems/CommandBars/RubberduckCommandBar.cs +++ b/Rubberduck.Core/UI/Command/MenuItems/CommandBars/RubberduckCommandBar.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Runtime.InteropServices; using Rubberduck.Resources; using Rubberduck.Parsing; using Rubberduck.Parsing.Symbols; @@ -99,30 +100,49 @@ public void SetStatusLabelCaption(ParserState state, int? errorCount = null) private void SetStatusLabelCaption(string caption, int? errorCount = null) { - var reparseCommandButton = FindChildByTag(typeof(ReparseCommandMenuItem).FullName) as ReparseCommandMenuItem; - if (reparseCommandButton == null) { return; } - - var showErrorsCommandButton = FindChildByTag(typeof(ShowParserErrorsCommandMenuItem).FullName) as ShowParserErrorsCommandMenuItem; - if (showErrorsCommandButton == null) { return; } - - _uiDispatcher.Invoke(() => + //This try-catch block guarantees that problems with the COM registration of the command bar classes + //only affect the status label text instead of aborting the status change or even crashing the host. + //See issue #5349 at https://github.com/rubberduck-vba/Rubberduck/issues/5349 + try { - try + var reparseCommandButton = + FindChildByTag(typeof(ReparseCommandMenuItem).FullName) as ReparseCommandMenuItem; + if (reparseCommandButton == null) { - reparseCommandButton.SetCaption(caption); - reparseCommandButton.SetToolTip(string.Format(RubberduckUI.ReparseToolTipText, caption)); - if (errorCount.HasValue && errorCount.Value > 0) - { - showErrorsCommandButton.SetToolTip( - string.Format(RubberduckUI.ParserErrorToolTipText, errorCount.Value)); - } + return; } - catch (Exception exception) + + var showErrorsCommandButton = + FindChildByTag(typeof(ShowParserErrorsCommandMenuItem).FullName) as ShowParserErrorsCommandMenuItem; + if (showErrorsCommandButton == null) { - Logger.Error(exception, "Exception thrown trying to set the status label caption on the UI thread."); + return; } - }); - Localize(); + + _uiDispatcher.Invoke(() => + { + try + { + reparseCommandButton.SetCaption(caption); + reparseCommandButton.SetToolTip(string.Format(RubberduckUI.ReparseToolTipText, caption)); + if (errorCount.HasValue && errorCount.Value > 0) + { + showErrorsCommandButton.SetToolTip( + string.Format(RubberduckUI.ParserErrorToolTipText, errorCount.Value)); + } + } + catch (Exception exception) + { + Logger.Error(exception, + "Exception thrown trying to set the status label caption on the UI thread."); + } + }); + Localize(); + } + catch (COMException exception) + { + Logger.Error(exception, "COMException thrown trying to set the status label caption."); + } } private void SetContextSelectionCaption(string caption, int contextReferenceCount, string description) diff --git a/Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs b/Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs index 5012588c5a..7297f03439 100644 --- a/Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs +++ b/Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs @@ -428,6 +428,20 @@ private void HandleStateChanged(object sender, ParserStateEventArgs e) } private async void RefreshInspections(CancellationToken token) + { + //We have to catch all exceptions here since this method is a fire-and-forget async action. + //Accordingly, any exception bubbling out of this method will likely take down the runtime and, thus, crash the host. + try + { + await RefreshInspections_Internal(token); + } + catch (Exception ex) + { + Logger.Error(ex,"Unhandled exception when refreshing inspection results."); + } + } + + private async Task RefreshInspections_Internal(CancellationToken token) { var stopwatch = Stopwatch.StartNew(); IsBusy = true; From 94197a910d56e1f8bd498e79ecd7dd0d6bc4c79c Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sat, 25 Jan 2020 15:16:38 +0100 Subject: [PATCH 200/461] Introduce high priority state changed event The order in which event handlers are executed is not guaranteed. Because of this we had the problem that the status message change for the state change to Ready happened after the status message change in the inspections, which are executed async. As the result, the message 'Inspection' was immediately overwritten and did not last until the inspections had finished. --- .../CommandBars/RubberduckCommandBar.cs | 29 +++++++++---------- .../VBA/RubberduckParserState.cs | 22 ++++++++++++++ 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/Rubberduck.Core/UI/Command/MenuItems/CommandBars/RubberduckCommandBar.cs b/Rubberduck.Core/UI/Command/MenuItems/CommandBars/RubberduckCommandBar.cs index 9f757f4773..84dc1a5fc7 100644 --- a/Rubberduck.Core/UI/Command/MenuItems/CommandBars/RubberduckCommandBar.cs +++ b/Rubberduck.Core/UI/Command/MenuItems/CommandBars/RubberduckCommandBar.cs @@ -4,7 +4,6 @@ using System.Linq; using System.Runtime.InteropServices; using Rubberduck.Resources; -using Rubberduck.Parsing; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.UIContext; using Rubberduck.Parsing.VBA; @@ -15,18 +14,18 @@ namespace Rubberduck.UI.Command.MenuItems.CommandBars public class RubberduckCommandBar : AppCommandBarBase, IDisposable { private readonly IContextFormatter _formatter; - private readonly IParseCoordinator _parser; + private readonly RubberduckParserState _state; private readonly ISelectionChangeService _selectionService; - public RubberduckCommandBar(IParseCoordinator parser, IEnumerable items, IContextFormatter formatter, ISelectionChangeService selectionService, IUiDispatcher uiDispatcher) + public RubberduckCommandBar(RubberduckParserState state, IEnumerable items, IContextFormatter formatter, ISelectionChangeService selectionService, IUiDispatcher uiDispatcher) : base("Rubberduck", CommandBarPosition.Top, items, uiDispatcher) { - _parser = parser; + _state = state; _formatter = formatter; _selectionService = selectionService; - _parser.State.StateChanged += OnParserStateChanged; - _parser.State.StatusMessageUpdate += OnParserStatusMessageUpdate; + _state.StateChangedHighPriority += OnParserStateChanged; + _state.StatusMessageUpdate += OnParserStatusMessageUpdate; _selectionService.SelectionChanged += OnSelectionChange; } @@ -36,14 +35,14 @@ public override void Initialize() { base.Initialize(); SetStatusLabelCaption(ParserState.Pending); - EvaluateCanExecute(_parser.State); + EvaluateCanExecute(_state); } private Declaration _lastDeclaration; private ParserState _lastStatus = ParserState.None; private void EvaluateCanExecute(RubberduckParserState state, Declaration selected) { - var currentStatus = _parser.State.Status; + var currentStatus = _state.Status; if (_lastStatus == currentStatus && (selected == null || selected.Equals(_lastDeclaration)) && (selected != null || _lastDeclaration == null)) @@ -69,7 +68,7 @@ private void OnSelectionChange(object sender, DeclarationChangedEventArgs e) var description = e.Declaration?.DescriptionString ?? string.Empty; //& renders the next character as if it was an accelerator. SetContextSelectionCaption(caption?.Replace("&", "&&"), refCount, description); - EvaluateCanExecute(_parser.State, e.Declaration); + EvaluateCanExecute(_state, e.Declaration); } @@ -82,14 +81,14 @@ private void OnParserStatusMessageUpdate(object sender, RubberduckStatusMessageE message = RubberduckUI.ParserState_LoadingReference; } - SetStatusLabelCaption(message, _parser.State.ModuleExceptions.Count); + SetStatusLabelCaption(message, _state.ModuleExceptions.Count); } private void OnParserStateChanged(object sender, EventArgs e) { - _lastStatus = _parser.State.Status; - EvaluateCanExecute(_parser.State); - SetStatusLabelCaption(_parser.State.Status, _parser.State.ModuleExceptions.Count); + _lastStatus = _state.Status; + EvaluateCanExecute(_state); + SetStatusLabelCaption(_state.Status, _state.ModuleExceptions.Count); } public void SetStatusLabelCaption(ParserState state, int? errorCount = null) @@ -182,8 +181,8 @@ protected virtual void Dispose(bool disposing) } _selectionService.SelectionChanged -= OnSelectionChange; - _parser.State.StateChanged -= OnParserStateChanged; - _parser.State.StatusMessageUpdate -= OnParserStatusMessageUpdate; + _state.StateChanged -= OnParserStateChanged; + _state.StatusMessageUpdate -= OnParserStatusMessageUpdate; RemoveCommandBar(); diff --git a/Rubberduck.Parsing/VBA/RubberduckParserState.cs b/Rubberduck.Parsing/VBA/RubberduckParserState.cs index fcb54a2871..038b71c630 100644 --- a/Rubberduck.Parsing/VBA/RubberduckParserState.cs +++ b/Rubberduck.Parsing/VBA/RubberduckParserState.cs @@ -359,6 +359,7 @@ public IReadOnlyList> ModuleExc } } + public event EventHandler StateChangedHighPriority; public event EventHandler StateChanged; private int _stateChangedInvocations; @@ -367,6 +368,27 @@ private void OnStateChanged(object requestor, CancellationToken token, ParserSta Interlocked.Increment(ref _stateChangedInvocations); Logger.Info($"{nameof(RubberduckParserState)} ({_stateChangedInvocations}) is invoking {nameof(StateChanged)} ({Status})"); + + var highPriorityHandler = StateChangedHighPriority; + if (highPriorityHandler != null && !token.IsCancellationRequested) + { + try + { + var args = new ParserStateEventArgs(state, oldStatus, token); + highPriorityHandler.Invoke(requestor, args); + } + catch (OperationCanceledException cancellation) + { + throw; + } + catch (Exception e) + { + // Error state, because this implies consumers are not exception-safe! + // this behaviour could leave us in a state where some consumers have correctly updated and some have not + Logger.Error(e, "An exception occurred when notifying consumers of updated parser state."); + } + } + var handler = StateChanged; if (handler != null && !token.IsCancellationRequested) { From a51d3565c93ea3b09e9597581f8d78ce135862d0 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sat, 25 Jan 2020 23:37:49 +0100 Subject: [PATCH 201/461] Actually catch the right exception at the correct place COMExceptions were already handled in FindChildByTag in AppCommandBar. The problem is that the faulty registration causes an InvalidCastException. --- .../CommandBars/AppCommandBarBase.cs | 8 ++- .../CommandBars/RubberduckCommandBar.cs | 64 ++++++++----------- 2 files changed, 34 insertions(+), 38 deletions(-) diff --git a/Rubberduck.Core/UI/Command/MenuItems/CommandBars/AppCommandBarBase.cs b/Rubberduck.Core/UI/Command/MenuItems/CommandBars/AppCommandBarBase.cs index ff67c2ff84..94e99bbcc7 100644 --- a/Rubberduck.Core/UI/Command/MenuItems/CommandBars/AppCommandBarBase.cs +++ b/Rubberduck.Core/UI/Command/MenuItems/CommandBars/AppCommandBarBase.cs @@ -37,7 +37,13 @@ protected ICommandMenuItem FindChildByTag(string tag) } catch (COMException exception) { - Logger.Error(exception,$"COMException while finding child with tag '{tag}'."); + Logger.Error(exception, $"COMException while finding child with tag '{tag}' in the command bar."); + } + catch (InvalidCastException exception) + { + //This exception will be encountered whenever the registration of the command bar control not correct in the system. + //See issue #5349 at https://github.com/rubberduck-vba/Rubberduck/issues/5349 + Logger.Error(exception, $"Invalid cast exception while finding child with tag '{tag}' in the command bar."); } return null; } diff --git a/Rubberduck.Core/UI/Command/MenuItems/CommandBars/RubberduckCommandBar.cs b/Rubberduck.Core/UI/Command/MenuItems/CommandBars/RubberduckCommandBar.cs index 84dc1a5fc7..78e53cb6ba 100644 --- a/Rubberduck.Core/UI/Command/MenuItems/CommandBars/RubberduckCommandBar.cs +++ b/Rubberduck.Core/UI/Command/MenuItems/CommandBars/RubberduckCommandBar.cs @@ -99,49 +99,39 @@ public void SetStatusLabelCaption(ParserState state, int? errorCount = null) private void SetStatusLabelCaption(string caption, int? errorCount = null) { - //This try-catch block guarantees that problems with the COM registration of the command bar classes - //only affect the status label text instead of aborting the status change or even crashing the host. - //See issue #5349 at https://github.com/rubberduck-vba/Rubberduck/issues/5349 - try + var reparseCommandButton = + FindChildByTag(typeof(ReparseCommandMenuItem).FullName) as ReparseCommandMenuItem; + if (reparseCommandButton == null) { - var reparseCommandButton = - FindChildByTag(typeof(ReparseCommandMenuItem).FullName) as ReparseCommandMenuItem; - if (reparseCommandButton == null) - { - return; - } + return; + } - var showErrorsCommandButton = - FindChildByTag(typeof(ShowParserErrorsCommandMenuItem).FullName) as ShowParserErrorsCommandMenuItem; - if (showErrorsCommandButton == null) - { - return; - } + var showErrorsCommandButton = + FindChildByTag(typeof(ShowParserErrorsCommandMenuItem).FullName) as ShowParserErrorsCommandMenuItem; + if (showErrorsCommandButton == null) + { + return; + } - _uiDispatcher.Invoke(() => + _uiDispatcher.Invoke(() => + { + try { - try + reparseCommandButton.SetCaption(caption); + reparseCommandButton.SetToolTip(string.Format(RubberduckUI.ReparseToolTipText, caption)); + if (errorCount.HasValue && errorCount.Value > 0) { - reparseCommandButton.SetCaption(caption); - reparseCommandButton.SetToolTip(string.Format(RubberduckUI.ReparseToolTipText, caption)); - if (errorCount.HasValue && errorCount.Value > 0) - { - showErrorsCommandButton.SetToolTip( - string.Format(RubberduckUI.ParserErrorToolTipText, errorCount.Value)); - } + showErrorsCommandButton.SetToolTip( + string.Format(RubberduckUI.ParserErrorToolTipText, errorCount.Value)); } - catch (Exception exception) - { - Logger.Error(exception, - "Exception thrown trying to set the status label caption on the UI thread."); - } - }); - Localize(); - } - catch (COMException exception) - { - Logger.Error(exception, "COMException thrown trying to set the status label caption."); - } + } + catch (Exception exception) + { + Logger.Error(exception, + "Exception thrown trying to set the status label caption on the UI thread."); + } + }); + Localize(); } private void SetContextSelectionCaption(string caption, int contextReferenceCount, string description) From 8781f560a7375583839c4480f155208b0d99c8f1 Mon Sep 17 00:00:00 2001 From: jonathan-rizk Date: Tue, 28 Jan 2020 11:16:06 -0600 Subject: [PATCH 202/461] ProcedureNotUsedInspection ignores declarations that have ITestAnnotation annotations. --- .../Concrete/ProcedureNotUsedInspection.cs | 4 +++- .../Concrete/ModuleCleanupAnnotation.cs | 2 +- .../Concrete/ModuleInitializeAnnotation.cs | 2 +- .../Concrete/TestCleanupAnnotation.cs | 2 +- .../Concrete/TestInitializeAnnotation.cs | 2 +- .../Concrete/TestMethodAnnotation.cs | 2 +- .../Annotations/ITestAnnotation.cs | 12 ++++++++++++ .../ProcedureNotUsedInspectionTests.cs | 17 +++++++++++++++++ 8 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 Rubberduck.Parsing/Annotations/ITestAnnotation.cs diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs index 797586b4e0..3ccc3a7a68 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs @@ -6,6 +6,7 @@ using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; +using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; @@ -99,7 +100,8 @@ private bool IsIgnoredDeclaration(Declaration declaration, IEnumerable x.Annotation is ITestAnnotation); return result; } diff --git a/Rubberduck.Parsing/Annotations/Concrete/ModuleCleanupAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/ModuleCleanupAnnotation.cs index 4c04e6d314..b0b0253e04 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/ModuleCleanupAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/ModuleCleanupAnnotation.cs @@ -7,7 +7,7 @@ namespace Rubberduck.Parsing.Annotations /// /// Marks a method that the test engine will execute after all unit tests in a test module have executed. /// - public sealed class ModuleCleanupAnnotation : AnnotationBase + public sealed class ModuleCleanupAnnotation : AnnotationBase, ITestAnnotation { public ModuleCleanupAnnotation() : base("ModuleCleanup", AnnotationTarget.Member) diff --git a/Rubberduck.Parsing/Annotations/Concrete/ModuleInitializeAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/ModuleInitializeAnnotation.cs index a6254bff3b..6ed55372ce 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/ModuleInitializeAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/ModuleInitializeAnnotation.cs @@ -7,7 +7,7 @@ namespace Rubberduck.Parsing.Annotations /// /// Marks a method that the test engine will execute before executing the first unit test in a test module. /// - public sealed class ModuleInitializeAnnotation : AnnotationBase + public sealed class ModuleInitializeAnnotation : AnnotationBase, ITestAnnotation { public ModuleInitializeAnnotation() : base("ModuleInitialize", AnnotationTarget.Member) diff --git a/Rubberduck.Parsing/Annotations/Concrete/TestCleanupAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/TestCleanupAnnotation.cs index 069280d0b5..943f396564 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/TestCleanupAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/TestCleanupAnnotation.cs @@ -7,7 +7,7 @@ namespace Rubberduck.Parsing.Annotations /// /// Marks a method that the test engine will execute after executing each unit test in a test module. /// - public sealed class TestCleanupAnnotation : AnnotationBase + public sealed class TestCleanupAnnotation : AnnotationBase, ITestAnnotation { public TestCleanupAnnotation() : base("TestCleanup", AnnotationTarget.Member) diff --git a/Rubberduck.Parsing/Annotations/Concrete/TestInitializeAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/TestInitializeAnnotation.cs index ed273930e6..6c0124f747 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/TestInitializeAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/TestInitializeAnnotation.cs @@ -7,7 +7,7 @@ namespace Rubberduck.Parsing.Annotations /// /// Marks a method that the test engine will execute before executing each unit test in a test module. /// - public sealed class TestInitializeAnnotation : AnnotationBase + public sealed class TestInitializeAnnotation : AnnotationBase, ITestAnnotation { public TestInitializeAnnotation() : base("TestInitialize", AnnotationTarget.Member) diff --git a/Rubberduck.Parsing/Annotations/Concrete/TestMethodAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/TestMethodAnnotation.cs index 89f83dc328..55541052d0 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/TestMethodAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/TestMethodAnnotation.cs @@ -10,7 +10,7 @@ namespace Rubberduck.Parsing.Annotations /// /// Marks a method that the test engine will execute as a unit test. /// - public sealed class TestMethodAnnotation : AnnotationBase + public sealed class TestMethodAnnotation : AnnotationBase, ITestAnnotation { public TestMethodAnnotation() : base("TestMethod", AnnotationTarget.Member) diff --git a/Rubberduck.Parsing/Annotations/ITestAnnotation.cs b/Rubberduck.Parsing/Annotations/ITestAnnotation.cs new file mode 100644 index 0000000000..b862a17e45 --- /dev/null +++ b/Rubberduck.Parsing/Annotations/ITestAnnotation.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Parsing.Annotations +{ + public interface ITestAnnotation + { + } +} diff --git a/RubberduckTests/Inspections/ProcedureNotUsedInspectionTests.cs b/RubberduckTests/Inspections/ProcedureNotUsedInspectionTests.cs index 7f1b87076e..80e85ca6ee 100644 --- a/RubberduckTests/Inspections/ProcedureNotUsedInspectionTests.cs +++ b/RubberduckTests/Inspections/ProcedureNotUsedInspectionTests.cs @@ -111,6 +111,23 @@ Private Sub abc_Foo(ByVal arg1 As Integer, ByVal arg2 As String) Assert.AreEqual(0, InspectionResultsForModules(modules).Count(result => result.Target.DeclarationType == DeclarationType.Procedure)); } + [TestCase("@TestMethod(\"TestCategory\")")] + [TestCase("@ModuleInitialize")] + [TestCase("@ModuleCleanup")] + [TestCase("@TestInitialize")] + [TestCase("@TestCleanup")] + [Category("Inspections")] + public void ProcedureNotUsed_NoResultForTestRelatedMethods(string annotationText) + { + string inputCode = + $@" +'{annotationText} +Private Sub TestRelatedMethod() +End Sub"; + + Assert.AreEqual(0, InspectionResultsForModules(("TestClass", inputCode, ComponentType.StandardModule)).Count()); + } + [TestCase("Class_Initialize")] [TestCase("class_initialize")] [TestCase("Class_Terminate")] From a9cdee7d38c912e9a4c43ca0ebc19a4f10ffc8fd Mon Sep 17 00:00:00 2001 From: jonathan-rizk Date: Tue, 28 Jan 2020 11:51:06 -0600 Subject: [PATCH 203/461] declarations of ProcedureNotUsedInspection ignore ITestAnnotations --- .../Concrete/ProcedureNotUsedInspection.cs | 4 +++- .../Concrete/ModuleCleanupAnnotation.cs | 2 +- .../Concrete/ModuleInitializeAnnotation.cs | 2 +- .../Concrete/TestCleanupAnnotation.cs | 2 +- .../Concrete/TestInitializeAnnotation.cs | 2 +- .../Concrete/TestMethodAnnotation.cs | 2 +- .../Annotations/ITestAnnotation.cs | 12 ++++++++++++ .../ProcedureNotUsedInspectionTests.cs | 17 +++++++++++++++++ 8 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 Rubberduck.Parsing/Annotations/ITestAnnotation.cs diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs index 797586b4e0..3ccc3a7a68 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs @@ -6,6 +6,7 @@ using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; +using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; @@ -99,7 +100,8 @@ private bool IsIgnoredDeclaration(Declaration declaration, IEnumerable x.Annotation is ITestAnnotation); return result; } diff --git a/Rubberduck.Parsing/Annotations/Concrete/ModuleCleanupAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/ModuleCleanupAnnotation.cs index 4c04e6d314..b0b0253e04 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/ModuleCleanupAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/ModuleCleanupAnnotation.cs @@ -7,7 +7,7 @@ namespace Rubberduck.Parsing.Annotations /// /// Marks a method that the test engine will execute after all unit tests in a test module have executed. /// - public sealed class ModuleCleanupAnnotation : AnnotationBase + public sealed class ModuleCleanupAnnotation : AnnotationBase, ITestAnnotation { public ModuleCleanupAnnotation() : base("ModuleCleanup", AnnotationTarget.Member) diff --git a/Rubberduck.Parsing/Annotations/Concrete/ModuleInitializeAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/ModuleInitializeAnnotation.cs index a6254bff3b..6ed55372ce 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/ModuleInitializeAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/ModuleInitializeAnnotation.cs @@ -7,7 +7,7 @@ namespace Rubberduck.Parsing.Annotations /// /// Marks a method that the test engine will execute before executing the first unit test in a test module. /// - public sealed class ModuleInitializeAnnotation : AnnotationBase + public sealed class ModuleInitializeAnnotation : AnnotationBase, ITestAnnotation { public ModuleInitializeAnnotation() : base("ModuleInitialize", AnnotationTarget.Member) diff --git a/Rubberduck.Parsing/Annotations/Concrete/TestCleanupAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/TestCleanupAnnotation.cs index 069280d0b5..943f396564 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/TestCleanupAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/TestCleanupAnnotation.cs @@ -7,7 +7,7 @@ namespace Rubberduck.Parsing.Annotations /// /// Marks a method that the test engine will execute after executing each unit test in a test module. /// - public sealed class TestCleanupAnnotation : AnnotationBase + public sealed class TestCleanupAnnotation : AnnotationBase, ITestAnnotation { public TestCleanupAnnotation() : base("TestCleanup", AnnotationTarget.Member) diff --git a/Rubberduck.Parsing/Annotations/Concrete/TestInitializeAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/TestInitializeAnnotation.cs index ed273930e6..6c0124f747 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/TestInitializeAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/TestInitializeAnnotation.cs @@ -7,7 +7,7 @@ namespace Rubberduck.Parsing.Annotations /// /// Marks a method that the test engine will execute before executing each unit test in a test module. /// - public sealed class TestInitializeAnnotation : AnnotationBase + public sealed class TestInitializeAnnotation : AnnotationBase, ITestAnnotation { public TestInitializeAnnotation() : base("TestInitialize", AnnotationTarget.Member) diff --git a/Rubberduck.Parsing/Annotations/Concrete/TestMethodAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/TestMethodAnnotation.cs index 89f83dc328..55541052d0 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/TestMethodAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/TestMethodAnnotation.cs @@ -10,7 +10,7 @@ namespace Rubberduck.Parsing.Annotations /// /// Marks a method that the test engine will execute as a unit test. /// - public sealed class TestMethodAnnotation : AnnotationBase + public sealed class TestMethodAnnotation : AnnotationBase, ITestAnnotation { public TestMethodAnnotation() : base("TestMethod", AnnotationTarget.Member) diff --git a/Rubberduck.Parsing/Annotations/ITestAnnotation.cs b/Rubberduck.Parsing/Annotations/ITestAnnotation.cs new file mode 100644 index 0000000000..b862a17e45 --- /dev/null +++ b/Rubberduck.Parsing/Annotations/ITestAnnotation.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Rubberduck.Parsing.Annotations +{ + public interface ITestAnnotation + { + } +} diff --git a/RubberduckTests/Inspections/ProcedureNotUsedInspectionTests.cs b/RubberduckTests/Inspections/ProcedureNotUsedInspectionTests.cs index 7f1b87076e..80e85ca6ee 100644 --- a/RubberduckTests/Inspections/ProcedureNotUsedInspectionTests.cs +++ b/RubberduckTests/Inspections/ProcedureNotUsedInspectionTests.cs @@ -111,6 +111,23 @@ Private Sub abc_Foo(ByVal arg1 As Integer, ByVal arg2 As String) Assert.AreEqual(0, InspectionResultsForModules(modules).Count(result => result.Target.DeclarationType == DeclarationType.Procedure)); } + [TestCase("@TestMethod(\"TestCategory\")")] + [TestCase("@ModuleInitialize")] + [TestCase("@ModuleCleanup")] + [TestCase("@TestInitialize")] + [TestCase("@TestCleanup")] + [Category("Inspections")] + public void ProcedureNotUsed_NoResultForTestRelatedMethods(string annotationText) + { + string inputCode = + $@" +'{annotationText} +Private Sub TestRelatedMethod() +End Sub"; + + Assert.AreEqual(0, InspectionResultsForModules(("TestClass", inputCode, ComponentType.StandardModule)).Count()); + } + [TestCase("Class_Initialize")] [TestCase("class_initialize")] [TestCase("Class_Terminate")] From 57521e509755eb627e5a4f6a7feef2d11737ce16 Mon Sep 17 00:00:00 2001 From: jonathan-rizk Date: Tue, 28 Jan 2020 16:57:57 -0600 Subject: [PATCH 204/461] removed unnecessary namespaces --- Rubberduck.Parsing/Annotations/ITestAnnotation.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Rubberduck.Parsing/Annotations/ITestAnnotation.cs b/Rubberduck.Parsing/Annotations/ITestAnnotation.cs index b862a17e45..9ffd0bf9a6 100644 --- a/Rubberduck.Parsing/Annotations/ITestAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/ITestAnnotation.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Rubberduck.Parsing.Annotations +namespace Rubberduck.Parsing.Annotations { public interface ITestAnnotation { From 91218d055279ea09ee4081d90816459705b5ec38 Mon Sep 17 00:00:00 2001 From: jonathan-rizk Date: Wed, 29 Jan 2020 08:38:09 -0600 Subject: [PATCH 205/461] ITestAnnotation inherits IAnnotation --- Rubberduck.Parsing/Annotations/ITestAnnotation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rubberduck.Parsing/Annotations/ITestAnnotation.cs b/Rubberduck.Parsing/Annotations/ITestAnnotation.cs index 9ffd0bf9a6..d4c3bcb1e7 100644 --- a/Rubberduck.Parsing/Annotations/ITestAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/ITestAnnotation.cs @@ -1,6 +1,6 @@ namespace Rubberduck.Parsing.Annotations { - public interface ITestAnnotation + public interface ITestAnnotation : IAnnotation { } } From 8bcd3cf8a91fe8aca0be3d234b62ec0bb138329d Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Thu, 30 Jan 2020 12:28:53 -0500 Subject: [PATCH 206/461] Revert "Replace string ReferenceLibrary keys" --- RubberduckTests/Grammar/ResolverTests.cs | 10 +- ...icationWorksheetFunctionInspectionTests.cs | 3 +- ...elMemberMayReturnNothingInspectionTests.cs | 3 +- ...NameIsValidCellReferenceInspectionTests.cs | 3 +- .../HostSpecificExpressionInspectionTests.cs | 4 +- ...icitActiveSheetReferenceInspectionTests.cs | 5 +- ...tActiveWorkbookReferenceInspectionTests.cs | 3 +- .../Inspections/InspectionTestsBase.cs | 10 +- ...gOnInappropriateArgumentInspectionTests.cs | 3 +- ...WithNonArgumentParameterInspectionTests.cs | 3 +- .../MemberNotOnInterfaceInspectionTests.cs | 58 +++++----- .../ObjectVariableNotSetInspectionTests.cs | 29 +++-- .../ParameterNotUsedInspectionTests.cs | 3 +- .../ShadowedDeclarationInspectionTests.cs | 10 +- ...SheetAccessedUsingStringInspectionTests.cs | 2 +- .../UndeclaredVariableInspectionTests.cs | 9 +- .../UntypedFunctionUsageInspectionTests.cs | 7 +- .../UseMeaningfulNameInspectionTests.cs | 2 +- .../ValueRequiredInspectionTests.cs | 3 +- RubberduckTests/Mocks/MockProjectBuilder.cs | 11 -- RubberduckTests/Mocks/MockVbeBuilder.cs | 102 +++++++++--------- .../AccessSheetUsingCodeNameQuickFixTests.cs | 2 +- ...plicationWorksheetFunctionQuickFixTests.cs | 2 +- .../ExpandBangNotationQuickFixTests.cs | 4 +- .../ExpandDefaultMemberQuickFixTests.cs | 6 +- .../QuickFixes/IgnoreOnceQuickFixTests.cs | 6 +- ...ingOnInappropriateArgumentQuickFixTests.cs | 2 +- .../UntypedFunctionUsageQuickFixTests.cs | 2 +- ...KeywordForObjectAssignmentQuickFixTests.cs | 2 +- .../Refactoring/MoveCloserToUsageTests.cs | 2 +- .../Refactoring/Rename/RenameTests.cs | 4 +- .../Symbols/DeclarationFinderTests.cs | 2 +- .../SelectedDeclarationProviderTests.cs | 2 +- 33 files changed, 145 insertions(+), 174 deletions(-) diff --git a/RubberduckTests/Grammar/ResolverTests.cs b/RubberduckTests/Grammar/ResolverTests.cs index 6e5da78a69..93ffc0b61a 100644 --- a/RubberduckTests/Grammar/ResolverTests.cs +++ b/RubberduckTests/Grammar/ResolverTests.cs @@ -6820,7 +6820,7 @@ End Function .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Class1", ComponentType.ClassModule, classCode) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference(ReferenceLibrary.VBA) + .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) .AddProjectToVbeBuilder() .Build(); @@ -6853,7 +6853,7 @@ End Function .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Class1", ComponentType.ClassModule, classCode) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference(ReferenceLibrary.VBA) + .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) .AddProjectToVbeBuilder() .Build(); @@ -6890,7 +6890,7 @@ End Function .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Class1", ComponentType.ClassModule, classCode) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference(ReferenceLibrary.VBA) + .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) .AddProjectToVbeBuilder() .Build(); @@ -6927,7 +6927,7 @@ End Function .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Class1", ComponentType.ClassModule, classCode) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference(ReferenceLibrary.VBA) + .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) .AddProjectToVbeBuilder() .Build(); @@ -6964,7 +6964,7 @@ End Function .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Class1", ComponentType.ClassModule, classCode) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference(ReferenceLibrary.VBA) + .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) .AddProjectToVbeBuilder() .Build(); diff --git a/RubberduckTests/Inspections/ApplicationWorksheetFunctionInspectionTests.cs b/RubberduckTests/Inspections/ApplicationWorksheetFunctionInspectionTests.cs index b49b2ddf57..c934bedda0 100644 --- a/RubberduckTests/Inspections/ApplicationWorksheetFunctionInspectionTests.cs +++ b/RubberduckTests/Inspections/ApplicationWorksheetFunctionInspectionTests.cs @@ -5,7 +5,6 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; -using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -13,7 +12,7 @@ namespace RubberduckTests.Inspections public class ApplicationWorksheetFunctionInspectionTests : InspectionTestsBase { private IEnumerable GetInspectionResultsUsingExcelLibrary(string inputCode) - => InspectionResultsForModules(("Module1", inputCode, ComponentType.StandardModule), ReferenceLibrary.Excel); + => InspectionResultsForModules(("Module1", inputCode, ComponentType.StandardModule), "Excel"); [Test] [Category("Inspections")] diff --git a/RubberduckTests/Inspections/ExcelMemberMayReturnNothingInspectionTests.cs b/RubberduckTests/Inspections/ExcelMemberMayReturnNothingInspectionTests.cs index eb38da4a52..e2125bee83 100644 --- a/RubberduckTests/Inspections/ExcelMemberMayReturnNothingInspectionTests.cs +++ b/RubberduckTests/Inspections/ExcelMemberMayReturnNothingInspectionTests.cs @@ -5,7 +5,6 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; -using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -349,7 +348,7 @@ End Sub } private IEnumerable InspectionResults(string inputCode) - => InspectionResultsForModules(("Module1", inputCode, ComponentType.StandardModule), ReferenceLibrary.Excel); + => InspectionResultsForModules(("Module1", inputCode, ComponentType.StandardModule), "Excel"); protected override IInspection InspectionUnderTest(RubberduckParserState state) { diff --git a/RubberduckTests/Inspections/ExcelUdfNameIsValidCellReferenceInspectionTests.cs b/RubberduckTests/Inspections/ExcelUdfNameIsValidCellReferenceInspectionTests.cs index 3f6ee64ec3..c9749eb7df 100644 --- a/RubberduckTests/Inspections/ExcelUdfNameIsValidCellReferenceInspectionTests.cs +++ b/RubberduckTests/Inspections/ExcelUdfNameIsValidCellReferenceInspectionTests.cs @@ -4,7 +4,6 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; -using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -107,7 +106,7 @@ public void ExcelUdfNameIsValidCellReferenceInspection_ReturnsNoResult_NonFuncti } private int InspectionResultCount(string inputCode, ComponentType moduleType) - => InspectionResultsForModules(("UnderTest", inputCode, moduleType), ReferenceLibrary.Excel).Count(); + => InspectionResultsForModules(("UnderTest", inputCode, moduleType), "Excel").Count(); protected override IInspection InspectionUnderTest(RubberduckParserState state) { diff --git a/RubberduckTests/Inspections/HostSpecificExpressionInspectionTests.cs b/RubberduckTests/Inspections/HostSpecificExpressionInspectionTests.cs index 9a29f0107b..379e39a2c9 100644 --- a/RubberduckTests/Inspections/HostSpecificExpressionInspectionTests.cs +++ b/RubberduckTests/Inspections/HostSpecificExpressionInspectionTests.cs @@ -22,9 +22,9 @@ Public Sub DoSomething() [A1] = 42 End Sub "; - var vbe = MockVbeBuilder.BuildFromModules(("Module1", code, ComponentType.StandardModule), new ReferenceLibrary[] { ReferenceLibrary.VBA, ReferenceLibrary.Excel }); + var vbe = MockVbeBuilder.BuildFromModules(("Module1", code, ComponentType.StandardModule), new string[] { "VBA", "Excel" }); var mockHost = new Mock(); - mockHost.SetupGet(m => m.ApplicationName).Returns(ReferenceLibrary.Excel.Name()); + mockHost.SetupGet(m => m.ApplicationName).Returns("Excel"); vbe.Setup(m => m.HostApplication()).Returns(() => mockHost.Object); Assert.AreEqual(1, InspectionResults(vbe.Object).Count()); diff --git a/RubberduckTests/Inspections/ImplicitActiveSheetReferenceInspectionTests.cs b/RubberduckTests/Inspections/ImplicitActiveSheetReferenceInspectionTests.cs index 2cb862163b..04d5d5ccf5 100644 --- a/RubberduckTests/Inspections/ImplicitActiveSheetReferenceInspectionTests.cs +++ b/RubberduckTests/Inspections/ImplicitActiveSheetReferenceInspectionTests.cs @@ -4,7 +4,6 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; -using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -22,7 +21,7 @@ Dim arr1() As Variant End Sub "; var modules = new(string, string, ComponentType)[] { ("Class1", inputCode, ComponentType.ClassModule) }; - Assert.AreEqual(1, InspectionResultsForModules(modules, ReferenceLibrary.Excel).Count()); + Assert.AreEqual(1, InspectionResultsForModules(modules, "Excel").Count()); } [Test] @@ -81,7 +80,7 @@ End Sub "; var modules = new(string, string, ComponentType)[] { ("Class1", inputCode, ComponentType.ClassModule) }; - Assert.AreEqual(0, InspectionResultsForModules(modules, ReferenceLibrary.Excel).Count()); + Assert.AreEqual(0, InspectionResultsForModules(modules, "Excel").Count()); } [Test] diff --git a/RubberduckTests/Inspections/ImplicitActiveWorkbookReferenceInspectionTests.cs b/RubberduckTests/Inspections/ImplicitActiveWorkbookReferenceInspectionTests.cs index 12fca8fe76..b29263d3d0 100644 --- a/RubberduckTests/Inspections/ImplicitActiveWorkbookReferenceInspectionTests.cs +++ b/RubberduckTests/Inspections/ImplicitActiveWorkbookReferenceInspectionTests.cs @@ -4,7 +4,6 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; -using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -182,7 +181,7 @@ Dim sheet As Worksheet private int ArrangeAndGetInspectionCount(string code) { var modules = new(string, string, ComponentType)[] { ("Module1", code, ComponentType.StandardModule) }; - return InspectionResultsForModules(modules, ReferenceLibrary.Excel).Count(); + return InspectionResultsForModules(modules, "Excel").Count(); } [Test] diff --git a/RubberduckTests/Inspections/InspectionTestsBase.cs b/RubberduckTests/Inspections/InspectionTestsBase.cs index 96192862bf..32b70660d9 100644 --- a/RubberduckTests/Inspections/InspectionTestsBase.cs +++ b/RubberduckTests/Inspections/InspectionTestsBase.cs @@ -30,13 +30,13 @@ public IEnumerable InspectionResultsForModules(IEnumerable<(s return InspectionResults(vbe); } - public IEnumerable InspectionResultsForModules((string name, string content, ComponentType componentType) module, params ReferenceLibrary[] libraries) - => InspectionResultsForModules(new(string, string, ComponentType)[] { module }, libraries); + public IEnumerable InspectionResultsForModules((string name, string content, ComponentType componentType) module, params string[] libraries) + => InspectionResultsForModules(new (string, string, ComponentType)[] { module }, libraries); - public IEnumerable InspectionResultsForModules(IEnumerable<(string name, string content, ComponentType componentType)> modules, ReferenceLibrary library) - => InspectionResultsForModules(modules, new ReferenceLibrary[] { library }); + public IEnumerable InspectionResultsForModules(IEnumerable<(string name, string content, ComponentType componentType)> modules, string library) + => InspectionResultsForModules(modules, new string[] { library }); - public IEnumerable InspectionResultsForModules(IEnumerable<(string name, string content, ComponentType componentType)> modules, IEnumerable libraries) + public IEnumerable InspectionResultsForModules(IEnumerable<(string name, string content, ComponentType componentType)> modules, IEnumerable libraries) { var vbe = MockVbeBuilder.BuildFromModules(modules, libraries).Object; return InspectionResults(vbe); diff --git a/RubberduckTests/Inspections/IsMissingOnInappropriateArgumentInspectionTests.cs b/RubberduckTests/Inspections/IsMissingOnInappropriateArgumentInspectionTests.cs index cb597699cf..127b904610 100644 --- a/RubberduckTests/Inspections/IsMissingOnInappropriateArgumentInspectionTests.cs +++ b/RubberduckTests/Inspections/IsMissingOnInappropriateArgumentInspectionTests.cs @@ -4,7 +4,6 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; -using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -209,7 +208,7 @@ private int ArrangeAndGetInspectionCount(string code) ("Module1", code, ComponentType.StandardModule) }; - return InspectionResultsForModules(modules, ReferenceLibrary.VBA).Count(); + return InspectionResultsForModules(modules, "VBA").Count(); } protected override IInspection InspectionUnderTest(RubberduckParserState state) diff --git a/RubberduckTests/Inspections/IsMissingWithNonArgumentParameterInspectionTests.cs b/RubberduckTests/Inspections/IsMissingWithNonArgumentParameterInspectionTests.cs index eceaa31520..78d588e0ac 100644 --- a/RubberduckTests/Inspections/IsMissingWithNonArgumentParameterInspectionTests.cs +++ b/RubberduckTests/Inspections/IsMissingWithNonArgumentParameterInspectionTests.cs @@ -4,7 +4,6 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; -using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -131,7 +130,7 @@ private int ArrangeAndGetInspectionCount(string code) ("Module1", code, ComponentType.StandardModule) }; - return InspectionResultsForModules(modules, ReferenceLibrary.VBA).Count(); + return InspectionResultsForModules(modules, "VBA").Count(); } protected override IInspection InspectionUnderTest(RubberduckParserState state) diff --git a/RubberduckTests/Inspections/MemberNotOnInterfaceInspectionTests.cs b/RubberduckTests/Inspections/MemberNotOnInterfaceInspectionTests.cs index b65d589321..9d9b3f7210 100644 --- a/RubberduckTests/Inspections/MemberNotOnInterfaceInspectionTests.cs +++ b/RubberduckTests/Inspections/MemberNotOnInterfaceInspectionTests.cs @@ -11,7 +11,7 @@ namespace RubberduckTests.Inspections [TestFixture] public class MemberNotOnInterfaceInspectionTests : InspectionTestsBase { - private int ArrangeParserAndGetResultCount(string inputCode, ReferenceLibrary library = ReferenceLibrary.Scripting) + private int ArrangeParserAndGetResultCount(string inputCode, string library) => InspectionResultsForModules(("Codez", inputCode, ComponentType.StandardModule), library).Count(); [Test] @@ -24,7 +24,7 @@ Dim dict As Dictionary Set dict = New Dictionary dict.NonMember End Sub"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -37,7 +37,7 @@ Dim dict As Dictionary Set dict = New Dictionary dict.NonMember End Sub"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -48,7 +48,7 @@ public void MemberNotOnInterface_ReturnsResult_ApplicationObject() @"Sub Foo() Application.NonMember End Sub"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, ReferenceLibrary.Excel)); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Excel")); } [Test] @@ -59,7 +59,7 @@ public void MemberNotOnInterface_ReturnsResult_UnDeclaredMemberOnParameter() @"Sub Foo(dict As Dictionary) dict.NonMember End Sub"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -72,7 +72,7 @@ Dim dict As Dictionary Set dict = New Dictionary Debug.Print dict.Count End Sub"; - Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -84,7 +84,7 @@ public void MemberNotOnInterface_DoesNotReturnResult_NonExtensible() Dim x As File Debug.Print x.NonMember End Sub"; - Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -98,7 +98,7 @@ With dict .NonMember End With End Sub"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -111,7 +111,7 @@ Dim dict As Dictionary Set dict = New Dictionary dict!SomeIdentifier = 42 End Sub"; - Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -125,7 +125,7 @@ With dict !SomeIdentifier = 42 End With End Sub"; - Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -136,7 +136,7 @@ public void MemberNotOnInterface_DoesNotReturnResult_ProjectReference() @"Sub Foo() Dim dict As Scripting.Dictionary End Sub"; - Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -150,7 +150,7 @@ Dim dict As Dictionary '@Ignore MemberNotOnInterface dict.NonMember End Sub"; - Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -163,7 +163,7 @@ With New Dictionary .FooBar End With End Sub"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -180,7 +180,7 @@ End Sub Private Sub Bar(baz As Long) End Sub"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -197,7 +197,7 @@ End Sub Private Function Bar(baz As Long) As Variant End Function"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -214,7 +214,7 @@ End Sub Private Function Bar(baz As Long) As Variant End Function"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -231,7 +231,7 @@ End Sub Private Function Bar(baz As Long) As Variant End Function"; - Assert.AreEqual(2, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(2, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -248,7 +248,7 @@ End Sub Private Function Bar(baz As Long) As Variant End Function"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -265,7 +265,7 @@ End Sub Private Function Bar(baz As Long) As Variant End Function"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -282,7 +282,7 @@ End Sub Private Function Bar(baz As Long) As Variant End Function"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -299,7 +299,7 @@ End Sub Private Function Bar(baz As Long) As Variant End Function"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -319,7 +319,7 @@ End Function Private Sub Barr(baz As Long) End Sub"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -339,7 +339,7 @@ End Function Private Sub Barr(baz As Long) End Sub"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -359,7 +359,7 @@ End Function Private Sub Barr(baz As Long) End Sub"; - Assert.AreEqual(3, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(3, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -379,7 +379,7 @@ End Function Private Sub Barr(baz As Long) End Sub"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -392,7 +392,7 @@ With New Dictionary !FooBar = 42 End With End Sub"; - Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -405,7 +405,7 @@ With New Dictionary .Add 42, 42 End With End Sub"; - Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode)); + Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode, "Scripting")); } [Test] @@ -443,7 +443,7 @@ End Sub var projectBuilder = vbeBuilder.ProjectBuilder("testproject", ProjectProtection.Unprotected); projectBuilder.MockUserFormBuilder("UserForm1", userForm1Code).AddFormToProjectBuilder() .AddComponent("ReferencingModule", ComponentType.StandardModule, analyzedCode) - .AddReference(ReferenceLibrary.MsForms); + .AddReference("MSForms", MockVbeBuilder.LibraryPathMsForms, 2, 0, true); vbeBuilder.AddProject(projectBuilder.Build()); var vbe = vbeBuilder.Build(); @@ -464,7 +464,7 @@ Debug.Print bar.Left var vbeBuilder = new MockVbeBuilder(); var projectBuilder = vbeBuilder.ProjectBuilder("testproject", ProjectProtection.Unprotected); projectBuilder.MockUserFormBuilder("UserForm1", inputCode).AddFormToProjectBuilder() - .AddReference(ReferenceLibrary.MsForms); + .AddReference("MSForms", MockVbeBuilder.LibraryPathMsForms, 2, 0, true); vbeBuilder.AddProject(projectBuilder.Build()); var vbe = vbeBuilder.Build(); diff --git a/RubberduckTests/Inspections/ObjectVariableNotSetInspectionTests.cs b/RubberduckTests/Inspections/ObjectVariableNotSetInspectionTests.cs index 5bc572eea7..7213b63a23 100644 --- a/RubberduckTests/Inspections/ObjectVariableNotSetInspectionTests.cs +++ b/RubberduckTests/Inspections/ObjectVariableNotSetInspectionTests.cs @@ -5,7 +5,6 @@ using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor; using Rubberduck.VBEditor.SafeComWrappers; -using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -141,7 +140,7 @@ Dim target As String target = Range(""A1"") target.Value = ""all good"" End Sub"; - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.Excel); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "Excel"); } [Test] @@ -157,7 +156,7 @@ Dim target As Collection testParam = target testParam.Add 100 End Sub"; - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.VBA); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "VBA"); } [Test] @@ -193,7 +192,7 @@ public void ObjectVariableNotSet_GivenVariantVariableAssignedNewObject_ReturnsRe Private Sub TestSub(ByRef testParam As Variant) testParam = New Collection End Sub"; - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.VBA); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "VBA"); } [Test] @@ -226,7 +225,7 @@ Dim target As Range target.Value = ""forgot something?"" End Sub"; - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.Excel); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "Excel"); } [Test] @@ -244,7 +243,7 @@ Dim target As Range target.Value = ""All good"" End Sub"; - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.Excel); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "Excel"); } [Test] @@ -286,7 +285,7 @@ Private Sub TestSelfAssigned() Dim arg1 As new Collection arg1.Add 7 End Sub"; - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.VBA); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "VBA"); } [Test] @@ -343,7 +342,7 @@ public void ObjectVariableNotSet_FunctionReturnNotSet_ReturnsResult() Private Function Test() As Collection Test = New Collection End Function"; - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.VBA); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "VBA"); } [Test] @@ -494,7 +493,7 @@ Dim bar As Collection bar.Add ""x"", ""x"" foo = ""Test"" & bar.Item(""x"") End Sub"; - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.VBA); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "VBA"); } [Test] @@ -528,7 +527,7 @@ Dim foo As Range Dim bar As Variant bar = foo End Sub"; - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.Excel); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "Excel"); } [Test] @@ -544,7 +543,7 @@ Dim bar As Variant bar = foo End Sub"; //The default member of Recordset is Fields, which is an object. - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.AdoDb); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "ADODB"); } [Test] @@ -560,7 +559,7 @@ Dim bar As Variant foo = bar End Sub"; //The default member of Recordset is Fields, which is an object and only has a paramterized default member. - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.AdoDb); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "ADODB"); } [Test] @@ -574,7 +573,7 @@ Private Sub Test() Dim foo As Variant foo = New Connection End Sub"; - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.AdoDb); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "ADODB"); } [Test] @@ -589,7 +588,7 @@ Dim foo As Variant foo = New Recordset End Sub"; //The default member of Recordset is Fields, which is an object. - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.AdoDb); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "ADODB"); } [Test] @@ -1411,7 +1410,7 @@ protected override IInspection InspectionUnderTest(RubberduckParserState state) return new ObjectVariableNotSetInspection(state); } - private void AssertInputCodeYieldsExpectedInspectionResultCount(string inputCode, int expected, params ReferenceLibrary[] testLibraries) + private void AssertInputCodeYieldsExpectedInspectionResultCount(string inputCode, int expected, params string[] testLibraries) { var inspectionResults = InspectionResultsForModules(("Class1", inputCode, ComponentType.ClassModule), testLibraries); Assert.AreEqual(expected, inspectionResults.Count()); diff --git a/RubberduckTests/Inspections/ParameterNotUsedInspectionTests.cs b/RubberduckTests/Inspections/ParameterNotUsedInspectionTests.cs index 2bb26ec277..02f950e91b 100644 --- a/RubberduckTests/Inspections/ParameterNotUsedInspectionTests.cs +++ b/RubberduckTests/Inspections/ParameterNotUsedInspectionTests.cs @@ -4,7 +4,6 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; -using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -75,7 +74,7 @@ Debug.Print rst(""Field"") ("Module1", inputCode, ComponentType.StandardModule), }; - Assert.AreEqual(0, InspectionResultsForModules(modules, ReferenceLibrary.AdoDb).Count()); + Assert.AreEqual(0, InspectionResultsForModules(modules, "ADODB").Count()); } [Test] diff --git a/RubberduckTests/Inspections/ShadowedDeclarationInspectionTests.cs b/RubberduckTests/Inspections/ShadowedDeclarationInspectionTests.cs index 17182c2568..45939d83a2 100644 --- a/RubberduckTests/Inspections/ShadowedDeclarationInspectionTests.cs +++ b/RubberduckTests/Inspections/ShadowedDeclarationInspectionTests.cs @@ -5127,7 +5127,7 @@ public void ShadowedDeclaration_DoesNotReturnResult_AssertBecauseOfDebugAssert(s var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("TestClass", ComponentType.ClassModule, code) - .AddReference(ReferenceLibrary.VBA) + .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) .AddProjectToVbeBuilder() .Build(); @@ -5153,7 +5153,7 @@ Dim Assert As Long var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("TestClass", ComponentType.ClassModule, code) - .AddReference(ReferenceLibrary.VBA) + .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) .AddProjectToVbeBuilder() .Build(); @@ -5178,7 +5178,7 @@ public void ShadowedDeclaration_DoesNotReturnResult_AssertParameterAssertBecause var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("TestClass", ComponentType.ClassModule, code) - .AddReference(ReferenceLibrary.VBA) + .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) .AddProjectToVbeBuilder() .Build(); @@ -5213,7 +5213,7 @@ Dim Assert As Long var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("TestClass", ComponentType.ClassModule, code) - .AddReference(ReferenceLibrary.VBA) + .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) .AddProjectToVbeBuilder() .Build(); @@ -5247,7 +5247,7 @@ Public Sub Foo(Assert As Boolean) var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("TestClass", ComponentType.ClassModule, code) - .AddReference(ReferenceLibrary.VBA) + .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) .AddProjectToVbeBuilder() .Build(); diff --git a/RubberduckTests/Inspections/SheetAccessedUsingStringInspectionTests.cs b/RubberduckTests/Inspections/SheetAccessedUsingStringInspectionTests.cs index 4b26ae6b41..9b02593134 100644 --- a/RubberduckTests/Inspections/SheetAccessedUsingStringInspectionTests.cs +++ b/RubberduckTests/Inspections/SheetAccessedUsingStringInspectionTests.cs @@ -194,7 +194,7 @@ private IEnumerable ArrangeParserAndGetResults(string inputCo CreateVBComponentPropertyMock("CodeName", "Sheet1").Object }) .AddReference("ReferencedProject", string.Empty, 0, 0) - .AddReference(ReferenceLibrary.Excel) + .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) .Build(); var vbe = builder.AddProject(referencedProject).AddProject(project).Build(); diff --git a/RubberduckTests/Inspections/UndeclaredVariableInspectionTests.cs b/RubberduckTests/Inspections/UndeclaredVariableInspectionTests.cs index 5ddcab68d2..560dbe93e7 100644 --- a/RubberduckTests/Inspections/UndeclaredVariableInspectionTests.cs +++ b/RubberduckTests/Inspections/UndeclaredVariableInspectionTests.cs @@ -4,7 +4,6 @@ using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; -using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -21,7 +20,7 @@ public void UndeclaredVariable_ReturnsResult() Debug.Print a End Sub"; - Assert.AreEqual(1, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), ReferenceLibrary.VBA).Count()); + Assert.AreEqual(1, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), "VBA").Count()); } [Test] @@ -35,7 +34,7 @@ Dim a As Long Debug.Print a End Sub"; - Assert.AreEqual(0, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), ReferenceLibrary.VBA).Count()); + Assert.AreEqual(0, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), "VBA").Count()); } [Test] @@ -50,7 +49,7 @@ Sub Test() Debug.Print a End Sub"; - Assert.AreEqual(0, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), ReferenceLibrary.VBA).Count()); + Assert.AreEqual(0, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), "VBA").Count()); } [Test] @@ -82,7 +81,7 @@ public void UndeclaredVariable_ReturnsNoResultIfAnnotated() Debug.Print a End Sub"; - Assert.AreEqual(0, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), ReferenceLibrary.VBA).Count()); + Assert.AreEqual(0, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), "VBA").Count()); } [Test] diff --git a/RubberduckTests/Inspections/UntypedFunctionUsageInspectionTests.cs b/RubberduckTests/Inspections/UntypedFunctionUsageInspectionTests.cs index 472525837e..db1f13d4fd 100644 --- a/RubberduckTests/Inspections/UntypedFunctionUsageInspectionTests.cs +++ b/RubberduckTests/Inspections/UntypedFunctionUsageInspectionTests.cs @@ -4,7 +4,6 @@ using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.Parsing.Inspections.Abstract; -using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -21,7 +20,7 @@ Dim str As String str = Left(""test"", 1) End Sub"; - Assert.AreEqual(1, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), ReferenceLibrary.VBA).Count()); + Assert.AreEqual(1, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), "VBA").Count()); } [Test] @@ -34,7 +33,7 @@ Dim str As String str = Left$(""test"", 1) End Sub"; - Assert.AreEqual(0, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), ReferenceLibrary.VBA).Count()); + Assert.AreEqual(0, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), "VBA").Count()); } [Test] @@ -49,7 +48,7 @@ Dim str As String str = Left(""test"", 1) End Sub"; - Assert.AreEqual(0, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), ReferenceLibrary.VBA).Count()); + Assert.AreEqual(0, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), "VBA").Count()); } [Test] diff --git a/RubberduckTests/Inspections/UseMeaningfulNameInspectionTests.cs b/RubberduckTests/Inspections/UseMeaningfulNameInspectionTests.cs index d495db90c0..0f9c4b7122 100644 --- a/RubberduckTests/Inspections/UseMeaningfulNameInspectionTests.cs +++ b/RubberduckTests/Inspections/UseMeaningfulNameInspectionTests.cs @@ -161,7 +161,7 @@ internal static Mock> GetInspectio private IEnumerable InspectionResultsForModules(params (string name, string content, ComponentType componentType)[] modules) { - var vbe = MockVbeBuilder.BuildFromModules("TestProject", modules, Enumerable.Empty()); + var vbe = MockVbeBuilder.BuildFromModules("TestProject", modules, Enumerable.Empty()); return InspectionResults(vbe.Object); } diff --git a/RubberduckTests/Inspections/ValueRequiredInspectionTests.cs b/RubberduckTests/Inspections/ValueRequiredInspectionTests.cs index 92134ccf4f..18f35c3f36 100644 --- a/RubberduckTests/Inspections/ValueRequiredInspectionTests.cs +++ b/RubberduckTests/Inspections/ValueRequiredInspectionTests.cs @@ -4,7 +4,6 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; -using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -383,7 +382,7 @@ End Function ("Module1", moduleCode, ComponentType.StandardModule), }; - Assert.IsFalse(InspectionResultsForModules(modules, ReferenceLibrary.VBA).Any()); + Assert.IsFalse(InspectionResultsForModules(modules, "VBA").Any()); } protected override IInspection InspectionUnderTest(RubberduckParserState state) diff --git a/RubberduckTests/Mocks/MockProjectBuilder.cs b/RubberduckTests/Mocks/MockProjectBuilder.cs index 27953242c5..30ab100eb9 100644 --- a/RubberduckTests/Mocks/MockProjectBuilder.cs +++ b/RubberduckTests/Mocks/MockProjectBuilder.cs @@ -104,17 +104,6 @@ public MockProjectBuilder AddComponent(Mock component, Mock - /// Adds a mock reference to the project. - /// - /// The reference library's enum. - /// Returns the instance. - public MockProjectBuilder AddReference(ReferenceLibrary referenceLibrary) - { - var (name, path, versionMajor, versionMinor, isBuiltIn) = MockVbeBuilder.ReferenceLibraries[referenceLibrary]; - return AddReference(name, path, versionMajor, versionMinor, isBuiltIn); - } - /// /// Adds a mock reference to the project. /// diff --git a/RubberduckTests/Mocks/MockVbeBuilder.cs b/RubberduckTests/Mocks/MockVbeBuilder.cs index 5bdeda3c78..acad78aa93 100644 --- a/RubberduckTests/Mocks/MockVbeBuilder.cs +++ b/RubberduckTests/Mocks/MockVbeBuilder.cs @@ -1,3 +1,4 @@ +using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -10,28 +11,6 @@ namespace RubberduckTests.Mocks { - public enum ReferenceLibrary - { - VBA, - Excel, - MsOffice, - StdOle, - MsForms, - VBIDE, - Scripting, - Regex, - MsXml, - ShDoc, - AdoDb, - AdoRecordset, - } - - public static class ReferenceLibraryExtensions - { - public static string Name(this ReferenceLibrary val) => MockVbeBuilder.ReferenceLibraryIdentifiers[val].Name; - public static string Path(this ReferenceLibrary val) => MockVbeBuilder.ReferenceLibraryIdentifiers[val].Path; - } - /// /// Builds a mock . /// @@ -41,34 +20,50 @@ public class MockVbeBuilder public const string TestProjectName = "TestProject1"; public const string TestModuleName = "TestModule1"; private readonly Mock _vbe; - - public static Dictionary ReferenceLibraryIdentifiers = new Dictionary() + private readonly Mock _vbeEvents; + + #region standard library paths (referenced in all VBA projects hosted in Microsoft Excel) + public static readonly string LibraryPathVBA = @"C:\PROGRA~1\COMMON~1\MICROS~1\VBA\VBA7.1\VBE7.DLL"; // standard library, priority locked + public static readonly string LibraryPathMsExcel = @"C:\Program Files\Microsoft Office\Office15\EXCEL.EXE"; // mock host application, priority locked + public static readonly string LibraryPathMsOffice = @"C:\Program Files\Common Files\Microsoft Shared\OFFICE15\MSO.DLL"; + public static readonly string LibraryPathStdOle = @"C:\Windows\System32\stdole2.tlb"; + public static readonly string LibraryPathMsForms = @"C:\Windows\system32\FM20.DLL"; // standard in projects with a UserForm module + #endregion + + public static readonly string LibraryPathVBIDE = @"C:\Program Files (x86)\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.OLB"; + public static readonly string LibraryPathScripting = @"C:\Windows\System32\scrrun.dll"; + public static readonly string LibraryPathRegex = @"C:\Windows\System32\vbscript.dll\3"; + public static readonly string LibraryPathMsXml = @"C:\Windows\System32\msxml6.dll"; + public static readonly string LibraryPathShDoc = @"C:\Windows\System32\ieframe.dll"; + public static readonly string LibraryPathAdoDb = @"C:\Program Files\Common Files\System\ado\msado15.dll"; + public static readonly string LibraryPathAdoRecordset = @"C:\Program Files\Common Files\System\ado\msador15.dll"; + + public static readonly Dictionary LibraryPaths = new Dictionary { - //standard library paths (referenced in all VBA projects hosted in Microsoft Excel) - [ReferenceLibrary.VBA] = ("VBA", @"C:\PROGRA~1\COMMON~1\MICROS~1\VBA\VBA7.1\VBE7.DLL"), //standard library, priority locked" - [ReferenceLibrary.Excel] = ("Excel", @"C:\Program Files\Microsoft Office\Office15\EXCEL.EXE"), // mock host application, priority locked - [ReferenceLibrary.MsOffice] = ("Office", @"C:\Program Files\Common Files\Microsoft Shared\OFFICE15\MSO.DLL"), - [ReferenceLibrary.StdOle] = ("stdole", @"C:\Windows\System32\stdole2.tlb"), - [ReferenceLibrary.MsForms] = ("MSForms", @"C:\Windows\system32\FM20.DLL"), // standard in projects with a UserForm module - //end standard library paths - [ReferenceLibrary.VBIDE] = ("VBIDE", @"C:\Program Files (x86)\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.OLB"), - [ReferenceLibrary.Scripting] = ("Scripting", @"C:\Windows\System32\scrrun.dll"), - [ReferenceLibrary.Regex] = ("VBScript_RegExp_55", @"C:\Windows\System32\vbscript.dll\3"), - [ReferenceLibrary.MsXml] = ("MSXML2", @"C:\Windows\System32\msxml6.dll"), - [ReferenceLibrary.ShDoc] = ("SHDocVw", @"C:\Windows\System32\ieframe.dll"), - [ReferenceLibrary.AdoDb] = ("ADODB", @"C:\Program Files\Common Files\System\ado\msado15.dll"), - [ReferenceLibrary.AdoRecordset] = ("ADOR", @"C:\Program Files\Common Files\System\ado\msador15.dll"), + ["VBA"] = LibraryPathVBA, + ["Excel"] = LibraryPathMsExcel, + ["Office"] = LibraryPathMsOffice, + ["stdole"] = LibraryPathStdOle, + ["MSForms"] = LibraryPathMsForms, + ["VBIDE"] = LibraryPathVBIDE, + ["Scripting"] = LibraryPathScripting, + ["VBScript_RegExp_55"] = LibraryPathRegex, + ["MSXML2"] = LibraryPathMsXml, + ["SHDocVw"] = LibraryPathShDoc, + ["ADODB"] = LibraryPathAdoDb, + ["ADOR"] = LibraryPathAdoRecordset }; - internal static readonly Dictionary ReferenceLibraries = new Dictionary + private static readonly Dictionary> AddReference = new Dictionary> { - [ReferenceLibrary.VBA] = (ReferenceLibrary.VBA.Name(), ReferenceLibrary.VBA.Path(), 4, 2, true), - [ReferenceLibrary.Excel] = (ReferenceLibrary.Excel.Name(), ReferenceLibrary.Excel.Path(), 1, 8, true), - [ReferenceLibrary.Scripting] = (ReferenceLibrary.Scripting.Name(), ReferenceLibrary.Scripting.Path(), 1, 0, true), - [ReferenceLibrary.AdoDb] = (ReferenceLibrary.AdoDb.Name(), ReferenceLibrary.AdoDb.Path(), 6, 1, false), - [ReferenceLibrary.MsForms] = (ReferenceLibrary.MsForms.Name(), ReferenceLibrary.MsForms.Path(), 2, 0, true), + ["Excel"] = (MockProjectBuilder builder) => builder.AddReference("Excel", LibraryPathMsExcel, 1, 8, true), + ["VBA"] = (MockProjectBuilder builder) => builder.AddReference("VBA", LibraryPathVBA, 4, 2, true), + ["Scripting"] = (MockProjectBuilder builder) => builder.AddReference("Scripting", LibraryPathScripting, 1, 0, true), + ["ADODB"] = (MockProjectBuilder builder) => builder.AddReference("ADODB", LibraryPathAdoDb, 6, 1, false), + ["MSForms"] = (MockProjectBuilder builder) => builder.AddReference("MSForms", LibraryPathMsForms, 2, 0, true), }; + //private Mock _vbWindows; private readonly Windows _windows = new Windows(); private readonly ICollection _projects = new List(); @@ -165,7 +160,7 @@ public static Mock BuildFromSingleModule(string content, string name, Comp if (referenceStdLibs) { - builder.AddReference(ReferenceLibrary.VBA); + builder.AddReference("VBA", LibraryPathVBA, 4, 2, true); } var project = builder.Build(); @@ -199,24 +194,24 @@ public static Mock BuildFromModules(params (string name, string content, C /// Builds a mock VBE containing a single "TestProject1" with multiple modules. /// public static Mock BuildFromModules(IEnumerable<(string name, string content, ComponentType componentType)> modules) - => BuildFromModules(modules, Enumerable.Empty()); + => BuildFromModules(modules, Enumerable.Empty()); /// /// Builds a mock VBE containing a single "TestProject1" with one module and one or more libraries. /// - public static Mock BuildFromModules((string name, string content, ComponentType componentType) module, params ReferenceLibrary[] libraries) - => BuildFromModules(new(string, string, ComponentType)[] { module }, libraries); + public static Mock BuildFromModules((string name, string content, ComponentType componentType) module, params string[] libraries) + => BuildFromModules(new (string, string, ComponentType)[] { module }, libraries); /// /// Builds a mock VBE containing a single "TestProject1" with multiple modules and libraries. /// - public static Mock BuildFromModules(IEnumerable<(string name, string content, ComponentType componentType)> modules, IEnumerable libraries) - => BuildFromModules(TestProjectName, modules, libraries); + public static Mock BuildFromModules(IEnumerable<(string name, string content, ComponentType componentType)> modules, IEnumerable libraryNames) + => BuildFromModules(TestProjectName, modules, libraryNames); /// /// Builds a mock VBE containing one project with multiple modules and libraries. /// - public static Mock BuildFromModules(string projectName, IEnumerable<(string name, string content, ComponentType componentType)> modules, IEnumerable referenceLibraries) + public static Mock BuildFromModules(string projectName, IEnumerable<(string name, string content, ComponentType componentType)> modules, IEnumerable libraryNames) { var vbeBuilder = new MockVbeBuilder(); @@ -226,10 +221,9 @@ public static Mock BuildFromModules(string projectName, IEnumerable<(strin builder.AddComponent(name, componentType, content); } - foreach (var refLibrary in referenceLibraries) + foreach (var name in libraryNames) { - var (name, path, versionMajor, versionMinor, isBuiltIn) = ReferenceLibraries[refLibrary]; - builder.AddReference(name, path, versionMajor, versionMinor, isBuiltIn); + AddReference[name](builder); } var project = builder.Build(); diff --git a/RubberduckTests/QuickFixes/AccessSheetUsingCodeNameQuickFixTests.cs b/RubberduckTests/QuickFixes/AccessSheetUsingCodeNameQuickFixTests.cs index 00edeb3f5f..b1cc1701b3 100644 --- a/RubberduckTests/QuickFixes/AccessSheetUsingCodeNameQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/AccessSheetUsingCodeNameQuickFixTests.cs @@ -207,7 +207,7 @@ protected override IVBE TestVbe(string code, out IVBComponent component) CreateVBComponentPropertyMock("Name", "Name").Object, CreateVBComponentPropertyMock("CodeName", "CodeName").Object }) - .AddReference(ReferenceLibrary.Excel) + .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) .Build(); component = project.Object.VBComponents[0]; diff --git a/RubberduckTests/QuickFixes/ApplicationWorksheetFunctionQuickFixTests.cs b/RubberduckTests/QuickFixes/ApplicationWorksheetFunctionQuickFixTests.cs index f7ff8c175d..d005c6a09c 100644 --- a/RubberduckTests/QuickFixes/ApplicationWorksheetFunctionQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ApplicationWorksheetFunctionQuickFixTests.cs @@ -93,7 +93,7 @@ protected override IVBE TestVbe(string code, out IVBComponent component) var builder = new MockVbeBuilder(); var project = builder.ProjectBuilder("VBAProject", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, code) - .AddReference(ReferenceLibrary.Excel) + .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) .Build(); var vbe = builder.AddProject(project).Build().Object; diff --git a/RubberduckTests/QuickFixes/ExpandBangNotationQuickFixTests.cs b/RubberduckTests/QuickFixes/ExpandBangNotationQuickFixTests.cs index 25103f5f24..f94feb9399 100644 --- a/RubberduckTests/QuickFixes/ExpandBangNotationQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ExpandBangNotationQuickFixTests.cs @@ -193,7 +193,7 @@ End Sub var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference(ReferenceLibrary.Excel) + .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) .AddProjectToVbeBuilder() .Build(); @@ -224,7 +224,7 @@ End Sub var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference(ReferenceLibrary.Excel) + .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) .AddProjectToVbeBuilder() .Build(); diff --git a/RubberduckTests/QuickFixes/ExpandDefaultMemberQuickFixTests.cs b/RubberduckTests/QuickFixes/ExpandDefaultMemberQuickFixTests.cs index 4668bebe40..309a9ca5d6 100644 --- a/RubberduckTests/QuickFixes/ExpandDefaultMemberQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ExpandDefaultMemberQuickFixTests.cs @@ -667,7 +667,7 @@ End Sub var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference(ReferenceLibrary.Excel) + .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) .AddProjectToVbeBuilder() .Build(); @@ -700,7 +700,7 @@ End Sub var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference(ReferenceLibrary.Excel) + .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) .AddProjectToVbeBuilder() .Build(); @@ -731,7 +731,7 @@ End Sub var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference(ReferenceLibrary.Excel) + .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) .AddProjectToVbeBuilder() .Build(); diff --git a/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs b/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs index 13a1fdf2b3..01771d522e 100644 --- a/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs @@ -738,7 +738,7 @@ Dim str As String var builder = new MockVbeBuilder(); var project = builder.ProjectBuilder("VBAProject", ProjectProtection.Unprotected) .AddComponent("MyClass", ComponentType.ClassModule, inputCode) - .AddReference(ReferenceLibrary.VBA) + .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) .Build(); var vbe = builder.AddProject(project).Build(); @@ -1152,7 +1152,7 @@ private IEnumerable InspectionResults(IInspection inspection, var builder = new MockVbeBuilder(); var project = builder.ProjectBuilder("TestProject1", "TestProject1", ProjectProtection.Unprotected) .AddComponent("Class1", ComponentType.ClassModule, inputCode) - .AddReference(ReferenceLibrary.Excel) + .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) .Build(); var component = project.Object.VBComponents[0]; var vbe = builder.AddProject(project).Build(); @@ -1165,7 +1165,7 @@ private IEnumerable InspectionResults(IInspection inspection, var builder = new MockVbeBuilder(); var project = builder.ProjectBuilder("VBAProject", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, inputCode) - .AddReference(ReferenceLibrary.Excel) + .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) .Build(); var vbe = builder.AddProject(project).Build(); diff --git a/RubberduckTests/QuickFixes/IsMissingOnInappropriateArgumentQuickFixTests.cs b/RubberduckTests/QuickFixes/IsMissingOnInappropriateArgumentQuickFixTests.cs index c0fd3ad76d..d65dfb22ef 100644 --- a/RubberduckTests/QuickFixes/IsMissingOnInappropriateArgumentQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/IsMissingOnInappropriateArgumentQuickFixTests.cs @@ -448,7 +448,7 @@ protected override IVBE TestVbe(string code, out IVBComponent component) var builder = new MockVbeBuilder(); var project = builder.ProjectBuilder("TestProject1", "TestProject1", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, code) - .AddReference(ReferenceLibrary.VBA) + .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) .Build(); var vbe = builder.AddProject(project).Build(); component = project.Object.VBComponents.First(); diff --git a/RubberduckTests/QuickFixes/UntypedFunctionUsageQuickFixTests.cs b/RubberduckTests/QuickFixes/UntypedFunctionUsageQuickFixTests.cs index f1cfe72333..6a73594103 100644 --- a/RubberduckTests/QuickFixes/UntypedFunctionUsageQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/UntypedFunctionUsageQuickFixTests.cs @@ -33,7 +33,7 @@ Dim str As String var builder = new MockVbeBuilder(); var project = builder.ProjectBuilder("VBAProject", ProjectProtection.Unprotected) .AddComponent("MyClass", ComponentType.ClassModule, inputCode) - .AddReference(ReferenceLibrary.VBA) + .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) .Build(); var vbe = builder.AddProject(project).Build(); diff --git a/RubberduckTests/QuickFixes/UseSetKeywordForObjectAssignmentQuickFixTests.cs b/RubberduckTests/QuickFixes/UseSetKeywordForObjectAssignmentQuickFixTests.cs index 82568fad75..8398e54891 100644 --- a/RubberduckTests/QuickFixes/UseSetKeywordForObjectAssignmentQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/UseSetKeywordForObjectAssignmentQuickFixTests.cs @@ -149,7 +149,7 @@ protected override IVBE TestVbe(string code, out IVBComponent component) var builder = new MockVbeBuilder(); var project = builder.ProjectBuilder("VBAProject", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, code) - .AddReference(ReferenceLibrary.Excel) + .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) .Build(); var vbe = builder.AddProject(project).Build().Object; diff --git a/RubberduckTests/Refactoring/MoveCloserToUsageTests.cs b/RubberduckTests/Refactoring/MoveCloserToUsageTests.cs index 6de5d2ddb2..53b09e1643 100644 --- a/RubberduckTests/Refactoring/MoveCloserToUsageTests.cs +++ b/RubberduckTests/Refactoring/MoveCloserToUsageTests.cs @@ -824,7 +824,7 @@ Dim baz As Excel.Range var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Module", ComponentType.StandardModule, inputCode) - .AddReference(ReferenceLibrary.Excel) + .AddReference("EXCEL", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) .AddProjectToVbeBuilder() .Build() .Object; diff --git a/RubberduckTests/Refactoring/Rename/RenameTests.cs b/RubberduckTests/Refactoring/Rename/RenameTests.cs index 02701260b9..2547b18287 100644 --- a/RubberduckTests/Refactoring/Rename/RenameTests.cs +++ b/RubberduckTests/Refactoring/Rename/RenameTests.cs @@ -3205,8 +3205,8 @@ private static IVBE BuildProject(string projectName, IEnumerable Date: Thu, 30 Jan 2020 19:25:29 +0100 Subject: [PATCH 207/461] Unsubscribe from the right event in RubberduckCommandBar --- .../UI/Command/MenuItems/CommandBars/RubberduckCommandBar.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rubberduck.Core/UI/Command/MenuItems/CommandBars/RubberduckCommandBar.cs b/Rubberduck.Core/UI/Command/MenuItems/CommandBars/RubberduckCommandBar.cs index 78e53cb6ba..af1e1bf217 100644 --- a/Rubberduck.Core/UI/Command/MenuItems/CommandBars/RubberduckCommandBar.cs +++ b/Rubberduck.Core/UI/Command/MenuItems/CommandBars/RubberduckCommandBar.cs @@ -171,7 +171,7 @@ protected virtual void Dispose(bool disposing) } _selectionService.SelectionChanged -= OnSelectionChange; - _state.StateChanged -= OnParserStateChanged; + _state.StateChangedHighPriority -= OnParserStateChanged; _state.StatusMessageUpdate -= OnParserStatusMessageUpdate; RemoveCommandBar(); From 4cb31c1775875e1a613254655e30e9888cddaea1 Mon Sep 17 00:00:00 2001 From: jonathan-rizk Date: Fri, 31 Jan 2020 20:29:27 -0600 Subject: [PATCH 208/461] exclude disabled hotkeys when determining which hotkeys should display the hotkey mod. label. --- Rubberduck.Core/UI/Settings/GeneralSettingsViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rubberduck.Core/UI/Settings/GeneralSettingsViewModel.cs b/Rubberduck.Core/UI/Settings/GeneralSettingsViewModel.cs index e096f13b16..c1d53a5ea2 100644 --- a/Rubberduck.Core/UI/Settings/GeneralSettingsViewModel.cs +++ b/Rubberduck.Core/UI/Settings/GeneralSettingsViewModel.cs @@ -112,7 +112,7 @@ public bool ShouldDisplayHotkeyModificationLabel { get { - return _hotkeys.Any(s => !s.IsValid); + return _hotkeys.Any(s => !s.IsValid && s.IsEnabled); } } From 52bb5e1ab76be3d3d43a171786aa1fb401926112 Mon Sep 17 00:00:00 2001 From: Brian Zenger Date: Fri, 31 Jan 2020 20:33:46 -0800 Subject: [PATCH 209/461] Modified to use ReferenceLibrary enums --- RubberduckTests/Grammar/ResolverTests.cs | 10 +- ...icationWorksheetFunctionInspectionTests.cs | 3 +- ...elMemberMayReturnNothingInspectionTests.cs | 3 +- ...NameIsValidCellReferenceInspectionTests.cs | 3 +- .../HostSpecificExpressionInspectionTests.cs | 2 +- ...icitActiveSheetReferenceInspectionTests.cs | 11 +- ...tActiveWorkbookReferenceInspectionTests.cs | 3 +- .../Inspections/InspectionTestsBase.cs | 8 +- ...gOnInappropriateArgumentInspectionTests.cs | 3 +- ...WithNonArgumentParameterInspectionTests.cs | 3 +- .../MemberNotOnInterfaceInspectionTests.cs | 58 ++++----- .../ObjectVariableNotSetInspectionTests.cs | 29 ++--- .../ParameterNotUsedInspectionTests.cs | 3 +- .../ShadowedDeclarationInspectionTests.cs | 10 +- ...SheetAccessedUsingStringInspectionTests.cs | 2 +- .../UnassignedVariableUsageInspectionTests.cs | 13 +- .../UndeclaredVariableInspectionTests.cs | 9 +- .../UntypedFunctionUsageInspectionTests.cs | 7 +- .../UseMeaningfulNameInspectionTests.cs | 2 +- .../ValueRequiredInspectionTests.cs | 3 +- RubberduckTests/Mocks/MockProjectBuilder.cs | 21 +++- RubberduckTests/Mocks/MockVbeBuilder.cs | 114 +++++++++--------- .../AccessSheetUsingCodeNameQuickFixTests.cs | 2 +- ...plicationWorksheetFunctionQuickFixTests.cs | 2 +- .../ExpandBangNotationQuickFixTests.cs | 4 +- .../ExpandDefaultMemberQuickFixTests.cs | 6 +- .../QuickFixes/IgnoreOnceQuickFixTests.cs | 6 +- ...ingOnInappropriateArgumentQuickFixTests.cs | 2 +- .../UntypedFunctionUsageQuickFixTests.cs | 2 +- ...KeywordForObjectAssignmentQuickFixTests.cs | 2 +- .../Refactoring/MoveCloserToUsageTests.cs | 2 +- .../Refactoring/Rename/RenameTests.cs | 4 +- .../Symbols/DeclarationFinderTests.cs | 2 +- .../SelectedDeclarationProviderTests.cs | 2 +- 34 files changed, 193 insertions(+), 163 deletions(-) diff --git a/RubberduckTests/Grammar/ResolverTests.cs b/RubberduckTests/Grammar/ResolverTests.cs index 93ffc0b61a..6e5da78a69 100644 --- a/RubberduckTests/Grammar/ResolverTests.cs +++ b/RubberduckTests/Grammar/ResolverTests.cs @@ -6820,7 +6820,7 @@ End Function .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Class1", ComponentType.ClassModule, classCode) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) + .AddReference(ReferenceLibrary.VBA) .AddProjectToVbeBuilder() .Build(); @@ -6853,7 +6853,7 @@ End Function .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Class1", ComponentType.ClassModule, classCode) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) + .AddReference(ReferenceLibrary.VBA) .AddProjectToVbeBuilder() .Build(); @@ -6890,7 +6890,7 @@ End Function .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Class1", ComponentType.ClassModule, classCode) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) + .AddReference(ReferenceLibrary.VBA) .AddProjectToVbeBuilder() .Build(); @@ -6927,7 +6927,7 @@ End Function .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Class1", ComponentType.ClassModule, classCode) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) + .AddReference(ReferenceLibrary.VBA) .AddProjectToVbeBuilder() .Build(); @@ -6964,7 +6964,7 @@ End Function .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Class1", ComponentType.ClassModule, classCode) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) + .AddReference(ReferenceLibrary.VBA) .AddProjectToVbeBuilder() .Build(); diff --git a/RubberduckTests/Inspections/ApplicationWorksheetFunctionInspectionTests.cs b/RubberduckTests/Inspections/ApplicationWorksheetFunctionInspectionTests.cs index c934bedda0..b49b2ddf57 100644 --- a/RubberduckTests/Inspections/ApplicationWorksheetFunctionInspectionTests.cs +++ b/RubberduckTests/Inspections/ApplicationWorksheetFunctionInspectionTests.cs @@ -5,6 +5,7 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; +using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -12,7 +13,7 @@ namespace RubberduckTests.Inspections public class ApplicationWorksheetFunctionInspectionTests : InspectionTestsBase { private IEnumerable GetInspectionResultsUsingExcelLibrary(string inputCode) - => InspectionResultsForModules(("Module1", inputCode, ComponentType.StandardModule), "Excel"); + => InspectionResultsForModules(("Module1", inputCode, ComponentType.StandardModule), ReferenceLibrary.Excel); [Test] [Category("Inspections")] diff --git a/RubberduckTests/Inspections/ExcelMemberMayReturnNothingInspectionTests.cs b/RubberduckTests/Inspections/ExcelMemberMayReturnNothingInspectionTests.cs index e2125bee83..eb38da4a52 100644 --- a/RubberduckTests/Inspections/ExcelMemberMayReturnNothingInspectionTests.cs +++ b/RubberduckTests/Inspections/ExcelMemberMayReturnNothingInspectionTests.cs @@ -5,6 +5,7 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; +using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -348,7 +349,7 @@ End Sub } private IEnumerable InspectionResults(string inputCode) - => InspectionResultsForModules(("Module1", inputCode, ComponentType.StandardModule), "Excel"); + => InspectionResultsForModules(("Module1", inputCode, ComponentType.StandardModule), ReferenceLibrary.Excel); protected override IInspection InspectionUnderTest(RubberduckParserState state) { diff --git a/RubberduckTests/Inspections/ExcelUdfNameIsValidCellReferenceInspectionTests.cs b/RubberduckTests/Inspections/ExcelUdfNameIsValidCellReferenceInspectionTests.cs index c9749eb7df..3f6ee64ec3 100644 --- a/RubberduckTests/Inspections/ExcelUdfNameIsValidCellReferenceInspectionTests.cs +++ b/RubberduckTests/Inspections/ExcelUdfNameIsValidCellReferenceInspectionTests.cs @@ -4,6 +4,7 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; +using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -106,7 +107,7 @@ public void ExcelUdfNameIsValidCellReferenceInspection_ReturnsNoResult_NonFuncti } private int InspectionResultCount(string inputCode, ComponentType moduleType) - => InspectionResultsForModules(("UnderTest", inputCode, moduleType), "Excel").Count(); + => InspectionResultsForModules(("UnderTest", inputCode, moduleType), ReferenceLibrary.Excel).Count(); protected override IInspection InspectionUnderTest(RubberduckParserState state) { diff --git a/RubberduckTests/Inspections/HostSpecificExpressionInspectionTests.cs b/RubberduckTests/Inspections/HostSpecificExpressionInspectionTests.cs index 379e39a2c9..12b8085f11 100644 --- a/RubberduckTests/Inspections/HostSpecificExpressionInspectionTests.cs +++ b/RubberduckTests/Inspections/HostSpecificExpressionInspectionTests.cs @@ -22,7 +22,7 @@ Public Sub DoSomething() [A1] = 42 End Sub "; - var vbe = MockVbeBuilder.BuildFromModules(("Module1", code, ComponentType.StandardModule), new string[] { "VBA", "Excel" }); + var vbe = MockVbeBuilder.BuildFromModules(("Module1", code, ComponentType.StandardModule), new ReferenceLibrary[] { ReferenceLibrary.VBA, ReferenceLibrary.Excel }); var mockHost = new Mock(); mockHost.SetupGet(m => m.ApplicationName).Returns("Excel"); vbe.Setup(m => m.HostApplication()).Returns(() => mockHost.Object); diff --git a/RubberduckTests/Inspections/ImplicitActiveSheetReferenceInspectionTests.cs b/RubberduckTests/Inspections/ImplicitActiveSheetReferenceInspectionTests.cs index 04d5d5ccf5..acc57a05df 100644 --- a/RubberduckTests/Inspections/ImplicitActiveSheetReferenceInspectionTests.cs +++ b/RubberduckTests/Inspections/ImplicitActiveSheetReferenceInspectionTests.cs @@ -4,6 +4,7 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; +using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -21,7 +22,7 @@ Dim arr1() As Variant End Sub "; var modules = new(string, string, ComponentType)[] { ("Class1", inputCode, ComponentType.ClassModule) }; - Assert.AreEqual(1, InspectionResultsForModules(modules, "Excel").Count()); + Assert.AreEqual(1, InspectionResultsForModules(modules, ReferenceLibrary.Excel).Count()); } [Test] @@ -35,7 +36,7 @@ Dim arr1() As Variant End Sub "; var modules = new (string, string, ComponentType)[] { ("Class1", inputCode, ComponentType.ClassModule) }; - Assert.AreEqual(1, InspectionResultsForModules(modules, "Excel").Count()); + Assert.AreEqual(1, InspectionResultsForModules(modules, ReferenceLibrary.Excel).Count()); } [Test] @@ -49,7 +50,7 @@ Dim arr1() As Variant End Sub "; var modules = new (string, string, ComponentType)[] { ("Class1", inputCode, ComponentType.ClassModule) }; - Assert.AreEqual(1, InspectionResultsForModules(modules, "Excel").Count()); + Assert.AreEqual(1, InspectionResultsForModules(modules, ReferenceLibrary.Excel).Count()); } [Test] @@ -63,7 +64,7 @@ Dim arr1() As Variant End Sub "; var modules = new (string, string, ComponentType)[] { ("Class1", inputCode, ComponentType.ClassModule) }; - Assert.AreEqual(1, InspectionResultsForModules(modules, "Excel").Count()); + Assert.AreEqual(1, InspectionResultsForModules(modules, ReferenceLibrary.Excel).Count()); } [Test] @@ -80,7 +81,7 @@ End Sub "; var modules = new(string, string, ComponentType)[] { ("Class1", inputCode, ComponentType.ClassModule) }; - Assert.AreEqual(0, InspectionResultsForModules(modules, "Excel").Count()); + Assert.AreEqual(0, InspectionResultsForModules(modules, ReferenceLibrary.Excel).Count()); } [Test] diff --git a/RubberduckTests/Inspections/ImplicitActiveWorkbookReferenceInspectionTests.cs b/RubberduckTests/Inspections/ImplicitActiveWorkbookReferenceInspectionTests.cs index b29263d3d0..12fca8fe76 100644 --- a/RubberduckTests/Inspections/ImplicitActiveWorkbookReferenceInspectionTests.cs +++ b/RubberduckTests/Inspections/ImplicitActiveWorkbookReferenceInspectionTests.cs @@ -4,6 +4,7 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; +using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -181,7 +182,7 @@ Dim sheet As Worksheet private int ArrangeAndGetInspectionCount(string code) { var modules = new(string, string, ComponentType)[] { ("Module1", code, ComponentType.StandardModule) }; - return InspectionResultsForModules(modules, "Excel").Count(); + return InspectionResultsForModules(modules, ReferenceLibrary.Excel).Count(); } [Test] diff --git a/RubberduckTests/Inspections/InspectionTestsBase.cs b/RubberduckTests/Inspections/InspectionTestsBase.cs index 32b70660d9..4ada1584d3 100644 --- a/RubberduckTests/Inspections/InspectionTestsBase.cs +++ b/RubberduckTests/Inspections/InspectionTestsBase.cs @@ -30,13 +30,13 @@ public IEnumerable InspectionResultsForModules(IEnumerable<(s return InspectionResults(vbe); } - public IEnumerable InspectionResultsForModules((string name, string content, ComponentType componentType) module, params string[] libraries) + public IEnumerable InspectionResultsForModules((string name, string content, ComponentType componentType) module, params ReferenceLibrary[] libraries) => InspectionResultsForModules(new (string, string, ComponentType)[] { module }, libraries); - public IEnumerable InspectionResultsForModules(IEnumerable<(string name, string content, ComponentType componentType)> modules, string library) - => InspectionResultsForModules(modules, new string[] { library }); + public IEnumerable InspectionResultsForModules(IEnumerable<(string name, string content, ComponentType componentType)> modules, ReferenceLibrary library) + => InspectionResultsForModules(modules, new ReferenceLibrary[] { library }); - public IEnumerable InspectionResultsForModules(IEnumerable<(string name, string content, ComponentType componentType)> modules, IEnumerable libraries) + public IEnumerable InspectionResultsForModules(IEnumerable<(string name, string content, ComponentType componentType)> modules, IEnumerable libraries) { var vbe = MockVbeBuilder.BuildFromModules(modules, libraries).Object; return InspectionResults(vbe); diff --git a/RubberduckTests/Inspections/IsMissingOnInappropriateArgumentInspectionTests.cs b/RubberduckTests/Inspections/IsMissingOnInappropriateArgumentInspectionTests.cs index 127b904610..cb597699cf 100644 --- a/RubberduckTests/Inspections/IsMissingOnInappropriateArgumentInspectionTests.cs +++ b/RubberduckTests/Inspections/IsMissingOnInappropriateArgumentInspectionTests.cs @@ -4,6 +4,7 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; +using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -208,7 +209,7 @@ private int ArrangeAndGetInspectionCount(string code) ("Module1", code, ComponentType.StandardModule) }; - return InspectionResultsForModules(modules, "VBA").Count(); + return InspectionResultsForModules(modules, ReferenceLibrary.VBA).Count(); } protected override IInspection InspectionUnderTest(RubberduckParserState state) diff --git a/RubberduckTests/Inspections/IsMissingWithNonArgumentParameterInspectionTests.cs b/RubberduckTests/Inspections/IsMissingWithNonArgumentParameterInspectionTests.cs index 78d588e0ac..eceaa31520 100644 --- a/RubberduckTests/Inspections/IsMissingWithNonArgumentParameterInspectionTests.cs +++ b/RubberduckTests/Inspections/IsMissingWithNonArgumentParameterInspectionTests.cs @@ -4,6 +4,7 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; +using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -130,7 +131,7 @@ private int ArrangeAndGetInspectionCount(string code) ("Module1", code, ComponentType.StandardModule) }; - return InspectionResultsForModules(modules, "VBA").Count(); + return InspectionResultsForModules(modules, ReferenceLibrary.VBA).Count(); } protected override IInspection InspectionUnderTest(RubberduckParserState state) diff --git a/RubberduckTests/Inspections/MemberNotOnInterfaceInspectionTests.cs b/RubberduckTests/Inspections/MemberNotOnInterfaceInspectionTests.cs index 9d9b3f7210..b65d589321 100644 --- a/RubberduckTests/Inspections/MemberNotOnInterfaceInspectionTests.cs +++ b/RubberduckTests/Inspections/MemberNotOnInterfaceInspectionTests.cs @@ -11,7 +11,7 @@ namespace RubberduckTests.Inspections [TestFixture] public class MemberNotOnInterfaceInspectionTests : InspectionTestsBase { - private int ArrangeParserAndGetResultCount(string inputCode, string library) + private int ArrangeParserAndGetResultCount(string inputCode, ReferenceLibrary library = ReferenceLibrary.Scripting) => InspectionResultsForModules(("Codez", inputCode, ComponentType.StandardModule), library).Count(); [Test] @@ -24,7 +24,7 @@ Dim dict As Dictionary Set dict = New Dictionary dict.NonMember End Sub"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -37,7 +37,7 @@ Dim dict As Dictionary Set dict = New Dictionary dict.NonMember End Sub"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -48,7 +48,7 @@ public void MemberNotOnInterface_ReturnsResult_ApplicationObject() @"Sub Foo() Application.NonMember End Sub"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Excel")); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, ReferenceLibrary.Excel)); } [Test] @@ -59,7 +59,7 @@ public void MemberNotOnInterface_ReturnsResult_UnDeclaredMemberOnParameter() @"Sub Foo(dict As Dictionary) dict.NonMember End Sub"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -72,7 +72,7 @@ Dim dict As Dictionary Set dict = New Dictionary Debug.Print dict.Count End Sub"; - Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -84,7 +84,7 @@ public void MemberNotOnInterface_DoesNotReturnResult_NonExtensible() Dim x As File Debug.Print x.NonMember End Sub"; - Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -98,7 +98,7 @@ With dict .NonMember End With End Sub"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -111,7 +111,7 @@ Dim dict As Dictionary Set dict = New Dictionary dict!SomeIdentifier = 42 End Sub"; - Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -125,7 +125,7 @@ With dict !SomeIdentifier = 42 End With End Sub"; - Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -136,7 +136,7 @@ public void MemberNotOnInterface_DoesNotReturnResult_ProjectReference() @"Sub Foo() Dim dict As Scripting.Dictionary End Sub"; - Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -150,7 +150,7 @@ Dim dict As Dictionary '@Ignore MemberNotOnInterface dict.NonMember End Sub"; - Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -163,7 +163,7 @@ With New Dictionary .FooBar End With End Sub"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -180,7 +180,7 @@ End Sub Private Sub Bar(baz As Long) End Sub"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -197,7 +197,7 @@ End Sub Private Function Bar(baz As Long) As Variant End Function"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -214,7 +214,7 @@ End Sub Private Function Bar(baz As Long) As Variant End Function"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -231,7 +231,7 @@ End Sub Private Function Bar(baz As Long) As Variant End Function"; - Assert.AreEqual(2, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(2, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -248,7 +248,7 @@ End Sub Private Function Bar(baz As Long) As Variant End Function"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -265,7 +265,7 @@ End Sub Private Function Bar(baz As Long) As Variant End Function"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -282,7 +282,7 @@ End Sub Private Function Bar(baz As Long) As Variant End Function"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -299,7 +299,7 @@ End Sub Private Function Bar(baz As Long) As Variant End Function"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -319,7 +319,7 @@ End Function Private Sub Barr(baz As Long) End Sub"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -339,7 +339,7 @@ End Function Private Sub Barr(baz As Long) End Sub"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -359,7 +359,7 @@ End Function Private Sub Barr(baz As Long) End Sub"; - Assert.AreEqual(3, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(3, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -379,7 +379,7 @@ End Function Private Sub Barr(baz As Long) End Sub"; - Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(1, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -392,7 +392,7 @@ With New Dictionary !FooBar = 42 End With End Sub"; - Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -405,7 +405,7 @@ With New Dictionary .Add 42, 42 End With End Sub"; - Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode, "Scripting")); + Assert.AreEqual(0, ArrangeParserAndGetResultCount(inputCode)); } [Test] @@ -443,7 +443,7 @@ End Sub var projectBuilder = vbeBuilder.ProjectBuilder("testproject", ProjectProtection.Unprotected); projectBuilder.MockUserFormBuilder("UserForm1", userForm1Code).AddFormToProjectBuilder() .AddComponent("ReferencingModule", ComponentType.StandardModule, analyzedCode) - .AddReference("MSForms", MockVbeBuilder.LibraryPathMsForms, 2, 0, true); + .AddReference(ReferenceLibrary.MsForms); vbeBuilder.AddProject(projectBuilder.Build()); var vbe = vbeBuilder.Build(); @@ -464,7 +464,7 @@ Debug.Print bar.Left var vbeBuilder = new MockVbeBuilder(); var projectBuilder = vbeBuilder.ProjectBuilder("testproject", ProjectProtection.Unprotected); projectBuilder.MockUserFormBuilder("UserForm1", inputCode).AddFormToProjectBuilder() - .AddReference("MSForms", MockVbeBuilder.LibraryPathMsForms, 2, 0, true); + .AddReference(ReferenceLibrary.MsForms); vbeBuilder.AddProject(projectBuilder.Build()); var vbe = vbeBuilder.Build(); diff --git a/RubberduckTests/Inspections/ObjectVariableNotSetInspectionTests.cs b/RubberduckTests/Inspections/ObjectVariableNotSetInspectionTests.cs index 7213b63a23..5bc572eea7 100644 --- a/RubberduckTests/Inspections/ObjectVariableNotSetInspectionTests.cs +++ b/RubberduckTests/Inspections/ObjectVariableNotSetInspectionTests.cs @@ -5,6 +5,7 @@ using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor; using Rubberduck.VBEditor.SafeComWrappers; +using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -140,7 +141,7 @@ Dim target As String target = Range(""A1"") target.Value = ""all good"" End Sub"; - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "Excel"); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.Excel); } [Test] @@ -156,7 +157,7 @@ Dim target As Collection testParam = target testParam.Add 100 End Sub"; - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "VBA"); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.VBA); } [Test] @@ -192,7 +193,7 @@ public void ObjectVariableNotSet_GivenVariantVariableAssignedNewObject_ReturnsRe Private Sub TestSub(ByRef testParam As Variant) testParam = New Collection End Sub"; - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "VBA"); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.VBA); } [Test] @@ -225,7 +226,7 @@ Dim target As Range target.Value = ""forgot something?"" End Sub"; - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "Excel"); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.Excel); } [Test] @@ -243,7 +244,7 @@ Dim target As Range target.Value = ""All good"" End Sub"; - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "Excel"); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.Excel); } [Test] @@ -285,7 +286,7 @@ Private Sub TestSelfAssigned() Dim arg1 As new Collection arg1.Add 7 End Sub"; - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "VBA"); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.VBA); } [Test] @@ -342,7 +343,7 @@ public void ObjectVariableNotSet_FunctionReturnNotSet_ReturnsResult() Private Function Test() As Collection Test = New Collection End Function"; - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "VBA"); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.VBA); } [Test] @@ -493,7 +494,7 @@ Dim bar As Collection bar.Add ""x"", ""x"" foo = ""Test"" & bar.Item(""x"") End Sub"; - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "VBA"); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.VBA); } [Test] @@ -527,7 +528,7 @@ Dim foo As Range Dim bar As Variant bar = foo End Sub"; - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "Excel"); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.Excel); } [Test] @@ -543,7 +544,7 @@ Dim bar As Variant bar = foo End Sub"; //The default member of Recordset is Fields, which is an object. - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "ADODB"); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.AdoDb); } [Test] @@ -559,7 +560,7 @@ Dim bar As Variant foo = bar End Sub"; //The default member of Recordset is Fields, which is an object and only has a paramterized default member. - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "ADODB"); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.AdoDb); } [Test] @@ -573,7 +574,7 @@ Private Sub Test() Dim foo As Variant foo = New Connection End Sub"; - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "ADODB"); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.AdoDb); } [Test] @@ -588,7 +589,7 @@ Dim foo As Variant foo = New Recordset End Sub"; //The default member of Recordset is Fields, which is an object. - AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, "ADODB"); + AssertInputCodeYieldsExpectedInspectionResultCount(input, expectResultCount, ReferenceLibrary.AdoDb); } [Test] @@ -1410,7 +1411,7 @@ protected override IInspection InspectionUnderTest(RubberduckParserState state) return new ObjectVariableNotSetInspection(state); } - private void AssertInputCodeYieldsExpectedInspectionResultCount(string inputCode, int expected, params string[] testLibraries) + private void AssertInputCodeYieldsExpectedInspectionResultCount(string inputCode, int expected, params ReferenceLibrary[] testLibraries) { var inspectionResults = InspectionResultsForModules(("Class1", inputCode, ComponentType.ClassModule), testLibraries); Assert.AreEqual(expected, inspectionResults.Count()); diff --git a/RubberduckTests/Inspections/ParameterNotUsedInspectionTests.cs b/RubberduckTests/Inspections/ParameterNotUsedInspectionTests.cs index 02f950e91b..2bb26ec277 100644 --- a/RubberduckTests/Inspections/ParameterNotUsedInspectionTests.cs +++ b/RubberduckTests/Inspections/ParameterNotUsedInspectionTests.cs @@ -4,6 +4,7 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; +using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -74,7 +75,7 @@ Debug.Print rst(""Field"") ("Module1", inputCode, ComponentType.StandardModule), }; - Assert.AreEqual(0, InspectionResultsForModules(modules, "ADODB").Count()); + Assert.AreEqual(0, InspectionResultsForModules(modules, ReferenceLibrary.AdoDb).Count()); } [Test] diff --git a/RubberduckTests/Inspections/ShadowedDeclarationInspectionTests.cs b/RubberduckTests/Inspections/ShadowedDeclarationInspectionTests.cs index 45939d83a2..17182c2568 100644 --- a/RubberduckTests/Inspections/ShadowedDeclarationInspectionTests.cs +++ b/RubberduckTests/Inspections/ShadowedDeclarationInspectionTests.cs @@ -5127,7 +5127,7 @@ public void ShadowedDeclaration_DoesNotReturnResult_AssertBecauseOfDebugAssert(s var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("TestClass", ComponentType.ClassModule, code) - .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) + .AddReference(ReferenceLibrary.VBA) .AddProjectToVbeBuilder() .Build(); @@ -5153,7 +5153,7 @@ Dim Assert As Long var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("TestClass", ComponentType.ClassModule, code) - .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) + .AddReference(ReferenceLibrary.VBA) .AddProjectToVbeBuilder() .Build(); @@ -5178,7 +5178,7 @@ public void ShadowedDeclaration_DoesNotReturnResult_AssertParameterAssertBecause var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("TestClass", ComponentType.ClassModule, code) - .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) + .AddReference(ReferenceLibrary.VBA) .AddProjectToVbeBuilder() .Build(); @@ -5213,7 +5213,7 @@ Dim Assert As Long var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("TestClass", ComponentType.ClassModule, code) - .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) + .AddReference(ReferenceLibrary.VBA) .AddProjectToVbeBuilder() .Build(); @@ -5247,7 +5247,7 @@ Public Sub Foo(Assert As Boolean) var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("TestClass", ComponentType.ClassModule, code) - .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) + .AddReference(ReferenceLibrary.VBA) .AddProjectToVbeBuilder() .Build(); diff --git a/RubberduckTests/Inspections/SheetAccessedUsingStringInspectionTests.cs b/RubberduckTests/Inspections/SheetAccessedUsingStringInspectionTests.cs index 9b02593134..4b26ae6b41 100644 --- a/RubberduckTests/Inspections/SheetAccessedUsingStringInspectionTests.cs +++ b/RubberduckTests/Inspections/SheetAccessedUsingStringInspectionTests.cs @@ -194,7 +194,7 @@ private IEnumerable ArrangeParserAndGetResults(string inputCo CreateVBComponentPropertyMock("CodeName", "Sheet1").Object }) .AddReference("ReferencedProject", string.Empty, 0, 0) - .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) + .AddReference(ReferenceLibrary.Excel) .Build(); var vbe = builder.AddProject(referencedProject).AddProject(project).Build(); diff --git a/RubberduckTests/Inspections/UnassignedVariableUsageInspectionTests.cs b/RubberduckTests/Inspections/UnassignedVariableUsageInspectionTests.cs index 96e87cd41a..9d74b018b9 100644 --- a/RubberduckTests/Inspections/UnassignedVariableUsageInspectionTests.cs +++ b/RubberduckTests/Inspections/UnassignedVariableUsageInspectionTests.cs @@ -4,6 +4,7 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; +using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -303,7 +304,7 @@ Dim bar As Variant bar = Len(foo) End Sub "; - var inspectionResults = InspectionResultsForModules(("TestModule", code, ComponentType.StandardModule), "VBA"); + var inspectionResults = InspectionResultsForModules(("TestModule", code, ComponentType.StandardModule), ReferenceLibrary.VBA); Assert.AreEqual(0, inspectionResults.Count()); } @@ -318,7 +319,7 @@ Dim bar As Variant bar = LenB(foo) End Sub "; - var inspectionResults = InspectionResultsForModules(("TestModule", code, ComponentType.StandardModule), "VBA"); + var inspectionResults = InspectionResultsForModules(("TestModule", code, ComponentType.StandardModule), ReferenceLibrary.VBA); Assert.AreEqual(0, inspectionResults.Count()); } @@ -334,7 +335,7 @@ Dim bar As Variant bar = foo + 5 End Sub "; - var inspectionResults = InspectionResultsForModules(("TestModule", code, ComponentType.StandardModule), "VBA"); + var inspectionResults = InspectionResultsForModules(("TestModule", code, ComponentType.StandardModule), ReferenceLibrary.VBA); Assert.AreEqual(1, inspectionResults.Count()); } @@ -350,7 +351,7 @@ Dim bar As Variant bar = foo + 5 End Sub "; - var inspectionResults = InspectionResultsForModules(("TestModule", code, ComponentType.StandardModule), "VBA"); + var inspectionResults = InspectionResultsForModules(("TestModule", code, ComponentType.StandardModule), ReferenceLibrary.VBA); Assert.AreEqual(1, inspectionResults.Count()); } @@ -365,7 +366,7 @@ Dim bar As Variant bar = Len(foo + 5) End Sub "; - var inspectionResults = InspectionResultsForModules(("TestModule", code, ComponentType.StandardModule), "VBA"); + var inspectionResults = InspectionResultsForModules(("TestModule", code, ComponentType.StandardModule), ReferenceLibrary.VBA); Assert.AreEqual(1, inspectionResults.Count()); } @@ -380,7 +381,7 @@ Dim bar As Variant bar = LenB(foo + 5) End Sub "; - var inspectionResults = InspectionResultsForModules(("TestModule", code, ComponentType.StandardModule), "VBA"); + var inspectionResults = InspectionResultsForModules(("TestModule", code, ComponentType.StandardModule), ReferenceLibrary.VBA); Assert.AreEqual(1, inspectionResults.Count()); } diff --git a/RubberduckTests/Inspections/UndeclaredVariableInspectionTests.cs b/RubberduckTests/Inspections/UndeclaredVariableInspectionTests.cs index 560dbe93e7..5ddcab68d2 100644 --- a/RubberduckTests/Inspections/UndeclaredVariableInspectionTests.cs +++ b/RubberduckTests/Inspections/UndeclaredVariableInspectionTests.cs @@ -4,6 +4,7 @@ using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; +using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -20,7 +21,7 @@ public void UndeclaredVariable_ReturnsResult() Debug.Print a End Sub"; - Assert.AreEqual(1, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), "VBA").Count()); + Assert.AreEqual(1, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), ReferenceLibrary.VBA).Count()); } [Test] @@ -34,7 +35,7 @@ Dim a As Long Debug.Print a End Sub"; - Assert.AreEqual(0, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), "VBA").Count()); + Assert.AreEqual(0, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), ReferenceLibrary.VBA).Count()); } [Test] @@ -49,7 +50,7 @@ Sub Test() Debug.Print a End Sub"; - Assert.AreEqual(0, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), "VBA").Count()); + Assert.AreEqual(0, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), ReferenceLibrary.VBA).Count()); } [Test] @@ -81,7 +82,7 @@ public void UndeclaredVariable_ReturnsNoResultIfAnnotated() Debug.Print a End Sub"; - Assert.AreEqual(0, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), "VBA").Count()); + Assert.AreEqual(0, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), ReferenceLibrary.VBA).Count()); } [Test] diff --git a/RubberduckTests/Inspections/UntypedFunctionUsageInspectionTests.cs b/RubberduckTests/Inspections/UntypedFunctionUsageInspectionTests.cs index db1f13d4fd..472525837e 100644 --- a/RubberduckTests/Inspections/UntypedFunctionUsageInspectionTests.cs +++ b/RubberduckTests/Inspections/UntypedFunctionUsageInspectionTests.cs @@ -4,6 +4,7 @@ using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.Parsing.Inspections.Abstract; +using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -20,7 +21,7 @@ Dim str As String str = Left(""test"", 1) End Sub"; - Assert.AreEqual(1, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), "VBA").Count()); + Assert.AreEqual(1, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), ReferenceLibrary.VBA).Count()); } [Test] @@ -33,7 +34,7 @@ Dim str As String str = Left$(""test"", 1) End Sub"; - Assert.AreEqual(0, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), "VBA").Count()); + Assert.AreEqual(0, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), ReferenceLibrary.VBA).Count()); } [Test] @@ -48,7 +49,7 @@ Dim str As String str = Left(""test"", 1) End Sub"; - Assert.AreEqual(0, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), "VBA").Count()); + Assert.AreEqual(0, InspectionResultsForModules(("MyClass", inputCode, ComponentType.ClassModule), ReferenceLibrary.VBA).Count()); } [Test] diff --git a/RubberduckTests/Inspections/UseMeaningfulNameInspectionTests.cs b/RubberduckTests/Inspections/UseMeaningfulNameInspectionTests.cs index 0f9c4b7122..d495db90c0 100644 --- a/RubberduckTests/Inspections/UseMeaningfulNameInspectionTests.cs +++ b/RubberduckTests/Inspections/UseMeaningfulNameInspectionTests.cs @@ -161,7 +161,7 @@ internal static Mock> GetInspectio private IEnumerable InspectionResultsForModules(params (string name, string content, ComponentType componentType)[] modules) { - var vbe = MockVbeBuilder.BuildFromModules("TestProject", modules, Enumerable.Empty()); + var vbe = MockVbeBuilder.BuildFromModules("TestProject", modules, Enumerable.Empty()); return InspectionResults(vbe.Object); } diff --git a/RubberduckTests/Inspections/ValueRequiredInspectionTests.cs b/RubberduckTests/Inspections/ValueRequiredInspectionTests.cs index 18f35c3f36..92134ccf4f 100644 --- a/RubberduckTests/Inspections/ValueRequiredInspectionTests.cs +++ b/RubberduckTests/Inspections/ValueRequiredInspectionTests.cs @@ -4,6 +4,7 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; +using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -382,7 +383,7 @@ End Function ("Module1", moduleCode, ComponentType.StandardModule), }; - Assert.IsFalse(InspectionResultsForModules(modules, "VBA").Any()); + Assert.IsFalse(InspectionResultsForModules(modules, ReferenceLibrary.VBA).Any()); } protected override IInspection InspectionUnderTest(RubberduckParserState state) diff --git a/RubberduckTests/Mocks/MockProjectBuilder.cs b/RubberduckTests/Mocks/MockProjectBuilder.cs index 30ab100eb9..8ef17772b4 100644 --- a/RubberduckTests/Mocks/MockProjectBuilder.cs +++ b/RubberduckTests/Mocks/MockProjectBuilder.cs @@ -43,7 +43,7 @@ public void RemoveComponent(Mock component) } public MockProjectBuilder(string name, string filename, ProjectProtection protection, ProjectType projectType, Func getVbe, MockVbeBuilder mockVbeBuilder) - :this( + : this( name, filename, Guid.NewGuid().ToString(), @@ -104,6 +104,17 @@ public MockProjectBuilder AddComponent(Mock component, Mock + /// Adds a mock reference to the project. + /// + /// The reference library's enum. + /// Returns the instance. + public MockProjectBuilder AddReference(ReferenceLibrary referenceLibrary) + { + var (name, path, versionMajor, versionMinor, isBuiltIn) = MockVbeBuilder.ReferenceLibraries[referenceLibrary]; + return AddReference(name, path, versionMajor, versionMinor, isBuiltIn); + } + /// /// Adds a mock reference to the project. /// @@ -191,7 +202,7 @@ private Mock CreateComponentsMock() result.Setup(m => m[It.IsAny()]).Returns(index => Components.ElementAt(index)); result.Setup(m => m[It.IsAny()]).Returns(name => Components.Single(item => item.Name == name)); result.SetupGet(m => m.Count).Returns(() => Components.Count); - + result.Setup(m => m.Add(It.IsAny())) .Callback((ComponentType c) => { @@ -272,7 +283,7 @@ public Mock CreateReferenceMock(string name, string filePath, int ma return result; } - private Mock CreateComponentMock(string name, ComponentType type, string content, Selection selection, + private Mock CreateComponentMock(string name, ComponentType type, string content, Selection selection, IEnumerable properties, out Mock moduleMock) { var result = new Mock(); @@ -356,7 +367,7 @@ private Mock CreateCodeModuleMock(string content) codeModule.Setup(m => m.GetLines(It.IsAny())) .Returns((Selection selection) => string.Join(Environment.NewLine, lines.Skip(selection.StartLine - 1).Take(selection.LineCount))); - + codeModule.Setup(m => m.GetLines(It.IsAny(), It.IsAny())) .Returns((start, count) => string.Join(Environment.NewLine, lines.Skip(start - 1).Take(count))); @@ -423,4 +434,4 @@ private Mock CreateCodePaneMock(string name, Selection selection, Moc return codePane; } } -} +} \ No newline at end of file diff --git a/RubberduckTests/Mocks/MockVbeBuilder.cs b/RubberduckTests/Mocks/MockVbeBuilder.cs index acad78aa93..a29ec5f9a3 100644 --- a/RubberduckTests/Mocks/MockVbeBuilder.cs +++ b/RubberduckTests/Mocks/MockVbeBuilder.cs @@ -1,4 +1,3 @@ -using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -11,6 +10,28 @@ namespace RubberduckTests.Mocks { + public enum ReferenceLibrary + { + VBA, + Excel, + MsOffice, + StdOle, + MsForms, + VBIDE, + Scripting, + Regex, + MsXml, + ShDoc, + AdoDb, + AdoRecordset, + } + + public static class ReferenceLibraryExtensions + { + public static string Name(this ReferenceLibrary val) => MockVbeBuilder.ReferenceLibraryIdentifiers[val].Name; + public static string Path(this ReferenceLibrary val) => MockVbeBuilder.ReferenceLibraryIdentifiers[val].Path; + } + /// /// Builds a mock . /// @@ -20,50 +41,34 @@ public class MockVbeBuilder public const string TestProjectName = "TestProject1"; public const string TestModuleName = "TestModule1"; private readonly Mock _vbe; - private readonly Mock _vbeEvents; - - #region standard library paths (referenced in all VBA projects hosted in Microsoft Excel) - public static readonly string LibraryPathVBA = @"C:\PROGRA~1\COMMON~1\MICROS~1\VBA\VBA7.1\VBE7.DLL"; // standard library, priority locked - public static readonly string LibraryPathMsExcel = @"C:\Program Files\Microsoft Office\Office15\EXCEL.EXE"; // mock host application, priority locked - public static readonly string LibraryPathMsOffice = @"C:\Program Files\Common Files\Microsoft Shared\OFFICE15\MSO.DLL"; - public static readonly string LibraryPathStdOle = @"C:\Windows\System32\stdole2.tlb"; - public static readonly string LibraryPathMsForms = @"C:\Windows\system32\FM20.DLL"; // standard in projects with a UserForm module - #endregion - - public static readonly string LibraryPathVBIDE = @"C:\Program Files (x86)\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.OLB"; - public static readonly string LibraryPathScripting = @"C:\Windows\System32\scrrun.dll"; - public static readonly string LibraryPathRegex = @"C:\Windows\System32\vbscript.dll\3"; - public static readonly string LibraryPathMsXml = @"C:\Windows\System32\msxml6.dll"; - public static readonly string LibraryPathShDoc = @"C:\Windows\System32\ieframe.dll"; - public static readonly string LibraryPathAdoDb = @"C:\Program Files\Common Files\System\ado\msado15.dll"; - public static readonly string LibraryPathAdoRecordset = @"C:\Program Files\Common Files\System\ado\msador15.dll"; - - public static readonly Dictionary LibraryPaths = new Dictionary + + public static Dictionary ReferenceLibraryIdentifiers = new Dictionary() { - ["VBA"] = LibraryPathVBA, - ["Excel"] = LibraryPathMsExcel, - ["Office"] = LibraryPathMsOffice, - ["stdole"] = LibraryPathStdOle, - ["MSForms"] = LibraryPathMsForms, - ["VBIDE"] = LibraryPathVBIDE, - ["Scripting"] = LibraryPathScripting, - ["VBScript_RegExp_55"] = LibraryPathRegex, - ["MSXML2"] = LibraryPathMsXml, - ["SHDocVw"] = LibraryPathShDoc, - ["ADODB"] = LibraryPathAdoDb, - ["ADOR"] = LibraryPathAdoRecordset + //standard library paths (referenced in all VBA projects hosted in Microsoft Excel) + [ReferenceLibrary.VBA] = ("VBA", @"C:\PROGRA~1\COMMON~1\MICROS~1\VBA\VBA7.1\VBE7.DLL"), //standard library, priority locked" + [ReferenceLibrary.Excel] = ("Excel", @"C:\Program Files\Microsoft Office\Office15\EXCEL.EXE"), // mock host application, priority locked + [ReferenceLibrary.MsOffice] = ("Office", @"C:\Program Files\Common Files\Microsoft Shared\OFFICE15\MSO.DLL"), + [ReferenceLibrary.StdOle] = ("stdole", @"C:\Windows\System32\stdole2.tlb"), + [ReferenceLibrary.MsForms] = ("MSForms", @"C:\Windows\system32\FM20.DLL"), // standard in projects with a UserForm module + //end standard library paths + [ReferenceLibrary.VBIDE] = ("VBIDE", @"C:\Program Files (x86)\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.OLB"), + [ReferenceLibrary.Scripting] = ("Scripting", @"C:\Windows\System32\scrrun.dll"), + [ReferenceLibrary.Regex] = ("VBScript_RegExp_55", @"C:\Windows\System32\vbscript.dll\3"), + [ReferenceLibrary.MsXml] = ("MSXML2", @"C:\Windows\System32\msxml6.dll"), + [ReferenceLibrary.ShDoc] = ("SHDocVw", @"C:\Windows\System32\ieframe.dll"), + [ReferenceLibrary.AdoDb] = ("ADODB", @"C:\Program Files\Common Files\System\ado\msado15.dll"), + [ReferenceLibrary.AdoRecordset] = ("ADOR", @"C:\Program Files\Common Files\System\ado\msador15.dll"), }; - private static readonly Dictionary> AddReference = new Dictionary> + internal static readonly Dictionary ReferenceLibraries = new Dictionary { - ["Excel"] = (MockProjectBuilder builder) => builder.AddReference("Excel", LibraryPathMsExcel, 1, 8, true), - ["VBA"] = (MockProjectBuilder builder) => builder.AddReference("VBA", LibraryPathVBA, 4, 2, true), - ["Scripting"] = (MockProjectBuilder builder) => builder.AddReference("Scripting", LibraryPathScripting, 1, 0, true), - ["ADODB"] = (MockProjectBuilder builder) => builder.AddReference("ADODB", LibraryPathAdoDb, 6, 1, false), - ["MSForms"] = (MockProjectBuilder builder) => builder.AddReference("MSForms", LibraryPathMsForms, 2, 0, true), + [ReferenceLibrary.VBA] = (ReferenceLibrary.VBA.Name(), ReferenceLibrary.VBA.Path(), 4, 2, true), + [ReferenceLibrary.Excel] = (ReferenceLibrary.Excel.Name(), ReferenceLibrary.Excel.Path(), 1, 8, true), + [ReferenceLibrary.Scripting] = (ReferenceLibrary.Scripting.Name(), ReferenceLibrary.Scripting.Path(), 1, 0, true), + [ReferenceLibrary.AdoDb] = (ReferenceLibrary.AdoDb.Name(), ReferenceLibrary.AdoDb.Path(), 6, 1, false), + [ReferenceLibrary.MsForms] = (ReferenceLibrary.MsForms.Name(), ReferenceLibrary.MsForms.Path(), 2, 0, true), }; - //private Mock _vbWindows; private readonly Windows _windows = new Windows(); private readonly ICollection _projects = new List(); @@ -160,7 +165,7 @@ public static Mock BuildFromSingleModule(string content, string name, Comp if (referenceStdLibs) { - builder.AddReference("VBA", LibraryPathVBA, 4, 2, true); + builder.AddReference(ReferenceLibrary.VBA); } var project = builder.Build(); @@ -194,24 +199,24 @@ public static Mock BuildFromModules(params (string name, string content, C /// Builds a mock VBE containing a single "TestProject1" with multiple modules. /// public static Mock BuildFromModules(IEnumerable<(string name, string content, ComponentType componentType)> modules) - => BuildFromModules(modules, Enumerable.Empty()); + => BuildFromModules(modules, Enumerable.Empty()); /// /// Builds a mock VBE containing a single "TestProject1" with one module and one or more libraries. /// - public static Mock BuildFromModules((string name, string content, ComponentType componentType) module, params string[] libraries) - => BuildFromModules(new (string, string, ComponentType)[] { module }, libraries); + public static Mock BuildFromModules((string name, string content, ComponentType componentType) module, params ReferenceLibrary[] libraries) + => BuildFromModules(new(string, string, ComponentType)[] { module }, libraries); /// /// Builds a mock VBE containing a single "TestProject1" with multiple modules and libraries. /// - public static Mock BuildFromModules(IEnumerable<(string name, string content, ComponentType componentType)> modules, IEnumerable libraryNames) - => BuildFromModules(TestProjectName, modules, libraryNames); + public static Mock BuildFromModules(IEnumerable<(string name, string content, ComponentType componentType)> modules, IEnumerable libraries) + => BuildFromModules(TestProjectName, modules, libraries); /// /// Builds a mock VBE containing one project with multiple modules and libraries. /// - public static Mock BuildFromModules(string projectName, IEnumerable<(string name, string content, ComponentType componentType)> modules, IEnumerable libraryNames) + public static Mock BuildFromModules(string projectName, IEnumerable<(string name, string content, ComponentType componentType)> modules, IEnumerable referenceLibraries) { var vbeBuilder = new MockVbeBuilder(); @@ -221,9 +226,10 @@ public static Mock BuildFromModules(string projectName, IEnumerable<(strin builder.AddComponent(name, componentType, content); } - foreach (var name in libraryNames) + foreach (var refLibrary in referenceLibraries) { - AddReference[name](builder); + var (name, path, versionMajor, versionMinor, isBuiltIn) = ReferenceLibraries[refLibrary]; + builder.AddReference(name, path, versionMajor, versionMinor, isBuiltIn); } var project = builder.Build(); @@ -263,7 +269,7 @@ private Mock CreateVbeMock() vbe.Setup(m => m.Windows).Returns(() => _windows); vbe.SetupProperty(m => m.ActiveCodePane); vbe.SetupProperty(m => m.ActiveVBProject); - + vbe.SetupGet(m => m.SelectedVBComponent).Returns(() => vbe.Object.ActiveCodePane?.CodeModule?.Parent); vbe.Setup(m => m.GetActiveSelection()).Returns(() => vbe.Object.ActiveCodePane?.GetQualifiedSelection()); vbe.SetupGet(m => m.ActiveWindow).Returns(() => vbe.Object.ActiveCodePane.Window); @@ -289,8 +295,8 @@ private Mock CreateVbeMock() private static ICommandBars DummyCommandBars() { - var commandBars = new Mock(); - + var commandBars = new Mock(); + var dummyCommandBar = DummyCommandBar(); commandBars.SetupGet(m => m[It.IsAny()]).Returns(dummyCommandBar); @@ -333,7 +339,7 @@ private Mock CreateProjectsMock() result.Setup(m => m.GetEnumerator()).Returns(() => _projects.GetEnumerator()); result.As().Setup(m => m.GetEnumerator()).Returns(() => _projects.GetEnumerator()); - + result.Setup(m => m[It.IsAny()]).Returns(value => _projects.ElementAt(value)); result.SetupGet(m => m.Count).Returns(() => _projects.Count); @@ -370,7 +376,7 @@ private Mock CreateCodePanesMock() result.Setup(m => m.GetEnumerator()).Returns(() => _codePanes.GetEnumerator()); result.As().Setup(m => m.GetEnumerator()).Returns(() => _codePanes.GetEnumerator()); - + result.Setup(m => m[It.IsAny()]).Returns(value => _codePanes.ElementAt(value)); result.SetupGet(m => m.Count).Returns(() => _codePanes.Count); @@ -379,4 +385,4 @@ private Mock CreateCodePanesMock() public Mock MockProjectsCollection { get; private set; } } -} +} \ No newline at end of file diff --git a/RubberduckTests/QuickFixes/AccessSheetUsingCodeNameQuickFixTests.cs b/RubberduckTests/QuickFixes/AccessSheetUsingCodeNameQuickFixTests.cs index b1cc1701b3..00edeb3f5f 100644 --- a/RubberduckTests/QuickFixes/AccessSheetUsingCodeNameQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/AccessSheetUsingCodeNameQuickFixTests.cs @@ -207,7 +207,7 @@ protected override IVBE TestVbe(string code, out IVBComponent component) CreateVBComponentPropertyMock("Name", "Name").Object, CreateVBComponentPropertyMock("CodeName", "CodeName").Object }) - .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) + .AddReference(ReferenceLibrary.Excel) .Build(); component = project.Object.VBComponents[0]; diff --git a/RubberduckTests/QuickFixes/ApplicationWorksheetFunctionQuickFixTests.cs b/RubberduckTests/QuickFixes/ApplicationWorksheetFunctionQuickFixTests.cs index d005c6a09c..f7ff8c175d 100644 --- a/RubberduckTests/QuickFixes/ApplicationWorksheetFunctionQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ApplicationWorksheetFunctionQuickFixTests.cs @@ -93,7 +93,7 @@ protected override IVBE TestVbe(string code, out IVBComponent component) var builder = new MockVbeBuilder(); var project = builder.ProjectBuilder("VBAProject", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, code) - .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) + .AddReference(ReferenceLibrary.Excel) .Build(); var vbe = builder.AddProject(project).Build().Object; diff --git a/RubberduckTests/QuickFixes/ExpandBangNotationQuickFixTests.cs b/RubberduckTests/QuickFixes/ExpandBangNotationQuickFixTests.cs index f94feb9399..25103f5f24 100644 --- a/RubberduckTests/QuickFixes/ExpandBangNotationQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ExpandBangNotationQuickFixTests.cs @@ -193,7 +193,7 @@ End Sub var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) + .AddReference(ReferenceLibrary.Excel) .AddProjectToVbeBuilder() .Build(); @@ -224,7 +224,7 @@ End Sub var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) + .AddReference(ReferenceLibrary.Excel) .AddProjectToVbeBuilder() .Build(); diff --git a/RubberduckTests/QuickFixes/ExpandDefaultMemberQuickFixTests.cs b/RubberduckTests/QuickFixes/ExpandDefaultMemberQuickFixTests.cs index 309a9ca5d6..4668bebe40 100644 --- a/RubberduckTests/QuickFixes/ExpandDefaultMemberQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ExpandDefaultMemberQuickFixTests.cs @@ -667,7 +667,7 @@ End Sub var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) + .AddReference(ReferenceLibrary.Excel) .AddProjectToVbeBuilder() .Build(); @@ -700,7 +700,7 @@ End Sub var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) + .AddReference(ReferenceLibrary.Excel) .AddProjectToVbeBuilder() .Build(); @@ -731,7 +731,7 @@ End Sub var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, moduleCode) - .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) + .AddReference(ReferenceLibrary.Excel) .AddProjectToVbeBuilder() .Build(); diff --git a/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs b/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs index 01771d522e..13a1fdf2b3 100644 --- a/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs @@ -738,7 +738,7 @@ Dim str As String var builder = new MockVbeBuilder(); var project = builder.ProjectBuilder("VBAProject", ProjectProtection.Unprotected) .AddComponent("MyClass", ComponentType.ClassModule, inputCode) - .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) + .AddReference(ReferenceLibrary.VBA) .Build(); var vbe = builder.AddProject(project).Build(); @@ -1152,7 +1152,7 @@ private IEnumerable InspectionResults(IInspection inspection, var builder = new MockVbeBuilder(); var project = builder.ProjectBuilder("TestProject1", "TestProject1", ProjectProtection.Unprotected) .AddComponent("Class1", ComponentType.ClassModule, inputCode) - .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) + .AddReference(ReferenceLibrary.Excel) .Build(); var component = project.Object.VBComponents[0]; var vbe = builder.AddProject(project).Build(); @@ -1165,7 +1165,7 @@ private IEnumerable InspectionResults(IInspection inspection, var builder = new MockVbeBuilder(); var project = builder.ProjectBuilder("VBAProject", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, inputCode) - .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) + .AddReference(ReferenceLibrary.Excel) .Build(); var vbe = builder.AddProject(project).Build(); diff --git a/RubberduckTests/QuickFixes/IsMissingOnInappropriateArgumentQuickFixTests.cs b/RubberduckTests/QuickFixes/IsMissingOnInappropriateArgumentQuickFixTests.cs index d65dfb22ef..c0fd3ad76d 100644 --- a/RubberduckTests/QuickFixes/IsMissingOnInappropriateArgumentQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/IsMissingOnInappropriateArgumentQuickFixTests.cs @@ -448,7 +448,7 @@ protected override IVBE TestVbe(string code, out IVBComponent component) var builder = new MockVbeBuilder(); var project = builder.ProjectBuilder("TestProject1", "TestProject1", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, code) - .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) + .AddReference(ReferenceLibrary.VBA) .Build(); var vbe = builder.AddProject(project).Build(); component = project.Object.VBComponents.First(); diff --git a/RubberduckTests/QuickFixes/UntypedFunctionUsageQuickFixTests.cs b/RubberduckTests/QuickFixes/UntypedFunctionUsageQuickFixTests.cs index 6a73594103..f1cfe72333 100644 --- a/RubberduckTests/QuickFixes/UntypedFunctionUsageQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/UntypedFunctionUsageQuickFixTests.cs @@ -33,7 +33,7 @@ Dim str As String var builder = new MockVbeBuilder(); var project = builder.ProjectBuilder("VBAProject", ProjectProtection.Unprotected) .AddComponent("MyClass", ComponentType.ClassModule, inputCode) - .AddReference("VBA", MockVbeBuilder.LibraryPathVBA, 4, 2, true) + .AddReference(ReferenceLibrary.VBA) .Build(); var vbe = builder.AddProject(project).Build(); diff --git a/RubberduckTests/QuickFixes/UseSetKeywordForObjectAssignmentQuickFixTests.cs b/RubberduckTests/QuickFixes/UseSetKeywordForObjectAssignmentQuickFixTests.cs index 8398e54891..82568fad75 100644 --- a/RubberduckTests/QuickFixes/UseSetKeywordForObjectAssignmentQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/UseSetKeywordForObjectAssignmentQuickFixTests.cs @@ -149,7 +149,7 @@ protected override IVBE TestVbe(string code, out IVBComponent component) var builder = new MockVbeBuilder(); var project = builder.ProjectBuilder("VBAProject", ProjectProtection.Unprotected) .AddComponent("Module1", ComponentType.StandardModule, code) - .AddReference("Excel", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) + .AddReference(ReferenceLibrary.Excel) .Build(); var vbe = builder.AddProject(project).Build().Object; diff --git a/RubberduckTests/Refactoring/MoveCloserToUsageTests.cs b/RubberduckTests/Refactoring/MoveCloserToUsageTests.cs index 53b09e1643..6de5d2ddb2 100644 --- a/RubberduckTests/Refactoring/MoveCloserToUsageTests.cs +++ b/RubberduckTests/Refactoring/MoveCloserToUsageTests.cs @@ -824,7 +824,7 @@ Dim baz As Excel.Range var vbe = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Module", ComponentType.StandardModule, inputCode) - .AddReference("EXCEL", MockVbeBuilder.LibraryPathMsExcel, 1, 8, true) + .AddReference(ReferenceLibrary.Excel) .AddProjectToVbeBuilder() .Build() .Object; diff --git a/RubberduckTests/Refactoring/Rename/RenameTests.cs b/RubberduckTests/Refactoring/Rename/RenameTests.cs index 2547b18287..02701260b9 100644 --- a/RubberduckTests/Refactoring/Rename/RenameTests.cs +++ b/RubberduckTests/Refactoring/Rename/RenameTests.cs @@ -3205,8 +3205,8 @@ private static IVBE BuildProject(string projectName, IEnumerable Date: Sun, 2 Feb 2020 20:18:13 +0100 Subject: [PATCH 210/461] revert codecov bash uploader introduction This should improve build stability by eliminating a point of failure with the download of the coverage uploader depending on chocolatey again --- appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index fcd6e1a763..22b93a5d3f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -59,6 +59,7 @@ environment: before_build: - development/java/Rubberduck.Parsing/Grammar/gradlew.bat -p development/java/Rubberduck.Parsing/Grammar clean build - cinst innosetup -version 5.6.1 + - cinst codecov - cinst opencover.portable - nuget restore RubberduckMeta.sln - nuget restore Rubberduck.sln @@ -76,9 +77,8 @@ test_script: - | OpenCover.Console.exe -register:Path64 -returntargetcode -target:"nunit3-console.exe" -threshold:10 -targetargs:".\RubberduckTests\bin\RubberduckTests.dll" -output:".\Rubberduck_Coverage.xml" OpenCover.Console.exe -register:Path64 -returntargetcode -target:"nunit3-console.exe" -threshold:10 -targetargs:".\RubberduckTestsCodeAnalysis\bin\RubberduckTestsCodeAnalysis.dll" -output:".\RubberduckCodeAnalysis_Coverage.xml" - curl --silent https://codecov.io/bash --output codecov - bash codecov -f Rubberduck_Coverage.xml -f RubberduckCodeAnalysis_Coverage.xml - + codecov -f "Rubberduck_Coverage.xml RubberduckCodeAnalysis_Coverage.xml" + # Define the installer-name depending on what branch we're building on for: - From 6386d27b2a71f0601780b60299ff5f581e3b7102 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Mon, 3 Feb 2020 04:55:26 +0100 Subject: [PATCH 211/461] Split identifier reference inspection bases into generic and non-generic versions The generic ones take additional properties forwarded to the results as their properties and potentially used in the result description. The non-generic ones do not have soch properties. --- ...ReferenceInspectionFromDeclarationsBase.cs | 28 ++++++-- .../Abstract/DeclarationInspectionBase.cs | 67 +++++++++++++++++++ .../IdentifierReferenceInspectionBase.cs | 62 +++++++++++++++-- ...ReferenceInspectionFromDeclarationsBase.cs | 67 ++++++++++++++++--- .../Abstract/IsMissingInspectionBase.cs | 2 +- ...berAccessMayReturnNothingInspectionBase.cs | 2 +- ...entWithIncompatibleObjectTypeInspection.cs | 13 +--- .../Concrete/AssignmentNotUsedInspection.cs | 2 +- .../DefaultMemberRequiredInspection.cs | 2 +- .../ApplicationWorksheetFunctionInspection.cs | 2 +- .../ImplicitActiveSheetReferenceInspection.cs | 2 +- ...plicitActiveWorkbookReferenceInspection.cs | 2 +- .../SheetAccessedUsingStringInspection.cs | 6 +- .../FunctionReturnValueDiscardedInspection.cs | 2 +- .../ImplicitDefaultMemberAccessInspection.cs | 2 +- ...tRecursiveDefaultMemberAccessInspection.cs | 2 +- ...citUnboundDefaultMemberAccessInspection.cs | 2 +- .../IndexedDefaultMemberAccessInspection.cs | 2 +- ...dRecursiveDefaultMemberAccessInspection.cs | 2 +- ...xedUnboundDefaultMemberAccessInspection.cs | 2 +- ...issingOnInappropriateArgumentInspection.cs | 10 +-- ...ssingWithNonArgumentParameterInspection.cs | 6 +- .../ObjectVariableNotSetInspection.cs | 2 +- .../Concrete/ObsoleteMemberUsageInspection.cs | 2 +- .../Concrete/ProcedureRequiredInspection.cs | 2 +- ...entWithIncompatibleObjectTypeInspection.cs | 13 +--- .../UnassignedVariableUsageInspection.cs | 2 +- .../UntypedFunctionUsageInspection.cs | 2 +- .../Concrete/UseOfBangNotationInspection.cs | 2 +- .../UseOfRecursiveBangNotationInspection.cs | 2 +- .../UseOfUnboundBangNotationInspection.cs | 2 +- .../Concrete/ValueRequiredInspection.cs | 2 +- 32 files changed, 244 insertions(+), 74 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/ArgumentReferenceInspectionFromDeclarationsBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/ArgumentReferenceInspectionFromDeclarationsBase.cs index fb1d6e76d0..08bd0da63b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/ArgumentReferenceInspectionFromDeclarationsBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/ArgumentReferenceInspectionFromDeclarationsBase.cs @@ -14,10 +14,30 @@ protected ArgumentReferenceInspectionFromDeclarationsBase(RubberduckParserState protected abstract bool IsUnsuitableArgument(ArgumentReference reference, DeclarationFinder finder); - protected virtual (bool isResult, object properties) IsUnsuitableArgumentWithAdditionalProperties(ArgumentReference reference, DeclarationFinder finder) + protected override IEnumerable ObjectionableReferences(DeclarationFinder finder) + { + return ObjectionableDeclarations(finder) + .OfType() + .SelectMany(parameter => parameter.ArgumentReferences); + } + + protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) { - return (IsUnsuitableArgument(reference, finder), null); + if (!(reference is ArgumentReference argumentReference)) + { + return false; + } + + return IsUnsuitableArgument(argumentReference, finder); } + } + + public abstract class ArgumentReferenceInspectionFromDeclarationsBase : IdentifierReferenceInspectionFromDeclarationsBase + { + protected ArgumentReferenceInspectionFromDeclarationsBase(RubberduckParserState state) + : base(state) { } + + protected abstract (bool isResult, T properties) IsUnsuitableArgumentWithAdditionalProperties(ArgumentReference reference, DeclarationFinder finder); protected override IEnumerable ObjectionableReferences(DeclarationFinder finder) { @@ -26,11 +46,11 @@ protected override IEnumerable ObjectionableReferences(Decl .SelectMany(parameter => parameter.ArgumentReferences); } - protected override (bool isResult, object properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder) + protected override (bool isResult, T properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder) { if (!(reference is ArgumentReference argumentReference)) { - return (false, null); + return (false, default); } return IsUnsuitableArgumentWithAdditionalProperties(argumentReference, finder); diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs index d41e804a0c..d6a9f9f49f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs @@ -72,4 +72,71 @@ protected virtual IInspectionResult InspectionResult(Declaration declaration) declaration); } } + + public abstract class DeclarationInspectionBase : InspectionBase + { + protected readonly DeclarationType[] RelevantDeclarationTypes; + + protected DeclarationInspectionBase(RubberduckParserState state, params DeclarationType[] relevantDeclarationTypes) + : base(state) + { + RelevantDeclarationTypes = relevantDeclarationTypes; + } + + protected abstract (bool isResult, T properties) IsResultDeclarationWithAdditionalProperties(Declaration declaration, DeclarationFinder finder); + protected abstract string ResultDescription(Declaration declaration, T properties); + + protected override IEnumerable DoGetInspectionResults() + { + var finder = DeclarationFinderProvider.DeclarationFinder; + + var results = new List(); + foreach (var moduleDeclaration in State.DeclarationFinder.UserDeclarations(DeclarationType.Module)) + { + if (moduleDeclaration == null) + { + continue; + } + + var module = moduleDeclaration.QualifiedModuleName; + results.AddRange(DoGetInspectionResults(module, finder)); + } + + return results; + } + + private IEnumerable DoGetInspectionResults(QualifiedModuleName module) + { + var finder = DeclarationFinderProvider.DeclarationFinder; + return DoGetInspectionResults(module, finder); + } + + private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + { + var objectionableDeclarationsWithAdditionalProperties = RelevantDeclarationsInModule(module, finder) + .Select(declaration => (declaration, IsResultDeclarationWithAdditionalProperties(declaration, finder))) + .Where(tpl => tpl.Item2.isResult) + .Select(tpl => (tpl.declaration, tpl.Item2.properties)); + + return objectionableDeclarationsWithAdditionalProperties + .Select(tpl => InspectionResult(tpl.declaration, tpl.properties)) + .ToList(); + } + + protected virtual IEnumerable RelevantDeclarationsInModule(QualifiedModuleName module, DeclarationFinder finder) + { + return RelevantDeclarationTypes + .SelectMany(declarationType => DeclarationFinderProvider.DeclarationFinder.Members(module, declarationType)) + .Distinct(); + } + + protected virtual IInspectionResult InspectionResult(Declaration declaration, T properties) + { + return new DeclarationInspectionResult( + this, + ResultDescription(declaration, properties), + declaration, + properties: properties); + } + } } \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs index c566dcc7b4..dfd2f56c84 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs @@ -16,13 +16,67 @@ protected IdentifierReferenceInspectionBase(RubberduckParserState state) {} protected abstract bool IsResultReference(IdentifierReference reference, DeclarationFinder finder); - protected abstract string ResultDescription(IdentifierReference reference, dynamic properties = null); + protected abstract string ResultDescription(IdentifierReference reference); - protected virtual (bool isResult, object properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder) + protected override IEnumerable DoGetInspectionResults() { - return (IsResultReference(reference, finder), null); + var finder = DeclarationFinderProvider.DeclarationFinder; + + var results = new List(); + foreach (var moduleDeclaration in State.DeclarationFinder.UserDeclarations(DeclarationType.Module)) + { + if (moduleDeclaration == null) + { + continue; + } + + var module = moduleDeclaration.QualifiedModuleName; + results.AddRange(DoGetInspectionResults(module, finder)); + } + + return results; } + protected IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + { + var objectionableReferences = ReferencesInModule(module, finder) + .Where(reference => IsResultReference(reference, finder)); + + return objectionableReferences + .Select(reference => InspectionResult(reference, DeclarationFinderProvider)) + .ToList(); + } + + protected IEnumerable DoGetInspectionResults(QualifiedModuleName module) + { + var finder = DeclarationFinderProvider.DeclarationFinder; + return DoGetInspectionResults(module, finder); + } + + protected virtual IEnumerable ReferencesInModule(QualifiedModuleName module, DeclarationFinder finder) + { + return finder.IdentifierReferences(module); + } + + protected virtual IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider) + { + return new IdentifierReferenceInspectionResult( + this, + ResultDescription(reference), + declarationFinderProvider, + reference); + } + } + + public abstract class IdentifierReferenceInspectionBase : InspectionBase + { + protected IdentifierReferenceInspectionBase(RubberduckParserState state) + : base(state) + { } + + protected abstract (bool isResult, T properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder); + protected abstract string ResultDescription(IdentifierReference reference, T properties); + protected override IEnumerable DoGetInspectionResults() { var finder = DeclarationFinderProvider.DeclarationFinder; @@ -65,7 +119,7 @@ protected virtual IEnumerable ReferencesInModule(QualifiedM return finder.IdentifierReferences(module); } - protected virtual IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider, dynamic properties = null) + protected virtual IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider, T properties) { return new IdentifierReferenceInspectionResult( this, diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs index d450ca8035..7232cb7f21 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs @@ -16,7 +16,7 @@ protected IdentifierReferenceInspectionFromDeclarationsBase(RubberduckParserStat {} protected abstract IEnumerable ObjectionableDeclarations(DeclarationFinder finder); - protected abstract string ResultDescription(IdentifierReference reference, dynamic properties = null); + protected abstract string ResultDescription(IdentifierReference reference); protected override IEnumerable DoGetInspectionResults() { @@ -24,16 +24,14 @@ protected override IEnumerable DoGetInspectionResults() var objectionableReferences = ObjectionableReferences(finder); var resultReferences = ResultReferences(objectionableReferences, finder); return resultReferences - .Select(tpl => InspectionResult(tpl.reference, DeclarationFinderProvider, tpl.properties)) + .Select(reference => InspectionResult(reference, DeclarationFinderProvider)) .ToList(); } - private IEnumerable<(IdentifierReference reference, object properties)> ResultReferences(IEnumerable potentialResultReferences, DeclarationFinder finder) + private IEnumerable ResultReferences(IEnumerable potentialResultReferences, DeclarationFinder finder) { return potentialResultReferences - .Select(reference => (reference, IsResultReferenceWithAdditionalProperties(reference, finder))) - .Where(tpl => tpl.Item2.isResult) - .Select(tpl => (tpl.reference, tpl.Item2.properties)); + .Where(reference => IsResultReference(reference, finder)); } protected virtual IEnumerable ObjectionableReferences(DeclarationFinder finder) @@ -45,9 +43,60 @@ protected virtual IEnumerable ObjectionableReferences(Decla protected virtual bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) => true; - protected virtual (bool isResult, object properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder) + protected IEnumerable DoGetInspectionResults(QualifiedModuleName module) + { + var finder = DeclarationFinderProvider.DeclarationFinder; + var objectionableReferences = ObjectionableReferences(finder) + .Where(reference => reference.QualifiedModuleName.Equals(module)); + var resultReferences = ResultReferences(objectionableReferences, finder); + return resultReferences + .Select(reference => InspectionResult(reference, DeclarationFinderProvider)) + .ToList(); + } + + protected virtual IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider) + { + return new IdentifierReferenceInspectionResult( + this, + ResultDescription(reference), + declarationFinderProvider, + reference); + } + } + + public abstract class IdentifierReferenceInspectionFromDeclarationsBase : InspectionBase + { + protected IdentifierReferenceInspectionFromDeclarationsBase(RubberduckParserState state) + : base(state) + { } + + protected abstract IEnumerable ObjectionableDeclarations(DeclarationFinder finder); + protected abstract (bool isResult, T properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder); + protected abstract string ResultDescription(IdentifierReference reference, T properties); + + protected override IEnumerable DoGetInspectionResults() + { + var finder = DeclarationFinderProvider.DeclarationFinder; + var objectionableReferences = ObjectionableReferences(finder); + var resultReferences = ResultReferences(objectionableReferences, finder); + return resultReferences + .Select(tpl => InspectionResult(tpl.reference, DeclarationFinderProvider, tpl.properties)) + .ToList(); + } + + private IEnumerable<(IdentifierReference reference, T properties)> ResultReferences(IEnumerable potentialResultReferences, DeclarationFinder finder) + { + return potentialResultReferences + .Select(reference => (reference, IsResultReferenceWithAdditionalProperties(reference, finder))) + .Where(tpl => tpl.Item2.isResult) + .Select(tpl => (tpl.reference, tpl.Item2.properties)); + } + + protected virtual IEnumerable ObjectionableReferences(DeclarationFinder finder) { - return (IsResultReference(reference, finder), null); + var objectionableDeclarations = ObjectionableDeclarations(finder); + return objectionableDeclarations + .SelectMany(declaration => declaration.References); } protected IEnumerable DoGetInspectionResults(QualifiedModuleName module) @@ -61,7 +110,7 @@ protected IEnumerable DoGetInspectionResults(QualifiedModuleN .ToList(); } - protected virtual IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider, dynamic properties = null) + protected virtual IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider, T properties) { return new IdentifierReferenceInspectionResult( this, diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs index 441ffc9d06..5f5c86b5b5 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs @@ -8,7 +8,7 @@ namespace Rubberduck.Inspections.Inspections.Abstract { - public abstract class IsMissingInspectionBase : ArgumentReferenceInspectionFromDeclarationsBase + public abstract class IsMissingInspectionBase : ArgumentReferenceInspectionFromDeclarationsBase { protected IsMissingInspectionBase(RubberduckParserState state) : base(state) { } diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/MemberAccessMayReturnNothingInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/MemberAccessMayReturnNothingInspectionBase.cs index 6365866923..0a197ad7ed 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/MemberAccessMayReturnNothingInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/MemberAccessMayReturnNothingInspectionBase.cs @@ -100,7 +100,7 @@ private static IEnumerable GetReferenceNodes(INode node) } } - protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + protected override string ResultDescription(IdentifierReference reference) { var semiQualifiedName = $"{reference.Declaration.ParentDeclaration.IdentifierName}.{reference.IdentifierName}"; return string.Format(ResultTemplate, semiQualifiedName); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs index 202c3cc876..70dcfe4502 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs @@ -78,7 +78,7 @@ namespace Rubberduck.CodeAnalysis.Inspections.Concrete /// End Sub /// ]]> /// - public class ArgumentWithIncompatibleObjectTypeInspection : ArgumentReferenceInspectionFromDeclarationsBase + public class ArgumentWithIncompatibleObjectTypeInspection : ArgumentReferenceInspectionFromDeclarationsBase { private readonly ISetTypeResolver _setTypeResolver; @@ -103,7 +103,7 @@ private static bool ToBeConsidered(Declaration declaration) && declaration.IsObject; } - protected override (bool isResult, object properties) IsUnsuitableArgumentWithAdditionalProperties(ArgumentReference reference, DeclarationFinder finder) + protected override (bool isResult, string properties) IsUnsuitableArgumentWithAdditionalProperties(ArgumentReference reference, DeclarationFinder finder) { var argumentSetTypeName = ArgumentSetTypeName(reference, finder); @@ -115,12 +115,6 @@ protected override (bool isResult, object properties) IsUnsuitableArgumentWithAd return (true, argumentSetTypeName); } - protected override bool IsUnsuitableArgument(ArgumentReference reference, DeclarationFinder finder) - { - //No need to implement this since we overwrite IsUnsuitableArgumentWithAdditionalProperties. - throw new System.NotImplementedException(); - } - private string ArgumentSetTypeName(IdentifierReference argumentReference, DeclarationFinder finder) { var argumentExpression = argumentReference.Context as VBAParser.ExpressionContext; @@ -163,12 +157,11 @@ private static bool HasSubType(Declaration declaration, string typeName) return classType.Supertypes.Select(supertype => supertype.QualifiedModuleName.ToString()).Contains(typeName); } - protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + protected override string ResultDescription(IdentifierReference reference, string argumentTypeName) { var parameterName = reference.Declaration.IdentifierName; var parameterTypeName = reference.Declaration.FullAsTypeName; var argumentExpression = reference.Context.GetText(); - var argumentTypeName = (string)properties; return string.Format(InspectionResults.SetAssignmentWithIncompatibleObjectTypeInspection, parameterName, parameterTypeName, argumentExpression, argumentTypeName); } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs index 9511cfa773..70c9cdbe2d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs @@ -103,7 +103,7 @@ private static bool IsAssignmentOfNothing(IdentifierReference reference) && setStmtContext.expression().GetText().Equals(Tokens.Nothing); } - protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + protected override string ResultDescription(IdentifierReference reference) { return Description; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs index bca0d6ece6..64bfe5c634 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs @@ -73,7 +73,7 @@ protected override bool IsResultReference(IdentifierReference failedIndexedDefau return true; } - protected override string ResultDescription(IdentifierReference failedIndexedDefaultMemberAccess, dynamic properties = null) + protected override string ResultDescription(IdentifierReference failedIndexedDefaultMemberAccess) { var expression = failedIndexedDefaultMemberAccess.IdentifierName; var typeName = failedIndexedDefaultMemberAccess.Declaration?.FullAsTypeName; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs index 7cfc5223f9..b8bea5cb81 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs @@ -88,7 +88,7 @@ protected override IEnumerable ObjectionableDeclarations(Declaratio .Where(decl => worksheetFunctionNames.Contains(decl.IdentifierName)); } - protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + protected override string ResultDescription(IdentifierReference reference) { return string.Format(InspectionResults.ApplicationWorksheetFunctionInspection, reference.IdentifierName); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs index 65a78b61f4..7018921528 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs @@ -75,7 +75,7 @@ protected override IEnumerable ObjectionableDeclarations(Declaratio "Cells", "Range", "Columns", "Rows" }; - protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + protected override string ResultDescription(IdentifierReference reference) { return string.Format( InspectionResults.ImplicitActiveSheetReferenceInspection, diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveWorkbookReferenceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveWorkbookReferenceInspection.cs index 80a775f030..e8f8b120ed 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveWorkbookReferenceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveWorkbookReferenceInspection.cs @@ -72,7 +72,7 @@ protected override IEnumerable ObjectionableDeclarations(Declaratio return relevantProperties; } - protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + protected override string ResultDescription(IdentifierReference reference) { var referenceText = reference.Context.GetText(); return string.Format(InspectionResults.ImplicitActiveWorkbookReferenceInspection, referenceText); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs index e0047bcdab..b39f6195e4 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs @@ -45,7 +45,7 @@ namespace Rubberduck.Inspections.Concrete /// [RequiredHost("EXCEL.EXE")] [RequiredLibrary("Excel")] - public class SheetAccessedUsingStringInspection : IdentifierReferenceInspectionFromDeclarationsBase + public class SheetAccessedUsingStringInspection : IdentifierReferenceInspectionFromDeclarationsBase { private readonly IProjectsProvider _projectsProvider; @@ -86,7 +86,7 @@ protected override IEnumerable ObjectionableDeclarations(Declaratio return relevantProperties; } - protected override (bool isResult, object properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder) + protected override (bool isResult, PropertyBag properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder) { var sheetNameArgumentLiteralExpressionContext = SheetNameArgumentLiteralExpressionContext(reference); @@ -164,7 +164,7 @@ private static string ComponentPropertyValue(IVBComponent component, string prop return null; } - protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + protected override string ResultDescription(IdentifierReference reference, PropertyBag properties) { return InspectionResults.SheetAccessedUsingStringInspection; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueDiscardedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueDiscardedInspection.cs index d2889909aa..e626a3425e 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueDiscardedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueDiscardedInspection.cs @@ -88,7 +88,7 @@ private static bool IsCalledAsProcedure(ParserRuleContext context) return outputListParent == null; } - protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + protected override string ResultDescription(IdentifierReference reference) { var functionName = reference.Declaration.QualifiedName.ToString(); return string.Format(InspectionResults.FunctionReturnValueDiscardedInspection, functionName); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs index 690a6fc2a6..4eb9538eb4 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs @@ -64,7 +64,7 @@ protected override bool IsResultReference(IdentifierReference reference, Declara && !reference.IsIgnoringInspectionResultFor(AnnotationName); } - protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + protected override string ResultDescription(IdentifierReference reference) { var expression = reference.IdentifierName; var defaultMember = reference.Declaration.QualifiedName.ToString(); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs index df4fbecbb9..f2dae91a23 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs @@ -84,7 +84,7 @@ protected override bool IsResultReference(IdentifierReference reference, Declara && !reference.IsIgnoringInspectionResultFor(AnnotationName); } - protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + protected override string ResultDescription(IdentifierReference reference) { var expression = reference.IdentifierName; var defaultMember = reference.Declaration.QualifiedName.ToString(); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs index 92df7f3220..230f79ae34 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs @@ -71,7 +71,7 @@ protected override bool IsResultReference(IdentifierReference reference, Declara && !reference.IsIgnoringInspectionResultFor(AnnotationName); } - protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + protected override string ResultDescription(IdentifierReference reference) { var expression = reference.IdentifierName; return string.Format(InspectionResults.ImplicitUnboundDefaultMemberAccessInspection, expression); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs index 6218ee64fa..66adec3eb6 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs @@ -47,7 +47,7 @@ protected override bool IsResultReference(IdentifierReference reference, Declara && !reference.IsIgnoringInspectionResultFor(AnnotationName); } - protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + protected override string ResultDescription(IdentifierReference reference) { var expression = reference.IdentifierName; var defaultMember = reference.Declaration.QualifiedName.ToString(); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs index 37244bec0a..f37bb2305e 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs @@ -47,7 +47,7 @@ protected override bool IsResultReference(IdentifierReference reference, Declara && !reference.IsIgnoringInspectionResultFor(AnnotationName); } - protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + protected override string ResultDescription(IdentifierReference reference) { var expression = reference.IdentifierName; var defaultMember = reference.Declaration.QualifiedName.ToString(); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs index 8f32c92d90..5fabddaf34 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs @@ -54,7 +54,7 @@ protected override bool IsResultReference(IdentifierReference reference, Declara && !reference.IsIgnoringInspectionResultFor(AnnotationName); } - protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + protected override string ResultDescription(IdentifierReference reference) { var expression = reference.IdentifierName; return string.Format(InspectionResults.IndexedUnboundDefaultMemberAccessInspection, expression); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs index 625e474ed4..a168786ce1 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs @@ -40,7 +40,7 @@ public class IsMissingOnInappropriateArgumentInspection : IsMissingInspectionBas public IsMissingOnInappropriateArgumentInspection(RubberduckParserState state) : base(state) { } - protected override (bool isResult, object properties) IsUnsuitableArgumentWithAdditionalProperties(ArgumentReference reference, DeclarationFinder finder) + protected override (bool isResult, ParameterDeclaration properties) IsUnsuitableArgumentWithAdditionalProperties(ArgumentReference reference, DeclarationFinder finder) { var parameter = ParameterForReference(reference, finder); @@ -52,13 +52,7 @@ protected override (bool isResult, object properties) IsUnsuitableArgumentWithAd return (isResult, parameter); } - protected override bool IsUnsuitableArgument(ArgumentReference reference, DeclarationFinder finder) - { - //No need to implement this, since we override IsUnsuitableArgumentWithAdditionalProperties. - throw new System.NotImplementedException(); - } - - protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + protected override string ResultDescription(IdentifierReference reference, ParameterDeclaration parameter) { return InspectionResults.IsMissingOnInappropriateArgumentInspection; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs index d66455ace9..dd8ed58d57 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs @@ -35,14 +35,14 @@ public class IsMissingWithNonArgumentParameterInspection : IsMissingInspectionBa public IsMissingWithNonArgumentParameterInspection(RubberduckParserState state) : base(state) { } - protected override bool IsUnsuitableArgument(ArgumentReference reference, DeclarationFinder finder) + protected override (bool isResult, ParameterDeclaration properties) IsUnsuitableArgumentWithAdditionalProperties(ArgumentReference reference, DeclarationFinder finder) { var parameter = ParameterForReference(reference, finder); - return parameter == null; + return (parameter == null, null); } - protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + protected override string ResultDescription(IdentifierReference reference, ParameterDeclaration properties) { return InspectionResults.IsMissingWithNonArgumentParameterInspection; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs index 8c133debd9..d8d811ea60 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs @@ -98,7 +98,7 @@ protected override bool IsResultReference(IdentifierReference reference, Declara return true; } - protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + protected override string ResultDescription(IdentifierReference reference) { return string.Format(InspectionResults.ObjectVariableNotSetInspection, reference.IdentifierName); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs index b358ed5d2a..15881ffd29 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs @@ -64,7 +64,7 @@ protected override bool IsResultReference(IdentifierReference reference, Declara && declaration.Annotations.Any(pta => pta.Annotation is ObsoleteAnnotation); } - protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + protected override string ResultDescription(IdentifierReference reference) { var replacementDocumentation = reference.Declaration.Annotations .First(pta => pta.Annotation is ObsoleteAnnotation) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs index 007e933d29..a1d0f811b3 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs @@ -72,7 +72,7 @@ protected override bool IsResultReference(IdentifierReference failedCoercion, De return true; } - protected override string ResultDescription(IdentifierReference failedCoercion, dynamic properties = null) + protected override string ResultDescription(IdentifierReference failedCoercion) { var expression = failedCoercion.IdentifierName; var typeName = failedCoercion.Declaration?.FullAsTypeName; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs index eee1ac8e6b..dd7b8f7cac 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs @@ -72,7 +72,7 @@ namespace Rubberduck.CodeAnalysis.Inspections.Concrete /// End Sub /// ]]> /// - public class SetAssignmentWithIncompatibleObjectTypeInspection : IdentifierReferenceInspectionBase + public class SetAssignmentWithIncompatibleObjectTypeInspection : IdentifierReferenceInspectionBase { private readonly ISetTypeResolver _setTypeResolver; @@ -85,7 +85,7 @@ public SetAssignmentWithIncompatibleObjectTypeInspection(RubberduckParserState s Severity = CodeInspectionSeverity.Error; } - protected override (bool isResult, object properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder) + protected override (bool isResult, string properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder) { if (!ToBeConsidered(reference)) { @@ -102,12 +102,6 @@ protected override (bool isResult, object properties) IsResultReferenceWithAddit return (true, assignedTypeName); } - protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) - { - //No need to implement this since we override IsResultReferenceWithAdditionalProperties. - throw new System.NotImplementedException(); - } - private static bool ToBeConsidered(IdentifierReference reference) { if (reference == null || !reference.IsSetAssignment) @@ -166,11 +160,10 @@ private bool HasSubType(Declaration declaration, string typeName) return classType.Supertypes.Select(supertype => supertype.QualifiedModuleName.ToString()).Contains(typeName); } - protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + protected override string ResultDescription(IdentifierReference reference, string assignedTypeName) { var declarationName = reference.Declaration.IdentifierName; var variableTypeName = reference.Declaration.FullAsTypeName; - var assignedTypeName = (string)properties; return string.Format(InspectionResults.SetAssignmentWithIncompatibleObjectTypeInspection, declarationName, variableTypeName, assignedTypeName); } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs index 3715947792..dba6cb3bf1 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs @@ -135,7 +135,7 @@ protected override bool IsResultReference(IdentifierReference reference, Declara && !IsArrayReDim(reference); } - protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + protected override string ResultDescription(IdentifierReference reference) { var identifierName = reference.IdentifierName; return string.Format( diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UntypedFunctionUsageInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UntypedFunctionUsageInspection.cs index d3aea5cfa3..2e8af74cc4 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UntypedFunctionUsageInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UntypedFunctionUsageInspection.cs @@ -76,7 +76,7 @@ private IEnumerable BuiltInVariantStringFunctionsWithStringTypedVer && _tokens.Contains(item.IdentifierName.Substring("_B_var_".Length)))); } - protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + protected override string ResultDescription(IdentifierReference reference) { var declarationName = reference.Declaration.IdentifierName; return string.Format( diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfBangNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfBangNotationInspection.cs index 7ce54dcf80..998e3a5ca4 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfBangNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfBangNotationInspection.cs @@ -69,7 +69,7 @@ protected override bool IsResultReference(IdentifierReference reference, Declara && reference.Context is VBAParser.DictionaryAccessContext; } - protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + protected override string ResultDescription(IdentifierReference reference) { var expression = reference.IdentifierName; return string.Format(InspectionResults.UseOfBangNotationInspection, expression); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs index 091cffd053..a33860da11 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs @@ -77,7 +77,7 @@ protected override bool IsResultReference(IdentifierReference reference, Declara && reference.Context is VBAParser.DictionaryAccessContext; } - protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + protected override string ResultDescription(IdentifierReference reference) { var expression = reference.IdentifierName; return string.Format(InspectionResults.UseOfRecursiveBangNotationInspection, expression); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs index b415224753..a568cdfd40 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs @@ -76,7 +76,7 @@ protected override bool IsResultReference(IdentifierReference reference, Declara && reference.Context is VBAParser.DictionaryAccessContext; } - protected override string ResultDescription(IdentifierReference reference, dynamic properties = null) + protected override string ResultDescription(IdentifierReference reference) { var expression = reference.IdentifierName; return string.Format(InspectionResults.UseOfRecursiveBangNotationInspection, expression); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs index 5e29e43b76..7334e1cebf 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs @@ -75,7 +75,7 @@ protected override bool IsResultReference(IdentifierReference failedLetCoercion, return !failedLetCoercion.IsAssignment; } - protected override string ResultDescription(IdentifierReference failedLetCoercion, dynamic properties = null) + protected override string ResultDescription(IdentifierReference failedLetCoercion) { var expression = failedLetCoercion.IdentifierName; var typeName = failedLetCoercion.Declaration?.FullAsTypeName; From cc1327e021f5148b987a5049f497df678157a17f Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Mon, 3 Feb 2020 16:52:14 +0100 Subject: [PATCH 212/461] Fix bug in VariableNotAssignedInspection and add tests for module variables The inspection considered variables to be assigned by ref even if the variable only appeared as a sum-expression of the actual argument. This also improves `GetAncestot` to use pattern matching, which avoids an invalid cast exception. --- .../Concrete/VariableNotAssignedInspection.cs | 65 ++-- .../ParserRuleContextExtensions.cs | 51 +-- .../VariableNotAssignedInspectionTests.cs | 300 ++++++++++++++++++ 3 files changed, 370 insertions(+), 46 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotAssignedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotAssignedInspection.cs index 10bdf7b9aa..365701b7b8 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotAssignedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotAssignedInspection.cs @@ -1,14 +1,11 @@ -using System.Collections.Generic; using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -37,37 +34,61 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class VariableNotAssignedInspection : InspectionBase + public sealed class VariableNotAssignedInspection : DeclarationInspectionBase { public VariableNotAssignedInspection(RubberduckParserState state) - : base(state) { } + : base(state, DeclarationType.Variable) { } - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { - // ignore arrays. todo: ArrayIndicesNotAccessedInspection - var arrays = State.DeclarationFinder.UserDeclarations(DeclarationType.Variable).Where(declaration => declaration.IsArray); - - var declarations = State.DeclarationFinder.UserDeclarations(DeclarationType.Variable) - .Except(arrays) - .Where(declaration => - !declaration.IsWithEvents - && State.DeclarationFinder.MatchName(declaration.AsTypeName).All(item => item.DeclarationType != DeclarationType.UserDefinedType) // UDT variables don't need to be assigned - && !declaration.IsSelfAssigned - && !declaration.References.Any(reference => reference.IsAssignment || IsAssignedByRefArgument(reference.ParentScoping, reference))); + return declaration != null + && !declaration.IsArray // ignore arrays. todo: ArrayIndicesNotAccessedInspection + && !declaration.IsWithEvents + && !declaration.IsSelfAssigned + && !HasUdtType(declaration, finder) // UDT variables don't need to be assigned + && !declaration.References.Any(reference => reference.IsAssignment || IsAssignedByRefArgument(reference.ParentScoping, reference, finder)); + } - return declarations.Select(issue => - new DeclarationInspectionResult(this, string.Format(InspectionResults.VariableNotAssignedInspection, issue.IdentifierName), issue)); + private static bool HasUdtType(Declaration declaration, DeclarationFinder finder) + { + return finder.MatchName(declaration.AsTypeName) + .Any(item => item.DeclarationType == DeclarationType.UserDefinedType); } - private bool IsAssignedByRefArgument(Declaration enclosingProcedure, IdentifierReference reference) + private static bool IsAssignedByRefArgument(Declaration enclosingProcedure, IdentifierReference reference, DeclarationFinder finder) { - var argExpression = reference.Context.GetAncestor(); - var parameter = State.DeclarationFinder.FindParameterOfNonDefaultMemberFromSimpleArgumentNotPassedByValExplicitly(argExpression, enclosingProcedure); + var argExpression = ImmediateArgumentExpressionContext(reference); + + if (argExpression is null) + { + return false; + } + + var parameter = finder.FindParameterOfNonDefaultMemberFromSimpleArgumentNotPassedByValExplicitly(argExpression, enclosingProcedure); // note: not recursive, by design. return parameter != null && (parameter.IsImplicitByRef || parameter.IsByRef) && parameter.References.Any(r => r.IsAssignment); } + + private static VBAParser.ArgumentExpressionContext ImmediateArgumentExpressionContext(IdentifierReference reference) + { + var context = reference.Context; + //The context is either already a simpleNameExprContext or an IdentifierValueContext used in a sub-rule of some other lExpression alternative. + var lExpressionNameContext = context is VBAParser.SimpleNameExprContext simpleName + ? simpleName + : context.GetAncestor(); + + //To be an immediate argument and, thus, assignable by ref, the structure must be argumentExpression -> expression -> lExpression. + return lExpressionNameContext? + .Parent? + .Parent as VBAParser.ArgumentExpressionContext; + } + + protected override string ResultDescription(Declaration declaration) + { + return string.Format(InspectionResults.VariableNotAssignedInspection, declaration.IdentifierName); + } } } diff --git a/Rubberduck.Parsing/ParserRuleContextExtensions.cs b/Rubberduck.Parsing/ParserRuleContextExtensions.cs index 1347b16663..2997bd897d 100644 --- a/Rubberduck.Parsing/ParserRuleContextExtensions.cs +++ b/Rubberduck.Parsing/ParserRuleContextExtensions.cs @@ -66,8 +66,12 @@ public static TContext GetChild(this ParserRuleContext context) where return default; } - var results = context.children.Where(child => child is TContext); - return results.Any() ? (TContext)results.First() : default; + var results = context.children + .Where(child => child is TContext) + .ToList(); + return results.Any() + ? (TContext)results.First() + : default; } /// @@ -109,11 +113,8 @@ private static bool IsDescendentOf_Recursive(IParseTree context, IParseTree targ { return false; } - if (context == targetParent) - { - return true; - } - return IsDescendentOf_Recursive(context.Parent, targetParent); + return context == targetParent + || IsDescendentOf_Recursive(context.Parent, targetParent); } /// @@ -121,15 +122,15 @@ private static bool IsDescendentOf_Recursive(IParseTree context, IParseTree targ /// public static TContext GetAncestor(this ParserRuleContext context) { - if (context == null) + switch (context) { - return default; + case null: + return default; + case TContext _: + return GetAncestor_Recursive((ParserRuleContext)context.Parent); + default: + return GetAncestor_Recursive(context); } - if (context is TContext) - { - return GetAncestor_Recursive((ParserRuleContext)context.Parent); - } - return GetAncestor_Recursive(context); } /// @@ -143,15 +144,15 @@ public static bool TryGetAncestor(this ParserRuleContext context, out private static TContext GetAncestor_Recursive(ParserRuleContext context) { - if (context == null) + switch (context) { - return default; + case null: + return default; + case TContext tContext: + return tContext; + default: + return GetAncestor_Recursive((ParserRuleContext)context.Parent); } - if (context is TContext) - { - return (TContext)System.Convert.ChangeType(context, typeof(TContext)); - } - return GetAncestor_Recursive((ParserRuleContext)context.Parent); } /// @@ -169,9 +170,7 @@ public static ParserRuleContext GetAncestorContainingTokenIndex(this ParserRuleC return context; } - var parent = context.Parent as ParserRuleContext; - - if (parent == null) + if (!(context.Parent is ParserRuleContext parent)) { return default; } @@ -288,6 +287,7 @@ public static bool IsOptionCompareBinary(this ParserRuleContext context) return (optionContext is null) || !(optionContext.BINARY() is null); } + /// /// Returns the context's widest descendent of the generic type containing the token with the specified token index. /// public static TContext GetWidestDescendentContainingTokenIndex(this ParserRuleContext context, int tokenIndex) where TContext : ParserRuleContext @@ -296,6 +296,7 @@ public static TContext GetWidestDescendentContainingTokenIndex(this Pa return descendents.FirstOrDefault(); } + /// /// Returns the context's smallest descendent of the generic type containing the token with the specified token index. /// public static TContext GetSmallestDescendentContainingTokenIndex(this ParserRuleContext context, int tokenIndex) where TContext : ParserRuleContext @@ -333,6 +334,7 @@ public static IEnumerable GetDescendentsContainingTokenIndex return matches; } + /// /// Returns the context's widest descendent of the generic type containing the specified selection. /// public static TContext GetWidestDescendentContainingSelection(this ParserRuleContext context, Selection selection) where TContext : ParserRuleContext @@ -341,6 +343,7 @@ public static TContext GetWidestDescendentContainingSelection(this Par return descendents.FirstOrDefault(); } + /// /// Returns the context's smallest descendent of the generic type containing the specified selection. /// public static TContext GetSmallestDescendentContainingSelection(this ParserRuleContext context, Selection selection) where TContext : ParserRuleContext diff --git a/RubberduckTests/Inspections/VariableNotAssignedInspectionTests.cs b/RubberduckTests/Inspections/VariableNotAssignedInspectionTests.cs index d417d96b59..f24e33e2e4 100644 --- a/RubberduckTests/Inspections/VariableNotAssignedInspectionTests.cs +++ b/RubberduckTests/Inspections/VariableNotAssignedInspectionTests.cs @@ -3,6 +3,7 @@ using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; +using Rubberduck.VBEditor.SafeComWrappers; namespace RubberduckTests.Inspections { @@ -79,6 +80,305 @@ End Sub Assert.AreEqual(0, InspectionResultsForStandardModule(inputCode).Count()); } + + [Test] + [Category("Inspections")] + public void VariableNotAssigned_StrictlyInsideByRefAssignment_ReturnsResult() + { + const string inputCode = @" +Sub Foo() + Dim var1 As String + Bar var1 & ""WTF"" +End Sub + +Sub Bar(ByRef value As String) + value = ""test"" +End Sub +"; + + Assert.AreEqual(1, InspectionResultsForStandardModule(inputCode).Count()); + } + + [Test] + [Category("Inspections")] + public void VariableNotAssigned_ModuleVariable_ReturnsResult_Private() + { + const string inputCode = @" +Private myVariable As Variant + +Sub Foo() +End Sub +"; + + Assert.AreEqual(1, InspectionResultsForStandardModule(inputCode).Count()); + } + + [Test] + [Category("Inspections")] + public void VariableNotAssigned_ModuleVariable_ReturnsResult_Public() + { + const string inputCode = @" +Public myVariable As Variant + +Sub Foo() +End Sub +"; + + Assert.AreEqual(1, InspectionResultsForStandardModule(inputCode).Count()); + } + + [Test] + [Category("Inspections")] + public void VariableNotAssigned_GivenByRefAssignment_ModuleVariable_DoesNotReturnResult() + { + const string inputCode = @" +Public myVariable As Variant + +Sub Foo() + Bar myVariable +End Sub + +Sub Bar(ByRef value As String) + value = ""test"" +End Sub +"; + + Assert.AreEqual(0, InspectionResultsForStandardModule(inputCode).Count()); + } + + [Test] + [Category("Inspections")] + public void VariableNotAssigned_StrictlyInsideByRefAssignment_ModuleVariable_ReturnsResult() + { + const string inputCode = @" +Public myVariable As Variant + +Sub Foo() + Bar myVariable & ""WTF"" +End Sub + +Sub Bar(ByRef value As String) + value = ""test"" +End Sub +"; + + Assert.AreEqual(1, InspectionResultsForStandardModule(inputCode).Count()); + } + + [Test] + [Category("Inspections")] + public void VariableNotAssigned_AssignmentFromOtherModule_ModuleVariable_DoesNotReturnResult() + { + const string otherModuleCode = @" +Public myVariable As Variant +"; + + const string moduleCode = @" +Sub Foo() + myVariable = 42 +End Sub +"; + + Assert.AreEqual(0, InspectionResultsForModules( + ("OtherModule", otherModuleCode, ComponentType.StandardModule), + ("TestModule", moduleCode, ComponentType.StandardModule) + ).Count()); + } + + [Test] + [Category("Inspections")] + public void VariableNotAssigned_GivenByRefAssignmentInOtherModule_ModuleVariable_DoesNotReturnResult() + { + const string otherModuleCode = @" +Public myVariable As Variant +"; + + const string moduleCode = @" +Sub Foo() + Bar myVariable +End Sub + +Sub Bar(ByRef value As String) + value = ""test"" +End Sub +"; + + Assert.AreEqual(0, InspectionResultsForModules( + ("OtherModule", otherModuleCode, ComponentType.StandardModule), + ("TestModule", moduleCode, ComponentType.StandardModule) + ).Count()); + } + + [Test] + [Category("Inspections")] + public void VariableNotAssigned_StrictlyInsideByRefAssignmentInOtherModule_QualifiedModuleVariable_ReturnsResult() + { + const string otherModuleCode = @" +Public myVariable As Variant +"; + + const string moduleCode = @" +Sub Foo() + Bar myVariable & ""WTF"" +End Sub + +Sub Bar(ByRef value As String) + value = ""test"" +End Sub +"; + + Assert.AreEqual(1, InspectionResultsForModules( + ("OtherModule", otherModuleCode, ComponentType.StandardModule), + ("TestModule", moduleCode, ComponentType.StandardModule) + ).Count()); + } + + [Test] + [Category("Inspections")] + public void VariableNotAssigned_Assignment_QualifiedModuleVariable_DoesNotReturnResult() + { + const string otherModuleCode = @" +Public myVariable As Variant +"; + + const string moduleCode = @" +Sub Foo() + OtherModule.myVariable = 42 +End Sub +"; + + Assert.AreEqual(0, InspectionResultsForModules( + ("OtherModule", otherModuleCode, ComponentType.StandardModule), + ("TestModule", moduleCode, ComponentType.StandardModule) + ).Count()); + } + + [Test] + [Category("Inspections")] + public void VariableNotAssigned_GivenByRefAssignment_QualifiedModuleVariable_DoesNotReturnResult() + { + const string otherModuleCode = @" +Public myVariable As Variant +"; + + const string moduleCode = @" +Sub Foo() + Bar OtherModule.myVariable +End Sub + +Sub Bar(ByRef value As String) + value = ""test"" +End Sub +"; + + Assert.AreEqual(0, InspectionResultsForModules( + ("OtherModule", otherModuleCode, ComponentType.StandardModule), + ("TestModule", moduleCode, ComponentType.StandardModule) + ).Count()); + } + + [Test] + [Category("Inspections")] + public void VariableNotAssigned_StrictlyInsideByRefAssignment_QualifiedModuleVariable_ReturnsResult() + { + const string otherModuleCode = @" +Public myVariable As Variant +"; + + const string moduleCode = @" +Sub Foo() + Bar OtherModule.myVariable & ""WTF"" +End Sub + +Sub Bar(ByRef value As String) + value = ""test"" +End Sub +"; + + Assert.AreEqual(1, InspectionResultsForModules( + ("OtherModule", otherModuleCode, ComponentType.StandardModule), + ("TestModule", moduleCode, ComponentType.StandardModule) + ).Count()); + } + + [Test] + [Category("Inspections")] + public void VariableNotAssigned_AssignmentInOtherModule_ClassModuleVariable_DoesNotReturnResult() + { + const string classModuleCode = @" +Public myVariable As Variant +"; + + const string moduleCode = @" +Sub Foo() + Dim cls As TestClass + Set cls = New TestClass + cls.myVariable = 42 +End Sub + +Sub Bar(ByRef value As String) + value = ""test"" +End Sub +"; + + Assert.AreEqual(0, InspectionResultsForModules( + ("TestClass", classModuleCode, ComponentType.ClassModule), + ("TestModule", moduleCode, ComponentType.StandardModule) + ).Count()); + } + + [Test] + [Category("Inspections")] + public void VariableNotAssigned_GivenByRefAssignment_ClassModuleVariable_DoesNotReturnResult() + { + const string classModuleCode = @" +Public myVariable As Variant +"; + + const string moduleCode = @" +Sub Foo() + Dim cls As TestClass + Set cls = New TestClass + Bar cls.myVariable +End Sub + +Sub Bar(ByRef value As String) + value = ""test"" +End Sub +"; + + Assert.AreEqual(0, InspectionResultsForModules( + ("TestClass", classModuleCode, ComponentType.ClassModule), + ("TestModule", moduleCode, ComponentType.StandardModule) + ).Count()); + } + + [Test] + [Category("Inspections")] + public void VariableNotAssigned_StrictlyInsideByRefAssignment_ClassModuleVariable_ReturnsResult() + { + const string classModuleCode = @" +Public myVariable As Variant +"; + + const string moduleCode = @" +Sub Foo() + Dim cls As TestClass + Set cls = New TestClass + Bar cls.myVariable & ""WTF"" +End Sub + +Sub Bar(ByRef value As String) + value = ""test"" +End Sub +"; + + Assert.AreEqual(1, InspectionResultsForModules( + ("TestClass", classModuleCode, ComponentType.ClassModule), + ("TestModule", moduleCode, ComponentType.StandardModule) + ).Count()); + } + [Test] [Category("Inspections")] public void VariableNotAssigned_Ignored_DoesNotReturnResult() From 205e3dd38dedf724f0f3d37d80fc4edcd79923a7 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Mon, 3 Feb 2020 21:30:22 +0100 Subject: [PATCH 213/461] Fix KeywordUsedAsMemberInspection The problem was that the inspection normalized the names too much. The identifier name is already the name without the outermost brackets and spacesaround bracketed identifiers do matter. Also makes several inspections use the declaration inspection base class. --- .../Abstract/DeclarationInspectionBase.cs | 38 ++++++++++--- .../Abstract/ImplicitTypeInspectionBase.cs | 18 +++++++ .../Concrete/ConstantNotUsedInspection.cs | 33 ++++++------ .../Concrete/EmptyMethodInspection.cs | 1 - .../Concrete/EmptyModuleInspection.cs | 40 ++++++-------- .../ImplicitPublicMemberInspection.cs | 24 ++++----- .../ImplicitVariantReturnTypeInspection.cs | 22 ++------ .../ImplicitlyTypedConstInspection.cs | 53 ++++++++++--------- .../Concrete/IntegerDataTypeInspection.cs | 1 - .../Concrete/LineLabelNotUsedInspection.cs | 39 +++++++------- .../Concrete/ModuleWithoutFolderInspection.cs | 25 ++++----- .../Concrete/ObsoleteGlobalInspection.cs | 26 +++++---- .../Concrete/ShadowedDeclarationInspection.cs | 1 - .../KeywordsUsedAsMemberInspection.cs | 32 ++++++----- .../NonBreakingSpaceIdentifierInspection.cs | 26 ++++----- .../Concrete/UndeclaredVariableInspection.cs | 22 ++++---- .../ImplicitlyTypedConstInspectionTests.cs | 2 +- .../ThunderCode/ThunderCodeInspectionTests.cs | 22 +++++++- 18 files changed, 232 insertions(+), 193 deletions(-) create mode 100644 Rubberduck.CodeAnalysis/Inspections/Abstract/ImplicitTypeInspectionBase.cs diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs index d6a9f9f49f..119e71f0b3 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs @@ -12,11 +12,20 @@ namespace Rubberduck.Inspections.Abstract public abstract class DeclarationInspectionBase : InspectionBase { protected readonly DeclarationType[] RelevantDeclarationTypes; + protected readonly DeclarationType[] ExcludeDeclarationTypes; protected DeclarationInspectionBase(RubberduckParserState state, params DeclarationType[] relevantDeclarationTypes) : base(state) { RelevantDeclarationTypes = relevantDeclarationTypes; + ExcludeDeclarationTypes = new DeclarationType[0]; + } + + protected DeclarationInspectionBase(RubberduckParserState state, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) + : base(state) + { + RelevantDeclarationTypes = relevantDeclarationTypes; + ExcludeDeclarationTypes = excludeDeclarationTypes; } protected abstract bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder); @@ -59,9 +68,13 @@ private IEnumerable DoGetInspectionResults(QualifiedModuleNam protected virtual IEnumerable RelevantDeclarationsInModule(QualifiedModuleName module, DeclarationFinder finder) { - return RelevantDeclarationTypes - .SelectMany(declarationType => DeclarationFinderProvider.DeclarationFinder.Members(module, declarationType)) - .Distinct(); + var potentiallyRelevantDeclarations = RelevantDeclarationTypes.Length == 0 + ? finder.AllUserDeclarations + : RelevantDeclarationTypes + .SelectMany(declarationType => finder.Members(module, declarationType)) + .Distinct(); + return potentiallyRelevantDeclarations + .Where(declaration => !ExcludeDeclarationTypes.Contains(declaration.DeclarationType)); } protected virtual IInspectionResult InspectionResult(Declaration declaration) @@ -76,11 +89,20 @@ protected virtual IInspectionResult InspectionResult(Declaration declaration) public abstract class DeclarationInspectionBase : InspectionBase { protected readonly DeclarationType[] RelevantDeclarationTypes; + protected readonly DeclarationType[] ExcludeDeclarationTypes; protected DeclarationInspectionBase(RubberduckParserState state, params DeclarationType[] relevantDeclarationTypes) : base(state) { RelevantDeclarationTypes = relevantDeclarationTypes; + ExcludeDeclarationTypes = new DeclarationType[0]; + } + + protected DeclarationInspectionBase(RubberduckParserState state, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) + : base(state) + { + RelevantDeclarationTypes = relevantDeclarationTypes; + ExcludeDeclarationTypes = excludeDeclarationTypes; } protected abstract (bool isResult, T properties) IsResultDeclarationWithAdditionalProperties(Declaration declaration, DeclarationFinder finder); @@ -125,9 +147,13 @@ private IEnumerable DoGetInspectionResults(QualifiedModuleNam protected virtual IEnumerable RelevantDeclarationsInModule(QualifiedModuleName module, DeclarationFinder finder) { - return RelevantDeclarationTypes - .SelectMany(declarationType => DeclarationFinderProvider.DeclarationFinder.Members(module, declarationType)) - .Distinct(); + var potentiallyRelevantDeclarations = RelevantDeclarationTypes.Length == 0 + ? finder.AllUserDeclarations + : RelevantDeclarationTypes + .SelectMany(declarationType => finder.Members(module, declarationType)) + .Distinct(); + return potentiallyRelevantDeclarations + .Where(declaration => ! ExcludeDeclarationTypes.Contains(declaration.DeclarationType)); } protected virtual IInspectionResult InspectionResult(Declaration declaration, T properties) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/ImplicitTypeInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/ImplicitTypeInspectionBase.cs new file mode 100644 index 0000000000..0b9115f6ba --- /dev/null +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/ImplicitTypeInspectionBase.cs @@ -0,0 +1,18 @@ +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; + +namespace Rubberduck.Inspections.Abstract +{ + public abstract class ImplicitTypeInspectionBase : DeclarationInspectionBase + { + protected ImplicitTypeInspectionBase(RubberduckParserState state, params DeclarationType[] relevantDeclarationTypes) + :base(state, relevantDeclarationTypes) + { } + + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) + { + return !declaration.IsTypeSpecified; + } + } +} \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ConstantNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ConstantNotUsedInspection.cs index 76570ef5a7..6ad6aa5d0e 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ConstantNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ConstantNotUsedInspection.cs @@ -1,15 +1,10 @@ -using System.Collections.Generic; using System.Linq; -using Antlr4.Runtime; -using Rubberduck.Common; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -37,23 +32,25 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ConstantNotUsedInspection : InspectionBase + public sealed class ConstantNotUsedInspection : DeclarationInspectionBase { public ConstantNotUsedInspection(RubberduckParserState state) - : base(state) { } + : base(state, DeclarationType.Constant) { } - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { - var results = State.DeclarationFinder.UserDeclarations(DeclarationType.Constant) - .Where(declaration => declaration.Context != null - && !declaration.References.Any()) - .ToList(); + return declaration?.Context != null + && !declaration.References.Any(); + } - return results.Select(issue => - new DeclarationInspectionResult(this, - string.Format(InspectionResults.IdentifierNotUsedInspection, issue.DeclarationType.ToLocalizedString(), issue.IdentifierName), - issue, - new QualifiedContext(issue.QualifiedName.QualifiedModuleName, ((dynamic)issue.Context).identifier()))); + protected override string ResultDescription(Declaration declaration) + { + var declarationType = declaration.DeclarationType.ToLocalizedString(); + var declarationName = declaration.IdentifierName; + return string.Format( + InspectionResults.IdentifierNotUsedInspection, + declarationType, + declarationName); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyMethodInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyMethodInspection.cs index 4189946b2e..88c173ca2b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyMethodInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyMethodInspection.cs @@ -10,7 +10,6 @@ using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing.VBA.DeclarationCaching; -using Rubberduck.Parsing.VBA.Extensions; using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyModuleInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyModuleInspection.cs index f1030e3cf6..9016086a7b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyModuleInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyModuleInspection.cs @@ -1,16 +1,11 @@ -using System.Collections.Generic; -using System.Linq; +using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.VBA.Extensions; -using Rubberduck.VBEditor.SafeComWrappers; -using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.JunkDrawer.Extensions; +using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Parsing.VBA.Parsing; namespace Rubberduck.Inspections.Concrete { @@ -20,34 +15,29 @@ namespace Rubberduck.Inspections.Concrete /// /// An empty module does not need to exist and can be safely removed. /// - public sealed class EmptyModuleInspection : InspectionBase + public sealed class EmptyModuleInspection : DeclarationInspectionBase { private readonly EmptyModuleVisitor _emptyModuleVisitor; + private readonly IParseTreeProvider _parseTreeProvider; public EmptyModuleInspection(RubberduckParserState state) - : base(state) + : base(state, new []{DeclarationType.Module}, new []{DeclarationType.Document}) { _emptyModuleVisitor = new EmptyModuleVisitor(); + _parseTreeProvider = state; } - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { - var modulesToInspect = State.DeclarationFinder.AllModules - .Where(qmn => qmn.ComponentType == ComponentType.ClassModule - || qmn.ComponentType == ComponentType.StandardModule).ToHashSet(); + var module = declaration.QualifiedModuleName; + var tree = _parseTreeProvider.GetParseTree(module, CodeKind.CodePaneCode); - var treesToInspect = State.ParseTrees.Where(kvp => modulesToInspect.Contains(kvp.Key)); - - var emptyModules = treesToInspect - .Where(kvp => _emptyModuleVisitor.Visit(kvp.Value)) - .Select(kvp => kvp.Key) - .ToHashSet(); - - var emptyModuleDeclarations = State.DeclarationFinder.UserDeclarations(DeclarationType.Module) - .Where(declaration => emptyModules.Contains(declaration.QualifiedName.QualifiedModuleName)); + return _emptyModuleVisitor.Visit(tree); + } - return emptyModuleDeclarations.Select(declaration => - new DeclarationInspectionResult(this, string.Format(InspectionResults.EmptyModuleInspection, declaration.IdentifierName), declaration)); + protected override string ResultDescription(Declaration declaration) + { + return string.Format(InspectionResults.EmptyModuleInspection, declaration.IdentifierName); } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitPublicMemberInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitPublicMemberInspection.cs index 54a7ebfd8e..7b8e2c1be8 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitPublicMemberInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitPublicMemberInspection.cs @@ -1,11 +1,8 @@ -using System.Collections.Generic; -using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -30,10 +27,10 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ImplicitPublicMemberInspection : InspectionBase + public sealed class ImplicitPublicMemberInspection : DeclarationInspectionBase { public ImplicitPublicMemberInspection(RubberduckParserState state) - : base(state) { } + : base(state, ProcedureTypes) { } private static readonly DeclarationType[] ProcedureTypes = { @@ -44,15 +41,14 @@ public ImplicitPublicMemberInspection(RubberduckParserState state) DeclarationType.PropertySet }; - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { - var issues = from item in UserDeclarations - where ProcedureTypes.Contains(item.DeclarationType) - && item.Accessibility == Accessibility.Implicit - select new DeclarationInspectionResult(this, - string.Format(InspectionResults.ImplicitPublicMemberInspection, item.IdentifierName), - item); - return issues; + return declaration.Accessibility == Accessibility.Implicit; + } + + protected override string ResultDescription(Declaration declaration) + { + return string.Format(InspectionResults.ImplicitPublicMemberInspection, declaration.IdentifierName); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitVariantReturnTypeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitVariantReturnTypeInspection.cs index 0fff0e93d7..bd29777c43 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitVariantReturnTypeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitVariantReturnTypeInspection.cs @@ -1,14 +1,7 @@ -using System.Collections.Generic; -using System.Linq; -using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; namespace Rubberduck.Inspections.Concrete { @@ -32,20 +25,15 @@ namespace Rubberduck.Inspections.Concrete /// End Function /// ]]> /// - public sealed class ImplicitVariantReturnTypeInspection : InspectionBase + public sealed class ImplicitVariantReturnTypeInspection : ImplicitTypeInspectionBase { public ImplicitVariantReturnTypeInspection(RubberduckParserState state) - : base(state) { } + : base(state, DeclarationType.Function) + {} - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(Declaration declaration) { - var issues = from item in State.DeclarationFinder.UserDeclarations(DeclarationType.Function) - where !item.IsTypeSpecified - let issue = new {Declaration = item, QualifiedContext = new QualifiedContext(item.QualifiedName, item.Context)} - select new DeclarationInspectionResult(this, - string.Format(InspectionResults.ImplicitVariantReturnTypeInspection, item.IdentifierName), - item); - return issues; + return string.Format(InspectionResults.ImplicitVariantReturnTypeInspection, declaration.IdentifierName); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs index d589146ac1..dafd800c8b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs @@ -1,37 +1,40 @@ -using System.Collections.Generic; -using System.Linq; -using Rubberduck.Inspections.Abstract; +using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Symbols; using Rubberduck.Resources.Inspections; -namespace Rubberduck.CodeAnalysis.Inspections.Concrete +namespace Rubberduck.Inspections.Concrete { - public sealed class ImplicitlyTypedConstInspection : InspectionBase + /// + /// Warns about constants that don't have an explicitly defined type. + /// + /// + /// All constants have a declared type, whether a type is specified or not. The implicit type is determined by the compiler based on the value, which is not always the expected type. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public sealed class ImplicitlyTypedConstInspection : ImplicitTypeInspectionBase { public ImplicitlyTypedConstInspection(RubberduckParserState state) - : base(state) { } + : base(state, DeclarationType.Constant) + {} - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(Declaration declaration) { - var declarationFinder = DeclarationFinderProvider.DeclarationFinder; - - var implicitlyTypedConsts = declarationFinder.UserDeclarations(DeclarationType.Constant) - .Where(declaration => !declaration.IsTypeSpecified); - - return implicitlyTypedConsts.Select(Result); - } - - private IInspectionResult Result(Declaration declaration) - { - var description = string.Format(InspectionResults.ImplicitlyTypedConstInspection, declaration.IdentifierName); - - return new DeclarationInspectionResult( - this, - description, - declaration); + return string.Format(InspectionResults.ImplicitlyTypedConstInspection, declaration.IdentifierName); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IntegerDataTypeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IntegerDataTypeInspection.cs index 9cbbbf203f..7f7216d8f6 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IntegerDataTypeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IntegerDataTypeInspection.cs @@ -8,7 +8,6 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.VBA.Extensions; using Rubberduck.Resources; namespace Rubberduck.Inspections.Concrete diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/LineLabelNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/LineLabelNotUsedInspection.cs index 7d6f91f8f4..195169ec1e 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/LineLabelNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/LineLabelNotUsedInspection.cs @@ -1,16 +1,11 @@ -using System.Collections.Generic; using System.Linq; -using Antlr4.Runtime; -using Rubberduck.Common; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using static Rubberduck.Parsing.Grammar.VBAParser; using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -43,24 +38,28 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class LineLabelNotUsedInspection : InspectionBase + public sealed class LineLabelNotUsedInspection : DeclarationInspectionBase { - public LineLabelNotUsedInspection(RubberduckParserState state) : base(state) { } + public LineLabelNotUsedInspection(RubberduckParserState state) + : base(state, DeclarationType.LineLabel) + {} - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { - var labels = State.DeclarationFinder.UserDeclarations(DeclarationType.LineLabel); - var declarations = labels - .Where(declaration => - !declaration.IsWithEvents - && declaration.Context is IdentifierStatementLabelContext - && (!declaration.References.Any() || declaration.References.All(reference => reference.IsAssignment))); + return declaration != null + && !declaration.IsWithEvents + && declaration.Context is IdentifierStatementLabelContext + && declaration.References.All(reference => reference.IsAssignment); + } - return declarations.Select(issue => - new DeclarationInspectionResult(this, - string.Format(InspectionResults.IdentifierNotUsedInspection, issue.DeclarationType.ToLocalizedString(), issue.IdentifierName), - issue, - new QualifiedContext(issue.QualifiedName.QualifiedModuleName, ((IdentifierStatementLabelContext)issue.Context).legalLabelIdentifier()))); + protected override string ResultDescription(Declaration declaration) + { + var declarationType = declaration.DeclarationType.ToLocalizedString(); + var declarationName = declaration.IdentifierName; + return string.Format( + InspectionResults.IdentifierNotUsedInspection, + declarationType, + declarationName); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleWithoutFolderInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleWithoutFolderInspection.cs index ec1a4be9e0..a500171a3d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleWithoutFolderInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleWithoutFolderInspection.cs @@ -1,12 +1,10 @@ -using System.Collections.Generic; -using System.Linq; +using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.Annotations; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -30,21 +28,20 @@ namespace Rubberduck.Inspections.Concrete /// ' ... /// ]]> /// - public sealed class ModuleWithoutFolderInspection : InspectionBase + public sealed class ModuleWithoutFolderInspection : DeclarationInspectionBase { public ModuleWithoutFolderInspection(RubberduckParserState state) - : base(state) + : base(state, DeclarationType.Module) {} - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { - var modulesWithoutFolderAnnotation = State.DeclarationFinder.UserDeclarations(Parsing.Symbols.DeclarationType.Module) - .Where(w => !w.Annotations.Any(pta => pta.Annotation is FolderAnnotation)) - .ToList(); + return !declaration.Annotations.Any(pta => pta.Annotation is FolderAnnotation); + } - return modulesWithoutFolderAnnotation - .Select(declaration => - new DeclarationInspectionResult(this, string.Format(InspectionResults.ModuleWithoutFolderInspection, declaration.IdentifierName), declaration)); + protected override string ResultDescription(Declaration declaration) + { + return string.Format(InspectionResults.ModuleWithoutFolderInspection, declaration.IdentifierName); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteGlobalInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteGlobalInspection.cs index 3354c1ea52..f59eab96d1 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteGlobalInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteGlobalInspection.cs @@ -1,13 +1,9 @@ -using System.Collections.Generic; -using System.Linq; -using Rubberduck.Common; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -29,17 +25,25 @@ namespace Rubberduck.Inspections.Concrete /// Public Foo As Long /// ]]> /// - public sealed class ObsoleteGlobalInspection : InspectionBase + public sealed class ObsoleteGlobalInspection : DeclarationInspectionBase { public ObsoleteGlobalInspection(RubberduckParserState state) : base(state) { } - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { - return from item in UserDeclarations - where item.Accessibility == Accessibility.Global && item.Context != null - select new DeclarationInspectionResult(this, - string.Format(InspectionResults.ObsoleteGlobalInspection, item.DeclarationType.ToLocalizedString(), item.IdentifierName), item); + return declaration.Accessibility == Accessibility.Global + && declaration.Context != null; + } + + protected override string ResultDescription(Declaration declaration) + { + var declarationType = declaration.DeclarationType.ToLocalizedString(); + var declarationName = declaration.IdentifierName; + return string.Format( + InspectionResults.ObsoleteGlobalInspection, + declarationType, + declarationName); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ShadowedDeclarationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ShadowedDeclarationInspection.cs index 6ccde4fa7a..6fc3890a24 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ShadowedDeclarationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ShadowedDeclarationInspection.cs @@ -8,7 +8,6 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.VBA.Extensions; using Rubberduck.Resources; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/KeywordsUsedAsMemberInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/KeywordsUsedAsMemberInspection.cs index 788eed56c0..d54eef5057 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/KeywordsUsedAsMemberInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/KeywordsUsedAsMemberInspection.cs @@ -2,10 +2,12 @@ using System.Linq; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Results; +using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; namespace Rubberduck.Inspections.Inspections.Concrete.ThunderCode @@ -19,23 +21,21 @@ namespace Rubberduck.Inspections.Inspections.Concrete.ThunderCode /// While perfectly legal as Type or Enum member names, these identifiers should be avoided: /// they need to be square-bracketed everywhere they are used. /// - public class KeywordsUsedAsMemberInspection : InspectionBase + public class KeywordsUsedAsMemberInspection : DeclarationInspectionBase { - public KeywordsUsedAsMemberInspection(RubberduckParserState state) : base(state) { } + public KeywordsUsedAsMemberInspection(RubberduckParserState state) + : base(state, DeclarationType.EnumerationMember, DeclarationType.UserDefinedTypeMember) + {} - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { - return State.DeclarationFinder.UserDeclarations(DeclarationType.UserDefinedTypeMember) - .Concat(State.DeclarationFinder.UserDeclarations(DeclarationType.EnumerationMember)) - .Where(m => ReservedKeywords.Any(k => - k.ToLowerInvariant().Equals( - m.IdentifierName.Trim().TrimStart('[').TrimEnd(']').ToLowerInvariant()))) - .Select(m => new DeclarationInspectionResult( - this, - InspectionResults.KeywordsUsedAsMemberInspection. - ThunderCodeFormat(m.IdentifierName), - m - )); + var normalizedMemberName = declaration.IdentifierName.ToLowerInvariant(); + return ReservedKeywordsInLowerCase.Contains(normalizedMemberName); + } + + protected override string ResultDescription(Declaration declaration) + { + return InspectionResults.KeywordsUsedAsMemberInspection.ThunderCodeFormat(declaration.IdentifierName); } // MS-VBAL 3.3.5.2 Reserved Identifiers and IDENTIFIER @@ -164,5 +164,9 @@ protected override IEnumerable DoGetInspectionResults() Tokens.TypeOf, Tokens.XOr }; + + private static readonly HashSet ReservedKeywordsInLowerCase = + ReservedKeywords.Select(keyword => keyword.ToLowerInvariant()) + .ToHashSet(); } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NonBreakingSpaceIdentifierInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NonBreakingSpaceIdentifierInspection.cs index 4886765c01..4850c622af 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NonBreakingSpaceIdentifierInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NonBreakingSpaceIdentifierInspection.cs @@ -1,9 +1,7 @@ -using System.Collections.Generic; -using System.Linq; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Inspections.Abstract; +using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; namespace Rubberduck.Inspections.Inspections.Concrete.ThunderCode @@ -16,18 +14,22 @@ namespace Rubberduck.Inspections.Inspections.Concrete.ThunderCode /// code our friend Andrew Jackson would have written to confuse Rubberduck's parser and/or resolver. /// This inspection may accidentally reveal non-breaking spaces in code copied and pasted from a website. /// - public class NonBreakingSpaceIdentifierInspection : InspectionBase + public class NonBreakingSpaceIdentifierInspection : DeclarationInspectionBase { private const string Nbsp = "\u00A0"; - public NonBreakingSpaceIdentifierInspection(RubberduckParserState state) : base(state) { } + public NonBreakingSpaceIdentifierInspection(RubberduckParserState state) + : base(state) + {} - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { - return State.DeclarationFinder.AllUserDeclarations - .Where(d => d.IdentifierName.Contains(Nbsp)) - .Select(d => new DeclarationInspectionResult( - this, InspectionResults.NonBreakingSpaceIdentifierInspection.ThunderCodeFormat(d.IdentifierName), d)); + return declaration.IdentifierName.Contains(Nbsp); + } + + protected override string ResultDescription(Declaration declaration) + { + return InspectionResults.NonBreakingSpaceIdentifierInspection.ThunderCodeFormat(declaration.IdentifierName); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UndeclaredVariableInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UndeclaredVariableInspection.cs index 56f5927237..08e88954e9 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UndeclaredVariableInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UndeclaredVariableInspection.cs @@ -1,12 +1,8 @@ -using System.Collections.Generic; -using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -33,16 +29,20 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class UndeclaredVariableInspection : InspectionBase + public sealed class UndeclaredVariableInspection : DeclarationInspectionBase { public UndeclaredVariableInspection(RubberduckParserState state) - : base(state) { } + : base(state, DeclarationType.Variable) + {} - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { - return State.DeclarationFinder.UserDeclarations(DeclarationType.Variable) - .Where(item => item.IsUndeclared) - .Select(item => new DeclarationInspectionResult(this, string.Format(InspectionResults.UndeclaredVariableInspection, item.IdentifierName), item)); + return declaration.IsUndeclared; + } + + protected override string ResultDescription(Declaration declaration) + { + return string.Format(InspectionResults.UndeclaredVariableInspection, declaration.IdentifierName); } } } \ No newline at end of file diff --git a/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs b/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs index 36911c524b..c76b9cbede 100644 --- a/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs +++ b/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs @@ -1,6 +1,6 @@ using System.Linq; using NUnit.Framework; -using Rubberduck.CodeAnalysis.Inspections.Concrete; +using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/Inspections/ThunderCode/ThunderCodeInspectionTests.cs b/RubberduckTests/Inspections/ThunderCode/ThunderCodeInspectionTests.cs index a2fef0ec90..9e70612a12 100644 --- a/RubberduckTests/Inspections/ThunderCode/ThunderCodeInspectionTests.cs +++ b/RubberduckTests/Inspections/ThunderCode/ThunderCodeInspectionTests.cs @@ -43,8 +43,6 @@ public void NonBreakingSpaceIdentifier_IllegalInputCausesParserError(int expecte } } - - [Test] [TestCase(2, @"Do")] [TestCase(2, @"Loop")] @@ -69,6 +67,26 @@ Private Enum HawHaw ThunderCatsGo(func, inputCode, expectedCount); } + [Test] + [TestCase( @"[Do]")] + [TestCase(@"Do ")] + [TestCase(@" Do")] + [TestCase(@"")] + [TestCase(@"[]")] + public void KeywordsUsedAsMember_CorrectlyDistinguishesBracketedIdentifiers(string inputVariable) + { + var inputCode = $@" +Private Enum HawHaw + [{inputVariable}] = 1 +End Enum"; + + var func = new Func(state => + new KeywordsUsedAsMemberInspection(state)); + ThunderCatsGo(func, inputCode, 0); + } + + + // NOTE: the inspection only covers trivial cases and is not exhaustive // For that reason, some of test cases which the evil continuations exists // may still pass without any results. To cover them all would likely be too From c8f72427ba42daeaa2f9f067895c5fbe5806efcb Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Wed, 5 Feb 2020 01:40:13 +0100 Subject: [PATCH 214/461] Replace the dynamic PropertyBag on inspection results It is replaced by a generic method and a dedicated property for the names of disabled quick fixes. The three kinds of inspection results now also have one generic subtype each that takes an additional properties value of the generic type and returns it via the corresponding generic properties method. The consumer of the result properties still has to know the type of properties and what they represent (We want to avoid circular dependencies to the quick fixes.), but the properties can now be provided in a strongly typed fashion and lend themselves better to generation in inspection base classes. --- .../Abstract/DeclarationInspectionBase.cs | 12 ++- .../DeclarationInspectionMultiResultBase.cs | 93 ++++++++++++++++++ .../IdentifierReferenceInspectionBase.cs | 12 ++- ...ReferenceInspectionFromDeclarationsBase.cs | 12 ++- .../Abstract/InspectionResultBase.cs | 9 +- .../AttributeValueOutOfSyncInspection.cs | 65 ++++++------- .../DuplicatedAnnotationInspection.cs | 39 +++----- .../SheetAccessedUsingStringInspection.cs | 10 +- .../Concrete/MissingAttributeInspection.cs | 42 +++----- .../MissingMemberAnnotationInspection.cs | 56 ++++------- .../MissingModuleAnnotationInspection.cs | 69 +++++-------- ...bjectWhereProcedureIsRequiredInspection.cs | 8 +- .../SuspiciousLetAssignmentInspection.cs | 16 ++- .../UnhandledOnErrorResumeNextInspection.cs | 5 +- .../Concrete/UseMeaningfulNameInspection.cs | 97 +++++++++++++------ .../Results/DeclarationInspectionResult.cs | 46 ++++++++- .../IdentifierReferenceInspectionResult.cs | 43 +++++++- .../QualifiedContextInspectionResult.cs | 41 +++++++- .../AccessSheetUsingCodeNameQuickFix.cs | 6 +- .../AddAttributeAnnotationQuickFix.cs | 3 +- .../QuickFixes/AddMissingAttributeQuickFix.cs | 2 +- .../AdjustAttributeAnnotationQuickFix.cs | 25 ++--- .../AdjustAttributeValuesQuickFix.cs | 23 +++-- .../QuickFixes/ExpandDefaultMemberQuickFix.cs | 2 +- ...sMissingOnInappropriateArgumentQuickFix.cs | 6 +- .../QuickFixes/QuickFixProvider.cs | 22 +---- .../QuickFixes/RemoveAnnotationQuickFix.cs | 3 +- .../QuickFixes/RemoveAttributeQuickFix.cs | 6 +- .../RemoveDuplicatedAnnotationQuickFix.cs | 4 +- .../RestoreErrorHandlingQuickFix.cs | 4 +- .../AttributeAnnotationExtensions.cs | 6 +- .../Inspections/Abstract/IInspectionResult.cs | 3 +- .../AttributeValueOutOfSyncInspectionTests.cs | 6 +- .../MissingMemberAnnotationInspectionTests.cs | 3 +- .../MissingModuleAnnotationInspectionTests.cs | 3 +- ...WhereProcedureIsRequiredInspectionTests.cs | 6 +- .../SuspiciousLetAssignmentInspectionTests.cs | 9 +- .../QuickFixes/QuickFixProviderTests.cs | 2 +- ...RemoveDuplicatedAnnotationQuickFixTests.cs | 2 +- 39 files changed, 499 insertions(+), 322 deletions(-) create mode 100644 Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionMultiResultBase.cs diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs index 119e71f0b3..9a4aa5c7da 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs @@ -31,6 +31,8 @@ protected DeclarationInspectionBase(RubberduckParserState state, DeclarationType protected abstract bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder); protected abstract string ResultDescription(Declaration declaration); + protected virtual ICollection DisabledQuickFixes(Declaration declaration) => new List(); + protected override IEnumerable DoGetInspectionResults() { var finder = DeclarationFinderProvider.DeclarationFinder; @@ -82,7 +84,8 @@ protected virtual IInspectionResult InspectionResult(Declaration declaration) return new DeclarationInspectionResult( this, ResultDescription(declaration), - declaration); + declaration, + disabledQuickFixes: DisabledQuickFixes(declaration)); } } @@ -108,6 +111,8 @@ protected DeclarationInspectionBase(RubberduckParserState state, DeclarationType protected abstract (bool isResult, T properties) IsResultDeclarationWithAdditionalProperties(Declaration declaration, DeclarationFinder finder); protected abstract string ResultDescription(Declaration declaration, T properties); + protected virtual ICollection DisabledQuickFixes(Declaration declaration, T properties) => new List(); + protected override IEnumerable DoGetInspectionResults() { var finder = DeclarationFinderProvider.DeclarationFinder; @@ -158,11 +163,12 @@ protected virtual IEnumerable RelevantDeclarationsInModule(Qualifie protected virtual IInspectionResult InspectionResult(Declaration declaration, T properties) { - return new DeclarationInspectionResult( + return new DeclarationInspectionResult( this, ResultDescription(declaration, properties), declaration, - properties: properties); + properties: properties, + disabledQuickFixes: DisabledQuickFixes(declaration, properties)); } } } \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionMultiResultBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionMultiResultBase.cs new file mode 100644 index 0000000000..91af9db38b --- /dev/null +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionMultiResultBase.cs @@ -0,0 +1,93 @@ +using System.Collections.Generic; +using System.Linq; +using Rubberduck.Inspections.Results; +using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.VBEditor; + +namespace Rubberduck.Inspections.Abstract +{ + public abstract class DeclarationInspectionMultiResultBase : InspectionBase + { + protected readonly DeclarationType[] RelevantDeclarationTypes; + protected readonly DeclarationType[] ExcludeDeclarationTypes; + + protected DeclarationInspectionMultiResultBase(RubberduckParserState state, params DeclarationType[] relevantDeclarationTypes) + : base(state) + { + RelevantDeclarationTypes = relevantDeclarationTypes; + ExcludeDeclarationTypes = new DeclarationType[0]; + } + + protected DeclarationInspectionMultiResultBase(RubberduckParserState state, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) + : base(state) + { + RelevantDeclarationTypes = relevantDeclarationTypes; + ExcludeDeclarationTypes = excludeDeclarationTypes; + } + + protected abstract IEnumerable ResultProperties(Declaration declaration, DeclarationFinder finder); + protected abstract string ResultDescription(Declaration declaration, T properties); + + protected virtual ICollection DisabledQuickFixes(Declaration declaration, T properties) => new List(); + + protected override IEnumerable DoGetInspectionResults() + { + var finder = DeclarationFinderProvider.DeclarationFinder; + + var results = new List(); + foreach (var moduleDeclaration in State.DeclarationFinder.UserDeclarations(DeclarationType.Module)) + { + if (moduleDeclaration == null) + { + continue; + } + + var module = moduleDeclaration.QualifiedModuleName; + results.AddRange(DoGetInspectionResults(module, finder)); + } + + return results; + } + + private IEnumerable DoGetInspectionResults(QualifiedModuleName module) + { + var finder = DeclarationFinderProvider.DeclarationFinder; + return DoGetInspectionResults(module, finder); + } + + private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + { + var objectionableDeclarationsWithAdditionalProperties = RelevantDeclarationsInModule(module, finder) + .SelectMany(declaration => ResultProperties(declaration, finder) + .Select(properties => (declaration, properties))); + + return objectionableDeclarationsWithAdditionalProperties + .Select(tpl => InspectionResult(tpl.declaration, tpl.properties)) + .ToList(); + } + + protected virtual IEnumerable RelevantDeclarationsInModule(QualifiedModuleName module, DeclarationFinder finder) + { + var potentiallyRelevantDeclarations = RelevantDeclarationTypes.Length == 0 + ? finder.AllUserDeclarations + : RelevantDeclarationTypes + .SelectMany(declarationType => finder.Members(module, declarationType)) + .Distinct(); + return potentiallyRelevantDeclarations + .Where(declaration => ! ExcludeDeclarationTypes.Contains(declaration.DeclarationType)); + } + + protected virtual IInspectionResult InspectionResult(Declaration declaration, T properties) + { + return new DeclarationInspectionResult( + this, + ResultDescription(declaration, properties), + declaration, + properties: properties, + disabledQuickFixes: DisabledQuickFixes(declaration, properties)); + } + } +} \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs index dfd2f56c84..6a5b1b4fee 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs @@ -18,6 +18,8 @@ protected IdentifierReferenceInspectionBase(RubberduckParserState state) protected abstract bool IsResultReference(IdentifierReference reference, DeclarationFinder finder); protected abstract string ResultDescription(IdentifierReference reference); + protected virtual ICollection DisabledQuickFixes(IdentifierReference reference) => new List(); + protected override IEnumerable DoGetInspectionResults() { var finder = DeclarationFinderProvider.DeclarationFinder; @@ -64,7 +66,8 @@ protected virtual IInspectionResult InspectionResult(IdentifierReference referen this, ResultDescription(reference), declarationFinderProvider, - reference); + reference, + DisabledQuickFixes(reference)); } } @@ -77,6 +80,8 @@ protected IdentifierReferenceInspectionBase(RubberduckParserState state) protected abstract (bool isResult, T properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder); protected abstract string ResultDescription(IdentifierReference reference, T properties); + protected virtual ICollection DisabledQuickFixes(IdentifierReference reference, T properties) => new List(); + protected override IEnumerable DoGetInspectionResults() { var finder = DeclarationFinderProvider.DeclarationFinder; @@ -121,12 +126,13 @@ protected virtual IEnumerable ReferencesInModule(QualifiedM protected virtual IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider, T properties) { - return new IdentifierReferenceInspectionResult( + return new IdentifierReferenceInspectionResult( this, ResultDescription(reference, properties), declarationFinderProvider, reference, - properties); + properties, + DisabledQuickFixes(reference, properties)); } } } \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs index 7232cb7f21..0a3baba8a4 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs @@ -18,6 +18,8 @@ protected IdentifierReferenceInspectionFromDeclarationsBase(RubberduckParserStat protected abstract IEnumerable ObjectionableDeclarations(DeclarationFinder finder); protected abstract string ResultDescription(IdentifierReference reference); + protected virtual ICollection DisabledQuickFixes(IdentifierReference reference) => new List(); + protected override IEnumerable DoGetInspectionResults() { var finder = DeclarationFinderProvider.DeclarationFinder; @@ -60,7 +62,8 @@ protected virtual IInspectionResult InspectionResult(IdentifierReference referen this, ResultDescription(reference), declarationFinderProvider, - reference); + reference, + DisabledQuickFixes(reference)); } } @@ -74,6 +77,8 @@ protected IdentifierReferenceInspectionFromDeclarationsBase(RubberduckParserStat protected abstract (bool isResult, T properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder); protected abstract string ResultDescription(IdentifierReference reference, T properties); + protected virtual ICollection DisabledQuickFixes(IdentifierReference reference, T properties) => new List(); + protected override IEnumerable DoGetInspectionResults() { var finder = DeclarationFinderProvider.DeclarationFinder; @@ -112,12 +117,13 @@ protected IEnumerable DoGetInspectionResults(QualifiedModuleN protected virtual IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider, T properties) { - return new IdentifierReferenceInspectionResult( + return new IdentifierReferenceInspectionResult( this, ResultDescription(reference, properties), declarationFinderProvider, reference, - properties); + properties, + DisabledQuickFixes(reference, properties)); } } } \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionResultBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionResultBase.cs index e57d6c1b15..d3907786df 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionResultBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionResultBase.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using Antlr4.Runtime; using Rubberduck.Common; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.VBEditor; @@ -18,7 +17,7 @@ protected InspectionResultBase(IInspection inspection, Declaration target, QualifiedSelection qualifiedSelection, QualifiedMemberName? qualifiedMemberName, - dynamic properties) + ICollection disabledQuickFixes = null) { Inspection = inspection; Description = description?.Capitalize(); @@ -27,7 +26,7 @@ protected InspectionResultBase(IInspection inspection, Target = target; QualifiedSelection = qualifiedSelection; QualifiedMemberName = qualifiedMemberName; - Properties = properties ?? new PropertyBag(); + DisabledQuickFixes = disabledQuickFixes ?? new List(); } public IInspection Inspection { get; } @@ -36,7 +35,9 @@ protected InspectionResultBase(IInspection inspection, public QualifiedMemberName? QualifiedMemberName { get; } public ParserRuleContext Context { get; } public Declaration Target { get; } - public dynamic Properties { get; } + public ICollection DisabledQuickFixes { get; } + + public virtual T Properties() => default; public virtual bool ChangesInvalidateResult(ICollection modifiedModules) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/AttributeValueOutOfSyncInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/AttributeValueOutOfSyncInspection.cs index 38886b8486..399aee62df 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/AttributeValueOutOfSyncInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/AttributeValueOutOfSyncInspection.cs @@ -1,13 +1,11 @@ using System.Collections.Generic; using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Inspections; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; using Rubberduck.VBEditor.SafeComWrappers; @@ -39,45 +37,36 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [CannotAnnotate] - public sealed class AttributeValueOutOfSyncInspection : InspectionBase + public sealed class AttributeValueOutOfSyncInspection : DeclarationInspectionMultiResultBase<(IParseTreeAnnotation Annotation, string AttributeName, IReadOnlyList AttributeValues)> { public AttributeValueOutOfSyncInspection(RubberduckParserState state) :base(state) { } - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable<(IParseTreeAnnotation Annotation, string AttributeName, IReadOnlyList AttributeValues)> ResultProperties(Declaration declaration, DeclarationFinder finder) { - var declarationsWithAttributeAnnotations = State.DeclarationFinder.AllUserDeclarations - .Where(declaration => declaration.Annotations.Any(pta => pta.Annotation is IAttributeAnnotation)); - var results = new List(); - foreach (var declaration in declarationsWithAttributeAnnotations.Where(decl => decl.QualifiedModuleName.ComponentType != ComponentType.Document)) + if (declaration.QualifiedModuleName.ComponentType == ComponentType.Document) { - foreach (var annotationInstance in declaration.Annotations.Where(pta => pta.Annotation is IAttributeAnnotation)) - { - // cast is safe given the predicate in the foreach - var annotation = (IAttributeAnnotation)annotationInstance.Annotation; - if (HasDifferingAttributeValues(declaration, annotationInstance, out var attributeValues)) - { - var attributeName = annotation.Attribute(annotationInstance); - - var description = string.Format(InspectionResults.AttributeValueOutOfSyncInspection, - attributeName, - string.Join(", ", attributeValues), - annotation.Name); + return Enumerable.Empty<(IParseTreeAnnotation Annotation, string AttributeName, IReadOnlyList AttributeValues)>(); + } - var result = new DeclarationInspectionResult(this, description, declaration, - new QualifiedContext(declaration.QualifiedModuleName, annotationInstance.Context)); - result.Properties.Annotation = annotationInstance; - result.Properties.AttributeName = attributeName; - result.Properties.AttributeValues = attributeValues; + return OutOfSyncAttributeAnnotations(declaration); + } - results.Add(result); - } + private static IEnumerable<(IParseTreeAnnotation Annotation, string AttributeName, IReadOnlyList AttributeValues)> OutOfSyncAttributeAnnotations(Declaration declaration) + { + foreach (var pta in declaration.Annotations) + { + if (!(pta.Annotation is IAttributeAnnotation annotation) + || !HasDifferingAttributeValues(declaration, pta, out var attributeValues)) + { + continue; } - } - return results; + var attributeName = annotation.Attribute(pta); + yield return (pta, attributeName, attributeValues); + } } private static bool HasDifferingAttributeValues(Declaration declaration, IParseTreeAnnotation annotationInstance, out IReadOnlyList attributeValues) @@ -87,10 +76,10 @@ private static bool HasDifferingAttributeValues(Declaration declaration, IParseT attributeValues = new List(); return false; } - var attribute = annotation.Attribute(annotationInstance); + var attributeNodes = declaration.DeclarationType.HasFlag(DeclarationType.Module) - ? declaration.Attributes.AttributeNodesFor(annotationInstance) - : declaration.Attributes.AttributeNodesFor(annotationInstance, declaration.IdentifierName); + ? declaration.Attributes.AttributeNodesFor(annotationInstance) + : declaration.Attributes.AttributeNodesFor(annotationInstance, declaration.IdentifierName); foreach (var attributeNode in attributeNodes) { @@ -104,5 +93,15 @@ private static bool HasDifferingAttributeValues(Declaration declaration, IParseT attributeValues = new List(); return false; } + + protected override string ResultDescription(Declaration declaration, (IParseTreeAnnotation Annotation, string AttributeName, IReadOnlyList AttributeValues) properties) + { + var (pta, attributeName, attributeValues) = properties; + var annotationName = pta.Annotation.Name; + return string.Format(InspectionResults.AttributeValueOutOfSyncInspection, + attributeName, + string.Join(", ", attributeValues), + annotationName); + } } } \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DuplicatedAnnotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DuplicatedAnnotationInspection.cs index f0da7bac6f..1b79395881 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DuplicatedAnnotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DuplicatedAnnotationInspection.cs @@ -1,9 +1,10 @@ using System.Collections.Generic; using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Parsing.Annotations; +using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; namespace Rubberduck.Inspections.Concrete @@ -33,33 +34,23 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class DuplicatedAnnotationInspection : InspectionBase + public sealed class DuplicatedAnnotationInspection : DeclarationInspectionMultiResultBase { - public DuplicatedAnnotationInspection(RubberduckParserState state) : base(state) + public DuplicatedAnnotationInspection(RubberduckParserState state) + : base(state) + { } + + protected override IEnumerable ResultProperties(Declaration declaration, DeclarationFinder finder) { + return declaration.Annotations + .GroupBy(pta => pta.Annotation) + .Where(group => !group.First().Annotation.AllowMultiple && group.Count() > 1) + .Select(group => group.Key); } - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(Declaration declaration, IAnnotation annotation) { - var issues = new List(); - - foreach (var declaration in State.AllUserDeclarations) - { - var duplicateAnnotations = declaration.Annotations - .GroupBy(pta => pta.Annotation) - .Where(group => !group.First().Annotation.AllowMultiple && group.Count() > 1); - - issues.AddRange(duplicateAnnotations.Select(duplicate => - { - var result = new DeclarationInspectionResult( - this, string.Format(InspectionResults.DuplicatedAnnotationInspection, duplicate.Key.ToString()), declaration); - - result.Properties.Annotation = duplicate.Key; - return result; - })); - } - - return issues; + return string.Format(InspectionResults.DuplicatedAnnotationInspection, annotation); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs index b39f6195e4..21ea528c33 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs @@ -45,7 +45,7 @@ namespace Rubberduck.Inspections.Concrete /// [RequiredHost("EXCEL.EXE")] [RequiredLibrary("Excel")] - public class SheetAccessedUsingStringInspection : IdentifierReferenceInspectionFromDeclarationsBase + public class SheetAccessedUsingStringInspection : IdentifierReferenceInspectionFromDeclarationsBase { private readonly IProjectsProvider _projectsProvider; @@ -86,7 +86,7 @@ protected override IEnumerable ObjectionableDeclarations(Declaratio return relevantProperties; } - protected override (bool isResult, PropertyBag properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder) + protected override (bool isResult, string properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder) { var sheetNameArgumentLiteralExpressionContext = SheetNameArgumentLiteralExpressionContext(reference); @@ -104,9 +104,7 @@ protected override (bool isResult, PropertyBag properties) IsResultReferenceWith return (false, null); } - dynamic properties = new PropertyBag(); - properties.CodeName = codeName; - return (true, properties); + return (true, codeName); } private static VBAParser.LiteralExpressionContext SheetNameArgumentLiteralExpressionContext(IdentifierReference reference) @@ -164,7 +162,7 @@ private static string ComponentPropertyValue(IVBComponent component, string prop return null; } - protected override string ResultDescription(IdentifierReference reference, PropertyBag properties) + protected override string ResultDescription(IdentifierReference reference, string codeName) { return InspectionResults.SheetAccessedUsingStringInspection; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAttributeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAttributeInspection.cs index 8471baa580..76aa4bc62a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAttributeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAttributeInspection.cs @@ -9,6 +9,7 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; using Rubberduck.VBEditor.SafeComWrappers; @@ -39,42 +40,29 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [CannotAnnotate] - public sealed class MissingAttributeInspection : InspectionBase + public sealed class MissingAttributeInspection : DeclarationInspectionMultiResultBase { public MissingAttributeInspection(RubberduckParserState state) : base(state) {} - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable ResultProperties(Declaration declaration, DeclarationFinder finder) { - var declarationsWithAttributeAnnotations = State.DeclarationFinder.AllUserDeclarations - .Where(declaration => declaration.Annotations.Any(pta => pta.Annotation is IAttributeAnnotation) - && (declaration.DeclarationType.HasFlag(DeclarationType.Module) - || declaration.AttributesPassContext != null)); - var results = new List(); - - // prefilter declarations to reduce searchspace - var interestingDeclarations = declarationsWithAttributeAnnotations.Where(decl => decl.QualifiedModuleName.ComponentType != ComponentType.Document - && !decl.IsIgnoringInspectionResultFor(AnnotationName)); - foreach (var declaration in interestingDeclarations) + if (!declaration.DeclarationType.HasFlag(DeclarationType.Module) + && declaration.AttributesPassContext == null + || declaration.QualifiedModuleName.ComponentType == ComponentType.Document) { - foreach (var annotationInstance in declaration.Annotations.Where(pta => pta.Annotation is IAttributeAnnotation)) - { - var annotation = (IAttributeAnnotation)annotationInstance.Annotation; - if (MissesCorrespondingAttribute(declaration, annotationInstance)) - { - var description = string.Format(InspectionResults.MissingAttributeInspection, declaration.IdentifierName, annotation.Name); - - var result = new DeclarationInspectionResult(this, description, declaration, - new QualifiedContext(declaration.QualifiedModuleName, annotationInstance.Context)); - result.Properties.Annotation = annotationInstance; - - results.Add(result); - } - } + return Enumerable.Empty(); } - return results; + return declaration.Annotations + .Where(pta => pta.Annotation is IAttributeAnnotation + && MissesCorrespondingAttribute(declaration, pta)); + } + + protected override string ResultDescription(Declaration declaration, IParseTreeAnnotation pta) + { + return string.Format(InspectionResults.MissingAttributeInspection, declaration.IdentifierName, pta.Annotation.Name); } private static bool MissesCorrespondingAttribute(Declaration declaration, IParseTreeAnnotation annotationInstance) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingMemberAnnotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingMemberAnnotationInspection.cs index c9d17d4d3c..44a2036365 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingMemberAnnotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingMemberAnnotationInspection.cs @@ -1,13 +1,10 @@ using System.Collections.Generic; using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing; using Rubberduck.Parsing.Annotations; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; using Rubberduck.VBEditor.SafeComWrappers; @@ -37,48 +34,22 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class MissingMemberAnnotationInspection : InspectionBase + public sealed class MissingMemberAnnotationInspection : DeclarationInspectionMultiResultBase<(string AttributeName, IReadOnlyList AttriguteValues)> { public MissingMemberAnnotationInspection(RubberduckParserState state) - :base(state) + :base(state, new DeclarationType[0], new []{DeclarationType.Module }) {} - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable<(string AttributeName, IReadOnlyList AttriguteValues)> ResultProperties(Declaration declaration, DeclarationFinder finder) { - var memberDeclarationsWithAttributes = State.DeclarationFinder.AllUserDeclarations - .Where(decl => !decl.DeclarationType.HasFlag(DeclarationType.Module) - && decl.Attributes.Any()); - - var declarationsToInspect = memberDeclarationsWithAttributes - // prefilter declarations to reduce searchspace - .Where(decl => decl.QualifiedModuleName.ComponentType != ComponentType.Document - && !decl.IsIgnoringInspectionResultFor(AnnotationName)); - - var results = new List(); - foreach (var declaration in declarationsToInspect) + if (declaration.QualifiedModuleName.ComponentType == ComponentType.Document) { - foreach (var attribute in declaration.Attributes) - { - if (MissesCorrespondingMemberAnnotation(declaration, attribute)) - { - var attributeBaseName = AttributeBaseName(declaration, attribute); - - var description = string.Format(InspectionResults.MissingMemberAnnotationInspection, - declaration.IdentifierName, - attributeBaseName, - string.Join(", ", attribute.Values)); - - var result = new DeclarationInspectionResult(this, description, declaration, - new QualifiedContext(declaration.QualifiedModuleName, declaration.Context)); - result.Properties.AttributeName = attributeBaseName; - result.Properties.AttributeValues = attribute.Values; - - results.Add(result); - } - } + return Enumerable.Empty<(string AttributeName, IReadOnlyList AttriguteValues)>(); } - return results; + return declaration.Attributes + .Where(attribute => MissesCorrespondingMemberAnnotation(declaration, attribute)) + .Select(attribute => (AttributeBaseName(declaration, attribute), attribute.Values)); } private static bool MissesCorrespondingMemberAnnotation(Declaration declaration, AttributeNode attribute) @@ -107,5 +78,14 @@ private static string AttributeBaseName(Declaration declaration, AttributeNode a { return Attributes.AttributeBaseName(attribute.Name, declaration.IdentifierName); } + + protected override string ResultDescription(Declaration declaration, (string AttributeName, IReadOnlyList AttriguteValues) properties) + { + var (attributeBaseName, attributeValues) = properties; + return string.Format(InspectionResults.MissingMemberAnnotationInspection, + declaration.IdentifierName, + attributeBaseName, + string.Join(", ", attributeValues)); + } } } \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingModuleAnnotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingModuleAnnotationInspection.cs index 7ac6a6646b..953347879d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingModuleAnnotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingModuleAnnotationInspection.cs @@ -1,16 +1,12 @@ using System.Collections.Generic; using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing; using Rubberduck.Parsing.Annotations; -using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; -using Rubberduck.VBEditor.SafeComWrappers; namespace Rubberduck.Inspections.Concrete { @@ -36,51 +32,28 @@ namespace Rubberduck.Inspections.Concrete /// ' ... /// ]]> /// - public sealed class MissingModuleAnnotationInspection : InspectionBase + public sealed class MissingModuleAnnotationInspection : DeclarationInspectionMultiResultBase<(string AttributeName, IReadOnlyList AttributeValues)> { public MissingModuleAnnotationInspection(RubberduckParserState state) - :base(state) + :base(state, new []{DeclarationType.Module}, new []{DeclarationType.Document}) {} - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable<(string AttributeName, IReadOnlyList AttributeValues)> ResultProperties(Declaration declaration, DeclarationFinder finder) { - var moduleDeclarationsWithAttributes = State.DeclarationFinder - .UserDeclarations(DeclarationType.Module) - .Where(decl => decl.Attributes.Any()); - - var declarationsToInspect = moduleDeclarationsWithAttributes - // prefilter declarations to reduce searchspace - .Where(decl => decl.QualifiedModuleName.ComponentType != ComponentType.Document - && !decl.IsIgnoringInspectionResultFor(AnnotationName)); - - var results = new List(); - foreach (var declaration in declarationsToInspect) - { - foreach (var attribute in declaration.Attributes) - { - if (IsDefaultAttribute(declaration, attribute)) - { - continue; - } - - if (MissesCorrespondingModuleAnnotation(declaration, attribute)) - { - var description = string.Format(InspectionResults.MissingMemberAnnotationInspection, - declaration.IdentifierName, - attribute.Name, - string.Join(", ", attribute.Values)); - - var result = new DeclarationInspectionResult(this, description, declaration, - new QualifiedContext(declaration.QualifiedModuleName, declaration.Context)); - result.Properties.AttributeName = attribute.Name; - result.Properties.AttributeValues = attribute.Values; + return declaration.Attributes + .Where(attribute => IsResultAttribute(attribute, declaration)) + .Select(PropertiesFromAttribute); + } - results.Add(result); - } - } - } + private static bool IsResultAttribute(AttributeNode attribute, Declaration declaration) + { + return !IsDefaultAttribute(declaration, attribute) + && MissesCorrespondingModuleAnnotation(declaration, attribute); + } - return results; + private static (string AttributeName, IReadOnlyList AttributeValues) PropertiesFromAttribute(AttributeNode attribute) + { + return (attribute.Name, attribute.Values); } private static bool IsDefaultAttribute(Declaration declaration, AttributeNode attribute) @@ -107,5 +80,13 @@ private static bool MissesCorrespondingModuleAnnotation(Declaration declaration, return !declaration.Annotations.Where(pta => pta.Annotation is IAttributeAnnotation) .Any(pta => ((IAttributeAnnotation)pta.Annotation).Attribute(pta).Equals(attribute.Name)); } + + protected override string ResultDescription(Declaration declaration, (string AttributeName, IReadOnlyList AttributeValues) properties) + { + return string.Format(InspectionResults.MissingMemberAnnotationInspection, + declaration.IdentifierName, + properties.AttributeName, + string.Join(", ", properties.AttributeValues)); + } } } \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs index 07ce23c3f0..f0e4050264 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs @@ -130,13 +130,13 @@ private IEnumerable UnboundInspectionResults(QualifiedModuleN private IInspectionResult UnboundInspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider) { - var result = new IdentifierReferenceInspectionResult( + var disabledQuickFixes = new List{ "ExpandDefaultMemberQuickFix" }; + return new IdentifierReferenceInspectionResult( this, UnboundResultDescription(reference), declarationFinderProvider, - reference); - result.Properties.DisableFixes = "ExpandDefaultMemberQuickFix"; - return result; + reference, + disabledQuickFixes); } private static string UnboundResultDescription(IdentifierReference reference) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs index 2a6392550c..e61503077b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs @@ -132,18 +132,16 @@ private bool IsImplicitDefaultMemberAssignment(IdentifierReference reference) private IInspectionResult InspectionResult(IdentifierReference lhsReference, IdentifierReference rhsReference, bool isUnbound) { - var result = new IdentifierReferenceInspectionResult( + var disabledQuickFixes = isUnbound + ? new List {"ExpandDefaultMemberQuickFix"} + : new List(); + return new IdentifierReferenceInspectionResult( this, ResultDescription(lhsReference, rhsReference), DeclarationFinderProvider, - lhsReference); - result.Properties.RhSReference = rhsReference; - if (isUnbound) - { - result.Properties.DisableFixes = "ExpandDefaultMemberQuickFix"; - } - - return result; + lhsReference, + rhsReference, + disabledQuickFixes); } private string ResultDescription(IdentifierReference lhsReference, IdentifierReference rhsReference) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs index 70b8878a63..b9168b5374 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs @@ -56,10 +56,9 @@ protected override IEnumerable DoGetInspectionResults() return Listener.Contexts .Select(result => { - dynamic properties = new PropertyBag(); - properties.UnhandledContexts = _unhandledContextsMap[result]; + var unhandledContexts = _unhandledContextsMap[result]; - return new QualifiedContextInspectionResult(this, InspectionResults.UnhandledOnErrorResumeNextInspection, result, properties); + return new QualifiedContextInspectionResult>(this, InspectionResults.UnhandledOnErrorResumeNextInspection, result, unhandledContexts); }); } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseMeaningfulNameInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseMeaningfulNameInspection.cs index 2446ba1bb1..549705af54 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseMeaningfulNameInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseMeaningfulNameInspection.cs @@ -1,17 +1,17 @@ using System.Collections.Generic; -using System.Globalization; using System.Linq; using Rubberduck.CodeAnalysis.Settings; -using Rubberduck.Common; using Rubberduck.Inspections.Abstract; +using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections; +using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Refactorings.Common; -using Rubberduck.Resources; using Rubberduck.SettingsProvider; +using Rubberduck.VBEditor; using static Rubberduck.Parsing.Grammar.VBAParser; namespace Rubberduck.Inspections.Concrete @@ -56,41 +56,82 @@ public UseMeaningfulNameInspection(RubberduckParserState state, IConfigurationSe protected override IEnumerable DoGetInspectionResults() { + var finder = DeclarationFinderProvider.DeclarationFinder; var settings = _settings.Read(); var whitelistedNames = settings.WhitelistedIdentifiers.Select(s => s.Identifier).ToArray(); + var handlers = finder.FindEventHandlers().ToHashSet(); - var handlers = State.DeclarationFinder.FindEventHandlers(); + var results = new List(); + foreach (var moduleDeclaration in State.DeclarationFinder.UserDeclarations(DeclarationType.Module)) + { + if (moduleDeclaration == null) + { + continue; + } + + var module = moduleDeclaration.QualifiedModuleName; + results.AddRange(DoGetInspectionResults(module, finder, whitelistedNames, handlers)); + } + + return results; + } + + private IEnumerable DoGetInspectionResults(QualifiedModuleName module) + { + var finder = DeclarationFinderProvider.DeclarationFinder; + var settings = _settings.Read(); + var whitelistedNames = settings.WhitelistedIdentifiers.Select(s => s.Identifier).ToArray(); + var handlers = finder.FindEventHandlers().ToHashSet(); + return DoGetInspectionResults(module, finder, whitelistedNames, handlers); + } - var issues = UserDeclarations - .Where(declaration => !string.IsNullOrEmpty(declaration.IdentifierName) && - !IgnoreDeclarationTypes.Contains(declaration.DeclarationType) && - !(declaration.Context is LineNumberLabelContext) && - (declaration.ParentDeclaration == null || - !IgnoreDeclarationTypes.Contains(declaration.ParentDeclaration.DeclarationType) && - !handlers.Contains(declaration.ParentDeclaration)) && - !whitelistedNames.Contains(declaration.IdentifierName) && - !VBAIdentifierValidator.IsMeaningfulIdentifier(declaration.IdentifierName)); + private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder, string[] whitelistedNames, ICollection eventHandlers) + { + var objectionableDeclarations = finder.Members(module) + .Where(declaration => IsResultDeclaration(declaration, finder, whitelistedNames, eventHandlers)); - return (from issue in issues select CreateInspectionResult(this, issue)) + return objectionableDeclarations + .Select(InspectionResult) .ToList(); } - private static DeclarationInspectionResult CreateInspectionResult(IInspection inspection, Declaration issue) + private static bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder, string[] whitelistedNames, ICollection eventHandlers) { - dynamic properties = null; + return !string.IsNullOrEmpty(declaration.IdentifierName) + && !IgnoreDeclarationTypes.Contains(declaration.DeclarationType) + && !(declaration.Context is LineNumberLabelContext) + && (declaration.ParentDeclaration == null + || !IgnoreDeclarationTypes.Contains(declaration.ParentDeclaration.DeclarationType) + && !eventHandlers.Contains(declaration.ParentDeclaration)) + && !whitelistedNames.Contains(declaration.IdentifierName) + && !VBAIdentifierValidator.IsMeaningfulIdentifier(declaration.IdentifierName); + } - if (issue.DeclarationType.HasFlag(DeclarationType.Module) || - issue.DeclarationType.HasFlag(DeclarationType.Project)) - { - properties = new PropertyBag(); - properties.DisableFixes = "IgnoreOnceQuickFix"; - } + private IInspectionResult InspectionResult(Declaration declaration) + { + return new DeclarationInspectionResult( + this, + ResultDescription(declaration), + declaration, + disabledQuickFixes: DisabledQuickFixes(declaration)); + } - return new DeclarationInspectionResult(inspection, - string.Format(Resources.Inspections.InspectionResults.IdentifierNameInspection, - RubberduckUI.ResourceManager.GetString("DeclarationType_" + issue.DeclarationType, - CultureInfo.CurrentUICulture), issue.IdentifierName), - issue, properties: properties); + private static string ResultDescription(Declaration declaration) + { + var declarationType = declaration.DeclarationType.ToLocalizedString(); + var declarationName = declaration.IdentifierName; + return string.Format( + Resources.Inspections.InspectionResults.IdentifierNameInspection, + declarationType, + declarationName); + } + + private static ICollection DisabledQuickFixes(Declaration declaration) + { + return declaration.DeclarationType.HasFlag(DeclarationType.Module) + || declaration.DeclarationType.HasFlag(DeclarationType.Project) + ? new List {"IgnoreOnceQuickFix"} + : new List(); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Results/DeclarationInspectionResult.cs b/Rubberduck.CodeAnalysis/Inspections/Results/DeclarationInspectionResult.cs index fe06244018..5b6196b193 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Results/DeclarationInspectionResult.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Results/DeclarationInspectionResult.cs @@ -9,17 +9,21 @@ namespace Rubberduck.Inspections.Results { public class DeclarationInspectionResult : InspectionResultBase { - public DeclarationInspectionResult(IInspection inspection, string description, Declaration target, QualifiedContext context = null, dynamic properties = null) : - base(inspection, + public DeclarationInspectionResult( + IInspection inspection, + string description, + Declaration target, + QualifiedContext context = null, + ICollection disabledQuickFixes = null) + : base(inspection, description, context == null ? target.QualifiedName.QualifiedModuleName : context.ModuleName, context == null ? target.Context : context.Context, target, target.QualifiedSelection, GetQualifiedMemberName(target), - (object)properties) - { - } + disabledQuickFixes) + {} private static QualifiedMemberName? GetQualifiedMemberName(Declaration target) { @@ -39,4 +43,36 @@ public override bool ChangesInvalidateResult(ICollection mo || base.ChangesInvalidateResult(modifiedModules); } } + + public class DeclarationInspectionResult : DeclarationInspectionResult + { + private readonly TProperties _properties; + + public DeclarationInspectionResult( + IInspection inspection, + string description, + Declaration target, + TProperties properties, + QualifiedContext context = null, + ICollection disabledQuickFixes = null) : + base( + inspection, + description, + target, + context, + disabledQuickFixes) + { + _properties = properties; + } + + public override T Properties() + { + if (_properties is T properties) + { + return properties; + } + + return base.Properties(); + } + } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Results/IdentifierReferenceInspectionResult.cs b/Rubberduck.CodeAnalysis/Inspections/Results/IdentifierReferenceInspectionResult.cs index 62bbd59a0a..319d87b819 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Results/IdentifierReferenceInspectionResult.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Results/IdentifierReferenceInspectionResult.cs @@ -13,15 +13,20 @@ public class IdentifierReferenceInspectionResult : InspectionResultBase { public IdentifierReference Reference { get; } - public IdentifierReferenceInspectionResult(IInspection inspection, string description, IDeclarationFinderProvider declarationFinderProvider, IdentifierReference reference, dynamic properties = null) : - base(inspection, + public IdentifierReferenceInspectionResult( + IInspection inspection, + string description, + IDeclarationFinderProvider declarationFinderProvider, + IdentifierReference reference, + ICollection disabledQuickFixes = null) + : base(inspection, description, reference.QualifiedModuleName, reference.Context, reference.Declaration, new QualifiedSelection(reference.QualifiedModuleName, reference.Context.GetSelection()), GetQualifiedMemberName(declarationFinderProvider, reference), - (object)properties) + disabledQuickFixes) { Reference = reference; } @@ -38,4 +43,36 @@ public override bool ChangesInvalidateResult(ICollection mo || base.ChangesInvalidateResult(modifiedModules); } } + + public class IdentifierReferenceInspectionResult : IdentifierReferenceInspectionResult + { + private readonly TProperties _properties; + + public IdentifierReferenceInspectionResult( + IInspection inspection, + string description, + IDeclarationFinderProvider declarationFinderProvider, + IdentifierReference reference, + TProperties properties, + ICollection disabledQuickFixes = null) + : base( + inspection, + description, + declarationFinderProvider, + reference, + disabledQuickFixes) + { + _properties = properties; + } + + public override T Properties() + { + if (_properties is T properties) + { + return properties; + } + + return base.Properties(); + } + } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Results/QualifiedContextInspectionResult.cs b/Rubberduck.CodeAnalysis/Inspections/Results/QualifiedContextInspectionResult.cs index eec677f2d1..0fa0caf6b8 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Results/QualifiedContextInspectionResult.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Results/QualifiedContextInspectionResult.cs @@ -1,4 +1,5 @@ -using Rubberduck.Inspections.Abstract; +using System.Collections.Generic; +using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.VBEditor; @@ -7,7 +8,11 @@ namespace Rubberduck.Inspections.Results { public class QualifiedContextInspectionResult : InspectionResultBase { - public QualifiedContextInspectionResult(IInspection inspection, string description, QualifiedContext context, dynamic properties = null) : + public QualifiedContextInspectionResult( + IInspection inspection, + string description, + QualifiedContext context, + ICollection disabledQuickFixes = null) : base(inspection, description, context.ModuleName, @@ -15,7 +20,37 @@ public QualifiedContextInspectionResult(IInspection inspection, string descripti null, new QualifiedSelection(context.ModuleName, context.Context.GetSelection()), context.MemberName, - (object)properties) + disabledQuickFixes) {} } + + public class QualifiedContextInspectionResult : QualifiedContextInspectionResult + { + private readonly TProperties _properties; + + public QualifiedContextInspectionResult( + IInspection inspection, + string description, + QualifiedContext context, + TProperties properties, + ICollection disabledQuickFixes = null) : + base( + inspection, + description, + context, + disabledQuickFixes) + { + _properties = properties; + } + + public override T Properties() + { + if (_properties is T properties) + { + return properties; + } + + return base.Properties(); + } + } } diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AccessSheetUsingCodeNameQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/AccessSheetUsingCodeNameQuickFix.cs index df7661274d..32dac50ac1 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AccessSheetUsingCodeNameQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/AccessSheetUsingCodeNameQuickFix.cs @@ -62,7 +62,8 @@ public override void Fix(IInspectionResult result, IRewriteSession rewriteSessio var indexExprContext = referenceResult.Context.Parent.Parent as VBAParser.IndexExprContext ?? referenceResult.Context.Parent as VBAParser.IndexExprContext; - rewriter.Replace(indexExprContext, (string)referenceResult.Properties.CodeName); + var codeName = referenceResult.Properties(); + rewriter.Replace(indexExprContext, codeName); } else { @@ -97,7 +98,8 @@ public override void Fix(IInspectionResult result, IRewriteSession rewriteSessio foreach (var reference in sheetDeclaration.References) { - rewriter.Replace(reference.Context, (string)referenceResult.Properties.CodeName); + var codeName = referenceResult.Properties(); + rewriter.Replace(reference.Context, codeName); } rewriter.Remove(setStatement); diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AddAttributeAnnotationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/AddAttributeAnnotationQuickFix.cs index 18dcb03530..e08068df9e 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AddAttributeAnnotationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/AddAttributeAnnotationQuickFix.cs @@ -61,8 +61,7 @@ public AddAttributeAnnotationQuickFix(IAnnotationUpdater annotationUpdater, IAtt public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) { var declaration = result.Target; - string attributeName = result.Properties.AttributeName; - IReadOnlyList attributeValues = result.Properties.AttributeValues; + var (attributeName, attributeValues) = result.Properties<(string attributeName, IReadOnlyList AttributeValues)>(); var (annotationType, annotationValues) = declaration.DeclarationType.HasFlag(DeclarationType.Module) ? _attributeAnnotationProvider.ModuleAttributeAnnotation(attributeName, attributeValues) : _attributeAnnotationProvider.MemberAttributeAnnotation(AttributeBaseName(attributeName, declaration), attributeValues); diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AddMissingAttributeQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/AddMissingAttributeQuickFix.cs index 8e30786aea..cc644801fd 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AddMissingAttributeQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/AddMissingAttributeQuickFix.cs @@ -55,7 +55,7 @@ public AddMissingAttributeQuickFix(IAttributesUpdater attributesUpdater) public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) { var declaration = result.Target; - IParseTreeAnnotation annotationInstance = result.Properties.Annotation; + var annotationInstance = result.Properties(); if (!(annotationInstance.Annotation is IAttributeAnnotation annotation)) { return; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeAnnotationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeAnnotationQuickFix.cs index 45a2fc233a..671c4e86aa 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeAnnotationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeAnnotationQuickFix.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Annotations; @@ -60,29 +59,26 @@ public AdjustAttributeAnnotationQuickFix(IAnnotationUpdater annotationUpdater, I public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) { - IParseTreeAnnotation oldAnnotation = result.Properties.Annotation; - string attributeName = result.Properties.AttributeName; - IReadOnlyList attributeValues = result.Properties.AttributeValues; - var declaration = result.Target; + var (oldParseTreeAnnotation, attributeBaseName, attributeValues) = result.Properties<(IParseTreeAnnotation Annotation, string AttributeName, IReadOnlyList AttributeValues)>(); + if (declaration.DeclarationType.HasFlag(DeclarationType.Module)) { var componentType = declaration.QualifiedModuleName.ComponentType; - if (IsDefaultAttribute(componentType, attributeName, attributeValues)) + if (IsDefaultAttribute(componentType, attributeBaseName, attributeValues)) { - _annotationUpdater.RemoveAnnotation(rewriteSession, oldAnnotation); + _annotationUpdater.RemoveAnnotation(rewriteSession, oldParseTreeAnnotation); } else { - var (newAnnotation, newAnnotationValues) = _attributeAnnotationProvider.ModuleAttributeAnnotation(attributeName, attributeValues); - _annotationUpdater.UpdateAnnotation(rewriteSession, oldAnnotation, newAnnotation, newAnnotationValues); + var (newAnnotation, newAnnotationValues) = _attributeAnnotationProvider.ModuleAttributeAnnotation(attributeBaseName, attributeValues); + _annotationUpdater.UpdateAnnotation(rewriteSession, oldParseTreeAnnotation, newAnnotation, newAnnotationValues); } } else { - var attributeBaseName = AttributeBaseName(attributeName, declaration); var (newAnnotation, newAnnotationValues) = _attributeAnnotationProvider.MemberAttributeAnnotation(attributeBaseName, attributeValues); - _annotationUpdater.UpdateAnnotation(rewriteSession, oldAnnotation, newAnnotation, newAnnotationValues); + _annotationUpdater.UpdateAnnotation(rewriteSession, oldParseTreeAnnotation, newAnnotation, newAnnotationValues); } } @@ -91,11 +87,6 @@ private static bool IsDefaultAttribute(ComponentType componentType, string attri return Attributes.IsDefaultAttribute(componentType, attributeName, attributeValues); } - private static string AttributeBaseName(string attributeName, Declaration declaration) - { - return Attributes.AttributeBaseName(attributeName, declaration.IdentifierName); - } - public override string Description(IInspectionResult result) => Resources.Inspections.QuickFixes.AdjustAttributeAnnotationQuickFix; public override bool CanFixInProcedure => true; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeValuesQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeValuesQuickFix.cs index ba50cdb8c9..deca488c50 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeValuesQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeValuesQuickFix.cs @@ -62,18 +62,23 @@ public AdjustAttributeValuesQuickFix(IAttributesUpdater attributesUpdater) public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) { var declaration = result.Target; - IParseTreeAnnotation annotationInstance = result.Properties.Annotation; + var (parseTreeAnnotation, attributeBaseName, attributeValues) = result.Properties<(IParseTreeAnnotation Annotation, string AttributeName, IReadOnlyList AttributeValues)>(); - Debug.Assert(annotationInstance.Annotation is IAttributeAnnotation); - IAttributeAnnotation annotation = (IAttributeAnnotation)annotationInstance.Annotation; - IReadOnlyList attributeValues = result.Properties.AttributeValues; - - var attribute = annotation.Attribute(annotationInstance); var attributeName = declaration.DeclarationType.HasFlag(DeclarationType.Module) - ? attribute - : $"{declaration.IdentifierName}.{attribute}"; + ? attributeBaseName + : Attributes.MemberAttributeName(attributeBaseName, declaration.IdentifierName); + + if (!(parseTreeAnnotation.Annotation is IAttributeAnnotation attributeAnnotation)) + { + var message = $"Tried to adjust values of attribute {attributeName} to values of non-attribute annotation {parseTreeAnnotation.Annotation.Name} in component {declaration.QualifiedModuleName}."; + Logger.Warn(message); + Debug.Fail(message); + return; + } + + var attributeValuesFromAnnotation = attributeAnnotation.AttributeValues(parseTreeAnnotation); - _attributesUpdater.UpdateAttribute(rewriteSession, declaration, attributeName, annotation.AttributeValues(annotationInstance), oldValues: attributeValues); + _attributesUpdater.UpdateAttribute(rewriteSession, declaration, attributeName, attributeValuesFromAnnotation, oldValues: attributeValues); } public override string Description(IInspectionResult result) => Resources.Inspections.QuickFixes.AdjustAttributeValuesQuickFix; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ExpandDefaultMemberQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/ExpandDefaultMemberQuickFix.cs index d7f95a949f..d05b10bc9f 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ExpandDefaultMemberQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/ExpandDefaultMemberQuickFix.cs @@ -76,7 +76,7 @@ public override void Fix(IInspectionResult result, IRewriteSession rewriteSessio if (result.Inspection is SuspiciousLetAssignmentInspection) { - IdentifierReference rhsReference = result.Properties.RhSReference; + var rhsReference = result.Properties(); var rhsLExpressionContext = rhsReference.Context; var rhsSelection = rhsReference.QualifiedSelection; InsertDefaultMember(rhsLExpressionContext, rhsSelection, finder, rewriter); diff --git a/Rubberduck.CodeAnalysis/QuickFixes/IsMissingOnInappropriateArgumentQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/IsMissingOnInappropriateArgumentQuickFix.cs index 319823205d..de0fb5189a 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/IsMissingOnInappropriateArgumentQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/IsMissingOnInappropriateArgumentQuickFix.cs @@ -51,10 +51,10 @@ public IsMissingOnInappropriateArgumentQuickFix(IDeclarationFinderProvider decla public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) { - if (!(result.Properties is ParameterDeclaration parameter)) + var parameter = result.Properties(); + if (parameter == null) { - Logger.Trace( - $"Properties for IsMissingOnInappropriateArgumentQuickFix was {(result.Properties == null ? "null" : "not a ParameterDeclaration")}."); + Logger.Trace($"Properties for IsMissingOnInappropriateArgumentQuickFix was null."); return; } diff --git a/Rubberduck.CodeAnalysis/QuickFixes/QuickFixProvider.cs b/Rubberduck.CodeAnalysis/QuickFixes/QuickFixProvider.cs index 9db846ea2a..9db5bcd29c 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/QuickFixProvider.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/QuickFixProvider.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using Microsoft.CSharp.RuntimeBinder; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.VBA.Parsing; @@ -49,25 +48,8 @@ public IEnumerable QuickFixes(Type inspectionType) public IEnumerable QuickFixes(IInspectionResult result) { - return QuickFixes(result.Inspection.GetType()).Where(fix => - { - string value; - try - { - value = result.Properties.DisableFixes; - } - catch (RuntimeBinderException) - { - return true; - } - - if (value == null) - { - return true; - } - - return !value.Split(',').Contains(fix.GetType().Name); - }) + return QuickFixes(result.Inspection.GetType()) + .Where(fix => !result.DisabledQuickFixes.Contains(fix.GetType().Name)) .OrderBy(fix => fix.SupportedInspections.Count); // most specific fixes first; keeps "ignore once" last } diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveAnnotationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveAnnotationQuickFix.cs index f1659620d0..62826bc0c6 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveAnnotationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveAnnotationQuickFix.cs @@ -1,5 +1,6 @@ using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Concrete; +using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.VBA; @@ -48,7 +49,7 @@ public RemoveAnnotationQuickFix(IAnnotationUpdater annotationUpdater) public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) { - _annotationUpdater.RemoveAnnotation(rewriteSession, result.Properties.Annotation); + _annotationUpdater.RemoveAnnotation(rewriteSession, result.Properties()); } public override string Description(IInspectionResult result) => Resources.Inspections.QuickFixes.RemoveAnnotationQuickFix; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveAttributeQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveAttributeQuickFix.cs index 11a8e0da2d..947a586138 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveAttributeQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveAttributeQuickFix.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Concrete; +using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; @@ -51,12 +52,11 @@ public RemoveAttributeQuickFix(IAttributesUpdater attributesUpdater) public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) { var declaration = result.Target; - string attributeBaseName = result.Properties.AttributeName; - IReadOnlyList attributeValues = result.Properties.AttributeValues; + var (attributeBaseName, attributeValues) = result.Properties<(string AttributeName, IReadOnlyList AttributeValues)>(); var attributeName = declaration.DeclarationType.HasFlag(DeclarationType.Module) ? attributeBaseName - : $"{declaration.IdentifierName}.{attributeBaseName}"; + : Attributes.MemberAttributeName(attributeBaseName,declaration.IdentifierName); _attributesUpdater.RemoveAttribute(rewriteSession, declaration, attributeName, attributeValues); } diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveDuplicatedAnnotationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveDuplicatedAnnotationQuickFix.cs index a85e50cea5..c61c1213a0 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveDuplicatedAnnotationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveDuplicatedAnnotationQuickFix.cs @@ -1,6 +1,7 @@ using System.Linq; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Concrete; +using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.VBA; @@ -47,8 +48,9 @@ public RemoveDuplicatedAnnotationQuickFix(IAnnotationUpdater annotationUpdater) public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) { + var resultAnnotation = result.Properties(); var duplicateAnnotations = result.Target.Annotations - .Where(pta => pta.Annotation == result.Properties.Annotation) + .Where(pta => pta.Annotation == resultAnnotation) .OrderBy(annotation => annotation.AnnotatedLine) .Skip(1) .ToList(); diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs index 506285c1c7..02110e07ea 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing; @@ -88,7 +89,8 @@ public override void Fix(IInspectionResult result, IRewriteSession rewriteSessio var context = (VBAParser.OnErrorStmtContext)result.Context; var labels = bodyElementContext.GetDescendents().ToArray(); var maximumExistingLabelIndex = GetMaximumExistingLabelIndex(labels); - int offset = result.Properties.UnhandledContexts.IndexOf(result.Context); + var unhandledContexts = result.Properties>(); + var offset = unhandledContexts.IndexOf(result.Context); var labelIndex = maximumExistingLabelIndex + offset; var labelSuffix = labelIndex == 0 diff --git a/Rubberduck.Parsing/Annotations/AttributeAnnotationExtensions.cs b/Rubberduck.Parsing/Annotations/AttributeAnnotationExtensions.cs index e355eea270..f258d46b7f 100644 --- a/Rubberduck.Parsing/Annotations/AttributeAnnotationExtensions.cs +++ b/Rubberduck.Parsing/Annotations/AttributeAnnotationExtensions.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Collections.Generic; namespace Rubberduck.Parsing.Annotations { diff --git a/Rubberduck.Parsing/Inspections/Abstract/IInspectionResult.cs b/Rubberduck.Parsing/Inspections/Abstract/IInspectionResult.cs index 48cbdedad4..4cbdb656e4 100644 --- a/Rubberduck.Parsing/Inspections/Abstract/IInspectionResult.cs +++ b/Rubberduck.Parsing/Inspections/Abstract/IInspectionResult.cs @@ -14,7 +14,8 @@ public interface IInspectionResult : IComparable, IComparable IInspection Inspection { get; } Declaration Target { get; } ParserRuleContext Context { get; } - dynamic Properties { get; } + ICollection DisabledQuickFixes { get; } + T Properties(); bool ChangesInvalidateResult(ICollection modifiedModules); } } diff --git a/RubberduckTests/Inspections/AttributeValueOutOfSyncInspectionTests.cs b/RubberduckTests/Inspections/AttributeValueOutOfSyncInspectionTests.cs index a70bb11340..23a82b6070 100644 --- a/RubberduckTests/Inspections/AttributeValueOutOfSyncInspectionTests.cs +++ b/RubberduckTests/Inspections/AttributeValueOutOfSyncInspectionTests.cs @@ -218,12 +218,12 @@ Public Sub Foo() var inspectionResults = InspectionResults(inputCode); var inspectionResult = inspectionResults.First(); - var pta = (IParseTreeAnnotation)inspectionResult.Properties.Annotation; + var (pta, attributeName, attributeValues) = inspectionResult.Properties<(IParseTreeAnnotation Annotation, string AttributeName, IReadOnlyList AttributeValues)>(); Assert.IsInstanceOf(pta.Annotation); - Assert.AreEqual("VB_UserMemId", inspectionResult.Properties.AttributeName); + Assert.AreEqual("VB_UserMemId", attributeName); Assert.AreEqual("-4", ((IAttributeAnnotation)pta.Annotation).AttributeValues(pta)[0]); - Assert.AreEqual("40", inspectionResult.Properties.AttributeValues[0]); + Assert.AreEqual("40", attributeValues[0]); } private IEnumerable InspectionResults(string inputCode, ComponentType componentType = ComponentType.StandardModule) diff --git a/RubberduckTests/Inspections/MissingMemberAnnotationInspectionTests.cs b/RubberduckTests/Inspections/MissingMemberAnnotationInspectionTests.cs index 438b700d75..5a60adf4e0 100644 --- a/RubberduckTests/Inspections/MissingMemberAnnotationInspectionTests.cs +++ b/RubberduckTests/Inspections/MissingMemberAnnotationInspectionTests.cs @@ -177,8 +177,7 @@ Public Sub Foo() var expectedAttributeValues = new List{"-4"}; var inspectionResult = inspectionResults.Single(); - var actualAttributeBaseName = inspectionResult.Properties.AttributeName; - var actualAttributeValues = inspectionResult.Properties.AttributeValues; + var (actualAttributeBaseName, actualAttributeValues) = inspectionResult.Properties<(string AttributeName, IReadOnlyList AttributeValues)>(); Assert.AreEqual(expectedAttributeName, actualAttributeBaseName); Assert.AreEqual(expectedAttributeValues.Count, actualAttributeValues.Count); diff --git a/RubberduckTests/Inspections/MissingModuleAnnotationInspectionTests.cs b/RubberduckTests/Inspections/MissingModuleAnnotationInspectionTests.cs index 36e68c6997..20ba2663f0 100644 --- a/RubberduckTests/Inspections/MissingModuleAnnotationInspectionTests.cs +++ b/RubberduckTests/Inspections/MissingModuleAnnotationInspectionTests.cs @@ -425,8 +425,7 @@ Public Sub Foo() var expectedAttributeValues = new List { "\"Desc\"" }; var inspectionResult = inspectionResults.Single(); - var actualAttributeBaseName = inspectionResult.Properties.AttributeName; - var actualAttributeValues = inspectionResult.Properties.AttributeValues; + var (actualAttributeBaseName, actualAttributeValues) = inspectionResult.Properties<(string AttributeName, IReadOnlyList AttributeValues)>(); Assert.AreEqual(expectedAttributeName, actualAttributeBaseName); Assert.AreEqual(expectedAttributeValues.Count, actualAttributeValues.Count); diff --git a/RubberduckTests/Inspections/ObjectWhereProcedureIsRequiredInspectionTests.cs b/RubberduckTests/Inspections/ObjectWhereProcedureIsRequiredInspectionTests.cs index c6226af377..8528b16263 100644 --- a/RubberduckTests/Inspections/ObjectWhereProcedureIsRequiredInspectionTests.cs +++ b/RubberduckTests/Inspections/ObjectWhereProcedureIsRequiredInspectionTests.cs @@ -84,7 +84,8 @@ End Sub ("Module1", moduleCode, ComponentType.StandardModule)); var result = inspectionResults.Single(); - Assert.AreEqual("ExpandDefaultMemberQuickFix", result.Properties.DisableFixes); + var actuallyDisabledQuickFix = result.DisabledQuickFixes.Single(); + Assert.AreEqual("ExpandDefaultMemberQuickFix", actuallyDisabledQuickFix); } [Test] [Category("Inspections")] @@ -238,7 +239,8 @@ End Sub ("Module1", moduleCode, ComponentType.StandardModule)); var result = inspectionResults.Single(); - Assert.AreEqual("ExpandDefaultMemberQuickFix", result.Properties.DisableFixes); + var actuallyDisabledQuickFix = result.DisabledQuickFixes.Single(); + Assert.AreEqual("ExpandDefaultMemberQuickFix", actuallyDisabledQuickFix); } [Test] diff --git a/RubberduckTests/Inspections/SuspiciousLetAssignmentInspectionTests.cs b/RubberduckTests/Inspections/SuspiciousLetAssignmentInspectionTests.cs index 25624b38db..178585ec7a 100644 --- a/RubberduckTests/Inspections/SuspiciousLetAssignmentInspectionTests.cs +++ b/RubberduckTests/Inspections/SuspiciousLetAssignmentInspectionTests.cs @@ -2,6 +2,7 @@ using NUnit.Framework; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; @@ -46,13 +47,13 @@ End Sub ("Module1", moduleCode, ComponentType.StandardModule)); var inspectionResult = inspectionResults.Single(); - - Assert.IsNotNull(inspectionResult.Properties.RhSReference); + var rhsReference = inspectionResult.Properties(); + Assert.IsNotNull(rhsReference); if (assignedTypeName.Equals("Object") || assignedToTypeName.Equals("Object")) { - var deactivatedFixes = inspectionResult.Properties.DisableFixes; - Assert.AreEqual("ExpandDefaultMemberQuickFix", deactivatedFixes); + var deactivatedFix = inspectionResult.DisabledQuickFixes.Single(); + Assert.AreEqual("ExpandDefaultMemberQuickFix", deactivatedFix); } } diff --git a/RubberduckTests/QuickFixes/QuickFixProviderTests.cs b/RubberduckTests/QuickFixes/QuickFixProviderTests.cs index 4209bcd87c..23827a6cc1 100644 --- a/RubberduckTests/QuickFixes/QuickFixProviderTests.cs +++ b/RubberduckTests/QuickFixes/QuickFixProviderTests.cs @@ -83,7 +83,7 @@ public void ResultDisablesFix() var quickFixProvider = new QuickFixProvider(rewritingManager, failureNotifier, new IQuickFix[] { new RemoveUnusedDeclarationQuickFix() }); var result = inspectionResults.First(); - result.Properties.DisableFixes = nameof(RemoveUnusedDeclarationQuickFix); + result.DisabledQuickFixes.Add(nameof(RemoveUnusedDeclarationQuickFix)); Assert.AreEqual(0, quickFixProvider.QuickFixes(result).Count()); } diff --git a/RubberduckTests/QuickFixes/RemoveDuplicatedAnnotationQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveDuplicatedAnnotationQuickFixTests.cs index 7fd4bc1510..356e58296b 100644 --- a/RubberduckTests/QuickFixes/RemoveDuplicatedAnnotationQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveDuplicatedAnnotationQuickFixTests.cs @@ -182,7 +182,7 @@ Public Sub Foo '@TestMethod Public Sub Foo End Sub"; - Func conditionToFix = result => result.Properties.Annotation is ObsoleteAnnotation; + Func conditionToFix = result => result.Properties() is ObsoleteAnnotation; var actualCode = ApplyQuickFixToFirstInspectionResultSatisfyingPredicate(inputCode, state => new DuplicatedAnnotationInspection(state), conditionToFix); Assert.AreEqual(expectedCode, actualCode); } From a1b4ee7eab64a46b50a82a55db8c734cc2938047 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Wed, 5 Feb 2020 08:52:03 +0100 Subject: [PATCH 215/461] Only inspect correctly scoped declarations in declaration inspection base classes In the case where the declaration type does not matter all declarations were inspected instead of those in the module. This led to results being generated multiple times if there are multiple modules. In addition, common behaviour of the declaration inspection base classes has been extracted into a further base class. --- .../Abstract/DeclarationInspectionBase.cs | 114 ++---------------- .../Abstract/DeclarationInspectionBaseBase.cs | 68 +++++++++++ .../DeclarationInspectionMultiResultBase.cs | 57 +-------- 3 files changed, 86 insertions(+), 153 deletions(-) create mode 100644 Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs index 9a4aa5c7da..ea3b5cc195 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs @@ -9,56 +9,22 @@ namespace Rubberduck.Inspections.Abstract { - public abstract class DeclarationInspectionBase : InspectionBase + public abstract class DeclarationInspectionBase : DeclarationInspectionBaseBase { - protected readonly DeclarationType[] RelevantDeclarationTypes; - protected readonly DeclarationType[] ExcludeDeclarationTypes; - protected DeclarationInspectionBase(RubberduckParserState state, params DeclarationType[] relevantDeclarationTypes) - : base(state) - { - RelevantDeclarationTypes = relevantDeclarationTypes; - ExcludeDeclarationTypes = new DeclarationType[0]; - } + : base(state, relevantDeclarationTypes) + {} protected DeclarationInspectionBase(RubberduckParserState state, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) - : base(state) - { - RelevantDeclarationTypes = relevantDeclarationTypes; - ExcludeDeclarationTypes = excludeDeclarationTypes; - } + : base(state, relevantDeclarationTypes, excludeDeclarationTypes) + {} protected abstract bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder); protected abstract string ResultDescription(Declaration declaration); protected virtual ICollection DisabledQuickFixes(Declaration declaration) => new List(); - protected override IEnumerable DoGetInspectionResults() - { - var finder = DeclarationFinderProvider.DeclarationFinder; - - var results = new List(); - foreach (var moduleDeclaration in State.DeclarationFinder.UserDeclarations(DeclarationType.Module)) - { - if (moduleDeclaration == null) - { - continue; - } - - var module = moduleDeclaration.QualifiedModuleName; - results.AddRange(DoGetInspectionResults(module, finder)); - } - - return results; - } - - private IEnumerable DoGetInspectionResults(QualifiedModuleName module) - { - var finder = DeclarationFinderProvider.DeclarationFinder; - return DoGetInspectionResults(module, finder); - } - - private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { var objectionableDeclarations = RelevantDeclarationsInModule(module, finder) .Where(declaration => IsResultDeclaration(declaration, finder)); @@ -68,17 +34,6 @@ private IEnumerable DoGetInspectionResults(QualifiedModuleNam .ToList(); } - protected virtual IEnumerable RelevantDeclarationsInModule(QualifiedModuleName module, DeclarationFinder finder) - { - var potentiallyRelevantDeclarations = RelevantDeclarationTypes.Length == 0 - ? finder.AllUserDeclarations - : RelevantDeclarationTypes - .SelectMany(declarationType => finder.Members(module, declarationType)) - .Distinct(); - return potentiallyRelevantDeclarations - .Where(declaration => !ExcludeDeclarationTypes.Contains(declaration.DeclarationType)); - } - protected virtual IInspectionResult InspectionResult(Declaration declaration) { return new DeclarationInspectionResult( @@ -89,56 +44,22 @@ protected virtual IInspectionResult InspectionResult(Declaration declaration) } } - public abstract class DeclarationInspectionBase : InspectionBase + public abstract class DeclarationInspectionBase : DeclarationInspectionBaseBase { - protected readonly DeclarationType[] RelevantDeclarationTypes; - protected readonly DeclarationType[] ExcludeDeclarationTypes; - protected DeclarationInspectionBase(RubberduckParserState state, params DeclarationType[] relevantDeclarationTypes) - : base(state) - { - RelevantDeclarationTypes = relevantDeclarationTypes; - ExcludeDeclarationTypes = new DeclarationType[0]; - } + : base(state, relevantDeclarationTypes) + {} protected DeclarationInspectionBase(RubberduckParserState state, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) - : base(state) - { - RelevantDeclarationTypes = relevantDeclarationTypes; - ExcludeDeclarationTypes = excludeDeclarationTypes; - } + : base(state, relevantDeclarationTypes, excludeDeclarationTypes) + {} protected abstract (bool isResult, T properties) IsResultDeclarationWithAdditionalProperties(Declaration declaration, DeclarationFinder finder); protected abstract string ResultDescription(Declaration declaration, T properties); protected virtual ICollection DisabledQuickFixes(Declaration declaration, T properties) => new List(); - protected override IEnumerable DoGetInspectionResults() - { - var finder = DeclarationFinderProvider.DeclarationFinder; - - var results = new List(); - foreach (var moduleDeclaration in State.DeclarationFinder.UserDeclarations(DeclarationType.Module)) - { - if (moduleDeclaration == null) - { - continue; - } - - var module = moduleDeclaration.QualifiedModuleName; - results.AddRange(DoGetInspectionResults(module, finder)); - } - - return results; - } - - private IEnumerable DoGetInspectionResults(QualifiedModuleName module) - { - var finder = DeclarationFinderProvider.DeclarationFinder; - return DoGetInspectionResults(module, finder); - } - - private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { var objectionableDeclarationsWithAdditionalProperties = RelevantDeclarationsInModule(module, finder) .Select(declaration => (declaration, IsResultDeclarationWithAdditionalProperties(declaration, finder))) @@ -150,17 +71,6 @@ private IEnumerable DoGetInspectionResults(QualifiedModuleNam .ToList(); } - protected virtual IEnumerable RelevantDeclarationsInModule(QualifiedModuleName module, DeclarationFinder finder) - { - var potentiallyRelevantDeclarations = RelevantDeclarationTypes.Length == 0 - ? finder.AllUserDeclarations - : RelevantDeclarationTypes - .SelectMany(declarationType => finder.Members(module, declarationType)) - .Distinct(); - return potentiallyRelevantDeclarations - .Where(declaration => ! ExcludeDeclarationTypes.Contains(declaration.DeclarationType)); - } - protected virtual IInspectionResult InspectionResult(Declaration declaration, T properties) { return new DeclarationInspectionResult( diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs new file mode 100644 index 0000000000..b1d513b8d5 --- /dev/null +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs @@ -0,0 +1,68 @@ +using System.Collections.Generic; +using System.Linq; +using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.VBEditor; + +namespace Rubberduck.Inspections.Abstract +{ + public abstract class DeclarationInspectionBaseBase : InspectionBase + { + protected readonly DeclarationType[] RelevantDeclarationTypes; + protected readonly DeclarationType[] ExcludeDeclarationTypes; + + protected DeclarationInspectionBaseBase(RubberduckParserState state, params DeclarationType[] relevantDeclarationTypes) + : base(state) + { + RelevantDeclarationTypes = relevantDeclarationTypes; + ExcludeDeclarationTypes = new DeclarationType[0]; + } + + protected DeclarationInspectionBaseBase(RubberduckParserState state, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) + : base(state) + { + RelevantDeclarationTypes = relevantDeclarationTypes; + ExcludeDeclarationTypes = excludeDeclarationTypes; + } + + protected abstract IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder); + + protected override IEnumerable DoGetInspectionResults() + { + var finder = DeclarationFinderProvider.DeclarationFinder; + + var results = new List(); + foreach (var moduleDeclaration in State.DeclarationFinder.UserDeclarations(DeclarationType.Module)) + { + if (moduleDeclaration == null) + { + continue; + } + + var module = moduleDeclaration.QualifiedModuleName; + results.AddRange(DoGetInspectionResults(module, finder)); + } + + return results; + } + + protected IEnumerable DoGetInspectionResults(QualifiedModuleName module) + { + var finder = DeclarationFinderProvider.DeclarationFinder; + return DoGetInspectionResults(module, finder); + } + + protected IEnumerable RelevantDeclarationsInModule(QualifiedModuleName module, DeclarationFinder finder) + { + var potentiallyRelevantDeclarations = RelevantDeclarationTypes.Length == 0 + ? finder.Members(module) + : RelevantDeclarationTypes + .SelectMany(declarationType => finder.Members(module, declarationType)) + .Distinct(); + return potentiallyRelevantDeclarations + .Where(declaration => !ExcludeDeclarationTypes.Contains(declaration.DeclarationType)); + } + } +} \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionMultiResultBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionMultiResultBase.cs index 91af9db38b..491e2f0d42 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionMultiResultBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionMultiResultBase.cs @@ -9,56 +9,22 @@ namespace Rubberduck.Inspections.Abstract { - public abstract class DeclarationInspectionMultiResultBase : InspectionBase + public abstract class DeclarationInspectionMultiResultBase : DeclarationInspectionBaseBase { - protected readonly DeclarationType[] RelevantDeclarationTypes; - protected readonly DeclarationType[] ExcludeDeclarationTypes; - protected DeclarationInspectionMultiResultBase(RubberduckParserState state, params DeclarationType[] relevantDeclarationTypes) - : base(state) - { - RelevantDeclarationTypes = relevantDeclarationTypes; - ExcludeDeclarationTypes = new DeclarationType[0]; - } + : base(state, relevantDeclarationTypes) + {} protected DeclarationInspectionMultiResultBase(RubberduckParserState state, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) - : base(state) - { - RelevantDeclarationTypes = relevantDeclarationTypes; - ExcludeDeclarationTypes = excludeDeclarationTypes; - } + : base(state, relevantDeclarationTypes, excludeDeclarationTypes) + {} protected abstract IEnumerable ResultProperties(Declaration declaration, DeclarationFinder finder); protected abstract string ResultDescription(Declaration declaration, T properties); protected virtual ICollection DisabledQuickFixes(Declaration declaration, T properties) => new List(); - protected override IEnumerable DoGetInspectionResults() - { - var finder = DeclarationFinderProvider.DeclarationFinder; - - var results = new List(); - foreach (var moduleDeclaration in State.DeclarationFinder.UserDeclarations(DeclarationType.Module)) - { - if (moduleDeclaration == null) - { - continue; - } - - var module = moduleDeclaration.QualifiedModuleName; - results.AddRange(DoGetInspectionResults(module, finder)); - } - - return results; - } - - private IEnumerable DoGetInspectionResults(QualifiedModuleName module) - { - var finder = DeclarationFinderProvider.DeclarationFinder; - return DoGetInspectionResults(module, finder); - } - - private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { var objectionableDeclarationsWithAdditionalProperties = RelevantDeclarationsInModule(module, finder) .SelectMany(declaration => ResultProperties(declaration, finder) @@ -69,17 +35,6 @@ private IEnumerable DoGetInspectionResults(QualifiedModuleNam .ToList(); } - protected virtual IEnumerable RelevantDeclarationsInModule(QualifiedModuleName module, DeclarationFinder finder) - { - var potentiallyRelevantDeclarations = RelevantDeclarationTypes.Length == 0 - ? finder.AllUserDeclarations - : RelevantDeclarationTypes - .SelectMany(declarationType => finder.Members(module, declarationType)) - .Distinct(); - return potentiallyRelevantDeclarations - .Where(declaration => ! ExcludeDeclarationTypes.Contains(declaration.DeclarationType)); - } - protected virtual IInspectionResult InspectionResult(Declaration declaration, T properties) { return new DeclarationInspectionResult( From 33103b559975f28247645a6987f57df349a21a7d Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Fri, 7 Feb 2020 00:47:01 +0100 Subject: [PATCH 216/461] Fix UnassignedVariableUsageInspection Further non-assignment accesses after an assignment via a by ref argument also triggered results. Moreover bracket expressions now have the QMN of the containing module. Furthermore, many declaration inspections have been converted to use the base classes. --- .../Abstract/ImplicitTypeInspectionBase.cs | 8 +- .../AssignedByValParameterInspection.cs | 31 +++---- .../Concrete/DefaultProjectNameInspection.cs | 38 ++++++-- .../Concrete/EmptyMethodInspection.cs | 50 ++-------- .../EncapsulatePublicFieldInspection.cs | 34 +++---- .../HostSpecificExpressionInspection.cs | 17 ++-- .../Concrete/HungarianNotationInspection.cs | 91 +++++++++++++++---- .../NonReturningFunctionInspection.cs | 88 ++++++++++-------- .../Concrete/ObsoleteGlobalInspection.cs | 3 +- .../SelfAssignedDeclarationInspection.cs | 37 ++++---- .../UnassignedVariableUsageInspection.cs | 31 ++++++- ...coreInPublicClassModuleMemberInspection.cs | 35 ++++--- .../Concrete/UseMeaningfulNameInspection.cs | 12 ++- .../Concrete/VariableNotUsedInspection.cs | 53 +++++++---- .../VariableTypeNotDeclaredInspection.cs | 38 ++++---- .../Concrete/WriteOnlyPropertyInspection.cs | 43 +++++---- .../Commands/UpdateFromFileCommand.cs | 5 - .../Bindings/SimpleNameDefaultBinding.cs | 2 +- .../DeclarationCaching/DeclarationFinder.cs | 38 ++++---- .../NonReturningFunctionInspectionTests.cs | 15 +++ .../ObsoleteGlobalInspectionTests.cs | 21 +++++ .../UnassignedVariableUsageInspectionTests.cs | 20 +++- 22 files changed, 430 insertions(+), 280 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/ImplicitTypeInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/ImplicitTypeInspectionBase.cs index 0b9115f6ba..003d995637 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/ImplicitTypeInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/ImplicitTypeInspectionBase.cs @@ -7,8 +7,12 @@ namespace Rubberduck.Inspections.Abstract public abstract class ImplicitTypeInspectionBase : DeclarationInspectionBase { protected ImplicitTypeInspectionBase(RubberduckParserState state, params DeclarationType[] relevantDeclarationTypes) - :base(state, relevantDeclarationTypes) - { } + : base(state, relevantDeclarationTypes) + {} + + protected ImplicitTypeInspectionBase(RubberduckParserState state, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) + : base(state, relevantDeclarationTypes, excludeDeclarationTypes) + {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignedByValParameterInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignedByValParameterInspection.cs index 71f792d6c0..215acb756f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignedByValParameterInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignedByValParameterInspection.cs @@ -1,12 +1,9 @@ -using System.Collections.Generic; using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -36,23 +33,23 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class AssignedByValParameterInspection : InspectionBase + public sealed class AssignedByValParameterInspection : DeclarationInspectionBase { public AssignedByValParameterInspection(RubberduckParserState state) - : base(state) - { } - - protected override IEnumerable DoGetInspectionResults() + : base(state, DeclarationType.Parameter) + {} + + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { - var parameters = State.DeclarationFinder.UserDeclarations(DeclarationType.Parameter) - .Cast() - .Where(item => !item.IsByRef - && item.References.Any(reference => reference.IsAssignment)); + return declaration is ParameterDeclaration parameter + && !parameter.IsByRef + && parameter.References + .Any(reference => reference.IsAssignment); + } - return parameters - .Select(param => new DeclarationInspectionResult(this, - string.Format(InspectionResults.AssignedByValParameterInspection, param.IdentifierName), - param)); + protected override string ResultDescription(Declaration declaration) + { + return string.Format(InspectionResults.AssignedByValParameterInspection, declaration.IdentifierName); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultProjectNameInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultProjectNameInspection.cs index 4e43bd4981..71b446677d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultProjectNameInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultProjectNameInspection.cs @@ -1,11 +1,10 @@ using System.Collections.Generic; -using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -16,20 +15,39 @@ namespace Rubberduck.Inspections.Concrete /// VBA projects should be meaningfully named, to avoid namespace clashes when referencing other VBA projects. /// [CannotAnnotate] - public sealed class DefaultProjectNameInspection : InspectionBase + public sealed class DefaultProjectNameInspection : DeclarationInspectionBase { public DefaultProjectNameInspection(RubberduckParserState state) - : base(state) { } + : base(state, DeclarationType.Project) + {} protected override IEnumerable DoGetInspectionResults() { - var projects = State.DeclarationFinder.UserDeclarations(DeclarationType.Project) - .Where(item => item.IdentifierName.StartsWith("VBAProject")) - .ToList(); + var finder = DeclarationFinderProvider.DeclarationFinder; - return projects - .Select(issue => new DeclarationInspectionResult(this, Description, issue)) - .ToList(); + var results = new List(); + foreach (var projectDeclaration in State.DeclarationFinder.UserDeclarations(DeclarationType.Project)) + { + if (projectDeclaration == null) + { + continue; + } + + var module = projectDeclaration.QualifiedModuleName; + results.AddRange(DoGetInspectionResults(module, finder)); + } + + return results; + } + + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) + { + return declaration.IdentifierName.StartsWith("VBAProject"); + } + + protected override string ResultDescription(Declaration declaration) + { + return Description; } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyMethodInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyMethodInspection.cs index 88c173ca2b..5d63f14dd3 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyMethodInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyMethodInspection.cs @@ -1,16 +1,9 @@ using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using System.Collections.Generic; -using System.Linq; using Rubberduck.Parsing.Symbols; -using Rubberduck.Common; using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing.VBA.DeclarationCaching; -using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete { @@ -35,47 +28,20 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - internal class EmptyMethodInspection : InspectionBase + internal class EmptyMethodInspection : DeclarationInspectionBase { public EmptyMethodInspection(RubberduckParserState state) - : base(state) { } + : base(state, DeclarationType.Member) + {} - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { - var finder = State.DeclarationFinder; - - var userInterfaces = UserInterfaces(finder); - var emptyMethods = EmptyNonInterfaceMethods(finder, userInterfaces); - - return emptyMethods.Select(Result); - } - - private static ICollection UserInterfaces(DeclarationFinder finder) - { - return finder - .FindAllUserInterfaces() - .Select(decl => decl.QualifiedModuleName) - .ToHashSet(); - } - - private static IEnumerable EmptyNonInterfaceMethods(DeclarationFinder finder, ICollection userInterfaces) - { - return finder - .UserDeclarations(DeclarationType.Member) - .Where(member => !userInterfaces.Contains(member.QualifiedModuleName) - && member is ModuleBodyElementDeclaration moduleBodyElement - && !moduleBodyElement.Block.ContainsExecutableStatements()); - } - - private IInspectionResult Result(Declaration member) - { - return new DeclarationInspectionResult( - this, - ResultDescription(member), - member); + return declaration is ModuleBodyElementDeclaration member + && !member.IsInterfaceMember + && !member.Block.ContainsExecutableStatements(); } - private static string ResultDescription(Declaration member) + protected override string ResultDescription(Declaration member) { var identifierName = member.IdentifierName; var declarationType = member.DeclarationType.ToLocalizedString(); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EncapsulatePublicFieldInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EncapsulatePublicFieldInspection.cs index 41d54ed992..8f3360e12d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EncapsulatePublicFieldInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EncapsulatePublicFieldInspection.cs @@ -1,12 +1,8 @@ -using System.Collections.Generic; -using System.Linq; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -31,25 +27,23 @@ namespace Rubberduck.Inspections.Concrete /// End Property /// ]]> /// - public sealed class EncapsulatePublicFieldInspection : InspectionBase + public sealed class EncapsulatePublicFieldInspection : DeclarationInspectionBase { public EncapsulatePublicFieldInspection(RubberduckParserState state) - : base(state) { } + : base(state, DeclarationType.Variable) + {} - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { - // we're creating a public field for every control on a form, needs to be ignored. - var fields = State.DeclarationFinder.UserDeclarations(DeclarationType.Variable) - .Where(item => item.DeclarationType != DeclarationType.Control - && (item.Accessibility == Accessibility.Public || - item.Accessibility == Accessibility.Global)) - .ToList(); + // we're creating a public field for every control on a form, needs to be ignored + return declaration.DeclarationType != DeclarationType.Control + && (declaration.Accessibility == Accessibility.Public + || declaration.Accessibility == Accessibility.Global); + } - return fields - .Select(issue => new DeclarationInspectionResult(this, - string.Format(InspectionResults.EncapsulatePublicFieldInspection, issue.IdentifierName), - issue)) - .ToList(); + protected override string ResultDescription(Declaration declaration) + { + return string.Format(InspectionResults.EncapsulatePublicFieldInspection, declaration.IdentifierName); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/HostSpecificExpressionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/HostSpecificExpressionInspection.cs index da3ac92d79..75ae75777d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/HostSpecificExpressionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/HostSpecificExpressionInspection.cs @@ -1,11 +1,11 @@ using System.Collections.Generic; using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -30,15 +30,20 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class HostSpecificExpressionInspection : InspectionBase + public sealed class HostSpecificExpressionInspection : DeclarationInspectionBase { public HostSpecificExpressionInspection(RubberduckParserState state) - : base(state) { } + : base(state, DeclarationType.BracketedExpression) + {} - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { - return Declarations.Where(item => item.DeclarationType == DeclarationType.BracketedExpression) - .Select(item => new DeclarationInspectionResult(this, string.Format(InspectionResults.HostSpecificExpressionInspection, item.IdentifierName), item)); + return true; + } + + protected override string ResultDescription(Declaration declaration) + { + return string.Format(InspectionResults.HostSpecificExpressionInspection, declaration.IdentifierName); } } } \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/HungarianNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/HungarianNotationInspection.cs index 1570e0e40c..7650a478cc 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/HungarianNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/HungarianNotationInspection.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; -using System.Globalization; using System.Linq; -using System.Text.RegularExpressions; using Rubberduck.CodeAnalysis.Settings; using Rubberduck.Common; using Rubberduck.Inspections.Abstract; @@ -10,8 +8,9 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Resources; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.SettingsProvider; +using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete { @@ -49,7 +48,6 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class HungarianNotationInspection : InspectionBase { - #region statics private static readonly List TargetDeclarationTypes = new List { DeclarationType.Parameter, @@ -72,8 +70,6 @@ public sealed class HungarianNotationInspection : InspectionBase DeclarationType.LibraryProcedure }; - #endregion - private readonly IConfigurationService _settings; public HungarianNotationInspection(RubberduckParserState state, IConfigurationService settings) @@ -84,22 +80,79 @@ public HungarianNotationInspection(RubberduckParserState state, IConfigurationSe protected override IEnumerable DoGetInspectionResults() { + var finder = DeclarationFinderProvider.DeclarationFinder; var settings = _settings.Read(); - var whitelistedNames = settings.WhitelistedIdentifiers.Select(s => s.Identifier).ToList(); + var whitelistedNames = settings.WhitelistedIdentifiers + .Select(s => s.Identifier) + .ToList(); + + var results = new List(); + foreach (var moduleDeclaration in State.DeclarationFinder.UserDeclarations(DeclarationType.Module)) + { + if (moduleDeclaration == null) + { + continue; + } + + var module = moduleDeclaration.QualifiedModuleName; + results.AddRange(DoGetInspectionResults(module, finder, whitelistedNames)); + } + + return results; + } + + private IEnumerable DoGetInspectionResults(QualifiedModuleName module) + { + var finder = DeclarationFinderProvider.DeclarationFinder; + var settings = _settings.Read(); + var whitelistedNames = settings.WhitelistedIdentifiers + .Select(s => s.Identifier) + .ToList(); + return DoGetInspectionResults(module, finder, whitelistedNames); + } + + private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder, List whitelistedNames) + { + var objectionableDeclarations = RelevantDeclarationsInModule(module, finder) + .Where(declaration => IsResultDeclaration(declaration, whitelistedNames)); - var hungarians = UserDeclarations - .Where(declaration => !whitelistedNames.Contains(declaration.IdentifierName) - && TargetDeclarationTypes.Contains(declaration.DeclarationType) - && !IgnoredProcedureTypes.Contains(declaration.DeclarationType) - && !IgnoredProcedureTypes.Contains(declaration.ParentDeclaration.DeclarationType) - && declaration.IdentifierName.TryMatchHungarianNotationCriteria(out _)) - .Select(issue => new DeclarationInspectionResult(this, - string.Format(Resources.Inspections.InspectionResults.IdentifierNameInspection, - RubberduckUI.ResourceManager.GetString($"DeclarationType_{issue.DeclarationType}", CultureInfo.CurrentUICulture), - issue.IdentifierName), - issue)); + return objectionableDeclarations + .Select(InspectionResult) + .ToList(); + } + + private static bool IsResultDeclaration(Declaration declaration, ICollection whitelistedNames) + { + return !whitelistedNames.Contains(declaration.IdentifierName) + && !IgnoredProcedureTypes.Contains(declaration.ParentDeclaration.DeclarationType) + && declaration.IdentifierName.TryMatchHungarianNotationCriteria(out _); + } - return hungarians; + private IInspectionResult InspectionResult(Declaration declaration) + { + return new DeclarationInspectionResult( + this, + ResultDescription(declaration), + declaration); + } + + private static string ResultDescription(Declaration declaration) + { + var declarationType = declaration.DeclarationType.ToLocalizedString(); + var declarationName = declaration.IdentifierName; + return string.Format( + Resources.Inspections.InspectionResults.IdentifierNameInspection, + declarationType, + declarationName); + } + + private IEnumerable RelevantDeclarationsInModule(QualifiedModuleName module, DeclarationFinder finder) + { + var potentiallyRelevantDeclarations = TargetDeclarationTypes + .SelectMany(declarationType => finder.Members(module, declarationType)) + .Distinct(); + return potentiallyRelevantDeclarations + .Where(declaration => !IgnoredProcedureTypes.Contains(declaration.DeclarationType)); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/NonReturningFunctionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/NonReturningFunctionInspection.cs index f906683e60..4c2ea5f3dc 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/NonReturningFunctionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/NonReturningFunctionInspection.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Inspections.Results; using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing; @@ -10,7 +9,7 @@ using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.VBA.Extensions; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -38,61 +37,69 @@ namespace Rubberduck.Inspections.Concrete /// End Function /// ]]> /// - public sealed class NonReturningFunctionInspection : InspectionBase + public sealed class NonReturningFunctionInspection : DeclarationInspectionBase { public NonReturningFunctionInspection(RubberduckParserState state) - : base(state) { } + : base(state, DeclarationType.Function) + { } - private static readonly DeclarationType[] ReturningMemberTypes = + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { - DeclarationType.Function, - DeclarationType.PropertyGet - }; + return declaration is ModuleBodyElementDeclaration member + && !member.IsInterfaceMember + && (IsReturningUserDefinedType(member) + && !IsUserDefinedTypeAssigned(member) + || !IsReturningUserDefinedType(member) + && !IsAssigned(member, finder)); + } - protected override IEnumerable DoGetInspectionResults() + private bool IsAssigned(Declaration member, DeclarationFinder finder) { - var interfaceMembers = State.DeclarationFinder.FindAllInterfaceMembers().ToHashSet(); + var inScopeIdentifierReferences = member.References + .Where(reference => reference.ParentScoping.Equals(member)); + return inScopeIdentifierReferences + .Any(reference => reference.IsAssignment + || IsAssignedByRefArgument(member, reference, finder)); + } - var functions = State.DeclarationFinder.UserDeclarations(DeclarationType.Function) - .Where(declaration => !interfaceMembers.Contains(declaration)); + private bool IsAssignedByRefArgument(Declaration enclosingProcedure, IdentifierReference reference, DeclarationFinder finder) + { + var argExpression = ImmediateArgumentExpressionContext(reference); - var unassigned = functions.Where(function => IsReturningUserDefinedType(function) - && !IsUserDefinedTypeAssigned(function) - || !IsReturningUserDefinedType(function) - && !IsAssigned(function)); + if (argExpression is null) + { + return false; + } - return unassigned - .Select(issue => - new DeclarationInspectionResult(this, - string.Format(InspectionResults.NonReturningFunctionInspection, issue.IdentifierName), - issue)); - } + var parameter = finder.FindParameterOfNonDefaultMemberFromSimpleArgumentNotPassedByValExplicitly(argExpression, enclosingProcedure); - private bool IsAssigned(Declaration function) - { - var inScopeIdentifierReferences = function.References.Where(r => r.ParentScoping.Equals(function)); - return inScopeIdentifierReferences.Any(reference => reference.IsAssignment - || IsAssignedByRefArgument(function, reference)); + // note: not recursive, by design. + return parameter != null + && (parameter.IsImplicitByRef || parameter.IsByRef) + && parameter.References.Any(r => r.IsAssignment); } - private bool IsAssignedByRefArgument(Declaration enclosingProcedure, IdentifierReference reference) + private static VBAParser.ArgumentExpressionContext ImmediateArgumentExpressionContext(IdentifierReference reference) { - var argExpression = reference.Context.GetAncestor(); - var parameter = State.DeclarationFinder.FindParameterOfNonDefaultMemberFromSimpleArgumentNotPassedByValExplicitly(argExpression, enclosingProcedure); + var context = reference.Context; + //The context is either already a simpleNameExprContext or an IdentifierValueContext used in a sub-rule of some other lExpression alternative. + var lExpressionNameContext = context is VBAParser.SimpleNameExprContext simpleName + ? simpleName + : context.GetAncestor(); - // note: not recursive, by design. - return parameter != null - && (parameter.IsImplicitByRef || parameter.IsByRef) - && parameter.References.Any(r => r.IsAssignment); + //To be an immediate argument and, thus, assignable by ref, the structure must be argumentExpression -> expression -> lExpression. + return lExpressionNameContext? + .Parent? + .Parent as VBAParser.ArgumentExpressionContext; } private static bool IsReturningUserDefinedType(Declaration member) { - return member.AsTypeDeclaration != null && - member.AsTypeDeclaration.DeclarationType == DeclarationType.UserDefinedType; + return member.AsTypeDeclaration != null + && member.AsTypeDeclaration.DeclarationType == DeclarationType.UserDefinedType; } - private bool IsUserDefinedTypeAssigned(Declaration member) + private static bool IsUserDefinedTypeAssigned(Declaration member) { // ref. #2257: // A function returning a UDT type shouldn't trip this inspection if @@ -102,7 +109,12 @@ private bool IsUserDefinedTypeAssigned(Declaration member) var result = visitor.VisitBlock(block); return result; } - + + protected override string ResultDescription(Declaration declaration) + { + return string.Format(InspectionResults.NonReturningFunctionInspection, declaration.IdentifierName); + } + /// /// A visitor that visits a member's body and returns true if any LET statement (assignment) is assigning the specified name. /// diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteGlobalInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteGlobalInspection.cs index f59eab96d1..179e93fc7f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteGlobalInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteGlobalInspection.cs @@ -33,7 +33,8 @@ public ObsoleteGlobalInspection(RubberduckParserState state) protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { return declaration.Accessibility == Accessibility.Global - && declaration.Context != null; + && declaration.Context != null + && declaration.DeclarationType != DeclarationType.BracketedExpression; } protected override string ResultDescription(Declaration declaration) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SelfAssignedDeclarationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SelfAssignedDeclarationInspection.cs index 348c793f62..1f49fcd9d4 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SelfAssignedDeclarationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SelfAssignedDeclarationInspection.cs @@ -1,13 +1,10 @@ -using System.Collections.Generic; -using System.Linq; +using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -43,24 +40,26 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class SelfAssignedDeclarationInspection : InspectionBase + public sealed class SelfAssignedDeclarationInspection : DeclarationInspectionBase { public SelfAssignedDeclarationInspection(RubberduckParserState state) - : base(state) { } + : base(state, DeclarationType.Variable) + {} - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { - return State.DeclarationFinder.UserDeclarations(DeclarationType.Variable) - .Where(declaration => declaration.IsSelfAssigned - && declaration.IsTypeSpecified - && !SymbolList.ValueTypes.Contains(declaration.AsTypeName) - && (declaration.AsTypeDeclaration == null - || declaration.AsTypeDeclaration.DeclarationType != DeclarationType.UserDefinedType) - && declaration.ParentScopeDeclaration != null - && declaration.ParentScopeDeclaration.DeclarationType.HasFlag(DeclarationType.Member)) - .Select(issue => new DeclarationInspectionResult(this, - string.Format(InspectionResults.SelfAssignedDeclarationInspection, issue.IdentifierName), - issue)); + return declaration.IsSelfAssigned + && declaration.IsTypeSpecified + && !SymbolList.ValueTypes.Contains(declaration.AsTypeName) + && (declaration.AsTypeDeclaration == null + || declaration.AsTypeDeclaration.DeclarationType != DeclarationType.UserDefinedType) + && declaration.ParentScopeDeclaration != null + && declaration.ParentScopeDeclaration.DeclarationType.HasFlag(DeclarationType.Member); + } + + protected override string ResultDescription(Declaration declaration) + { + return string.Format(InspectionResults.SelfAssignedDeclarationInspection, declaration.IdentifierName); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs index dba6cb3bf1..7917f8cffa 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs @@ -66,7 +66,9 @@ protected override IEnumerable ObjectionableDeclarations(Declaratio && finder.MatchName(declaration.AsTypeName) .All(d => d.DeclarationType != DeclarationType.UserDefinedType) && !declaration.References - .Any(reference => reference.IsAssignment)); + .Any(reference => reference.IsAssignment) + && !declaration.References + .Any(reference => IsAssignedByRefArgument(reference.ParentScoping, reference, finder))); } //We override this in order to look up the argument usage exclusion references only once. @@ -130,7 +132,6 @@ private static IEnumerable SingleVariableArgumentSelections( protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) { return reference != null - && !IsAssignedByRefArgument(reference.ParentScoping, reference, finder) && !IsArraySubscriptAssignment(reference) && !IsArrayReDim(reference); } @@ -145,13 +146,33 @@ protected override string ResultDescription(IdentifierReference reference) private static bool IsAssignedByRefArgument(Declaration enclosingProcedure, IdentifierReference reference, DeclarationFinder finder) { - var argExpression = reference.Context.GetAncestor(); + var argExpression = ImmediateArgumentExpressionContext(reference); + + if (argExpression is null) + { + return false; + } + var parameter = finder.FindParameterOfNonDefaultMemberFromSimpleArgumentNotPassedByValExplicitly(argExpression, enclosingProcedure); // note: not recursive, by design. return parameter != null - && (parameter.IsImplicitByRef || parameter.IsByRef) - && parameter.References.Any(r => r.IsAssignment); + && (parameter.IsImplicitByRef || parameter.IsByRef) + && parameter.References.Any(r => r.IsAssignment); + } + + private static VBAParser.ArgumentExpressionContext ImmediateArgumentExpressionContext(IdentifierReference reference) + { + var context = reference.Context; + //The context is either already a simpleNameExprContext or an IdentifierValueContext used in a sub-rule of some other lExpression alternative. + var lExpressionNameContext = context is VBAParser.SimpleNameExprContext simpleName + ? simpleName + : context.GetAncestor(); + + //To be an immediate argument and, thus, assignable by ref, the structure must be argumentExpression -> expression -> lExpression. + return lExpressionNameContext? + .Parent? + .Parent as VBAParser.ArgumentExpressionContext; } private static bool IsArraySubscriptAssignment(IdentifierReference reference) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnderscoreInPublicClassModuleMemberInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnderscoreInPublicClassModuleMemberInspection.cs index e42555972c..93b22538b8 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnderscoreInPublicClassModuleMemberInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnderscoreInPublicClassModuleMemberInspection.cs @@ -1,11 +1,8 @@ -using System.Collections.Generic; -using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -32,25 +29,25 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class UnderscoreInPublicClassModuleMemberInspection : InspectionBase + public sealed class UnderscoreInPublicClassModuleMemberInspection : DeclarationInspectionBase { public UnderscoreInPublicClassModuleMemberInspection(RubberduckParserState state) - : base(state) { } + : base(state, DeclarationType.Member) + {} - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { - var interfaceMembers = State.DeclarationFinder.FindAllInterfaceImplementingMembers().ToList(); - var eventHandlers = State.DeclarationFinder.FindEventHandlers().ToList(); - - var names = State.DeclarationFinder.UserDeclarations(Parsing.Symbols.DeclarationType.Member) - .Where(w => w.ParentDeclaration.DeclarationType.HasFlag(Parsing.Symbols.DeclarationType.ClassModule)) - .Where(w => !interfaceMembers.Contains(w) && !eventHandlers.Contains(w)) - .Where(w => w.Accessibility == Parsing.Symbols.Accessibility.Public || w.Accessibility == Parsing.Symbols.Accessibility.Implicit) - .Where(w => w.IdentifierName.Contains('_')) - .ToList(); + return declaration.IdentifierName.Contains("_") + && (declaration.Accessibility == Accessibility.Public + || declaration.Accessibility == Accessibility.Implicit) + && declaration.ParentDeclaration.DeclarationType.HasFlag(DeclarationType.ClassModule) + && !finder.FindEventHandlers().Contains(declaration) + && !(declaration is ModuleBodyElementDeclaration member && member.IsInterfaceImplementation); + } - return names.Select(issue => - new DeclarationInspectionResult(this, string.Format(InspectionResults.UnderscoreInPublicClassModuleMemberInspection, issue.IdentifierName), issue)); + protected override string ResultDescription(Declaration declaration) + { + return string.Format(InspectionResults.UnderscoreInPublicClassModuleMemberInspection, declaration.IdentifierName); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseMeaningfulNameInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseMeaningfulNameInspection.cs index 549705af54..3a4a7bc2b2 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseMeaningfulNameInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseMeaningfulNameInspection.cs @@ -58,7 +58,9 @@ protected override IEnumerable DoGetInspectionResults() { var finder = DeclarationFinderProvider.DeclarationFinder; var settings = _settings.Read(); - var whitelistedNames = settings.WhitelistedIdentifiers.Select(s => s.Identifier).ToArray(); + var whitelistedNames = settings.WhitelistedIdentifiers + .Select(s => s.Identifier) + .ToArray(); var handlers = finder.FindEventHandlers().ToHashSet(); var results = new List(); @@ -80,7 +82,9 @@ private IEnumerable DoGetInspectionResults(QualifiedModuleNam { var finder = DeclarationFinderProvider.DeclarationFinder; var settings = _settings.Read(); - var whitelistedNames = settings.WhitelistedIdentifiers.Select(s => s.Identifier).ToArray(); + var whitelistedNames = settings.WhitelistedIdentifiers + .Select(s => s.Identifier) + .ToArray(); var handlers = finder.FindEventHandlers().ToHashSet(); return DoGetInspectionResults(module, finder, whitelistedNames, handlers); } @@ -88,14 +92,14 @@ private IEnumerable DoGetInspectionResults(QualifiedModuleNam private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder, string[] whitelistedNames, ICollection eventHandlers) { var objectionableDeclarations = finder.Members(module) - .Where(declaration => IsResultDeclaration(declaration, finder, whitelistedNames, eventHandlers)); + .Where(declaration => IsResultDeclaration(declaration, whitelistedNames, eventHandlers)); return objectionableDeclarations .Select(InspectionResult) .ToList(); } - private static bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder, string[] whitelistedNames, ICollection eventHandlers) + private static bool IsResultDeclaration(Declaration declaration, string[] whitelistedNames, ICollection eventHandlers) { return !string.IsNullOrEmpty(declaration.IdentifierName) && !IgnoreDeclarationTypes.Contains(declaration.DeclarationType) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotUsedInspection.cs index 86a2516cd0..541ca5666e 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotUsedInspection.cs @@ -1,7 +1,5 @@ -using System.Collections.Generic; using System.Linq; using Antlr4.Runtime; -using Rubberduck.Common; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Results; using Rubberduck.Parsing; @@ -10,6 +8,8 @@ using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -37,30 +37,47 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class VariableNotUsedInspection : InspectionBase + public sealed class VariableNotUsedInspection : DeclarationInspectionBase { /// /// Inspection results for variables that are never referenced. /// /// - public VariableNotUsedInspection(RubberduckParserState state) : base(state) { } + public VariableNotUsedInspection(RubberduckParserState state) + : base(state, DeclarationType.Variable) + {} - /// - /// VariableNotUsedInspection override of InspectionBase.DoGetInspectionResults() - /// - /// Enumerable IInspectionResults - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) + { + return !declaration.IsWithEvents + && declaration.References + .All(reference => reference.IsAssignment); + } + + protected override IInspectionResult InspectionResult(Declaration declaration) { - var declarations = State.DeclarationFinder.UserDeclarations(DeclarationType.Variable) - .Where(declaration => - !declaration.IsWithEvents - && declaration.References.All(rf => rf.IsAssignment)); + return new DeclarationInspectionResult( + this, + ResultDescription(declaration), + declaration, + Context(declaration)); + } - return declarations.Select(issue => - new DeclarationInspectionResult(this, - string.Format(InspectionResults.IdentifierNotUsedInspection, issue.DeclarationType.ToLocalizedString(), issue.IdentifierName), - issue, - new QualifiedContext(issue.QualifiedName.QualifiedModuleName, ((dynamic)issue.Context).identifier()))); + protected override string ResultDescription(Declaration declaration) + { + var declarationType = declaration.DeclarationType.ToLocalizedString(); + var declarationName = declaration.IdentifierName; + return string.Format( + InspectionResults.IdentifierNotUsedInspection, + declarationType, + declarationName); + } + + private QualifiedContext Context(Declaration declaration) + { + var module = declaration.QualifiedModuleName; + var context = declaration.Context.GetDescendent(); + return new QualifiedContext(module, context); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableTypeNotDeclaredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableTypeNotDeclaredInspection.cs index c07110198f..1c50e53775 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableTypeNotDeclaredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableTypeNotDeclaredInspection.cs @@ -1,12 +1,9 @@ -using System.Collections.Generic; -using System.Linq; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Inspections.Abstract; +using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -34,21 +31,28 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class VariableTypeNotDeclaredInspection : InspectionBase + public sealed class VariableTypeNotDeclaredInspection : ImplicitTypeInspectionBase { public VariableTypeNotDeclaredInspection(RubberduckParserState state) - : base(state) { } + : base(state, new []{DeclarationType.Parameter, DeclarationType.Variable}, new[]{DeclarationType.Control}) + {} + + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) + { + return base.IsResultDeclaration(declaration, finder) + && !declaration.IsUndeclared + && (declaration.DeclarationType != DeclarationType.Parameter + || declaration is ParameterDeclaration parameter && !parameter.IsParamArray); + } - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(Declaration declaration) { - var issues = from item in State.DeclarationFinder.UserDeclarations(DeclarationType.Variable) - .Union(State.DeclarationFinder.UserDeclarations(DeclarationType.Parameter)) - where (item.DeclarationType != DeclarationType.Parameter || (item.DeclarationType == DeclarationType.Parameter && !item.IsArray)) - && item.DeclarationType != DeclarationType.Control - && !item.IsTypeSpecified - && !item.IsUndeclared - select new DeclarationInspectionResult(this, string.Format(InspectionResults.ImplicitVariantDeclarationInspection, item.DeclarationType, item.IdentifierName), item); - return issues; + var declarationType = declaration.DeclarationType.ToLocalizedString(); + var declarationName = declaration.IdentifierName; + return string.Format( + InspectionResults.ImplicitVariantDeclarationInspection, + declarationType, + declarationName); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/WriteOnlyPropertyInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/WriteOnlyPropertyInspection.cs index b0572304e5..af279b3a33 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/WriteOnlyPropertyInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/WriteOnlyPropertyInspection.cs @@ -1,12 +1,12 @@ using System.Collections.Generic; using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete { @@ -39,26 +39,35 @@ namespace Rubberduck.Inspections.Concrete /// End Property /// ]]> /// - public sealed class WriteOnlyPropertyInspection : InspectionBase + public sealed class WriteOnlyPropertyInspection : DeclarationInspectionBase { public WriteOnlyPropertyInspection(RubberduckParserState state) - : base(state) { } - - protected override IEnumerable DoGetInspectionResults() + : base(state, DeclarationType.PropertyLet, DeclarationType.PropertySet) { } + + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { - var setters = State.DeclarationFinder.UserDeclarations(DeclarationType.Property | DeclarationType.Procedure) - .Where(item => - (item.Accessibility == Accessibility.Implicit || - item.Accessibility == Accessibility.Public || - item.Accessibility == Accessibility.Global) - && State.DeclarationFinder.MatchName(item.IdentifierName).All(accessor => accessor.DeclarationType != DeclarationType.PropertyGet)) - .GroupBy(item => new {item.QualifiedName, item.DeclarationType}) + var setters = RelevantDeclarationsInModule(module, finder) + .Where(declaration => IsResultDeclaration(declaration, finder)) + .GroupBy(declaration => declaration.DeclarationType) .Select(grouping => grouping.First()); // don't get both Let and Set accessors - return setters.Select(setter => - new DeclarationInspectionResult(this, - string.Format(InspectionResults.WriteOnlyPropertyInspection, setter.IdentifierName), - setter)); + return setters + .Select(InspectionResult) + .ToList(); + } + + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) + { + return (declaration.Accessibility == Accessibility.Implicit + || declaration.Accessibility == Accessibility.Public + || declaration.Accessibility == Accessibility.Global) + && finder.MatchName(declaration.IdentifierName) + .All(accessor => accessor.DeclarationType != DeclarationType.PropertyGet); + } + + protected override string ResultDescription(Declaration declaration) + { + return string.Format(InspectionResults.WriteOnlyPropertyInspection, declaration.IdentifierName); } } } diff --git a/Rubberduck.Core/UI/CodeExplorer/Commands/UpdateFromFileCommand.cs b/Rubberduck.Core/UI/CodeExplorer/Commands/UpdateFromFileCommand.cs index 0b5534730d..b9b2e19197 100644 --- a/Rubberduck.Core/UI/CodeExplorer/Commands/UpdateFromFileCommand.cs +++ b/Rubberduck.Core/UI/CodeExplorer/Commands/UpdateFromFileCommand.cs @@ -1,17 +1,12 @@ using System.Collections.Generic; -using System.IO; using System.Linq; using Rubberduck.Interaction; -using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.VBA.DeclarationCaching; -using Rubberduck.Parsing.VBA.Extensions; using Rubberduck.Resources; using Rubberduck.VBEditor; using Rubberduck.VBEditor.Events; using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.Extensions; -using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; using Rubberduck.VBEditor.Utility; diff --git a/Rubberduck.Parsing/Binding/Bindings/SimpleNameDefaultBinding.cs b/Rubberduck.Parsing/Binding/Bindings/SimpleNameDefaultBinding.cs index 647b6f4046..557f0d5a8e 100644 --- a/Rubberduck.Parsing/Binding/Bindings/SimpleNameDefaultBinding.cs +++ b/Rubberduck.Parsing/Binding/Bindings/SimpleNameDefaultBinding.cs @@ -72,7 +72,7 @@ public IBoundExpression Resolve() if (_context.Start.Text == "[" && _context.Stop.Text == "]") { - var bracketedExpression = _declarationFinder.OnBracketedExpression(_context.GetText(), _context); + var bracketedExpression = _declarationFinder.OnBracketedExpression(_context.GetText(), _context, _module.QualifiedModuleName); return new SimpleNameExpression(bracketedExpression, ExpressionClassification.Unbound, _context); } diff --git a/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs b/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs index bf5ad33983..20ff753143 100644 --- a/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs +++ b/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs @@ -51,12 +51,12 @@ public class DeclarationFinder private Lazy>> _interfaceImplementations; private Lazy>> _implementationsByMember; - private Lazy> _nonBaseAsType; - private Lazy> _eventHandlers; - private Lazy> _controlEventHandlers; - private Lazy> _formEventHandlers; - private Lazy> _projects; - private Lazy> _classes; + private Lazy> _nonBaseAsType; + private Lazy> _eventHandlers; + private Lazy> _controlEventHandlers; + private Lazy> _formEventHandlers; + private Lazy> _projects; + private Lazy> _classes; private static QualifiedSelection GetGroupingKey(Declaration declaration) { @@ -160,7 +160,7 @@ private void InitializeLazyCollections() .ToDictionary() , true); - _nonBaseAsType = new Lazy>(() => + _nonBaseAsType = new Lazy>(() => _declarations .AllValues() .Where(d => !string.IsNullOrWhiteSpace(d.AsTypeName) @@ -170,11 +170,11 @@ private void InitializeLazyCollections() .ToList() , true); - _eventHandlers = new Lazy>(FindAllEventHandlers, true); - _controlEventHandlers = new Lazy>(FindAllFormControlHandlers, true); - _formEventHandlers = new Lazy>(FindAllFormEventHandlers, true); - _projects = new Lazy>(() => DeclarationsWithType(DeclarationType.Project).ToList(), true); - _classes = new Lazy>(() => DeclarationsWithType(DeclarationType.ClassModule).ToList(), true); + _eventHandlers = new Lazy>(FindAllEventHandlers, true); + _controlEventHandlers = new Lazy>(FindAllFormControlHandlers, true); + _formEventHandlers = new Lazy>(FindAllFormEventHandlers, true); + _projects = new Lazy>(() => DeclarationsWithType(DeclarationType.Project).ToList(), true); + _classes = new Lazy>(() => DeclarationsWithType(DeclarationType.ClassModule).ToList(), true); _handlersByWithEventsField = new Lazy>>(FindAllHandlersByWithEventField, true); _implementingMembers = new Lazy>>(FindAllImplementingMembers, true); @@ -317,12 +317,12 @@ public Declaration ModuleDeclaration(QualifiedModuleName module) public IEnumerable AllDeclarations => _declarations.AllValues(); - public IEnumerable FindDeclarationsWithNonBaseAsType() + public ICollection FindDeclarationsWithNonBaseAsType() { return _nonBaseAsType.Value; } - public IEnumerable FindEventHandlers() + public ICollection FindEventHandlers() { return _eventHandlers.Value; } @@ -335,7 +335,7 @@ public IEnumerable FindEventHandlers(Declaration eventDeclaration) .Single(handler => handler.IdentifierName == $"{withEventsField.IdentifierName}_{eventDeclaration.IdentifierName}")); } - public IEnumerable FindFormControlEventHandlers() + public ICollection FindFormControlEventHandlers() { return _controlEventHandlers.Value; } @@ -1062,12 +1062,12 @@ public void AddFailedIndexedDefaultMemberResolution(IdentifierReference failedPr store.AddFailedIndexedDefaultMemberResolution(failedProcedureCoercion); } - public Declaration OnBracketedExpression(string expression, ParserRuleContext context) + public Declaration OnBracketedExpression(string expression, ParserRuleContext context, QualifiedModuleName module) { var hostApp = FindProject(_hostApp == null ? "VBA" : _hostApp.ApplicationName); Debug.Assert(hostApp != null, "Host application project can't be null. Make sure VBA standard library is included if host is unknown."); - var qualifiedName = hostApp.QualifiedName.QualifiedModuleName.QualifyMemberName(expression); + var qualifiedName = module.QualifyMemberName(expression); var declarationType = DeclarationType.BracketedExpression; var undeclaredScope = (qualifiedName, declarationType); @@ -1238,7 +1238,7 @@ private List FindAllFormControlHandlers() return handlers.ToList(); } - private List FindAllEventHandlers() + private HashSet FindAllEventHandlers() { var handlerNames = BuiltInDeclarations(DeclarationType.Event) .SelectMany(e => @@ -1261,7 +1261,7 @@ private List FindAllEventHandlers() .Concat(_handlersByWithEventsField.Value.AllValues()) .Concat(FindFormControlEventHandlers()) .Concat(FindFormEventHandlers()); - return handlers.ToList(); + return handlers.ToHashSet(); // Local functions to help break up the complex logic in finding built-in handlers bool IsVBAClassSpecificHandler(Declaration item) diff --git a/RubberduckTests/Inspections/NonReturningFunctionInspectionTests.cs b/RubberduckTests/Inspections/NonReturningFunctionInspectionTests.cs index d8d43a7621..c615e47f27 100644 --- a/RubberduckTests/Inspections/NonReturningFunctionInspectionTests.cs +++ b/RubberduckTests/Inspections/NonReturningFunctionInspectionTests.cs @@ -100,6 +100,21 @@ Public Function Foo() As Boolean ByRefAssign (Foo) End Function +Public Sub ByRefAssign(ByRef a As Boolean) +End Sub +"; + Assert.AreEqual(1, InspectionResultsForStandardModule(inputCode).Count()); + } + + [Test] + [Category("Inspections")] + public void NonReturningFunction_ReturnsResult_GivenUseStrictlyInsideByRefAssignment() + { + const string inputCode = @" +Public Function Foo() As Boolean + ByRefAssign Foo + 42 +End Function + Public Sub ByRefAssign(ByRef a As Boolean) End Sub "; diff --git a/RubberduckTests/Inspections/ObsoleteGlobalInspectionTests.cs b/RubberduckTests/Inspections/ObsoleteGlobalInspectionTests.cs index 89a289ae41..82ee599ae3 100644 --- a/RubberduckTests/Inspections/ObsoleteGlobalInspectionTests.cs +++ b/RubberduckTests/Inspections/ObsoleteGlobalInspectionTests.cs @@ -1,8 +1,12 @@ using System.Linq; +using Moq; using NUnit.Framework; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; +using Rubberduck.VBEditor.SafeComWrappers; +using Rubberduck.VBEditor.SafeComWrappers.Abstract; +using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { @@ -47,6 +51,23 @@ public void ObsoleteGlobal_ReturnsResult_SomeConstantsUsed() Assert.AreEqual(1, InspectionResultsForStandardModule(inputCode).Count()); } + [Test] + [Category("Inspections")] + public void ObsoleteGlobal_ReturnsNoResult_BracketedExpression() + { + const string code = @" +Public Sub DoSomething() + [A1] = 42 +End Sub +"; + var vbe = MockVbeBuilder.BuildFromModules(("Module1", code, ComponentType.StandardModule), new ReferenceLibrary[] { ReferenceLibrary.VBA, ReferenceLibrary.Excel }); + var mockHost = new Mock(); + mockHost.SetupGet(m => m.ApplicationName).Returns("Excel"); + vbe.Setup(m => m.HostApplication()).Returns(() => mockHost.Object); + + Assert.AreEqual(0, InspectionResults(vbe.Object).Count()); + } + [Test] [Category("Inspections")] public void ObsoleteGlobal_Ignored_DoesNotReturnResult() diff --git a/RubberduckTests/Inspections/UnassignedVariableUsageInspectionTests.cs b/RubberduckTests/Inspections/UnassignedVariableUsageInspectionTests.cs index 9d74b018b9..097beca9b0 100644 --- a/RubberduckTests/Inspections/UnassignedVariableUsageInspectionTests.cs +++ b/RubberduckTests/Inspections/UnassignedVariableUsageInspectionTests.cs @@ -262,7 +262,6 @@ End Sub } [Test] - [Ignore("Test is green if executed manually, red otherwise. Possible concurrency issue?")] [Category("Inspections")] public void UnassignedVariableUsage_NoResultForAssignedByRefReference() { @@ -281,6 +280,25 @@ End Sub Assert.AreEqual(0, InspectionResultsForStandardModule(code).Count()); } + [Test] + [Category("Inspections")] + public void UnassignedVariableUsage_ResultForUseStrictlyInsideArgumentToByRefArgument() + { + const string code = @" +Sub DoSomething() + Dim foo + AssignThing foo + 42 + Dim bar As Variant + bar = foo +End Sub + +Sub AssignThing(ByRef thing As Variant) + thing = 42 +End Sub +"; + Assert.AreEqual(2, InspectionResultsForStandardModule(code).Count()); + } + [Test] [Category("Inspections")] public void UnassignedVariableUsage_NoResultIfNoReferences() From 47f3d5884b986e5c6c455164f36b1157fae13e8b Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sun, 9 Feb 2020 02:42:58 +0100 Subject: [PATCH 217/461] Make more declaration inspections use one of the base classes In particular, this includes a complete rewrite of ParameterCanBeByValInspection. --- ...elUdfNameIsValidCellReferenceInspection.cs | 1 - .../MoveFieldCloserToUsageInspection.cs | 1 - .../Concrete/ParameterCanBeByValInspection.cs | 315 +++++++++--------- .../Concrete/ParameterNotUsedInspection.cs | 1 - .../Concrete/ProcedureNotUsedInspection.cs | 125 ++++--- .../UnassignedVariableUsageInspection.cs | 3 - .../Concrete/UseMeaningfulNameInspection.cs | 5 +- .../PassParameterByValueQuickFix.cs | 1 - .../SpecialFormDeclarations.cs | 27 +- .../DeclarationCaching/DeclarationFinder.cs | 24 +- .../ParameterCanBeByValInspectionTests.cs | 32 +- 11 files changed, 281 insertions(+), 254 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs index dc800e2d3a..1f918b69a7 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Text.RegularExpressions; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Inspections.Abstract; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MoveFieldCloserToUsageInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MoveFieldCloserToUsageInspection.cs index f39cc1a0a3..25d0f07828 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MoveFieldCloserToUsageInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MoveFieldCloserToUsageInspection.cs @@ -6,7 +6,6 @@ using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; namespace Rubberduck.Inspections.Concrete { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterCanBeByValInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterCanBeByValInspection.cs index b60f9bb269..c0f3b2358b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterCanBeByValInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterCanBeByValInspection.cs @@ -1,17 +1,13 @@ -using System; -using System.Collections.Generic; using System.Diagnostics; using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; -using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.VBA.Extensions; +using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete { @@ -39,211 +35,216 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ParameterCanBeByValInspection : InspectionBase + public sealed class ParameterCanBeByValInspection : DeclarationInspectionBase { public ParameterCanBeByValInspection(RubberduckParserState state) - : base(state) { } + : base(state, DeclarationType.Parameter) + {} - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { - var parameters = State.DeclarationFinder - .UserDeclarations(DeclarationType.Parameter) - .OfType().ToList(); - var parametersThatCanBeChangedToBePassedByVal = new List(); - - var interfaceDeclarationMembers = State.DeclarationFinder.FindAllInterfaceMembers().ToList(); - var interfaceScopeDeclarations = State.DeclarationFinder - .FindAllInterfaceImplementingMembers() - .Concat(interfaceDeclarationMembers) - .ToHashSet(); + if (!(declaration is ParameterDeclaration parameter) + || !CanBeChangedToBePassedByValIndividually(parameter, finder)) + { + return false; + } - parametersThatCanBeChangedToBePassedByVal.AddRange(InterFaceMembersThatCanBeChangedToBePassedByVal(interfaceDeclarationMembers)); + var enclosingMember = declaration.ParentDeclaration; + if (IsLibraryMethod(enclosingMember)) + { + return false; + } - var eventMembers = State.DeclarationFinder.UserDeclarations(DeclarationType.Event).ToList(); - var formEventHandlerScopeDeclarations = State.DeclarationFinder.FindFormEventHandlers(); - var eventHandlerScopeDeclarations = State.DeclarationFinder.FindEventHandlers(); - var eventScopeDeclarations = eventMembers - .Concat(formEventHandlerScopeDeclarations) - .Concat(eventHandlerScopeDeclarations) - .ToHashSet(); + if (enclosingMember is EventDeclaration eventDeclaration) + { + return AllHandlerParametersCanBeChangedToByVal(parameter, eventDeclaration, finder); + } - parametersThatCanBeChangedToBePassedByVal.AddRange(EventMembersThatCanBeChangedToBePassedByVal(eventMembers)); + if (enclosingMember is ModuleBodyElementDeclaration member) + { + if(member.IsInterfaceMember) + { + return AllImplementationParametersCanBeChangedToByVal(parameter, member, finder); + } - parametersThatCanBeChangedToBePassedByVal - .AddRange(parameters.Where(parameter => CanBeChangedToBePassedByVal(parameter, eventScopeDeclarations, interfaceScopeDeclarations))); + if (member.IsInterfaceImplementation + || IsEventHandler(member, finder)) + { + return false; + } + } - return parametersThatCanBeChangedToBePassedByVal - .Select(parameter => new DeclarationInspectionResult(this, string.Format(InspectionResults.ParameterCanBeByValInspection, parameter.IdentifierName), parameter)); + return true; } - private bool CanBeChangedToBePassedByVal(ParameterDeclaration parameter, HashSet eventScopeDeclarations, HashSet interfaceScopeDeclarations) + private static bool IsLibraryMethod(Declaration declaration) { - var enclosingMember = parameter.ParentScopeDeclaration; - var isIssue = !interfaceScopeDeclarations.Contains(enclosingMember) - && !eventScopeDeclarations.Contains(enclosingMember) - && CanBeChangedToBePassedByValIndividually(parameter); - return isIssue; + return declaration.DeclarationType == DeclarationType.LibraryProcedure + || declaration.DeclarationType == DeclarationType.LibraryFunction; } - private bool CanBeChangedToBePassedByValIndividually(ParameterDeclaration parameter) + private static bool IsEventHandler(Declaration declaration, DeclarationFinder finder) { - var canPossiblyBeChangedToBePassedByVal = - !parameter.IsArray - && !parameter.IsParamArray - && (parameter.IsByRef || parameter.IsImplicitByRef) - && !IsParameterOfDeclaredLibraryFunction(parameter) - && (parameter.AsTypeDeclaration == null - || (!parameter.AsTypeDeclaration.DeclarationType.HasFlag(DeclarationType.ClassModule) - && parameter.AsTypeDeclaration.DeclarationType != DeclarationType.UserDefinedType)) - && !parameter.References.Any(reference => reference.IsAssignment) - && !IsPotentiallyUsedAsByRefParameter(parameter); - return canPossiblyBeChangedToBePassedByVal; + return finder.FindEventHandlers().Contains(declaration) + || finder.FindFormEventHandlers().Contains(declaration); } - private static bool IsParameterOfDeclaredLibraryFunction(ParameterDeclaration parameter) + private static bool CanBeChangedToBePassedByValIndividually(ParameterDeclaration parameter, DeclarationFinder finder) { - var parentMember = parameter.ParentScopeDeclaration; - return parentMember.DeclarationType == DeclarationType.LibraryFunction - || parentMember.DeclarationType == DeclarationType.LibraryProcedure; + return !parameter.IsArray + && !parameter.IsParamArray + && parameter.IsByRef + && !parameter.References + .Any(reference => reference.IsAssignment) + && (parameter.AsTypeDeclaration == null + || parameter.AsTypeDeclaration.DeclarationType != DeclarationType.UserDefinedType) + && !IsPotentiallyUsedAsByRefParameter(parameter, finder); } - private IEnumerable InterFaceMembersThatCanBeChangedToBePassedByVal(List interfaceMembers) + private static bool IsPotentiallyUsedAsByRefParameter(ParameterDeclaration parameter, DeclarationFinder finder) { - foreach (var memberDeclaration in interfaceMembers.OfType()) - { - var interfaceParameters = memberDeclaration.Parameters.ToList(); - if (!interfaceParameters.Any()) - { - continue; - } + return IsPotentiallyUsedAsByRefMethodParameter(parameter, finder) + || IsPotentiallyUsedAsByRefEventParameter(parameter, finder); + } - var parameterCanBeChangedToBeByVal = interfaceParameters.Select(parameter => CanBeChangedToBePassedByValIndividually(parameter)).ToList(); + private static bool IsPotentiallyUsedAsByRefMethodParameter(ParameterDeclaration parameter, DeclarationFinder finder) + { + var module = parameter.QualifiedModuleName; + return parameter.References.Any(reference => IsPotentiallyAssignedByRefArgument(module, reference, finder)); + } - var implementingMembers = State.DeclarationFinder.FindInterfaceImplementationMembers(memberDeclaration); - foreach (var implementingMember in implementingMembers) - { - var implementationParameters = implementingMember.Parameters.ToList(); + private static bool IsPotentiallyAssignedByRefArgument(QualifiedModuleName module, IdentifierReference reference, DeclarationFinder finder) + { + var argExpression = ImmediateArgumentExpressionContext(reference); - //If you hit this assert, reopen https://github.com/rubberduck-vba/Rubberduck/issues/3906 - Debug.Assert(parameterCanBeChangedToBeByVal.Count == implementationParameters.Count); + if (argExpression == null) + { + return false; + } - for (var i = 0; i < implementationParameters.Count; i++) - { - parameterCanBeChangedToBeByVal[i] = parameterCanBeChangedToBeByVal[i] - && CanBeChangedToBePassedByValIndividually(implementationParameters[i]); - } - } + var parameter = finder.FindParameterOfNonDefaultMemberFromSimpleArgumentNotPassedByValExplicitly(argExpression, module); - for (var i = 0; i < parameterCanBeChangedToBeByVal.Count; i++) - { - if (parameterCanBeChangedToBeByVal[i]) - { - yield return interfaceParameters[i]; - } - } + if (parameter == null) + { + //We have no idea what parameter it is passed to as argument. So, we have to err on the safe side and assume it is passed by reference. + return true; } + + //We do not check whether the argument the parameter is actually assigned to costly recursions. + return parameter.IsByRef; } - private IEnumerable EventMembersThatCanBeChangedToBePassedByVal(IEnumerable eventMembers) + private static VBAParser.ArgumentExpressionContext ImmediateArgumentExpressionContext(IdentifierReference reference) { - foreach (var memberDeclaration in eventMembers) - { - var eventParameters = (memberDeclaration as IParameterizedDeclaration)?.Parameters.ToList(); - if (!eventParameters?.Any() ?? false) - { - continue; - } - - var parameterCanBeChangedToBeByVal = eventParameters.Select(parameter => parameter.IsByRef).ToList(); + var context = reference.Context; + //The context is either already a simpleNameExprContext or an IdentifierValueContext used in a sub-rule of some other lExpression alternative. + var lExpressionNameContext = context is VBAParser.SimpleNameExprContext simpleName + ? simpleName + : context.GetAncestor(); + + //To be an immediate argument and, thus, assignable by ref, the structure must be argumentExpression -> expression -> lExpression. + return lExpressionNameContext? + .Parent? + .Parent as VBAParser.ArgumentExpressionContext; + } - var eventHandlers = State.DeclarationFinder - .FindEventHandlers(memberDeclaration) - .ToList(); + private static bool IsPotentiallyUsedAsByRefEventParameter(ParameterDeclaration parameter, DeclarationFinder finder) + { + var module = parameter.QualifiedModuleName; + return parameter.References.Any(reference => IsPotentiallyAssignedByRefEventArgument(module, reference, finder)); + } - foreach (var eventHandler in eventHandlers.OfType()) - { - var handlerParameters = eventHandler.Parameters.ToList(); + private static bool IsPotentiallyAssignedByRefEventArgument(QualifiedModuleName module, IdentifierReference reference, DeclarationFinder finder) + { + var eventArgExpression = ImmediateEventArgumentExpressionContext(reference); - //If you hit this assert, reopen https://github.com/rubberduck-vba/Rubberduck/issues/3906 - Debug.Assert(parameterCanBeChangedToBeByVal.Count == handlerParameters.Count); + if (eventArgExpression == null + || eventArgExpression.BYVAL() != null) + { + return false; + } - for (var i = 0; i < handlerParameters.Count; i++) - { - parameterCanBeChangedToBeByVal[i] = parameterCanBeChangedToBeByVal[i] - && CanBeChangedToBePassedByValIndividually(handlerParameters[i]); - } - } + var parameter = finder.FindParameterFromSimpleEventArgumentNotPassedByValExplicitly(eventArgExpression, module); - for (var i = 0; i < parameterCanBeChangedToBeByVal.Count; i++) - { - if (parameterCanBeChangedToBeByVal[i]) - { - yield return eventParameters[i]; - } - } + if (parameter == null) + { + //We have no idea what parameter it is passed to as argument. So, we have to err on the safe side and assume it is passed by reference. + return true; } + + return parameter.IsByRef; } - private bool IsPotentiallyUsedAsByRefParameter(ParameterDeclaration parameter) + private static VBAParser.EventArgumentContext ImmediateEventArgumentExpressionContext(IdentifierReference reference) { - return IsPotentiallyUsedAsByRefMethodParameter(parameter) - || IsPotentiallyUsedAsByRefEventParameter(parameter); + var context = reference.Context; + //The context is either already a simpleNameExprContext or an IdentifierValueContext used in a sub-rule of some other lExpression alternative. + var lExpressionNameContext = context is VBAParser.SimpleNameExprContext simpleName + ? simpleName + : context.GetAncestor(); + + //To be an immediate argument and, thus, assignable by ref, the structure must be argumentExpression -> expression -> lExpression. + return lExpressionNameContext? + .Parent? + .Parent as VBAParser.EventArgumentContext; } - private bool IsPotentiallyUsedAsByRefMethodParameter(ParameterDeclaration parameter) + private static bool AllImplementationParametersCanBeChangedToByVal(ParameterDeclaration parameter, ModuleBodyElementDeclaration interfaceMember, DeclarationFinder finder) { - //The condition on the text of the argument context excludes the cases where the argument is either passed explicitly by value - //or used inside a non-trivial expression, e.g. an arithmetic expression. - var argumentsBeingTheParameter = parameter.References - .Select(reference => reference.Context.GetAncestor()) - .Where(context => context != null && context.GetText().Equals(parameter.IdentifierName, StringComparison.OrdinalIgnoreCase)); - - foreach (var argument in argumentsBeingTheParameter) + if (!TryFindParameterIndex(parameter, interfaceMember, out var parameterIndex)) { - var parameterCorrespondingToArgument = State.DeclarationFinder - .FindParameterOfNonDefaultMemberFromSimpleArgumentNotPassedByValExplicitly(argument, parameter.QualifiedModuleName); + //This really should never happen. + Debug.Fail($"Could not find index for parameter {parameter.IdentifierName} in interface member {interfaceMember.IdentifierName}."); + return false; + } - if (parameterCorrespondingToArgument == null) - { - //We have no idea what parameter it is passed to ar argument. So, we have to err on the safe side and assume it is passed by reference. - return true; - } + var implementations = finder.FindInterfaceImplementationMembers(interfaceMember); + return implementations.All(implementation => ParameterAtIndexCanBeChangedToBePassedByValIfRelatedParameterCan(implementation, parameterIndex, finder)); + } - if (parameterCorrespondingToArgument.IsByRef) - { - return true; - } - } + private static bool TryFindParameterIndex(ParameterDeclaration parameter, IParameterizedDeclaration enclosingMember, out int parameterIndex) + { + parameterIndex = enclosingMember.Parameters + .ToList() + .IndexOf(parameter); + return parameterIndex != -1; + } - return false; + private static bool ParameterAtIndexCanBeChangedToBePassedByValIfRelatedParameterCan(IParameterizedDeclaration member, int parameterIndex, DeclarationFinder finder) + { + var parameter = member.Parameters.ElementAtOrDefault(parameterIndex); + return parameter != null + && CanBeChangedToBePassedByValIfRelatedParameterCan(parameter, finder); } - private bool IsPotentiallyUsedAsByRefEventParameter(ParameterDeclaration parameter) + private static bool CanBeChangedToBePassedByValIfRelatedParameterCan(ParameterDeclaration parameter, DeclarationFinder finder) { - //The condition on the text of the eventArgument context excludes the cases where the argument is either passed explicitly by value - //or used inside a non-trivial expression, e.g. an arithmetic expression. - var argumentsBeingTheParameter = parameter.References - .Select(reference => reference.Context.GetAncestor()) - .Where(context => context != null && context.GetText().Equals(parameter.IdentifierName, StringComparison.OrdinalIgnoreCase)); + return !parameter.References + .Any(reference => reference.IsAssignment) + && !IsPotentiallyUsedAsByRefParameter(parameter, finder); + } - foreach (var argument in argumentsBeingTheParameter) + private static bool AllHandlerParametersCanBeChangedToByVal(ParameterDeclaration parameter, EventDeclaration eventDeclaration, DeclarationFinder finder) + { + if (!TryFindParameterIndex(parameter, eventDeclaration, out var parameterIndex)) { - var parameterCorrespondingToArgument = State.DeclarationFinder - .FindParameterFromSimpleEventArgumentNotPassedByValExplicitly(argument, parameter.QualifiedModuleName); - - if (parameterCorrespondingToArgument == null) - { - //We have no idea what parameter it is passed to ar argument. So, we have to err on the safe side and assume it is passed by reference. - return true; - } + //This really should never happen. + Debug.Fail($"Could not find index for parameter {parameter.IdentifierName} in event {eventDeclaration.IdentifierName}."); + return false; + } - if (parameterCorrespondingToArgument.IsByRef) - { - return true; - } + if (!eventDeclaration.IsUserDefined) + { + return false; } - return false; + var handlers = finder.FindEventHandlers(eventDeclaration); + return handlers.All(handler => ParameterAtIndexCanBeChangedToBePassedByValIfRelatedParameterCan(handler, parameterIndex, finder)); + } + + protected override string ResultDescription(Declaration declaration) + { + return string.Format(InspectionResults.ParameterCanBeByValInspection, declaration.IdentifierName); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterNotUsedInspection.cs index a224f86a7b..d260b2c4da 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterNotUsedInspection.cs @@ -7,7 +7,6 @@ using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; namespace Rubberduck.Inspections.Concrete { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs index 3ccc3a7a68..4db0b65c3f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs @@ -1,14 +1,11 @@ -using System.Collections.Generic; using System.Linq; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Inspections.Results; -using Rubberduck.JunkDrawer.Extensions; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -43,44 +40,11 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ProcedureNotUsedInspection : InspectionBase + public sealed class ProcedureNotUsedInspection : DeclarationInspectionBase { - public ProcedureNotUsedInspection(RubberduckParserState state) : base(state) { } - - private static readonly string[] DocumentEventHandlerPrefixes = - { - "Chart_", - "Worksheet_", - "Workbook_", - "Document_", - "Application_", - "Session_" - }; - - protected override IEnumerable DoGetInspectionResults() - { - var classes = State.DeclarationFinder.UserDeclarations(DeclarationType.ClassModule) - .Concat(State.DeclarationFinder.UserDeclarations(DeclarationType.Document)) - .ToList(); - var modules = State.DeclarationFinder.UserDeclarations(DeclarationType.ProceduralModule).ToList(); - - var handlers = State.DeclarationFinder.FindEventHandlers().ToHashSet(); - - var interfaceMembers = State.DeclarationFinder.FindAllInterfaceMembers().ToHashSet(); - var implementingMembers = State.DeclarationFinder.FindAllInterfaceImplementingMembers().ToHashSet(); - - var items = State.AllUserDeclarations - .Where(item => !IsIgnoredDeclaration(item, interfaceMembers, implementingMembers, handlers, classes, modules)) - .ToList(); - var issues = items.Select(issue => new DeclarationInspectionResult(this, - string.Format(InspectionResults.IdentifierNotUsedInspection, issue.DeclarationType.ToLocalizedString(), issue.IdentifierName), - issue)); - - issues = DocumentEventHandlerPrefixes - .Aggregate(issues, (current, item) => current.Where(issue => !issue.Description.Contains($"'{item}"))); - - return issues.ToList(); - } + public ProcedureNotUsedInspection(RubberduckParserState state) + : base(state, ProcedureTypes) + {} private static readonly DeclarationType[] ProcedureTypes = { @@ -91,26 +55,43 @@ protected override IEnumerable DoGetInspectionResults() DeclarationType.Event }; - private bool IsIgnoredDeclaration(Declaration declaration, IEnumerable interfaceMembers, IEnumerable interfaceImplementingMembers , IEnumerable handlers, IEnumerable classes, IEnumerable modules) + private static readonly string[] ClassLifeCycleHandlers = { - var enumerable = classes as IList ?? classes.ToList(); - var result = !ProcedureTypes.Contains(declaration.DeclarationType) - || declaration.References.Any(r => !r.IsAssignment && !r.ParentScoping.Equals(declaration)) // recursive calls don't count - || handlers.Contains(declaration) - || IsPublicModuleMember(modules, declaration) - || IsClassLifeCycleHandler(enumerable, declaration) - || interfaceMembers.Contains(declaration) - || interfaceImplementingMembers.Contains(declaration) - || declaration.Annotations.Any(x => x.Annotation is ITestAnnotation); + "Class_Initialize", + "Class_Terminate" + }; - return result; + private static readonly string[] DocumentEventHandlerPrefixes = + { + "Chart_", + "Worksheet_", + "Workbook_", + "Document_", + "Application_", + "Session_" + }; + + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) + { + return !declaration.References + .Any(reference => !reference.IsAssignment + && !reference.ParentScoping.Equals(declaration)) // recursive calls don't count + && !finder.FindEventHandlers().Contains(declaration) + && !IsPublicModuleMember(declaration) + && !IsClassLifeCycleHandler(declaration) + && !(declaration is ModuleBodyElementDeclaration member + && (member.IsInterfaceMember + || member.IsInterfaceImplementation)) + && !declaration.Annotations + .Any(pta => pta.Annotation is ITestAnnotation) + && !IsDocumentEventHandler(declaration); } /// /// We cannot determine whether exposed members of standard modules are called or not, /// so we assume they are instead of flagging them as "never called". /// - private bool IsPublicModuleMember(IEnumerable modules, Declaration procedure) + private static bool IsPublicModuleMember(Declaration procedure) { if ((procedure.Accessibility != Accessibility.Implicit && procedure.Accessibility != Accessibility.Public)) @@ -118,30 +99,38 @@ private bool IsPublicModuleMember(IEnumerable modules, Declaration return false; } - var parent = modules.Where(item => item.ProjectId == procedure.ProjectId) - .SingleOrDefault(item => item.IdentifierName == procedure.ComponentName); - - return parent != null; + var parent = Declaration.GetModuleParent(procedure); + return parent != null + && parent.DeclarationType.HasFlag(DeclarationType.ProceduralModule); } - // TODO: Put this into grammar? - private static readonly string[] ClassLifeCycleHandlers = - { - "Class_Initialize", - "Class_Terminate" - }; - - private bool IsClassLifeCycleHandler(IEnumerable classes, Declaration procedure) + private static bool IsClassLifeCycleHandler(Declaration procedure) { if (!ClassLifeCycleHandlers.Contains(procedure.IdentifierName)) { return false; } - var parent = classes.Where(item => item.ProjectId == procedure.ProjectId) - .SingleOrDefault(item => item.IdentifierName == procedure.ComponentName); + var parent = Declaration.GetModuleParent(procedure); + return parent != null + && parent.DeclarationType.HasFlag(DeclarationType.ClassModule); + } - return parent != null; + private static bool IsDocumentEventHandler(Declaration declaration) + { + var declarationName = declaration.IdentifierName; + return DocumentEventHandlerPrefixes + .Any(prefix => declarationName.StartsWith(prefix)); + } + + protected override string ResultDescription(Declaration declaration) + { + var declarationType = declaration.DeclarationType.ToLocalizedString(); + var declarationName = declaration.IdentifierName; + return string.Format( + InspectionResults.IdentifierNotUsedInspection, + declarationType, + declarationName); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs index 7917f8cffa..76017188fd 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs @@ -1,13 +1,10 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; -using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseMeaningfulNameInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseMeaningfulNameInspection.cs index 3a4a7bc2b2..9f5063eac1 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseMeaningfulNameInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseMeaningfulNameInspection.cs @@ -4,7 +4,6 @@ using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Inspections.Results; -using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; @@ -61,7 +60,7 @@ protected override IEnumerable DoGetInspectionResults() var whitelistedNames = settings.WhitelistedIdentifiers .Select(s => s.Identifier) .ToArray(); - var handlers = finder.FindEventHandlers().ToHashSet(); + var handlers = finder.FindEventHandlers(); var results = new List(); foreach (var moduleDeclaration in State.DeclarationFinder.UserDeclarations(DeclarationType.Module)) @@ -85,7 +84,7 @@ private IEnumerable DoGetInspectionResults(QualifiedModuleNam var whitelistedNames = settings.WhitelistedIdentifiers .Select(s => s.Identifier) .ToArray(); - var handlers = finder.FindEventHandlers().ToHashSet(); + var handlers = finder.FindEventHandlers(); return DoGetInspectionResults(module, finder, whitelistedNames, handlers); } diff --git a/Rubberduck.CodeAnalysis/QuickFixes/PassParameterByValueQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/PassParameterByValueQuickFix.cs index f15cefa327..1222777721 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/PassParameterByValueQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/PassParameterByValueQuickFix.cs @@ -79,7 +79,6 @@ private void FixMethods(Declaration target, IRewriteSession rewriteSession) .ToList() : _declarationFinderProvider.DeclarationFinder .FindInterfaceImplementationMembers(target.ParentDeclaration) - .Cast() .ToList(); foreach (var member in members) diff --git a/Rubberduck.Parsing/Symbols/DeclarationLoaders/SpecialFormDeclarations.cs b/Rubberduck.Parsing/Symbols/DeclarationLoaders/SpecialFormDeclarations.cs index b040aa665b..bbb02af2ab 100644 --- a/Rubberduck.Parsing/Symbols/DeclarationLoaders/SpecialFormDeclarations.cs +++ b/Rubberduck.Parsing/Symbols/DeclarationLoaders/SpecialFormDeclarations.cs @@ -100,22 +100,37 @@ private static FunctionDeclaration LBoundFunctionWithoutParameters(Declaration p private static ParameterDeclaration ArrayNameParameter(Declaration parentModule, FunctionDeclaration parentFunction) { - var arrayParam = new ParameterDeclaration(new QualifiedMemberName(parentModule.QualifiedName.QualifiedModuleName, "Arrayname"), parentFunction, "Variant", null, null, false, false, true); + var arrayParam = new ParameterDeclaration( + new QualifiedMemberName(parentModule.QualifiedName.QualifiedModuleName, "Arrayname"), + parentFunction, + "Variant", + null, + null, + false, + false, + true); return arrayParam; } private static ParameterDeclaration DimensionParameter(Declaration parentModule, FunctionDeclaration parentFunction) { - var rankParam = new ParameterDeclaration(new QualifiedMemberName(parentModule.QualifiedName.QualifiedModuleName, "Dimension"), parentFunction, "Long", null, null, true, false); + var rankParam = new ParameterDeclaration( + new QualifiedMemberName(parentModule.QualifiedName.QualifiedModuleName, "Dimension"), + parentFunction, + "Long", + null, + null, + true, + false); return rankParam; } private static FunctionDeclaration UBoundFunction(Declaration parentModule) { - var uboundFunction = UBoundFunctionWithoutParameters(parentModule); - uboundFunction.AddParameter(ArrayNameParameter(parentModule, uboundFunction)); - uboundFunction.AddParameter(DimensionParameter(parentModule, uboundFunction)); - return uboundFunction; + var uBoundFunction = UBoundFunctionWithoutParameters(parentModule); + uBoundFunction.AddParameter(ArrayNameParameter(parentModule, uBoundFunction)); + uBoundFunction.AddParameter(DimensionParameter(parentModule, uBoundFunction)); + return uBoundFunction; } private static FunctionDeclaration UBoundFunctionWithoutParameters(Declaration parentModule) diff --git a/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs b/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs index 20ff753143..26c3dbf702 100644 --- a/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs +++ b/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs @@ -43,7 +43,7 @@ public class DeclarationFinder private IDictionary> _referencesByMember; private Lazy>> _builtInDeclarationsByType; - private Lazy>> _handlersByWithEventsField; + private Lazy>> _handlersByWithEventsField; private Lazy>> _implementingMembers; private Lazy>> _membersByImplementsContext; @@ -175,7 +175,7 @@ private void InitializeLazyCollections() _formEventHandlers = new Lazy>(FindAllFormEventHandlers, true); _projects = new Lazy>(() => DeclarationsWithType(DeclarationType.Project).ToList(), true); _classes = new Lazy>(() => DeclarationsWithType(DeclarationType.ClassModule).ToList(), true); - _handlersByWithEventsField = new Lazy>>(FindAllHandlersByWithEventField, true); + _handlersByWithEventsField = new Lazy>>(FindAllHandlersByWithEventField, true); _implementingMembers = new Lazy>>(FindAllImplementingMembers, true); _interfaceMembers = new Lazy>>(FindAllInterfaceMembersByModule, true); @@ -252,7 +252,7 @@ private IDictionary> FindAllInterfaceM .ToList()); } - private IDictionary> FindAllHandlersByWithEventField() + private IDictionary> FindAllHandlersByWithEventField() { var withEventsFields = UserDeclarations(DeclarationType.Variable).Where(item => item.IsWithEvents); var events = withEventsFields.Select(field => @@ -267,9 +267,9 @@ private IDictionary> FindAllHandlersByWithEventFi { item.WithEventsField, Handlers = item.AvailableEvents.SelectMany(evnt => - Members(item.WithEventsField.ParentDeclaration.QualifiedName.QualifiedModuleName) - .Where(member => member.DeclarationType == DeclarationType.Procedure - && member.IdentifierName == item.WithEventsField.IdentifierName + "_" + evnt.IdentifierName)) + Members(item.WithEventsField.ParentDeclaration.QualifiedName.QualifiedModuleName, DeclarationType.Procedure) + .Where(member => member.IdentifierName == $"{item.WithEventsField.IdentifierName}_{evnt.IdentifierName}")) + .OfType() }) .ToDictionary(item => item.WithEventsField, item => item.Handlers.ToList()); return handlersByWithEventsField; @@ -327,7 +327,7 @@ public ICollection FindEventHandlers() return _eventHandlers.Value; } - public IEnumerable FindEventHandlers(Declaration eventDeclaration) + public IEnumerable FindEventHandlers(Declaration eventDeclaration) { var withEventsDeclarations = FindWithEventFields(eventDeclaration); return withEventsDeclarations @@ -347,7 +347,7 @@ public IEnumerable FindFormControlEventHandlers(Declaration control && handlers.IdentifierName.StartsWith(control.IdentifierName + "_")); } - public IEnumerable FindFormEventHandlers() + public ICollection FindFormEventHandlers() { return _formEventHandlers.Value; } @@ -382,11 +382,11 @@ public IEnumerable DeclarationsWithType(DeclarationType type) return BuiltInDeclarations(type).Concat(UserDeclarations(type)); } - public IEnumerable FindHandlersForWithEventsField(Declaration field) + public IEnumerable FindHandlersForWithEventsField(Declaration field) { return _handlersByWithEventsField.Value.TryGetValue(field, out var result) ? result - : Enumerable.Empty(); + : Enumerable.Empty(); } public IEnumerable FindWithEventFields() @@ -1283,7 +1283,7 @@ bool IsHostSpecificHandler(Declaration item) } } - private List FindAllFormEventHandlers() + private HashSet FindAllFormEventHandlers() { var forms = DeclarationsWithType(DeclarationType.ClassModule). Where(declaration => declaration.QualifiedModuleName.ComponentType == ComponentType.UserForm); @@ -1298,7 +1298,7 @@ private List FindAllFormEventHandlers() var handlers = UserDeclarations(DeclarationType.Procedure) .Where(procedure => handlerNames.Contains(procedure.IdentifierName) && formScopes.Contains(procedure.ParentScope)); - return handlers.ToList(); + return handlers.ToHashSet(); } /// diff --git a/RubberduckTests/Inspections/ParameterCanBeByValInspectionTests.cs b/RubberduckTests/Inspections/ParameterCanBeByValInspectionTests.cs index 84e3a0b76a..819f591b6e 100644 --- a/RubberduckTests/Inspections/ParameterCanBeByValInspectionTests.cs +++ b/RubberduckTests/Inspections/ParameterCanBeByValInspectionTests.cs @@ -261,7 +261,7 @@ public void ParameterCanBeByVal_ReturnsResult_PassedToByRefEvent_ExplicilyByVal( Sub DoSomething(foo As Integer) RaiseEvent Bar(BYVAL foo) End Sub"; - Assert.AreEqual(1, InspectionResultsForStandardModule(inputCode).Where(result => result.Target.IdentifierName.Equals("foo")).Count()); + Assert.AreEqual(1, InspectionResultsForStandardModule(inputCode).Count(result => result.Target.IdentifierName.Equals("foo"))); } @@ -1106,6 +1106,36 @@ Debug.Print e Assert.AreEqual("e", InspectionResultsForStandardModule(inputCode).Single().Target.IdentifierName); } + [Test] + [Category("Inspections")] + public void ParameterCanBeByVal_LibraryFunction_DoesNotReturnResult() + { + const string inputCode1 = + @"Public Declare Function MyLibFunction Lib ""MyLib"" (arg1 As Integer) As Integer"; + + var modules = new (string, string, ComponentType)[] + { + ("Class1", inputCode1, ComponentType.ClassModule) + }; + + Assert.AreEqual(0, InspectionResultsForModules(modules).Count()); + } + + [Test] + [Category("Inspections")] + public void ParameterCanBeByVal_LibraryProcedure_DoesNotReturnResult() + { + const string inputCode1 = + @"Public Declare Sub MyLibProcedure Lib ""MyLib"" (arg1 As Integer)"; + + var modules = new (string, string, ComponentType)[] + { + ("Class1", inputCode1, ComponentType.ClassModule) + }; + + Assert.AreEqual(0, InspectionResultsForModules(modules).Count()); + } + [Test] [Category("Inspections")] public void InspectionName() From fa57ae76f6019f1dcf3e6b1f6eee1027f6974080 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sun, 9 Feb 2020 15:35:55 +0100 Subject: [PATCH 218/461] Redesign ParameterNotUsedInspection For interfaces, it now only reports parameters of the interface member and not of individual implementations. Moreover, it does it only if there are implementations and none uses the parameter. The same behaviour now also applies to user events and event handlers. (Parameters ofevent handlers of built-in events are never reported.) In addition, ClassModuleDeclaration.IsInterface has been enhanced to also retun true is there is an @Interface annotation on the class. --- .../Concrete/ParameterNotUsedInspection.cs | 128 +++++++++++---- .../Concrete/InterfaceAnnotation.cs | 6 +- .../Symbols/ClassModuleDeclaration.cs | 2 +- .../Symbols/IInterfaceExposable.cs | 5 +- .../ParameterNotUsedInspectionTests.cs | 151 +++++++++++++++++- 5 files changed, 256 insertions(+), 36 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterNotUsedInspection.cs index d260b2c4da..d7d50896ae 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterNotUsedInspection.cs @@ -1,12 +1,11 @@ -using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using Rubberduck.Common; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -37,34 +36,109 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ParameterNotUsedInspection : InspectionBase + public sealed class ParameterNotUsedInspection : DeclarationInspectionBase { public ParameterNotUsedInspection(RubberduckParserState state) - : base(state) { } + : base(state, DeclarationType.Parameter) + {} - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { - var interfaceMembers = State.DeclarationFinder.FindAllInterfaceMembers(); - var interfaceImplementationMembers = State.DeclarationFinder.FindAllInterfaceImplementingMembers(); - - var handlers = State.DeclarationFinder.FindEventHandlers(); - - var parameters = State.DeclarationFinder - .UserDeclarations(DeclarationType.Parameter) - .OfType() - .Where(parameter => !parameter.References.Any() - && parameter.ParentDeclaration.DeclarationType != DeclarationType.Event - && parameter.ParentDeclaration.DeclarationType != DeclarationType.LibraryFunction - && parameter.ParentDeclaration.DeclarationType != DeclarationType.LibraryProcedure - && !interfaceMembers.Contains(parameter.ParentDeclaration) - && !handlers.Contains(parameter.ParentDeclaration)) - .ToList(); - - var issues = from issue in parameters - let isInterfaceImplementationMember = interfaceImplementationMembers.Contains(issue.ParentDeclaration) - select new DeclarationInspectionResult(this, string.Format(InspectionResults.ParameterNotUsedInspection, issue.IdentifierName).Capitalize(), issue); - - return issues; + if (declaration.References.Any() + || !(declaration is ParameterDeclaration parameter)) + { + return false; + } + + var enclosingMember = parameter.ParentDeclaration; + if (IsLibraryMethod(enclosingMember)) + { + return false; + } + + if (enclosingMember is EventDeclaration eventDeclaration) + { + return ThereAreHandlersAndNoneUsesTheParameter(parameter, eventDeclaration, finder); + } + + if (enclosingMember is ModuleBodyElementDeclaration member) + { + if (member.IsInterfaceMember) + { + return ThereAreImplementationsAndNoneUsesTheParameter(parameter, member, finder); + } + + if (member.IsInterfaceImplementation + || finder.FindEventHandlers().Contains(member)) + { + return false; + } + } + + return true; + } + + private static bool IsLibraryMethod(Declaration declaration) + { + return declaration.DeclarationType == DeclarationType.LibraryProcedure + || declaration.DeclarationType == DeclarationType.LibraryFunction; + } + + private static bool ThereAreImplementationsAndNoneUsesTheParameter(ParameterDeclaration parameter, ModuleBodyElementDeclaration interfaceMember, DeclarationFinder finder) + { + if (!TryFindParameterIndex(parameter, interfaceMember, out var parameterIndex)) + { + //This really should never happen. + Debug.Fail($"Could not find index for parameter {parameter.IdentifierName} in interface member {interfaceMember.IdentifierName}."); + return false; + } + + var implementations = finder.FindInterfaceImplementationMembers(interfaceMember).ToList(); + + //We do not want to report all parameters of not implemented interfaces. + return implementations.Any() + && implementations.All(implementation => ParameterAtIndexIsNotUsed(implementation, parameterIndex)); + } + + private static bool TryFindParameterIndex(ParameterDeclaration parameter, IParameterizedDeclaration enclosingMember, out int parameterIndex) + { + parameterIndex = enclosingMember.Parameters + .ToList() + .IndexOf(parameter); + return parameterIndex != -1; + } + + private static bool ParameterAtIndexIsNotUsed(IParameterizedDeclaration declaration, int parameterIndex) + { + var parameter = declaration.Parameters.ElementAtOrDefault(parameterIndex); + return parameter != null + && !parameter.References.Any(); + } + + private static bool ThereAreHandlersAndNoneUsesTheParameter(ParameterDeclaration parameter, EventDeclaration eventDeclaration, DeclarationFinder finder) + { + if (!TryFindParameterIndex(parameter, eventDeclaration, out var parameterIndex)) + { + //This really should never happen. + Debug.Fail($"Could not find index for parameter {parameter.IdentifierName} in event {eventDeclaration.IdentifierName}."); + return false; + } + + if (!eventDeclaration.IsUserDefined) + { + return false; + } + + var handlers = finder.FindEventHandlers(eventDeclaration).ToList(); + + //We do not want to report all parameters of not handled events. + return handlers.Any() + && handlers.All(handler => ParameterAtIndexIsNotUsed(handler, parameterIndex)); + } + + protected override string ResultDescription(Declaration declaration) + { + return string.Format(InspectionResults.ParameterNotUsedInspection, declaration.IdentifierName).Capitalize(); } } } diff --git a/Rubberduck.Parsing/Annotations/Concrete/InterfaceAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/InterfaceAnnotation.cs index b8d7fbedda..1c526737c1 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/InterfaceAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/InterfaceAnnotation.cs @@ -1,8 +1,4 @@ -using System.Collections.Generic; -using Rubberduck.Parsing.Grammar; -using Rubberduck.VBEditor; - -namespace Rubberduck.Parsing.Annotations +namespace Rubberduck.Parsing.Annotations { /// /// Used to mark a class module as an interface, so that Rubberduck treats it as such even if it's not implemented in any opened project. diff --git a/Rubberduck.Parsing/Symbols/ClassModuleDeclaration.cs b/Rubberduck.Parsing/Symbols/ClassModuleDeclaration.cs index 4ac757a5eb..1eb4172d5d 100644 --- a/Rubberduck.Parsing/Symbols/ClassModuleDeclaration.cs +++ b/Rubberduck.Parsing/Symbols/ClassModuleDeclaration.cs @@ -188,7 +188,7 @@ private bool HasPredeclaredIdToCache() public IEnumerable Subtypes => _subtypes.Keys; - public bool IsInterface => _subtypes.Count > 0; + public bool IsInterface => _subtypes.Count > 0 || Annotations.Any(pta => pta.Annotation is InterfaceAnnotation); public bool IsUserInterface => Subtypes.Any(s => s.IsUserDefined); diff --git a/Rubberduck.Parsing/Symbols/IInterfaceExposable.cs b/Rubberduck.Parsing/Symbols/IInterfaceExposable.cs index 8306854682..3d75c5a7e2 100644 --- a/Rubberduck.Parsing/Symbols/IInterfaceExposable.cs +++ b/Rubberduck.Parsing/Symbols/IInterfaceExposable.cs @@ -39,7 +39,10 @@ internal static bool IsInterfaceMember(this IInterfaceExposable member) => /// The member to find the InterfaceDeclaration of. /// Tthe Declaration of the interface that this is a member of, or null if IsInterfaceMember is false. internal static ClassModuleDeclaration InterfaceDeclaration(this IInterfaceExposable member) => - member.ParentDeclaration is ClassModuleDeclaration parent && parent.IsInterface ? parent : null; + member.ParentDeclaration is ClassModuleDeclaration parent + && parent.IsInterface + ? parent + : null; /// /// Provides a default implementation of IInterfaceExposable.ImplementingIdentifierName diff --git a/RubberduckTests/Inspections/ParameterNotUsedInspectionTests.cs b/RubberduckTests/Inspections/ParameterNotUsedInspectionTests.cs index 2bb26ec277..88cf8fabe3 100644 --- a/RubberduckTests/Inspections/ParameterNotUsedInspectionTests.cs +++ b/RubberduckTests/Inspections/ParameterNotUsedInspectionTests.cs @@ -80,9 +80,8 @@ Debug.Print rst(""Field"") [Test] [Category("Inspections")] - public void ParameterNotUsed_ReturnsResult_InterfaceImplementation() + public void ParameterNotUsed_InterfaceWithImplementation_ReturnsResultForInterface() { - //Input const string inputCode1 = @"Public Sub DoSomething(ByVal a As Integer) End Sub"; @@ -96,11 +95,159 @@ Private Sub IClass1_DoSomething(ByVal a As Integer) { ("IClass1", inputCode1, ComponentType.ClassModule), ("Class1", inputCode2, ComponentType.ClassModule), + ("Class2", inputCode2, ComponentType.ClassModule), }; Assert.AreEqual(1, InspectionResultsForModules(modules).Count()); } + [Test] + [Category("Inspections")] + public void ParameterNotUsed_InterfaceWithImplementation_SomeUseParameter_DoesNotReturnResult() + { + const string inputCode1 = + @"Public Sub DoSomething(ByVal a As Integer) +End Sub"; + const string inputCode2 = + @"Implements IClass1 + +Private Sub IClass1_DoSomething(ByVal a As Integer) +End Sub"; + const string inputCode3 = + @"Implements IClass1 + +Private Sub IClass1_DoSomething(ByVal a As Integer) + Dim bar As Variant + bar = a +End Sub +"; + + var modules = new (string, string, ComponentType)[] + { + ("IClass1", inputCode1, ComponentType.ClassModule), + ("Class1", inputCode2, ComponentType.ClassModule), + ("Class2", inputCode3, ComponentType.ClassModule), + }; + + Assert.AreEqual(0, InspectionResultsForModules(modules).Count()); + } + + [Test] + [Category("Inspections")] + public void ParameterNotUsed_InterfaceWithoutImplementation_DoesNotReturnResult() + { + const string inputCode1 = + @"'@Interface +Public Sub DoSomething(ByVal a As Integer) +End Sub"; + + var modules = new (string, string, ComponentType)[] + { + ("IClass1", inputCode1, ComponentType.ClassModule) + }; + + Assert.AreEqual(0, InspectionResultsForModules(modules).Count()); + } + + [Test] + [Category("Inspections")] + public void ParameterNotUsed_EventMemberWithHandlers_ResultForEventOnly() + { + const string inputCode1 = + @"Public Event Foo(ByRef arg1 As Integer)"; + + const string inputCode2 = + @"Private WithEvents abc As Class1 + +Private Sub abc_Foo(ByRef arg1 As Integer) +End Sub"; + + var modules = new (string, string, ComponentType)[] + { + ("Class1", inputCode1, ComponentType.ClassModule), + ("Class2", inputCode2, ComponentType.ClassModule), + ("Class3", inputCode2, ComponentType.ClassModule), + }; + + Assert.AreEqual(1, InspectionResultsForModules(modules).Count()); + } + + [Test] + [Category("Inspections")] + public void ParameterNotUsed_EventMemberWithHandlers_SomeUseParameter_DoesNotReturnResult() + { + const string inputCode1 = + @"Public Event Foo(ByRef arg1 As Integer)"; + + const string inputCode2 = + @"Private WithEvents abc As Class1 + +Private Sub abc_Foo(ByRef arg1 As Integer) +End Sub"; + + const string inputCode3 = + @"Private WithEvents abc As Class1 + +Private Sub abc_Foo(ByRef arg1 As Integer) + Dim bar As Variant + bar = arg1 +End Sub"; + + var modules = new (string, string, ComponentType)[] + { + ("Class1", inputCode1, ComponentType.ClassModule), + ("Class2", inputCode2, ComponentType.ClassModule), + ("Class3", inputCode3, ComponentType.ClassModule), + }; + + Assert.AreEqual(0, InspectionResultsForModules(modules).Count()); + } + + [Test] + [Category("Inspections")] + public void ParameterNotUsed_EventMemberWithoutHandlers_DoesNotReturnResult() + { + const string inputCode1 = + @"Public Event Foo(ByRef arg1 As Integer)"; + + var modules = new (string, string, ComponentType)[] + { + ("Class1", inputCode1, ComponentType.ClassModule) + }; + + Assert.AreEqual(0, InspectionResultsForModules(modules).Count()); + } + + [Test] + [Category("Inspections")] + public void ParameterNotUsed_LibraryFunction_DoesNotReturnResult() + { + const string inputCode1 = + @"Public Declare Function MyLibFunction Lib ""MyLib"" (arg1 As Integer) As Integer"; + + var modules = new (string, string, ComponentType)[] + { + ("Class1", inputCode1, ComponentType.ClassModule) + }; + + Assert.AreEqual(0, InspectionResultsForModules(modules).Count()); + } + + [Test] + [Category("Inspections")] + public void ParameterNotUsed_LibraryProcedure_DoesNotReturnResult() + { + const string inputCode1 = + @"Public Declare Sub MyLibProcedure Lib ""MyLib"" (arg1 As Integer)"; + + var modules = new (string, string, ComponentType)[] + { + ("Class1", inputCode1, ComponentType.ClassModule) + }; + + Assert.AreEqual(0, InspectionResultsForModules(modules).Count()); + } + [Test] [Category("Inspections")] public void ParameterNotUsed_Ignored_DoesNotReturnResult() From 21bbebd40325a38296c089618c611b0c0316fb5b Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Mon, 10 Feb 2020 02:53:38 +0100 Subject: [PATCH 219/461] Stop reporting functions potentially conflicting as Udfs in private modules Also makes some more declaration inspections use the base classes. --- .../Abstract/DeclarationInspectionBaseBase.cs | 2 +- ...elUdfNameIsValidCellReferenceInspection.cs | 88 ++++++++++++++----- .../MoveFieldCloserToUsageInspection.cs | 82 ++++++++--------- ...NameIsValidCellReferenceInspectionTests.cs | 14 +++ 4 files changed, 121 insertions(+), 65 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs index b1d513b8d5..7d2f89dc8f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs @@ -48,7 +48,7 @@ protected override IEnumerable DoGetInspectionResults() return results; } - protected IEnumerable DoGetInspectionResults(QualifiedModuleName module) + protected virtual IEnumerable DoGetInspectionResults(QualifiedModuleName module) { var finder = DeclarationFinderProvider.DeclarationFinder; return DoGetInspectionResults(module, finder); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs index 1f918b69a7..80c80cf479 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs @@ -3,12 +3,14 @@ using System.Linq; using System.Text.RegularExpressions; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; +using Rubberduck.VBEditor; +using Rubberduck.VBEditor.SafeComWrappers; namespace Rubberduck.Inspections.Inspections.Concrete { @@ -33,9 +35,69 @@ namespace Rubberduck.Inspections.Inspections.Concrete /// ]]> /// [RequiredLibrary("Excel")] - public class ExcelUdfNameIsValidCellReferenceInspection : InspectionBase + public class ExcelUdfNameIsValidCellReferenceInspection : DeclarationInspectionBase { - public ExcelUdfNameIsValidCellReferenceInspection(RubberduckParserState state) : base(state) { } + public ExcelUdfNameIsValidCellReferenceInspection(RubberduckParserState state) + : base(state, new []{DeclarationType.Function}, new []{DeclarationType.PropertyGet, DeclarationType.LibraryFunction}) + { } + + protected override IEnumerable DoGetInspectionResults() + { + if (!State.DeclarationFinder.Projects.Any(project => !project.IsUserDefined + && project.IdentifierName == "Excel")) + { + return Enumerable.Empty(); + } + + return base.DoGetInspectionResults(); + } + + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) + { + if (!State.DeclarationFinder.Projects.Any(project => !project.IsUserDefined + && project.IdentifierName == "Excel")) + { + return Enumerable.Empty(); + } + + return base.DoGetInspectionResults(module); + } + + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + { + if (module.ComponentType != ComponentType.StandardModule) + { + return Enumerable.Empty(); + } + + var proceduralModuleDeclaration = finder.Members(module, DeclarationType.ProceduralModule) + .SingleOrDefault() as ProceduralModuleDeclaration; + + if (proceduralModuleDeclaration == null + || proceduralModuleDeclaration.IsPrivateModule) + { + return Enumerable.Empty(); + } + + return base.DoGetInspectionResults(module, finder); + } + + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) + { + if (!VisibleAsUdf.Contains(declaration.Accessibility)) + { + return false; + } + + var cellIdMatch = ValidCellIdRegex.Match(declaration.IdentifierName); + if (!cellIdMatch.Success) + { + return false; + } + + var row = Convert.ToUInt32(cellIdMatch.Groups["Row"].Value); + return row > 0 && row <= MaximumExcelRows; + } private static readonly Regex ValidCellIdRegex = new Regex(@"^([a-z]|[a-z]{2}|[a-w][a-z]{2}|x([a-e][a-z]|f[a-d]))(?\d+)$", @@ -45,25 +107,9 @@ public ExcelUdfNameIsValidCellReferenceInspection(RubberduckParserState state) : private const uint MaximumExcelRows = 1048576; - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(Declaration declaration) { - var excel = State.DeclarationFinder.Projects.SingleOrDefault(item => !item.IsUserDefined && item.IdentifierName == "Excel"); - if (excel == null) - { - return Enumerable.Empty(); - } - - var candidates = UserDeclarations.OfType().Where(decl => - decl.ParentScopeDeclaration.DeclarationType == DeclarationType.ProceduralModule && - VisibleAsUdf.Contains(decl.Accessibility)); - - return (from function in candidates.Where(decl => ValidCellIdRegex.IsMatch(decl.IdentifierName)) - let row = Convert.ToUInt32(ValidCellIdRegex.Matches(function.IdentifierName)[0].Groups["Row"].Value) - where row > 0 && row <= MaximumExcelRows - select new DeclarationInspectionResult(this, - string.Format(InspectionResults.ExcelUdfNameIsValidCellReferenceInspection, function.IdentifierName), - function)) - .Cast().ToList(); + return string.Format(InspectionResults.ExcelUdfNameIsValidCellReferenceInspection, declaration.IdentifierName); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MoveFieldCloserToUsageInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MoveFieldCloserToUsageInspection.cs index 25d0f07828..620c7caa95 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MoveFieldCloserToUsageInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MoveFieldCloserToUsageInspection.cs @@ -1,11 +1,9 @@ -using System.Collections.Generic; -using System.Linq; +using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -38,58 +36,56 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class MoveFieldCloserToUsageInspection : InspectionBase + public sealed class MoveFieldCloserToUsageInspection : DeclarationInspectionBase { public MoveFieldCloserToUsageInspection(RubberduckParserState state) - : base(state) { } + : base(state, DeclarationType.Variable) + {} - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { - return State.DeclarationFinder.UserDeclarations(DeclarationType.Variable) - .Where(declaration => - { - if (declaration.IsWithEvents - || !new[] {DeclarationType.ClassModule, DeclarationType.Document, DeclarationType.ProceduralModule}.Contains(declaration.ParentDeclaration.DeclarationType)) - { - return false; - } + if (declaration.IsWithEvents + || !IsField(declaration)) + { + return false; + } - var asType = declaration.AsTypeDeclaration; - if (asType != null && asType.ProjectName.Equals("Rubberduck") && - (asType.IdentifierName.Equals("PermissiveAssertClass") || asType.IdentifierName.Equals("AssertClass"))) - { - return false; - } + if (IsRubberduckAssertField(declaration)) + { + return false; + } - var firstReference = declaration.References.FirstOrDefault(); + var firstReference = declaration.References.FirstOrDefault(); + var usageMember = firstReference?.ParentScoping; - if (firstReference == null || - declaration.References.Any(r => r.ParentScoping != firstReference.ParentScoping)) - { - return false; - } + if (usageMember == null + || declaration.References.Any(reference => !reference.ParentScoping.Equals(usageMember))) + { + return false; + } - var parentDeclaration = ParentDeclaration(firstReference); + return usageMember.DeclarationType == DeclarationType.Procedure + || usageMember.DeclarationType == DeclarationType.Function; + } - return parentDeclaration != null && - !new[] - { - DeclarationType.PropertyGet, - DeclarationType.PropertyLet, - DeclarationType.PropertySet - }.Contains(parentDeclaration.DeclarationType); - }) - .Select(issue => - new DeclarationInspectionResult(this, string.Format(InspectionResults.MoveFieldCloserToUsageInspection, issue.IdentifierName), issue)); + private static bool IsField(Declaration variableDeclaration) + { + var parentDeclarationType = variableDeclaration.ParentDeclaration.DeclarationType; + return parentDeclarationType.HasFlag(DeclarationType.Module); } - private Declaration ParentDeclaration(IdentifierReference reference) + private static bool IsRubberduckAssertField(Declaration fieldDeclaration) { - var declarationTypes = new[] {DeclarationType.Function, DeclarationType.Procedure, DeclarationType.Property}; + var asType = fieldDeclaration.AsTypeDeclaration; + return asType != null + && asType.ProjectName.Equals("Rubberduck") + && (asType.IdentifierName.Equals("PermissiveAssertClass") + || asType.IdentifierName.Equals("AssertClass")); + } - return UserDeclarations.SingleOrDefault(d => - reference.ParentScoping.Equals(d) && declarationTypes.Contains(d.DeclarationType) && - d.QualifiedName.QualifiedModuleName.Equals(reference.QualifiedModuleName)); + protected override string ResultDescription(Declaration declaration) + { + return string.Format(InspectionResults.MoveFieldCloserToUsageInspection, declaration.IdentifierName); } } } diff --git a/RubberduckTests/Inspections/ExcelUdfNameIsValidCellReferenceInspectionTests.cs b/RubberduckTests/Inspections/ExcelUdfNameIsValidCellReferenceInspectionTests.cs index 3f6ee64ec3..474a55cc79 100644 --- a/RubberduckTests/Inspections/ExcelUdfNameIsValidCellReferenceInspectionTests.cs +++ b/RubberduckTests/Inspections/ExcelUdfNameIsValidCellReferenceInspectionTests.cs @@ -32,6 +32,20 @@ End Function Assert.AreEqual(1, InspectionResultCount(string.Format(codeTemplate, identifier), ComponentType.StandardModule)); } + [Test] + [Category("Inspections")] + public void ExcelUdfNameIsValidCellReferenceInspection_ReturnsResult_ValidCellsInPrivateModule() + { + const string code = + @"Option Private Module +Public Function A1() As Long + A1 = 42 +End Function +"; + + Assert.AreEqual(0, InspectionResultCount(code, ComponentType.StandardModule)); + } + [TestCase("Foo")] [TestCase("XXX69")] [TestCase("XKCD42")] From 51987c34c19f83c759561e83b4410d25b5de1b1a Mon Sep 17 00:00:00 2001 From: Clemens Lieb Date: Mon, 10 Feb 2020 12:25:28 +0100 Subject: [PATCH 220/461] Delete -multiinst --- -multiinst | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 -multiinst diff --git a/-multiinst b/-multiinst deleted file mode 100644 index e69de29bb2..0000000000 From e096043f07541f01806b72cefa07a662da3c69b5 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Mon, 10 Feb 2020 23:48:11 +0100 Subject: [PATCH 221/461] Redesign MemberNotOnInterfaceInspection and IntegerDataTypeInspection --- .../Abstract/DeclarationInspectionBaseBase.cs | 2 +- .../Concrete/IntegerDataTypeInspection.cs | 77 ++++++++++-------- .../MemberNotOnInterfaceInspection.cs | 79 +++++++++++++------ 3 files changed, 99 insertions(+), 59 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs index 7d2f89dc8f..63f7cfe7b8 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs @@ -54,7 +54,7 @@ protected virtual IEnumerable DoGetInspectionResults(Qualifie return DoGetInspectionResults(module, finder); } - protected IEnumerable RelevantDeclarationsInModule(QualifiedModuleName module, DeclarationFinder finder) + protected virtual IEnumerable RelevantDeclarationsInModule(QualifiedModuleName module, DeclarationFinder finder) { var potentiallyRelevantDeclarations = RelevantDeclarationTypes.Length == 0 ? finder.Members(module) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IntegerDataTypeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IntegerDataTypeInspection.cs index 7f7216d8f6..290467caa2 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IntegerDataTypeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IntegerDataTypeInspection.cs @@ -1,14 +1,9 @@ -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; -using Rubberduck.JunkDrawer.Extensions; +using Rubberduck.Inspections.Abstract; +using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Resources; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -35,41 +30,57 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class IntegerDataTypeInspection : InspectionBase + public sealed class IntegerDataTypeInspection : DeclarationInspectionBase { - public IntegerDataTypeInspection(RubberduckParserState state) : base(state) - { - } + public IntegerDataTypeInspection(RubberduckParserState state) + : base(state) + { } - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { - var interfaceImplementationMembers = State.DeclarationFinder.FindAllInterfaceImplementingMembers().ToHashSet(); + if (declaration.AsTypeName != Tokens.Integer) + { + return false; + } - var excludeParameterMembers = State.DeclarationFinder.FindEventHandlers().ToHashSet(); - excludeParameterMembers.UnionWith(interfaceImplementationMembers); + switch (declaration) + { + case ParameterDeclaration parameter: + return ParameterIsResult(parameter, finder); + case ModuleBodyElementDeclaration member: + return MethodIsResult(member); + default: + return declaration.DeclarationType != DeclarationType.LibraryFunction; + } + } - var result = UserDeclarations - .Where(declaration => - declaration.AsTypeName == Tokens.Integer && - !interfaceImplementationMembers.Contains(declaration) && - declaration.DeclarationType != DeclarationType.LibraryFunction && - (declaration.DeclarationType != DeclarationType.Parameter || IncludeParameterDeclaration(declaration, excludeParameterMembers))) - .Select(issue => - new DeclarationInspectionResult(this, - string.Format(Resources.Inspections.InspectionResults.IntegerDataTypeInspection, - RubberduckUI.ResourceManager.GetString($"DeclarationType_{issue.DeclarationType}", CultureInfo.CurrentUICulture), issue.IdentifierName), - issue)); + private static bool ParameterIsResult(ParameterDeclaration parameter, DeclarationFinder finder) + { + var enclosingMember = parameter.ParentDeclaration; + if (!(enclosingMember is ModuleBodyElementDeclaration member)) + { + return false; + } - return result; + return !member.IsInterfaceImplementation + && member.DeclarationType != DeclarationType.LibraryFunction + && member.DeclarationType != DeclarationType.LibraryProcedure + && !finder.FindEventHandlers().Contains(member); } - private static bool IncludeParameterDeclaration(Declaration parameterDeclaration, ICollection parentDeclarationsToExclude) + private static bool MethodIsResult(ModuleBodyElementDeclaration member) { - var parentDeclaration = parameterDeclaration.ParentDeclaration; + return !member.IsInterfaceImplementation; + } - return parentDeclaration.DeclarationType != DeclarationType.LibraryFunction && - parentDeclaration.DeclarationType != DeclarationType.LibraryProcedure && - !parentDeclarationsToExclude.Contains(parentDeclaration); + protected override string ResultDescription(Declaration declaration) + { + var declarationType = declaration.DeclarationType.ToLocalizedString(); + var declarationName = declaration.IdentifierName; + return string.Format( + Resources.Inspections.InspectionResults.IntegerDataTypeInspection, + declarationType, + declarationName); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MemberNotOnInterfaceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MemberNotOnInterfaceInspection.cs index 507eae805a..26b8eb0abf 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MemberNotOnInterfaceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MemberNotOnInterfaceInspection.cs @@ -8,6 +8,9 @@ using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing; +using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete { @@ -37,36 +40,62 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class MemberNotOnInterfaceInspection : InspectionBase + public sealed class MemberNotOnInterfaceInspection : DeclarationInspectionBase { public MemberNotOnInterfaceInspection(RubberduckParserState state) - : base(state) { } + : base(state) + { } - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable RelevantDeclarationsInModule(QualifiedModuleName module, DeclarationFinder finder) { - // prefilter to reduce searchspace - var unresolved = State.DeclarationFinder.UnresolvedMemberDeclarations() - .Where(decl => !decl.IsIgnoringInspectionResultFor(AnnotationName)).ToList(); + return finder.UnresolvedMemberDeclarations(module); + } + + protected override (bool isResult, Declaration properties) IsResultDeclarationWithAdditionalProperties(Declaration declaration, DeclarationFinder finder) + { + if (!(declaration is UnboundMemberDeclaration member)) + { + return (false, null); + } + + var callingContext = member.CallingContext is VBAParser.NewExprContext newExprContext + ? (newExprContext.expression() as VBAParser.LExprContext)?.lExpression() + : member.CallingContext; + + if (callingContext == null) + { + return (false, null); + } + + var callingContextSelection = new QualifiedSelection(declaration.QualifiedModuleName, callingContext.GetSelection()); + var usageReferences = finder.IdentifierReferences(callingContextSelection); + var calledDeclaration = usageReferences + .Select(reference => reference.Declaration) + .FirstOrDefault(usageDeclaration => usageDeclaration != null + && HasResultType(usageDeclaration)); + var isResult = calledDeclaration != null + && calledDeclaration.DeclarationType != DeclarationType.Control; //TODO - remove this exception after resolving #2592. Also simplify to inspect the type directly. - var targets = Declarations.Where(decl => decl.AsTypeDeclaration != null && - !decl.AsTypeDeclaration.IsUserDefined && - decl.AsTypeDeclaration.DeclarationType.HasFlag(DeclarationType.ClassModule) && - ((ClassModuleDeclaration)decl.AsTypeDeclaration).IsExtensible) - .SelectMany(decl => decl.References).ToList(); - return unresolved - .Select(access => new - { - access, - callingContext = targets.FirstOrDefault(usage => usage.Context.Equals(access.CallingContext) - || (access.CallingContext is VBAParser.NewExprContext && - usage.Context.Parent.Parent.Equals(access.CallingContext)) - ) - }) - .Where(memberAccess => memberAccess.callingContext != null && - memberAccess.callingContext.Declaration.DeclarationType != DeclarationType.Control) //TODO - remove this exception after resolving #2592) - .Select(memberAccess => new DeclarationInspectionResult(this, - string.Format(InspectionResults.MemberNotOnInterfaceInspection, memberAccess.access.IdentifierName, - memberAccess.callingContext.Declaration.AsTypeDeclaration.IdentifierName), memberAccess.access)); + return (isResult, calledDeclaration?.AsTypeDeclaration); + } + + private static bool HasResultType(Declaration declaration) + { + var typeDeclaration = declaration.AsTypeDeclaration; + return typeDeclaration != null + && !typeDeclaration.IsUserDefined + && typeDeclaration is ClassModuleDeclaration classTypeDeclaration + && classTypeDeclaration.IsExtensible; + } + + protected override string ResultDescription(Declaration declaration, Declaration typeDeclaration) + { + var memberName = declaration.IdentifierName; + var typeName = typeDeclaration?.IdentifierName ?? string.Empty; + return string.Format( + InspectionResults.MemberNotOnInterfaceInspection, + memberName, + typeName); } } } From e7590af43434b405cebdefa033c2ed48fdfcf08a Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Wed, 12 Feb 2020 17:17:49 +0100 Subject: [PATCH 222/461] Add base classes for declaration inspections that use global information The information gets passed down to the method determining whether a declaration is a result. This means that the signatures of the methods are different from the the other base classes. So, these for a second hierarchy. This also changes the base classes to also look at the QMNs of user projects. Finally, this makes the final declaration inspections use the base classes. --- .../Abstract/DeclarationInspectionBaseBase.cs | 13 +- ...ionInspectionUsingGlobalInformationBase.cs | 84 ++++++++++++ ...nspectionUsingGlobalInformationBaseBase.cs | 87 ++++++++++++ .../Concrete/DefaultProjectNameInspection.cs | 19 --- .../Concrete/HungarianNotationInspection.cs | 71 ++-------- .../Concrete/ShadowedDeclarationInspection.cs | 126 +++++++++++------- .../Concrete/UseMeaningfulNameInspection.cs | 63 +-------- .../DeclarationCaching/DeclarationFinder.cs | 5 +- 8 files changed, 280 insertions(+), 188 deletions(-) create mode 100644 Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBase.cs create mode 100644 Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs index 63f7cfe7b8..3f46d4f1ef 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs @@ -34,7 +34,7 @@ protected override IEnumerable DoGetInspectionResults() var finder = DeclarationFinderProvider.DeclarationFinder; var results = new List(); - foreach (var moduleDeclaration in State.DeclarationFinder.UserDeclarations(DeclarationType.Module)) + foreach (var moduleDeclaration in finder.UserDeclarations(DeclarationType.Module)) { if (moduleDeclaration == null) { @@ -45,6 +45,17 @@ protected override IEnumerable DoGetInspectionResults() results.AddRange(DoGetInspectionResults(module, finder)); } + foreach (var projectDeclaration in finder.UserDeclarations(DeclarationType.Project)) + { + if (projectDeclaration == null) + { + continue; + } + + var module = projectDeclaration.QualifiedModuleName; + results.AddRange(DoGetInspectionResults(module, finder)); + } + return results; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBase.cs new file mode 100644 index 0000000000..1a75d36861 --- /dev/null +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBase.cs @@ -0,0 +1,84 @@ +using System.Collections.Generic; +using System.Linq; +using Rubberduck.Inspections.Results; +using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.VBEditor; + +namespace Rubberduck.Inspections.Abstract +{ + public abstract class DeclarationInspectionUsingGlobalInformationBase : DeclarationInspectionUsingGlobalInformationBaseBase + { + protected DeclarationInspectionUsingGlobalInformationBase(RubberduckParserState state, params DeclarationType[] relevantDeclarationTypes) + : base(state, relevantDeclarationTypes) + {} + + protected DeclarationInspectionUsingGlobalInformationBase(RubberduckParserState state, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) + : base(state, relevantDeclarationTypes, excludeDeclarationTypes) + {} + + protected abstract bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder, TGlobalInfo globalInfo); + protected abstract string ResultDescription(Declaration declaration); + + protected virtual ICollection DisabledQuickFixes(Declaration declaration) => new List(); + + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder, TGlobalInfo globalInfo) + { + var objectionableDeclarations = RelevantDeclarationsInModule(module, finder) + .Where(declaration => IsResultDeclaration(declaration, finder, globalInfo)); + + return objectionableDeclarations + .Select(InspectionResult) + .ToList(); + } + + protected virtual IInspectionResult InspectionResult(Declaration declaration) + { + return new DeclarationInspectionResult( + this, + ResultDescription(declaration), + declaration, + disabledQuickFixes: DisabledQuickFixes(declaration)); + } + } + + public abstract class DeclarationInspectionUsingGlobalInformationBase : DeclarationInspectionUsingGlobalInformationBaseBase + { + protected DeclarationInspectionUsingGlobalInformationBase(RubberduckParserState state, params DeclarationType[] relevantDeclarationTypes) + : base(state, relevantDeclarationTypes) + {} + + protected DeclarationInspectionUsingGlobalInformationBase(RubberduckParserState state, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) + : base(state, relevantDeclarationTypes, excludeDeclarationTypes) + {} + + protected abstract (bool isResult, TProperties properties) IsResultDeclarationWithAdditionalProperties(Declaration declaration, DeclarationFinder finder, TGlobalInfo globalInformation); + protected abstract string ResultDescription(Declaration declaration, TProperties properties); + + protected virtual ICollection DisabledQuickFixes(Declaration declaration, TProperties properties) => new List(); + + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder, TGlobalInfo globalInformation) + { + var objectionableDeclarationsWithAdditionalProperties = RelevantDeclarationsInModule(module, finder) + .Select(declaration => (declaration, IsResultDeclarationWithAdditionalProperties(declaration, finder, globalInformation))) + .Where(tpl => tpl.Item2.isResult) + .Select(tpl => (tpl.declaration, tpl.Item2.properties)); + + return objectionableDeclarationsWithAdditionalProperties + .Select(tpl => InspectionResult(tpl.declaration, tpl.properties)) + .ToList(); + } + + protected virtual IInspectionResult InspectionResult(Declaration declaration, TProperties properties) + { + return new DeclarationInspectionResult( + this, + ResultDescription(declaration, properties), + declaration, + properties: properties, + disabledQuickFixes: DisabledQuickFixes(declaration, properties)); + } + } +} \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs new file mode 100644 index 0000000000..3d302a05bf --- /dev/null +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs @@ -0,0 +1,87 @@ +using System.Collections.Generic; +using System.Linq; +using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.VBEditor; + +namespace Rubberduck.Inspections.Abstract +{ + public abstract class DeclarationInspectionUsingGlobalInformationBaseBase : InspectionBase + { + protected readonly DeclarationType[] RelevantDeclarationTypes; + protected readonly DeclarationType[] ExcludeDeclarationTypes; + + protected DeclarationInspectionUsingGlobalInformationBaseBase(RubberduckParserState state, params DeclarationType[] relevantDeclarationTypes) + : base(state) + { + RelevantDeclarationTypes = relevantDeclarationTypes; + ExcludeDeclarationTypes = new DeclarationType[0]; + } + + protected DeclarationInspectionUsingGlobalInformationBaseBase(RubberduckParserState state, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) + : base(state) + { + RelevantDeclarationTypes = relevantDeclarationTypes; + ExcludeDeclarationTypes = excludeDeclarationTypes; + } + + protected abstract IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder, T globalInformation); + protected abstract T GlobalInformation(DeclarationFinder finder); + + protected virtual T GlobalInformation(QualifiedModuleName module, DeclarationFinder finder) + { + return GlobalInformation(finder); + } + + protected override IEnumerable DoGetInspectionResults() + { + var finder = DeclarationFinderProvider.DeclarationFinder; + var globalInformation = GlobalInformation(finder); + + var results = new List(); + foreach (var moduleDeclaration in finder.UserDeclarations(DeclarationType.Module)) + { + if (moduleDeclaration == null) + { + continue; + } + + var module = moduleDeclaration.QualifiedModuleName; + results.AddRange(DoGetInspectionResults(module, finder, globalInformation)); + } + + foreach (var projectDeclaration in finder.UserDeclarations(DeclarationType.Project)) + { + if (projectDeclaration == null) + { + continue; + } + + var module = projectDeclaration.QualifiedModuleName; + results.AddRange(DoGetInspectionResults(module, finder, globalInformation)); + } + + return results; + } + + protected virtual IEnumerable DoGetInspectionResults(QualifiedModuleName module) + { + var finder = DeclarationFinderProvider.DeclarationFinder; + var globalInformation = GlobalInformation(module, finder); + return DoGetInspectionResults(module, finder, globalInformation); + } + + protected virtual IEnumerable RelevantDeclarationsInModule(QualifiedModuleName module, DeclarationFinder finder) + { + var potentiallyRelevantDeclarations = RelevantDeclarationTypes.Length == 0 + ? finder.Members(module) + : RelevantDeclarationTypes + .SelectMany(declarationType => finder.Members(module, declarationType)) + .Distinct(); + return potentiallyRelevantDeclarations + .Where(declaration => !ExcludeDeclarationTypes.Contains(declaration.DeclarationType)); + } + } +} \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultProjectNameInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultProjectNameInspection.cs index 71b446677d..edd4315579 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultProjectNameInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultProjectNameInspection.cs @@ -21,25 +21,6 @@ public DefaultProjectNameInspection(RubberduckParserState state) : base(state, DeclarationType.Project) {} - protected override IEnumerable DoGetInspectionResults() - { - var finder = DeclarationFinderProvider.DeclarationFinder; - - var results = new List(); - foreach (var projectDeclaration in State.DeclarationFinder.UserDeclarations(DeclarationType.Project)) - { - if (projectDeclaration == null) - { - continue; - } - - var module = projectDeclaration.QualifiedModuleName; - results.AddRange(DoGetInspectionResults(module, finder)); - } - - return results; - } - protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { return declaration.IdentifierName.StartsWith("VBAProject"); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/HungarianNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/HungarianNotationInspection.cs index 7650a478cc..c111529440 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/HungarianNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/HungarianNotationInspection.cs @@ -4,13 +4,10 @@ using Rubberduck.Common; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.SettingsProvider; -using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete { @@ -46,9 +43,9 @@ namespace Rubberduck.Inspections.Concrete /// End Function /// ]]> /// - public sealed class HungarianNotationInspection : InspectionBase + public sealed class HungarianNotationInspection : DeclarationInspectionUsingGlobalInformationBase> { - private static readonly List TargetDeclarationTypes = new List + private static readonly DeclarationType[] TargetDeclarationTypes = new [] { DeclarationType.Parameter, DeclarationType.Constant, @@ -64,7 +61,7 @@ public sealed class HungarianNotationInspection : InspectionBase DeclarationType.Variable }; - private static readonly List IgnoredProcedureTypes = new List + private static readonly DeclarationType[] IgnoredProcedureTypes = new [] { DeclarationType.LibraryFunction, DeclarationType.LibraryProcedure @@ -73,70 +70,27 @@ public sealed class HungarianNotationInspection : InspectionBase private readonly IConfigurationService _settings; public HungarianNotationInspection(RubberduckParserState state, IConfigurationService settings) - : base(state) + : base(state, TargetDeclarationTypes, IgnoredProcedureTypes) { _settings = settings; } - protected override IEnumerable DoGetInspectionResults() + protected override List GlobalInformation(DeclarationFinder finder) { - var finder = DeclarationFinderProvider.DeclarationFinder; var settings = _settings.Read(); - var whitelistedNames = settings.WhitelistedIdentifiers + return settings.WhitelistedIdentifiers .Select(s => s.Identifier) .ToList(); - - var results = new List(); - foreach (var moduleDeclaration in State.DeclarationFinder.UserDeclarations(DeclarationType.Module)) - { - if (moduleDeclaration == null) - { - continue; - } - - var module = moduleDeclaration.QualifiedModuleName; - results.AddRange(DoGetInspectionResults(module, finder, whitelistedNames)); - } - - return results; - } - - private IEnumerable DoGetInspectionResults(QualifiedModuleName module) - { - var finder = DeclarationFinderProvider.DeclarationFinder; - var settings = _settings.Read(); - var whitelistedNames = settings.WhitelistedIdentifiers - .Select(s => s.Identifier) - .ToList(); - return DoGetInspectionResults(module, finder, whitelistedNames); - } - - private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder, List whitelistedNames) - { - var objectionableDeclarations = RelevantDeclarationsInModule(module, finder) - .Where(declaration => IsResultDeclaration(declaration, whitelistedNames)); - - return objectionableDeclarations - .Select(InspectionResult) - .ToList(); } - private static bool IsResultDeclaration(Declaration declaration, ICollection whitelistedNames) + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder, List whitelistedNames) { return !whitelistedNames.Contains(declaration.IdentifierName) && !IgnoredProcedureTypes.Contains(declaration.ParentDeclaration.DeclarationType) && declaration.IdentifierName.TryMatchHungarianNotationCriteria(out _); } - private IInspectionResult InspectionResult(Declaration declaration) - { - return new DeclarationInspectionResult( - this, - ResultDescription(declaration), - declaration); - } - - private static string ResultDescription(Declaration declaration) + protected override string ResultDescription(Declaration declaration) { var declarationType = declaration.DeclarationType.ToLocalizedString(); var declarationName = declaration.IdentifierName; @@ -145,14 +99,5 @@ private static string ResultDescription(Declaration declaration) declarationType, declarationName); } - - private IEnumerable RelevantDeclarationsInModule(QualifiedModuleName module, DeclarationFinder finder) - { - var potentiallyRelevantDeclarations = TargetDeclarationTypes - .SelectMany(declarationType => finder.Members(module, declarationType)) - .Distinct(); - return potentiallyRelevantDeclarations - .Where(declaration => !IgnoredProcedureTypes.Contains(declaration.DeclarationType)); - } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ShadowedDeclarationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ShadowedDeclarationInspection.cs index 6fc3890a24..7f5fdf94e2 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ShadowedDeclarationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ShadowedDeclarationInspection.cs @@ -3,12 +3,15 @@ using System.Globalization; using System.Linq; using Rubberduck.Inspections.Abstract; +using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Inspections.Results; using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources; +using Rubberduck.VBEditor; using Rubberduck.VBEditor.SafeComWrappers; namespace Rubberduck.Inspections.Concrete @@ -40,7 +43,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ShadowedDeclarationInspection : InspectionBase + public sealed class ShadowedDeclarationInspection : DeclarationInspectionUsingGlobalInformationBase>, Declaration> { private enum DeclarationSite { @@ -50,55 +53,85 @@ private enum DeclarationSite SameComponent = 3 } - public ShadowedDeclarationInspection(RubberduckParserState state) : base(state) + public ShadowedDeclarationInspection(RubberduckParserState state) + : base(state) + {} + + protected override IDictionary> GlobalInformation(DeclarationFinder finder) { + return finder.UserDeclarations(DeclarationType.Project) + .OfType() + .ToDictionary(project => project.ProjectId, ReferencedProjectIds); } - protected override IEnumerable DoGetInspectionResults() + protected override IDictionary> GlobalInformation(QualifiedModuleName module, DeclarationFinder finder) { - var builtInEventHandlers = State.DeclarationFinder.FindEventHandlers().ToHashSet(); - - var issues = new List(); + return finder.UserDeclarations(DeclarationType.Project) + .Where(project => project.ProjectId == module.ProjectId) + .OfType() + .ToDictionary(project => project.ProjectId, ReferencedProjectIds); + } - var allUserProjects = State.DeclarationFinder.UserDeclarations(DeclarationType.Project).Cast(); + private static HashSet ReferencedProjectIds(ProjectDeclaration project) + { + return project.ProjectReferences + .Select(reference => reference.ReferencedProjectId) + .ToHashSet(); + } - foreach (var userProject in allUserProjects) + protected override (bool isResult, Declaration properties) IsResultDeclarationWithAdditionalProperties( + Declaration userDeclaration, + DeclarationFinder finder, + IDictionary> referencedProjectIdsByProjectId) + { + // The user has no control over build-in event handlers or their parameters, so we skip them. + //TODO: Find a way to restrict this to event handlers for built-in events. (Revisit after #5379 is closed.) + var eventHandlers = finder.FindEventHandlers(); + if (DeclarationIsPartOfEventHandler(userDeclaration, eventHandlers)) { - var referencedProjectIds = userProject.ProjectReferences.Select(reference => reference.ReferencedProjectId).ToHashSet(); + return (false, null); + } - var userDeclarations = UserDeclarations.Where(declaration => - declaration.ProjectId == userProject.ProjectId && - // User has no control over build-in event handlers or their parameters, so we skip them - !DeclarationIsPartOfBuiltInEventHandler(declaration, builtInEventHandlers)); + if(!referencedProjectIdsByProjectId.TryGetValue(userDeclaration.ProjectId, out var referencedProjectIds)) + { + referencedProjectIds = new HashSet(); + } - foreach (var userDeclaration in userDeclarations) - { - var shadowedDeclaration = State.DeclarationFinder - .MatchName(userDeclaration.IdentifierName).FirstOrDefault(declaration => - !declaration.Equals(userDeclaration) && - DeclarationCanBeShadowed(declaration, userDeclaration, GetDeclarationSite(declaration, userDeclaration, referencedProjectIds))); + var shadowedDeclaration = ShadowedDeclaration(userDeclaration, referencedProjectIds, finder); + return (shadowedDeclaration != null, shadowedDeclaration); + } - if (shadowedDeclaration != null) - { - issues.Add(new DeclarationInspectionResult(this, - string.Format(Resources.Inspections.InspectionResults.ShadowedDeclarationInspection, - RubberduckUI.ResourceManager.GetString("DeclarationType_" + userDeclaration.DeclarationType, CultureInfo.CurrentUICulture), - userDeclaration.QualifiedName, - RubberduckUI.ResourceManager.GetString("DeclarationType_" + shadowedDeclaration.DeclarationType, CultureInfo.CurrentUICulture), - shadowedDeclaration.QualifiedName), - userDeclaration)); - } - } + private static bool DeclarationIsPartOfEventHandler(Declaration declaration, ICollection eventHandlers) + { + if (eventHandlers.Contains(declaration)) + { + return true; } - return issues; + return declaration is ParameterDeclaration parameterDeclaration + && eventHandlers.Contains(parameterDeclaration.ParentDeclaration); + } + + private static Declaration ShadowedDeclaration(Declaration userDeclaration, ICollection referencedProjectIds, DeclarationFinder finder) + { + return finder.MatchName(userDeclaration.IdentifierName) + .FirstOrDefault(declaration => !declaration.Equals(userDeclaration) + && DeclarationCanBeShadowed(declaration, userDeclaration, referencedProjectIds)); + } + + private static bool DeclarationCanBeShadowed(Declaration originalDeclaration, Declaration userDeclaration, ICollection referencedProjectIds) + { + var originalDeclarationSite = GetDeclarationSite(originalDeclaration, userDeclaration, referencedProjectIds); + return DeclarationCanBeShadowed(originalDeclaration, userDeclaration, originalDeclarationSite); } private static DeclarationSite GetDeclarationSite(Declaration originalDeclaration, Declaration userDeclaration, ICollection referencedProjectIds) { if (originalDeclaration.ProjectId != userDeclaration.ProjectId) { - return referencedProjectIds.Contains(originalDeclaration.ProjectId) ? DeclarationSite.ReferencedProject : DeclarationSite.NotApplicable; + return referencedProjectIds.Contains(originalDeclaration.ProjectId) + ? DeclarationSite.ReferencedProject + : DeclarationSite.NotApplicable; } if (originalDeclaration.QualifiedName.QualifiedModuleName.ComponentName != userDeclaration.QualifiedName.QualifiedModuleName.ComponentName) @@ -109,17 +142,6 @@ private static DeclarationSite GetDeclarationSite(Declaration originalDeclaratio return DeclarationSite.SameComponent; } - private static bool DeclarationIsPartOfBuiltInEventHandler(Declaration declaration, ICollection builtInEventHandlers) - { - if (builtInEventHandlers.Contains(declaration)) - { - return true; - } - - return declaration is ParameterDeclaration parameterDeclaration && - builtInEventHandlers.Contains(parameterDeclaration.ParentDeclaration); - } - private static bool DeclarationCanBeShadowed(Declaration originalDeclaration, Declaration userDeclaration, DeclarationSite originalDeclarationSite) { switch (originalDeclarationSite) @@ -130,9 +152,9 @@ private static bool DeclarationCanBeShadowed(Declaration originalDeclaration, De return DeclarationInReferencedProjectCanBeShadowed(originalDeclaration, userDeclaration); case DeclarationSite.OtherComponent: return DeclarationInAnotherComponentCanBeShadowed(originalDeclaration, userDeclaration); + default: + return DeclarationInTheSameComponentCanBeShadowed(originalDeclaration, userDeclaration); } - - return DeclarationInTheSameComponentCanBeShadowed(originalDeclaration, userDeclaration); } private static bool DeclarationInReferencedProjectCanBeShadowed(Declaration originalDeclaration, Declaration userDeclaration) @@ -622,5 +644,19 @@ private static bool DeclarationIsLocal(Declaration declaration) DeclarationType.Parameter }.ToHashSet() }; + + protected override string ResultDescription(Declaration declaration, Declaration shadowedDeclaration) + { + var declarationType = declaration.DeclarationType.ToLocalizedString(); + var declarationName = declaration.QualifiedName.ToString(); + var shadowedDeclarationType = shadowedDeclaration.DeclarationType.ToLocalizedString(); + var shadowedDeclarationName = shadowedDeclaration.QualifiedName.ToString(); + return string.Format( + Resources.Inspections.InspectionResults.ShadowedDeclarationInspection, + declarationType, + declarationName, + shadowedDeclarationType, + shadowedDeclarationName); + } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseMeaningfulNameInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseMeaningfulNameInspection.cs index 9f5063eac1..784ef82cf1 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseMeaningfulNameInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseMeaningfulNameInspection.cs @@ -3,14 +3,11 @@ using Rubberduck.CodeAnalysis.Settings; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Refactorings.Common; using Rubberduck.SettingsProvider; -using Rubberduck.VBEditor; using static Rubberduck.Parsing.Grammar.VBAParser; namespace Rubberduck.Inspections.Concrete @@ -36,7 +33,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class UseMeaningfulNameInspection : InspectionBase + public sealed class UseMeaningfulNameInspection : DeclarationInspectionUsingGlobalInformationBase { private readonly IConfigurationService _settings; @@ -53,73 +50,27 @@ public UseMeaningfulNameInspection(RubberduckParserState state, IConfigurationSe DeclarationType.LibraryProcedure, }; - protected override IEnumerable DoGetInspectionResults() + protected override string[] GlobalInformation(DeclarationFinder finder) { - var finder = DeclarationFinderProvider.DeclarationFinder; var settings = _settings.Read(); - var whitelistedNames = settings.WhitelistedIdentifiers + return settings.WhitelistedIdentifiers .Select(s => s.Identifier) .ToArray(); - var handlers = finder.FindEventHandlers(); - - var results = new List(); - foreach (var moduleDeclaration in State.DeclarationFinder.UserDeclarations(DeclarationType.Module)) - { - if (moduleDeclaration == null) - { - continue; - } - - var module = moduleDeclaration.QualifiedModuleName; - results.AddRange(DoGetInspectionResults(module, finder, whitelistedNames, handlers)); - } - - return results; - } - - private IEnumerable DoGetInspectionResults(QualifiedModuleName module) - { - var finder = DeclarationFinderProvider.DeclarationFinder; - var settings = _settings.Read(); - var whitelistedNames = settings.WhitelistedIdentifiers - .Select(s => s.Identifier) - .ToArray(); - var handlers = finder.FindEventHandlers(); - return DoGetInspectionResults(module, finder, whitelistedNames, handlers); - } - - private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder, string[] whitelistedNames, ICollection eventHandlers) - { - var objectionableDeclarations = finder.Members(module) - .Where(declaration => IsResultDeclaration(declaration, whitelistedNames, eventHandlers)); - - return objectionableDeclarations - .Select(InspectionResult) - .ToList(); } - private static bool IsResultDeclaration(Declaration declaration, string[] whitelistedNames, ICollection eventHandlers) + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder, string[] whitelistedNames) { return !string.IsNullOrEmpty(declaration.IdentifierName) && !IgnoreDeclarationTypes.Contains(declaration.DeclarationType) && !(declaration.Context is LineNumberLabelContext) && (declaration.ParentDeclaration == null || !IgnoreDeclarationTypes.Contains(declaration.ParentDeclaration.DeclarationType) - && !eventHandlers.Contains(declaration.ParentDeclaration)) + && !finder.FindEventHandlers().Contains(declaration.ParentDeclaration)) && !whitelistedNames.Contains(declaration.IdentifierName) && !VBAIdentifierValidator.IsMeaningfulIdentifier(declaration.IdentifierName); } - private IInspectionResult InspectionResult(Declaration declaration) - { - return new DeclarationInspectionResult( - this, - ResultDescription(declaration), - declaration, - disabledQuickFixes: DisabledQuickFixes(declaration)); - } - - private static string ResultDescription(Declaration declaration) + protected override string ResultDescription(Declaration declaration) { var declarationType = declaration.DeclarationType.ToLocalizedString(); var declarationName = declaration.IdentifierName; @@ -129,7 +80,7 @@ private static string ResultDescription(Declaration declaration) declarationName); } - private static ICollection DisabledQuickFixes(Declaration declaration) + protected override ICollection DisabledQuickFixes(Declaration declaration) { return declaration.DeclarationType.HasFlag(DeclarationType.Module) || declaration.DeclarationType.HasFlag(DeclarationType.Project) diff --git a/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs b/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs index 26c3dbf702..96b4a1ec19 100644 --- a/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs +++ b/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs @@ -553,10 +553,7 @@ private IEnumerable FindEvents(Declaration module) return Enumerable.Empty(); } - var members = Members(module.QualifiedName.QualifiedModuleName); - return members == null - ? Enumerable.Empty() - : members.Where(declaration => declaration.DeclarationType == DeclarationType.Event); + return Members(module.QualifiedName.QualifiedModuleName, DeclarationType.Event); } public Declaration FindEvent(Declaration module, string eventName) From b4ae264db13c7c27e4956da9b8dad13e270b67d0 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Wed, 12 Feb 2020 18:56:08 +0100 Subject: [PATCH 223/461] Replace generic function on IInspectionResult with additional generic interface IWithInspectionResultProperties This change makes the structure look a bit cleaner. Unfortunately, the new interface cannot extend the old one because the corresponding generic inspection result classes have to inherit from the non-generic ones. --- .../Abstract/InspectionResultBase.cs | 2 -- .../Results/DeclarationInspectionResult.cs | 18 ++++-------------- .../IdentifierReferenceInspectionResult.cs | 18 ++++-------------- .../QualifiedContextInspectionResult.cs | 18 ++++-------------- .../AccessSheetUsingCodeNameQuickFix.cs | 6 +++--- .../AddAttributeAnnotationQuickFix.cs | 7 ++++++- .../QuickFixes/AddMissingAttributeQuickFix.cs | 7 ++++++- .../AdjustAttributeAnnotationQuickFix.cs | 7 ++++++- .../AdjustAttributeValuesQuickFix.cs | 7 ++++++- .../QuickFixes/ExpandDefaultMemberQuickFix.cs | 7 ++++++- ...sMissingOnInappropriateArgumentQuickFix.cs | 7 ++++++- .../QuickFixes/RemoveAnnotationQuickFix.cs | 7 ++++++- .../QuickFixes/RemoveAttributeQuickFix.cs | 7 ++++++- .../RemoveDuplicatedAnnotationQuickFix.cs | 7 ++++++- .../RestoreErrorHandlingQuickFix.cs | 7 ++++++- .../Inspections/Abstract/IInspectionResult.cs | 6 +++++- .../AttributeValueOutOfSyncInspectionTests.cs | 19 +++++++++++++------ .../MissingMemberAnnotationInspectionTests.cs | 17 ++++++++++++----- .../MissingModuleAnnotationInspectionTests.cs | 16 ++++++++++++---- .../SuspiciousLetAssignmentInspectionTests.cs | 18 +++++++++++++----- ...RemoveDuplicatedAnnotationQuickFixTests.cs | 3 ++- 21 files changed, 132 insertions(+), 79 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionResultBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionResultBase.cs index d3907786df..637723afff 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionResultBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionResultBase.cs @@ -37,8 +37,6 @@ protected InspectionResultBase(IInspection inspection, public Declaration Target { get; } public ICollection DisabledQuickFixes { get; } - public virtual T Properties() => default; - public virtual bool ChangesInvalidateResult(ICollection modifiedModules) { return modifiedModules.Contains(QualifiedName) diff --git a/Rubberduck.CodeAnalysis/Inspections/Results/DeclarationInspectionResult.cs b/Rubberduck.CodeAnalysis/Inspections/Results/DeclarationInspectionResult.cs index 5b6196b193..42dcf0a04d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Results/DeclarationInspectionResult.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Results/DeclarationInspectionResult.cs @@ -44,15 +44,13 @@ public override bool ChangesInvalidateResult(ICollection mo } } - public class DeclarationInspectionResult : DeclarationInspectionResult + public class DeclarationInspectionResult : DeclarationInspectionResult, IWithInspectionResultProperties { - private readonly TProperties _properties; - public DeclarationInspectionResult( IInspection inspection, string description, Declaration target, - TProperties properties, + T properties, QualifiedContext context = null, ICollection disabledQuickFixes = null) : base( @@ -62,17 +60,9 @@ public DeclarationInspectionResult( context, disabledQuickFixes) { - _properties = properties; + Properties = properties; } - public override T Properties() - { - if (_properties is T properties) - { - return properties; - } - - return base.Properties(); - } + public T Properties { get; } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Results/IdentifierReferenceInspectionResult.cs b/Rubberduck.CodeAnalysis/Inspections/Results/IdentifierReferenceInspectionResult.cs index 319d87b819..58167ee8d6 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Results/IdentifierReferenceInspectionResult.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Results/IdentifierReferenceInspectionResult.cs @@ -44,16 +44,14 @@ public override bool ChangesInvalidateResult(ICollection mo } } - public class IdentifierReferenceInspectionResult : IdentifierReferenceInspectionResult + public class IdentifierReferenceInspectionResult : IdentifierReferenceInspectionResult, IWithInspectionResultProperties { - private readonly TProperties _properties; - public IdentifierReferenceInspectionResult( IInspection inspection, string description, IDeclarationFinderProvider declarationFinderProvider, IdentifierReference reference, - TProperties properties, + T properties, ICollection disabledQuickFixes = null) : base( inspection, @@ -62,17 +60,9 @@ public IdentifierReferenceInspectionResult( reference, disabledQuickFixes) { - _properties = properties; + Properties = properties; } - public override T Properties() - { - if (_properties is T properties) - { - return properties; - } - - return base.Properties(); - } + public T Properties { get; } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Results/QualifiedContextInspectionResult.cs b/Rubberduck.CodeAnalysis/Inspections/Results/QualifiedContextInspectionResult.cs index 0fa0caf6b8..bdd871bf9f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Results/QualifiedContextInspectionResult.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Results/QualifiedContextInspectionResult.cs @@ -24,15 +24,13 @@ public QualifiedContextInspectionResult( {} } - public class QualifiedContextInspectionResult : QualifiedContextInspectionResult + public class QualifiedContextInspectionResult : QualifiedContextInspectionResult, IWithInspectionResultProperties { - private readonly TProperties _properties; - public QualifiedContextInspectionResult( IInspection inspection, string description, QualifiedContext context, - TProperties properties, + T properties, ICollection disabledQuickFixes = null) : base( inspection, @@ -40,17 +38,9 @@ public QualifiedContextInspectionResult( context, disabledQuickFixes) { - _properties = properties; + Properties = properties; } - public override T Properties() - { - if (_properties is T properties) - { - return properties; - } - - return base.Properties(); - } + public T Properties { get; } } } diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AccessSheetUsingCodeNameQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/AccessSheetUsingCodeNameQuickFix.cs index 32dac50ac1..54656657bc 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AccessSheetUsingCodeNameQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/AccessSheetUsingCodeNameQuickFix.cs @@ -48,7 +48,7 @@ public AccessSheetUsingCodeNameQuickFix(IDeclarationFinderProvider declarationFi public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) { - var referenceResult = (IdentifierReferenceInspectionResult)result; + var referenceResult = (IdentifierReferenceInspectionResult)result; var rewriter = rewriteSession.CheckOutModuleRewriter(referenceResult.QualifiedName); @@ -62,7 +62,7 @@ public override void Fix(IInspectionResult result, IRewriteSession rewriteSessio var indexExprContext = referenceResult.Context.Parent.Parent as VBAParser.IndexExprContext ?? referenceResult.Context.Parent as VBAParser.IndexExprContext; - var codeName = referenceResult.Properties(); + var codeName = referenceResult.Properties; rewriter.Replace(indexExprContext, codeName); } else @@ -98,7 +98,7 @@ public override void Fix(IInspectionResult result, IRewriteSession rewriteSessio foreach (var reference in sheetDeclaration.References) { - var codeName = referenceResult.Properties(); + var codeName = referenceResult.Properties; rewriter.Replace(reference.Context, codeName); } diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AddAttributeAnnotationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/AddAttributeAnnotationQuickFix.cs index e08068df9e..1a6c6cf813 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AddAttributeAnnotationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/AddAttributeAnnotationQuickFix.cs @@ -60,8 +60,13 @@ public AddAttributeAnnotationQuickFix(IAnnotationUpdater annotationUpdater, IAtt public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) { + if (!(result is IWithInspectionResultProperties<(string attributeName, IReadOnlyList AttributeValues)> resultProperties)) + { + return; + } + var declaration = result.Target; - var (attributeName, attributeValues) = result.Properties<(string attributeName, IReadOnlyList AttributeValues)>(); + var (attributeName, attributeValues) = resultProperties.Properties; var (annotationType, annotationValues) = declaration.DeclarationType.HasFlag(DeclarationType.Module) ? _attributeAnnotationProvider.ModuleAttributeAnnotation(attributeName, attributeValues) : _attributeAnnotationProvider.MemberAttributeAnnotation(AttributeBaseName(attributeName, declaration), attributeValues); diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AddMissingAttributeQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/AddMissingAttributeQuickFix.cs index cc644801fd..6fb4270878 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AddMissingAttributeQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/AddMissingAttributeQuickFix.cs @@ -54,8 +54,13 @@ public AddMissingAttributeQuickFix(IAttributesUpdater attributesUpdater) public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) { + if (!(result is IWithInspectionResultProperties resultProperties)) + { + return; + } + var declaration = result.Target; - var annotationInstance = result.Properties(); + var annotationInstance = resultProperties.Properties; if (!(annotationInstance.Annotation is IAttributeAnnotation annotation)) { return; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeAnnotationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeAnnotationQuickFix.cs index 671c4e86aa..89e234bfdc 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeAnnotationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeAnnotationQuickFix.cs @@ -59,8 +59,13 @@ public AdjustAttributeAnnotationQuickFix(IAnnotationUpdater annotationUpdater, I public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) { + if (!(result is IWithInspectionResultProperties<(IParseTreeAnnotation Annotation, string AttributeName, IReadOnlyList AttributeValues)> resultProperties)) + { + return; + } + var declaration = result.Target; - var (oldParseTreeAnnotation, attributeBaseName, attributeValues) = result.Properties<(IParseTreeAnnotation Annotation, string AttributeName, IReadOnlyList AttributeValues)>(); + var (oldParseTreeAnnotation, attributeBaseName, attributeValues) = resultProperties.Properties; if (declaration.DeclarationType.HasFlag(DeclarationType.Module)) { diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeValuesQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeValuesQuickFix.cs index deca488c50..6fe3076fff 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeValuesQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeValuesQuickFix.cs @@ -61,8 +61,13 @@ public AdjustAttributeValuesQuickFix(IAttributesUpdater attributesUpdater) public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) { + if (!(result is IWithInspectionResultProperties<(IParseTreeAnnotation Annotation, string AttributeName, IReadOnlyList AttributeValues)> resultProperties)) + { + return; + } + var declaration = result.Target; - var (parseTreeAnnotation, attributeBaseName, attributeValues) = result.Properties<(IParseTreeAnnotation Annotation, string AttributeName, IReadOnlyList AttributeValues)>(); + var (parseTreeAnnotation, attributeBaseName, attributeValues) = resultProperties.Properties; var attributeName = declaration.DeclarationType.HasFlag(DeclarationType.Module) ? attributeBaseName diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ExpandDefaultMemberQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/ExpandDefaultMemberQuickFix.cs index d05b10bc9f..c823a5ac55 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ExpandDefaultMemberQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/ExpandDefaultMemberQuickFix.cs @@ -76,7 +76,12 @@ public override void Fix(IInspectionResult result, IRewriteSession rewriteSessio if (result.Inspection is SuspiciousLetAssignmentInspection) { - var rhsReference = result.Properties(); + if (!(result is IWithInspectionResultProperties resultProperties)) + { + return; + } + + var rhsReference = resultProperties.Properties; var rhsLExpressionContext = rhsReference.Context; var rhsSelection = rhsReference.QualifiedSelection; InsertDefaultMember(rhsLExpressionContext, rhsSelection, finder, rewriter); diff --git a/Rubberduck.CodeAnalysis/QuickFixes/IsMissingOnInappropriateArgumentQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/IsMissingOnInappropriateArgumentQuickFix.cs index de0fb5189a..53c22f974b 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/IsMissingOnInappropriateArgumentQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/IsMissingOnInappropriateArgumentQuickFix.cs @@ -51,7 +51,12 @@ public IsMissingOnInappropriateArgumentQuickFix(IDeclarationFinderProvider decla public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) { - var parameter = result.Properties(); + if (!(result is IWithInspectionResultProperties resultProperties)) + { + return; + } + + var parameter = resultProperties.Properties; if (parameter == null) { Logger.Trace($"Properties for IsMissingOnInappropriateArgumentQuickFix was null."); diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveAnnotationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveAnnotationQuickFix.cs index 62826bc0c6..b05980df1f 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveAnnotationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveAnnotationQuickFix.cs @@ -49,7 +49,12 @@ public RemoveAnnotationQuickFix(IAnnotationUpdater annotationUpdater) public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) { - _annotationUpdater.RemoveAnnotation(rewriteSession, result.Properties()); + if (!(result is IWithInspectionResultProperties resultProperties)) + { + return; + } + + _annotationUpdater.RemoveAnnotation(rewriteSession, resultProperties.Properties); } public override string Description(IInspectionResult result) => Resources.Inspections.QuickFixes.RemoveAnnotationQuickFix; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveAttributeQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveAttributeQuickFix.cs index 947a586138..7783c17f3d 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveAttributeQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveAttributeQuickFix.cs @@ -51,8 +51,13 @@ public RemoveAttributeQuickFix(IAttributesUpdater attributesUpdater) public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) { + if (!(result is IWithInspectionResultProperties<(string AttributeName, IReadOnlyList AttributeValues)> resultProperties)) + { + return; + } + var declaration = result.Target; - var (attributeBaseName, attributeValues) = result.Properties<(string AttributeName, IReadOnlyList AttributeValues)>(); + var (attributeBaseName, attributeValues) = resultProperties.Properties; var attributeName = declaration.DeclarationType.HasFlag(DeclarationType.Module) ? attributeBaseName diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveDuplicatedAnnotationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveDuplicatedAnnotationQuickFix.cs index c61c1213a0..8d7cf1f468 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveDuplicatedAnnotationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveDuplicatedAnnotationQuickFix.cs @@ -48,7 +48,12 @@ public RemoveDuplicatedAnnotationQuickFix(IAnnotationUpdater annotationUpdater) public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) { - var resultAnnotation = result.Properties(); + if (!(result is IWithInspectionResultProperties resultProperties)) + { + return; + } + + var resultAnnotation = resultProperties.Properties; var duplicateAnnotations = result.Target.Annotations .Where(pta => pta.Annotation == resultAnnotation) .OrderBy(annotation => annotation.AnnotatedLine) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs index 02110e07ea..0332205111 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs @@ -55,6 +55,11 @@ public RestoreErrorHandlingQuickFix() public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) { + if (!(result is IWithInspectionResultProperties> resultProperties)) + { + return; + } + var exitStatement = "Exit "; VBAParser.BlockContext block; var bodyElementContext = result.Context.GetAncestor(); @@ -89,7 +94,7 @@ public override void Fix(IInspectionResult result, IRewriteSession rewriteSessio var context = (VBAParser.OnErrorStmtContext)result.Context; var labels = bodyElementContext.GetDescendents().ToArray(); var maximumExistingLabelIndex = GetMaximumExistingLabelIndex(labels); - var unhandledContexts = result.Properties>(); + var unhandledContexts = resultProperties.Properties; var offset = unhandledContexts.IndexOf(result.Context); var labelIndex = maximumExistingLabelIndex + offset; diff --git a/Rubberduck.Parsing/Inspections/Abstract/IInspectionResult.cs b/Rubberduck.Parsing/Inspections/Abstract/IInspectionResult.cs index 4cbdb656e4..5df13602c7 100644 --- a/Rubberduck.Parsing/Inspections/Abstract/IInspectionResult.cs +++ b/Rubberduck.Parsing/Inspections/Abstract/IInspectionResult.cs @@ -15,7 +15,11 @@ public interface IInspectionResult : IComparable, IComparable Declaration Target { get; } ParserRuleContext Context { get; } ICollection DisabledQuickFixes { get; } - T Properties(); bool ChangesInvalidateResult(ICollection modifiedModules); } + + public interface IWithInspectionResultProperties + { + T Properties { get; } + } } diff --git a/RubberduckTests/Inspections/AttributeValueOutOfSyncInspectionTests.cs b/RubberduckTests/Inspections/AttributeValueOutOfSyncInspectionTests.cs index 23a82b6070..cfe2cda9fb 100644 --- a/RubberduckTests/Inspections/AttributeValueOutOfSyncInspectionTests.cs +++ b/RubberduckTests/Inspections/AttributeValueOutOfSyncInspectionTests.cs @@ -218,12 +218,19 @@ Public Sub Foo() var inspectionResults = InspectionResults(inputCode); var inspectionResult = inspectionResults.First(); - var (pta, attributeName, attributeValues) = inspectionResult.Properties<(IParseTreeAnnotation Annotation, string AttributeName, IReadOnlyList AttributeValues)>(); - - Assert.IsInstanceOf(pta.Annotation); - Assert.AreEqual("VB_UserMemId", attributeName); - Assert.AreEqual("-4", ((IAttributeAnnotation)pta.Annotation).AttributeValues(pta)[0]); - Assert.AreEqual("40", attributeValues[0]); + if (inspectionResult is IWithInspectionResultProperties<(IParseTreeAnnotation Annotation, string AttributeName, IReadOnlyList AttributeValues)> resultProperties) + { + var (pta, attributeName, attributeValues) = resultProperties.Properties; + + Assert.IsInstanceOf(pta.Annotation); + Assert.AreEqual("VB_UserMemId", attributeName); + Assert.AreEqual("-4", ((IAttributeAnnotation)pta.Annotation).AttributeValues(pta)[0]); + Assert.AreEqual("40", attributeValues[0]); + } + else + { + Assert.Fail("Result is missing expected properties."); + } } private IEnumerable InspectionResults(string inputCode, ComponentType componentType = ComponentType.StandardModule) diff --git a/RubberduckTests/Inspections/MissingMemberAnnotationInspectionTests.cs b/RubberduckTests/Inspections/MissingMemberAnnotationInspectionTests.cs index 5a60adf4e0..84df636c79 100644 --- a/RubberduckTests/Inspections/MissingMemberAnnotationInspectionTests.cs +++ b/RubberduckTests/Inspections/MissingMemberAnnotationInspectionTests.cs @@ -177,11 +177,18 @@ Public Sub Foo() var expectedAttributeValues = new List{"-4"}; var inspectionResult = inspectionResults.Single(); - var (actualAttributeBaseName, actualAttributeValues) = inspectionResult.Properties<(string AttributeName, IReadOnlyList AttributeValues)>(); - - Assert.AreEqual(expectedAttributeName, actualAttributeBaseName); - Assert.AreEqual(expectedAttributeValues.Count, actualAttributeValues.Count); - Assert.AreEqual(expectedAttributeValues[0], actualAttributeValues[0]); + if (inspectionResult is IWithInspectionResultProperties<(string AttributeName, IReadOnlyListAttributeValues)> resultProperties) + { + var (actualAttributeBaseName, actualAttributeValues) = resultProperties.Properties; + + Assert.AreEqual(expectedAttributeName, actualAttributeBaseName); + Assert.AreEqual(expectedAttributeValues.Count, actualAttributeValues.Count); + Assert.AreEqual(expectedAttributeValues[0], actualAttributeValues[0]); + } + else + { + Assert.Fail("Result is missing expected properties."); + } } private IEnumerable InspectionResults(string inputCode, ComponentType componentType = ComponentType.StandardModule) diff --git a/RubberduckTests/Inspections/MissingModuleAnnotationInspectionTests.cs b/RubberduckTests/Inspections/MissingModuleAnnotationInspectionTests.cs index 20ba2663f0..6752a7da31 100644 --- a/RubberduckTests/Inspections/MissingModuleAnnotationInspectionTests.cs +++ b/RubberduckTests/Inspections/MissingModuleAnnotationInspectionTests.cs @@ -425,11 +425,19 @@ Public Sub Foo() var expectedAttributeValues = new List { "\"Desc\"" }; var inspectionResult = inspectionResults.Single(); - var (actualAttributeBaseName, actualAttributeValues) = inspectionResult.Properties<(string AttributeName, IReadOnlyList AttributeValues)>(); - Assert.AreEqual(expectedAttributeName, actualAttributeBaseName); - Assert.AreEqual(expectedAttributeValues.Count, actualAttributeValues.Count); - Assert.AreEqual(expectedAttributeValues[0], actualAttributeValues[0]); + if (inspectionResult is IWithInspectionResultProperties<(string AttributeName, IReadOnlyList AttributeValues)> resultProperties) + { + var (actualAttributeBaseName, actualAttributeValues) = resultProperties.Properties; + + Assert.AreEqual(expectedAttributeName, actualAttributeBaseName); + Assert.AreEqual(expectedAttributeValues.Count, actualAttributeValues.Count); + Assert.AreEqual(expectedAttributeValues[0], actualAttributeValues[0]); + } + else + { + Assert.Fail("Result is missing expected properties."); + } } private IEnumerable InspectionResults(string inputCode, ComponentType componentType = ComponentType.StandardModule) diff --git a/RubberduckTests/Inspections/SuspiciousLetAssignmentInspectionTests.cs b/RubberduckTests/Inspections/SuspiciousLetAssignmentInspectionTests.cs index 178585ec7a..17e96f0d2b 100644 --- a/RubberduckTests/Inspections/SuspiciousLetAssignmentInspectionTests.cs +++ b/RubberduckTests/Inspections/SuspiciousLetAssignmentInspectionTests.cs @@ -47,13 +47,21 @@ End Sub ("Module1", moduleCode, ComponentType.StandardModule)); var inspectionResult = inspectionResults.Single(); - var rhsReference = inspectionResult.Properties(); - Assert.IsNotNull(rhsReference); - if (assignedTypeName.Equals("Object") || assignedToTypeName.Equals("Object")) + if (inspectionResult is IWithInspectionResultProperties resultProperties) { - var deactivatedFix = inspectionResult.DisabledQuickFixes.Single(); - Assert.AreEqual("ExpandDefaultMemberQuickFix", deactivatedFix); + var rhsReference = resultProperties.Properties; + Assert.IsNotNull(rhsReference); + + if (assignedTypeName.Equals("Object") || assignedToTypeName.Equals("Object")) + { + var deactivatedFix = inspectionResult.DisabledQuickFixes.Single(); + Assert.AreEqual("ExpandDefaultMemberQuickFix", deactivatedFix); + } + } + else + { + Assert.Fail("Result is missing expected properties."); } } diff --git a/RubberduckTests/QuickFixes/RemoveDuplicatedAnnotationQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveDuplicatedAnnotationQuickFixTests.cs index 356e58296b..50065d7396 100644 --- a/RubberduckTests/QuickFixes/RemoveDuplicatedAnnotationQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveDuplicatedAnnotationQuickFixTests.cs @@ -182,7 +182,8 @@ Public Sub Foo '@TestMethod Public Sub Foo End Sub"; - Func conditionToFix = result => result.Properties() is ObsoleteAnnotation; + Func conditionToFix = result => result is IWithInspectionResultProperties resultProperties + && resultProperties.Properties is ObsoleteAnnotation; var actualCode = ApplyQuickFixToFirstInspectionResultSatisfyingPredicate(inputCode, state => new DuplicatedAnnotationInspection(state), conditionToFix); Assert.AreEqual(expectedCode, actualCode); } From a4ae6e5178b19a4bdb3350d9f0cb98bf136462e7 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Thu, 13 Feb 2020 13:54:34 +0100 Subject: [PATCH 224/461] Introduce IBaseRefactoring and split ReorderParameterRefactoring using it --- .../BaseRefactoringBase.cs | 40 ++ Rubberduck.Refactorings/IBaseRefactoring.cs | 26 ++ .../ReorderParameterBaseRefactoring.cs | 423 ++++++++++++++++++ .../ReorderParametersRefactoring.cs | 415 +---------------- .../ReorderParametersCommandTests.cs | 3 +- .../Refactoring/ReorderParametersTests.cs | 3 +- 6 files changed, 499 insertions(+), 411 deletions(-) create mode 100644 Rubberduck.Refactorings/BaseRefactoringBase.cs create mode 100644 Rubberduck.Refactorings/IBaseRefactoring.cs create mode 100644 Rubberduck.Refactorings/ReorderParameters/ReorderParameterBaseRefactoring.cs diff --git a/Rubberduck.Refactorings/BaseRefactoringBase.cs b/Rubberduck.Refactorings/BaseRefactoringBase.cs new file mode 100644 index 0000000000..d64dbd0aaf --- /dev/null +++ b/Rubberduck.Refactorings/BaseRefactoringBase.cs @@ -0,0 +1,40 @@ +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.VBA.Parsing; +using Rubberduck.Refactorings.Exceptions; + +namespace Rubberduck.Refactorings +{ + public abstract class BaseRefactoringBase : IBaseRefactoring + where TModel : class, IRefactoringModel + { + private readonly IRewritingManager _rewritingManager; + + protected BaseRefactoringBase(IRewritingManager rewritingManager) + { + _rewritingManager = rewritingManager; + } + + protected abstract void Refactor(TModel model, IRewriteSession rewriteSession); + + public virtual void Refactor(TModel model) + { + var rewriteSession = RewriteSession(RewriteSessionCodeKind); + + Refactor(model, rewriteSession); + + if (!rewriteSession.TryRewrite()) + { + throw new RewriteFailedException(rewriteSession); + } + } + + private IExecutableRewriteSession RewriteSession(CodeKind codeKind) + { + return codeKind == CodeKind.AttributesCode + ? _rewritingManager.CheckOutAttributesSession() + : _rewritingManager.CheckOutCodePaneSession(); + } + + protected virtual CodeKind RewriteSessionCodeKind => CodeKind.CodePaneCode; + } +} \ No newline at end of file diff --git a/Rubberduck.Refactorings/IBaseRefactoring.cs b/Rubberduck.Refactorings/IBaseRefactoring.cs new file mode 100644 index 0000000000..666dcfe06e --- /dev/null +++ b/Rubberduck.Refactorings/IBaseRefactoring.cs @@ -0,0 +1,26 @@ +namespace Rubberduck.Refactorings +{ + /// + /// The heart of a refactoring: this part of the refactoring performs the actual transformation of the code once all necessary information has been gathered. + /// + /// The model used by the refactoring containing all information needed to specify what to do. + public interface IBaseRefactoring where TModel : class, IRefactoringModel + { + /// + /// Performs the actual refactoring based on the parameters specified in the model. + /// + /// The model specifying all parameters of the refactoring + void Refactor(TModel model); + } + + public interface IBaseRefactoringWithPreview : IBaseRefactoring + where TModel : class, IRefactoringModel + { + /// + /// Returns some preview of the refactored code. + /// + /// The model used by the refactoring containing all information needed to specify what to do. + /// Preview of the refactored code + string Preview(TModel model); + } +} \ No newline at end of file diff --git a/Rubberduck.Refactorings/ReorderParameters/ReorderParameterBaseRefactoring.cs b/Rubberduck.Refactorings/ReorderParameters/ReorderParameterBaseRefactoring.cs new file mode 100644 index 0000000000..3fe1c5ad33 --- /dev/null +++ b/Rubberduck.Refactorings/ReorderParameters/ReorderParameterBaseRefactoring.cs @@ -0,0 +1,423 @@ +using System.Collections.Generic; +using System.Linq; +using Antlr4.Runtime; +using Rubberduck.Parsing; +using Rubberduck.Parsing.Binding; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.VBEditor; +using Rubberduck.VBEditor.Extensions; + +namespace Rubberduck.Refactorings.ReorderParameters +{ + public class ReorderParameterBaseRefactoring : BaseRefactoringBase + { + private readonly IDeclarationFinderProvider _declarationFinderProvider; + + public ReorderParameterBaseRefactoring(IDeclarationFinderProvider declarationFinderProvider, IRewritingManager rewritingManager) + : base(rewritingManager) + { + _declarationFinderProvider = declarationFinderProvider; + } + + public override void Refactor(ReorderParametersModel model) + { + if (!model.Parameters.Where((param, index) => param.Index != index).Any()) + { + //This is not an error: the user chose to leave everything as-is. + return; + } + + base.Refactor(model); + } + + protected override void Refactor(ReorderParametersModel model, IRewriteSession rewriteSession) + { + AdjustReferences(model, rewriteSession); + AdjustSignatures(model, rewriteSession); + + // if we are reordering a property getter, check if we need to reorder a letter/setter too + if (model.IsPropertyRefactoringWithGetter) + { + var setter = GetLetterOrSetter(model.TargetDeclaration, DeclarationType.PropertySet); + if (setter != null) + { + var setterModel = ModelForNewTarget(model, setter); + Refactor(setterModel, rewriteSession); + } + + var letter = GetLetterOrSetter(model.TargetDeclaration, DeclarationType.PropertyLet); + if (letter != null) + { + var letterModel = ModelForNewTarget(model, letter); + Refactor(letterModel, rewriteSession); + } + } + + var eventImplementations = _declarationFinderProvider.DeclarationFinder + .FindEventHandlers(model.TargetDeclaration); + + foreach (var eventHandler in eventImplementations) + { + var eventHandlerModel = ModelForNewTarget(model, eventHandler); + AdjustReferences(eventHandlerModel, rewriteSession); + AdjustSignatures(eventHandlerModel, rewriteSession); + } + + var interfaceImplementations = _declarationFinderProvider.DeclarationFinder + .FindInterfaceImplementationMembers(model.TargetDeclaration); + + foreach (var interfaceImplementation in interfaceImplementations) + { + var interfaceImplementationModel = ModelForNewTarget(model, interfaceImplementation); + AdjustReferences(interfaceImplementationModel, rewriteSession); + AdjustSignatures(interfaceImplementationModel, rewriteSession); + } + } + + private static void AdjustReferences(ReorderParametersModel model, IRewriteSession rewriteSession) + { + var parameterDeclarations = model.Parameters + .Select(param => param.Declaration) + .ToList(); + var argumentReferences = ArgumentReferencesByLocation(parameterDeclarations); + + foreach (var (module, moduleArgumentReferences) in argumentReferences) + { + AdjustReferences(model, module, moduleArgumentReferences, rewriteSession); + } + } + + private static Dictionary>> ArgumentReferencesByLocation(ICollection parameters) + { + return parameters + .SelectMany(parameterDeclaration => parameterDeclaration.ArgumentReferences) + .GroupBy(argumentReference => argumentReference.QualifiedModuleName) + .ToDictionary( + grouping => grouping.Key, + grouping => grouping + .GroupBy(reference => reference.ArgumentListSelection) + .ToDictionary(group => group.Key, group => group.ToList())); + } + + private static void AdjustReferences( + ReorderParametersModel model, + QualifiedModuleName module, + Dictionary> argumentReferences, + IRewriteSession rewriteSession) + { + var rewriter = rewriteSession.CheckOutModuleRewriter(module); + foreach (var (argumentListSelection, sameArgumentListReferences) in argumentReferences) + { + //This happens for (with) dictionary access expressions only, + //which cannot be reordered anyway. + if (argumentListSelection.Equals(Selection.Empty)) + { + continue; + } + + AdjustReferences(model, sameArgumentListReferences, rewriter); + } + } + + private static void AdjustReferences(ReorderParametersModel model, IReadOnlyCollection argumentReferences, IModuleRewriter rewriter) + { + if (!argumentReferences.Any()) + { + return; + } + + if (argumentReferences.Any(argReference => argReference.ArgumentType == ArgumentListArgumentType.Named)) + { + var positionalArguments = argumentReferences + .Where(argReference => argReference.ArgumentType == ArgumentListArgumentType.Positional); + MakeArgumentsNamed(positionalArguments, rewriter); + + var missingArguments = argumentReferences + .Where(argReference => argReference.ArgumentType == ArgumentListArgumentType.Missing) + .ToList(); + RemoveArguments(missingArguments, rewriter); + + return; + } + + var argumentReferencesWithoutParamArrayReferences = argumentReferences.Where(reference => + !((ParameterDeclaration)reference.Declaration).IsParamArray) + .ToList(); + + var argumentsWithNewPosition = ArgumentsWithNewPosition(model, argumentReferencesWithoutParamArrayReferences); + + if (argumentReferencesWithoutParamArrayReferences.Count == argumentReferences.Count) + { + //If no parameters for a param array are provided, the reordering can cause trailing missing arguments, which have to be removed. + argumentsWithNewPosition = RemoveMissingArgumentsTrailingAfterReorder(argumentsWithNewPosition, rewriter).ToList(); + } + + ReorderArguments(argumentsWithNewPosition, rewriter); + } + + private static void MakeArgumentsNamed(IEnumerable argumentReferences, IModuleRewriter rewriter) + { + foreach (var argumentReference in argumentReferences) + { + if (argumentReference.ArgumentType != ArgumentListArgumentType.Positional) + { + continue; + } + + MakePositionalArgumentNamed(argumentReference, rewriter); + } + } + + private static void MakePositionalArgumentNamed(ArgumentReference argumentReference, IModuleRewriter rewriter) + { + var parameterName = argumentReference.Declaration.IdentifierName; + var insertionCode = $"{parameterName}:="; + var argumentContext = argumentReference.Context; + var insertionIndex = argumentContext.Start.TokenIndex; + rewriter.InsertBefore(insertionIndex, insertionCode); + } + + private static void RemoveArguments(IReadOnlyCollection argumentReferences, IModuleRewriter rewriter) + { + if (!argumentReferences.Any()) + { + return; + } + + var argumentIndicesToRemove = argumentReferences.Select(argumentReference => argumentReference.ArgumentPosition); + var argumentIndexRangesToRemove = IndexRanges(argumentIndicesToRemove); + var argumentList = argumentReferences.First().ArgumentListContext; + + foreach (var (startIndex, stopIndex) in argumentIndexRangesToRemove) + { + RemoveArgumentRange(startIndex, stopIndex, argumentList, rewriter); + } + } + + private static IEnumerable<(int startIndex, int stopIndex)> IndexRanges(IEnumerable indices) + { + var sortedIndices = indices.OrderBy(num => num).ToList(); + var ranges = new List<(int startIndex, int stopIndex)>(); + int startIndex = -10; + int stopIndex = -10; + foreach (var currentIndex in sortedIndices) + { + if (currentIndex == stopIndex + 1) + { + stopIndex = currentIndex; + } + else + { + if (startIndex >= 0) + { + ranges.Add((startIndex, stopIndex)); + } + + startIndex = currentIndex; + stopIndex = currentIndex; + } + } + + if (startIndex >= 0) + { + ranges.Add((startIndex, stopIndex)); + } + + return ranges; + } + + private static void RemoveArgumentRange( + int startArgumentIndex, + int stopArgumentIndex, + VBAParser.ArgumentListContext argumentList, + IModuleRewriter rewriter) + { + var (startTokenIndex, stopTokenIndex) = TokenIndexRange(startArgumentIndex, stopArgumentIndex, argumentList.argument()); + rewriter.RemoveRange(startTokenIndex, stopTokenIndex); + } + + private static (int startTokenIndex, int stopTokenIndex) TokenIndexRange( + int startIndex, + int stopIndex, + IReadOnlyList contexts) + { + int startTokenIndex; + int stopTokenIndex; + + if (stopIndex == contexts.Count - 1) + { + startTokenIndex = startIndex == 0 + ? contexts[0].Start.TokenIndex + : contexts[startIndex - 1].Stop.TokenIndex + 1; + stopTokenIndex = contexts[stopIndex].Stop.TokenIndex; + return (startTokenIndex, stopTokenIndex); + } + + startTokenIndex = contexts[startIndex].Start.TokenIndex; + stopTokenIndex = contexts[stopIndex + 1].Start.TokenIndex - 1; + return (startTokenIndex, stopTokenIndex); + } + + private static IEnumerable<(ArgumentReference argumentReference, int newIndex)> RemoveMissingArgumentsTrailingAfterReorder( + IEnumerable<(ArgumentReference reference, int Index)> argumentsWithNewPosition, + IModuleRewriter rewriter) + { + var argumentsWithNewPositionOrderedBackwards = argumentsWithNewPosition + .OrderByDescending(tuple => tuple.Index) + .ToList(); + + var numberOfTrailingMissingMembers = NumberOfTrailingMissingArguments(argumentsWithNewPositionOrderedBackwards); + + if (numberOfTrailingMissingMembers > 0) + { + RemoveTrailingArguments(argumentsWithNewPositionOrderedBackwards, numberOfTrailingMissingMembers, rewriter); + } + + return argumentsWithNewPositionOrderedBackwards.Skip(numberOfTrailingMissingMembers); + } + + private static List<(ArgumentReference reference, int)> ArgumentsWithNewPosition(ReorderParametersModel model, IReadOnlyCollection argumentReferences) + { + var newIndex = NewIndicesOfParameterIndices(model); + var argumentsWithNewPosition = argumentReferences + .Select(reference => (reference, newIndex[reference.ArgumentPosition])) + .ToList(); + return argumentsWithNewPosition; + } + + private static int[] NewIndicesOfParameterIndices(ReorderParametersModel model) + { + var newIndices = new int[model.Parameters.Count]; + foreach (var (parameter, index) in model.Parameters.Select((parameter, index) => (parameter, index))) + { + newIndices[parameter.Index] = index; + } + + return newIndices; + } + + private static int NumberOfTrailingMissingArguments(IReadOnlyList<(ArgumentReference reference, int Index)> argumentsWithNewPositionOrderedBackwards) + { + var numberOfTrailingMissingMembers = 0; + while (numberOfTrailingMissingMembers < argumentsWithNewPositionOrderedBackwards.Count + && argumentsWithNewPositionOrderedBackwards[numberOfTrailingMissingMembers].reference.ArgumentType == + ArgumentListArgumentType.Missing) + { + numberOfTrailingMissingMembers++; + } + + return numberOfTrailingMissingMembers; + } + + private static void RemoveTrailingArguments( + IReadOnlyList<(ArgumentReference reference, int Index)> argumentsWithNewPositionOrderedBackwards, + int numberOfTrailingMissingMembers, + IModuleRewriter rewriter) + { + var stopNewArgumentIndex = argumentsWithNewPositionOrderedBackwards.Count - 1; + var startNewArgumentIndex = stopNewArgumentIndex - numberOfTrailingMissingMembers + 1; + + var argumentList = argumentsWithNewPositionOrderedBackwards[0].reference.ArgumentListContext; + RemoveArgumentRange(startNewArgumentIndex, stopNewArgumentIndex, argumentList, rewriter); + } + + private static void ReorderArguments( + IReadOnlyList<(ArgumentReference argumentReference, int newIndex)> argumentsWithNewPosition, + IModuleRewriter rewriter) + { + if (!argumentsWithNewPosition.Any()) + { + return; + } + + var argumentList = argumentsWithNewPosition[0].argumentReference.ArgumentListContext; + var arguments = argumentList.argument(); + foreach (var (argumentReference, newIndex) in argumentsWithNewPosition) + { + if (argumentReference.ArgumentPosition == newIndex) + { + continue; + } + + var replacementArgument = argumentReference.Context.GetText(); + var contextToReplace = arguments[newIndex]; + + if (contextToReplace.missingArgument() != null) + { + //Missing members have are empty and thus stopIndex < startIndex, which is not legal for replace. + rewriter.InsertBefore(contextToReplace.start.TokenIndex, replacementArgument); + } + else + { + rewriter.Replace(contextToReplace, replacementArgument); + } + } + } + + private static void AdjustSignatures(ReorderParametersModel model, IRewriteSession rewriteSession) + { + if (!model.Parameters.Any()) + { + return; + } + + var rewriter = rewriteSession.CheckOutModuleRewriter(model.TargetDeclaration.QualifiedModuleName); + var parameterList = model.Parameters[0].Declaration.Context.GetAncestor(); + var newIndices = NewIndicesOfParameterIndices(model); + + ReorderParameters(parameterList, newIndices, rewriter); + } + + private static void ReorderParameters(VBAParser.ArgListContext parameterList, int[] newIndices, IModuleRewriter rewriter) + { + if (!newIndices.Any()) + { + return; + } + + var parameterContexts = parameterList.arg(); + for (var oldIndex = 0; oldIndex < newIndices.Length; oldIndex++) + { + var newIndex = newIndices[oldIndex]; + + if (oldIndex == newIndex) + { + continue; + } + + var contextToReplace = parameterContexts[newIndex]; + var replacementParameter = parameterContexts[oldIndex].GetText(); + rewriter.Replace(contextToReplace, replacementParameter); + } + } + + private Declaration GetLetterOrSetter(Declaration declaration, DeclarationType declarationType) + { + return _declarationFinderProvider.DeclarationFinder + .UserDeclarations(declarationType) + .FirstOrDefault(item => item.QualifiedModuleName.Equals(declaration.QualifiedModuleName) + && item.IdentifierName == declaration.IdentifierName); + } + + private static ReorderParametersModel ModelForNewTarget(ReorderParametersModel oldModel, Declaration newTarget) + { + var newModel = new ReorderParametersModel(newTarget); + var newParameters = newModel.Parameters; + + var newReorderedParameters = oldModel.Parameters + .Select(param => newParameters[param.Index]) + .ToList(); + if (newReorderedParameters.Count < newParameters.Count) + { + var additionalParameters = newParameters.Skip(newReorderedParameters.Count); + newReorderedParameters.AddRange(additionalParameters); + } + + newModel.Parameters = newReorderedParameters; + return newModel; + } + } +} \ No newline at end of file diff --git a/Rubberduck.Refactorings/ReorderParameters/ReorderParametersRefactoring.cs b/Rubberduck.Refactorings/ReorderParameters/ReorderParametersRefactoring.cs index 162c4c5fc3..dd471bc2e1 100644 --- a/Rubberduck.Refactorings/ReorderParameters/ReorderParametersRefactoring.cs +++ b/Rubberduck.Refactorings/ReorderParameters/ReorderParametersRefactoring.cs @@ -1,16 +1,10 @@ -using Rubberduck.Parsing; -using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.Symbols; using Rubberduck.VBEditor; using Rubberduck.Parsing.Rewriter; -using System.Collections.Generic; using System.Linq; -using Antlr4.Runtime; -using Rubberduck.Parsing.Binding; using Rubberduck.Parsing.UIContext; using Rubberduck.Parsing.VBA; - using Rubberduck.Refactorings.Exceptions; -using Rubberduck.VBEditor.Extensions; +using Rubberduck.Refactorings.Exceptions; using Rubberduck.VBEditor.Utility; namespace Rubberduck.Refactorings.ReorderParameters @@ -19,8 +13,10 @@ public class ReorderParametersRefactoring : InteractiveRefactoringBase _baseRefactoring; public ReorderParametersRefactoring( + ReorderParameterBaseRefactoring baseRefactoring, IDeclarationFinderProvider declarationFinderProvider, IRefactoringPresenterFactory factory, IRewritingManager rewritingManager, @@ -29,6 +25,7 @@ public ReorderParametersRefactoring( IUiDispatcher uiDispatcher) :base(rewritingManager, selectionProvider, factory, uiDispatcher) { + _baseRefactoring = baseRefactoring; _declarationFinderProvider = declarationFinderProvider; _selectedDeclarationProvider = selectedDeclarationProvider; } @@ -136,407 +133,7 @@ private ReorderParametersModel ResolvedGetterTarget(ReorderParametersModel model protected override void RefactorImpl(ReorderParametersModel model) { - if (!model.Parameters.Where((param, index) => param.Index != index).Any()) - { - //This is not an error: the user chose to leave everything as-is. - return; - } - - var rewriteSession = RewritingManager.CheckOutCodePaneSession(); - - RefactorImpl(model, rewriteSession); - - if (!rewriteSession.TryRewrite()) - { - throw new RewriteFailedException(rewriteSession); - } - } - - private void RefactorImpl(ReorderParametersModel model, IRewriteSession rewriteSession) - { - AdjustReferences(model, rewriteSession); - AdjustSignatures(model, rewriteSession); - - // if we are reordering a property getter, check if we need to reorder a letter/setter too - if (model.IsPropertyRefactoringWithGetter) - { - var setter = GetLetterOrSetter(model.TargetDeclaration, DeclarationType.PropertySet); - if (setter != null) - { - var setterModel = ModelForNewTarget(model, setter); - RefactorImpl(setterModel, rewriteSession); - } - - var letter = GetLetterOrSetter(model.TargetDeclaration, DeclarationType.PropertyLet); - if (letter != null) - { - var letterModel = ModelForNewTarget(model, letter); - RefactorImpl(letterModel, rewriteSession); - } - } - - var eventImplementations = _declarationFinderProvider.DeclarationFinder - .FindEventHandlers(model.TargetDeclaration); - - foreach (var eventHandler in eventImplementations) - { - var eventHandlerModel = ModelForNewTarget(model, eventHandler); - AdjustReferences(eventHandlerModel, rewriteSession); - AdjustSignatures(eventHandlerModel, rewriteSession); - } - - var interfaceImplementations = _declarationFinderProvider.DeclarationFinder - .FindInterfaceImplementationMembers(model.TargetDeclaration); - - foreach (var interfaceImplementation in interfaceImplementations) - { - var interfaceImplementationModel = ModelForNewTarget(model, interfaceImplementation); - AdjustReferences(interfaceImplementationModel, rewriteSession); - AdjustSignatures(interfaceImplementationModel, rewriteSession); - } - } - - private static void AdjustReferences(ReorderParametersModel model, IRewriteSession rewriteSession) - { - var parameterDeclarations = model.Parameters - .Select(param => param.Declaration) - .ToList(); - var argumentReferences = ArgumentReferencesByLocation(parameterDeclarations); - - foreach (var (module, moduleArgumentReferences) in argumentReferences) - { - AdjustReferences(model, module, moduleArgumentReferences, rewriteSession); - } - } - - private static Dictionary>> ArgumentReferencesByLocation(ICollection parameters) - { - return parameters - .SelectMany(parameterDeclaration => parameterDeclaration.ArgumentReferences) - .GroupBy(argumentReference => argumentReference.QualifiedModuleName) - .ToDictionary( - grouping => grouping.Key, - grouping => grouping - .GroupBy(reference => reference.ArgumentListSelection) - .ToDictionary(group => group.Key, group => group.ToList())); - } - - private static void AdjustReferences( - ReorderParametersModel model, - QualifiedModuleName module, - Dictionary> argumentReferences, - IRewriteSession rewriteSession) - { - var rewriter = rewriteSession.CheckOutModuleRewriter(module); - foreach (var (argumentListSelection, sameArgumentListReferences) in argumentReferences) - { - //This happens for (with) dictionary access expressions only, - //which cannot be reordered anyway. - if (argumentListSelection.Equals(Selection.Empty)) - { - continue; - } - - AdjustReferences(model, sameArgumentListReferences, rewriter); - } - } - - private static void AdjustReferences(ReorderParametersModel model, IReadOnlyCollection argumentReferences, IModuleRewriter rewriter) - { - if (!argumentReferences.Any()) - { - return; - } - - if (argumentReferences.Any(argReference => argReference.ArgumentType == ArgumentListArgumentType.Named)) - { - var positionalArguments = argumentReferences - .Where(argReference => argReference.ArgumentType == ArgumentListArgumentType.Positional); - MakeArgumentsNamed(positionalArguments, rewriter); - - var missingArguments = argumentReferences - .Where(argReference => argReference.ArgumentType == ArgumentListArgumentType.Missing) - .ToList(); - RemoveArguments(missingArguments, rewriter); - - return; - } - - var argumentReferencesWithoutParamArrayReferences = argumentReferences.Where(reference => - !((ParameterDeclaration) reference.Declaration).IsParamArray) - .ToList(); - - var argumentsWithNewPosition = ArgumentsWithNewPosition(model, argumentReferencesWithoutParamArrayReferences); - - if (argumentReferencesWithoutParamArrayReferences.Count == argumentReferences.Count) - { - //If no parameters for a param array are provided, the reordering can cause trailing missing arguments, which have to be removed. - argumentsWithNewPosition = RemoveMissingArgumentsTrailingAfterReorder(argumentsWithNewPosition, rewriter).ToList(); - } - - ReorderArguments(argumentsWithNewPosition, rewriter); - } - - private static void MakeArgumentsNamed(IEnumerable argumentReferences, IModuleRewriter rewriter) - { - foreach (var argumentReference in argumentReferences) - { - if (argumentReference.ArgumentType != ArgumentListArgumentType.Positional) - { - continue; - } - - MakePositionalArgumentNamed(argumentReference, rewriter); - } - } - - private static void MakePositionalArgumentNamed(ArgumentReference argumentReference, IModuleRewriter rewriter) - { - var parameterName = argumentReference.Declaration.IdentifierName; - var insertionCode = $"{parameterName}:="; - var argumentContext = argumentReference.Context; - var insertionIndex = argumentContext.Start.TokenIndex; - rewriter.InsertBefore(insertionIndex, insertionCode); - } - - private static void RemoveArguments(IReadOnlyCollection argumentReferences, IModuleRewriter rewriter) - { - if (!argumentReferences.Any()) - { - return; - } - - var argumentIndicesToRemove = argumentReferences.Select(argumentReference => argumentReference.ArgumentPosition); - var argumentIndexRangesToRemove = IndexRanges(argumentIndicesToRemove); - var argumentList = argumentReferences.First().ArgumentListContext; - - foreach (var (startIndex, stopIndex) in argumentIndexRangesToRemove) - { - RemoveArgumentRange(startIndex, stopIndex, argumentList, rewriter); - } - } - - private static IEnumerable<(int startIndex, int stopIndex)> IndexRanges(IEnumerable indices) - { - var sortedIndices = indices.OrderBy(num => num).ToList(); - var ranges = new List<(int startIndex, int stopIndex)>(); - int startIndex = -10; - int stopIndex = -10; - foreach (var currentIndex in sortedIndices) - { - if (currentIndex == stopIndex + 1) - { - stopIndex = currentIndex; - } - else - { - if (startIndex >= 0) - { - ranges.Add((startIndex, stopIndex)); - } - - startIndex = currentIndex; - stopIndex = currentIndex; - } - } - - if (startIndex >= 0) - { - ranges.Add((startIndex, stopIndex)); - } - - return ranges; - } - - private static void RemoveArgumentRange( - int startArgumentIndex, - int stopArgumentIndex, - VBAParser.ArgumentListContext argumentList, - IModuleRewriter rewriter) - { - var (startTokenIndex, stopTokenIndex) = TokenIndexRange(startArgumentIndex, stopArgumentIndex, argumentList.argument()); - rewriter.RemoveRange(startTokenIndex, stopTokenIndex); - } - - private static (int startTokenIndex, int stopTokenIndex) TokenIndexRange( - int startIndex, - int stopIndex, - IReadOnlyList contexts) - { - int startTokenIndex; - int stopTokenIndex; - - if (stopIndex == contexts.Count - 1) - { - startTokenIndex = startIndex == 0 - ? contexts[0].Start.TokenIndex - : contexts[startIndex - 1].Stop.TokenIndex + 1; - stopTokenIndex = contexts[stopIndex].Stop.TokenIndex; - return (startTokenIndex, stopTokenIndex); - } - - startTokenIndex = contexts[startIndex].Start.TokenIndex; - stopTokenIndex = contexts[stopIndex + 1].Start.TokenIndex - 1; - return (startTokenIndex, stopTokenIndex); - } - - private static IEnumerable<(ArgumentReference argumentReference, int newIndex)> RemoveMissingArgumentsTrailingAfterReorder( - IEnumerable<(ArgumentReference reference, int Index)> argumentsWithNewPosition, - IModuleRewriter rewriter) - { - var argumentsWithNewPositionOrderedBackwards = argumentsWithNewPosition - .OrderByDescending(tuple => tuple.Index) - .ToList(); - - var numberOfTrailingMissingMembers = NumberOfTrailingMissingArguments(argumentsWithNewPositionOrderedBackwards); - - if (numberOfTrailingMissingMembers > 0) - { - RemoveTrailingArguments(argumentsWithNewPositionOrderedBackwards, numberOfTrailingMissingMembers, rewriter); - } - - return argumentsWithNewPositionOrderedBackwards.Skip(numberOfTrailingMissingMembers); - } - - private static List<(ArgumentReference reference, int)> ArgumentsWithNewPosition(ReorderParametersModel model, IReadOnlyCollection argumentReferences) - { - var newIndex = NewIndicesOfParameterIndices(model); - var argumentsWithNewPosition = argumentReferences - .Select(reference => (reference, newIndex[reference.ArgumentPosition])) - .ToList(); - return argumentsWithNewPosition; - } - - private static int[] NewIndicesOfParameterIndices(ReorderParametersModel model) - { - var newIndices = new int[model.Parameters.Count]; - foreach (var (parameter, index) in model.Parameters.Select((parameter, index) => (parameter, index))) - { - newIndices[parameter.Index] = index; - } - - return newIndices; - } - - private static int NumberOfTrailingMissingArguments(IReadOnlyList<(ArgumentReference reference, int Index)> argumentsWithNewPositionOrderedBackwards) - { - var numberOfTrailingMissingMembers = 0; - while (numberOfTrailingMissingMembers < argumentsWithNewPositionOrderedBackwards.Count - && argumentsWithNewPositionOrderedBackwards[numberOfTrailingMissingMembers].reference.ArgumentType == - ArgumentListArgumentType.Missing) - { - numberOfTrailingMissingMembers++; - } - - return numberOfTrailingMissingMembers; - } - - private static void RemoveTrailingArguments( - IReadOnlyList<(ArgumentReference reference, int Index)> argumentsWithNewPositionOrderedBackwards, - int numberOfTrailingMissingMembers, - IModuleRewriter rewriter) - { - var stopNewArgumentIndex = argumentsWithNewPositionOrderedBackwards.Count - 1; - var startNewArgumentIndex = stopNewArgumentIndex - numberOfTrailingMissingMembers + 1; - - var argumentList = argumentsWithNewPositionOrderedBackwards[0].reference.ArgumentListContext; - RemoveArgumentRange(startNewArgumentIndex, stopNewArgumentIndex, argumentList, rewriter); - } - - private static void ReorderArguments( - IReadOnlyList<(ArgumentReference argumentReference, int newIndex)> argumentsWithNewPosition, - IModuleRewriter rewriter) - { - if (!argumentsWithNewPosition.Any()) - { - return; - } - - var argumentList = argumentsWithNewPosition[0].argumentReference.ArgumentListContext; - var arguments = argumentList.argument(); - foreach (var (argumentReference, newIndex) in argumentsWithNewPosition) - { - if (argumentReference.ArgumentPosition == newIndex) - { - continue; - } - - var replacementArgument = argumentReference.Context.GetText(); - var contextToReplace = arguments[newIndex]; - - if (contextToReplace.missingArgument() != null) - { - //Missing members have are empty and thus stopIndex < startIndex, which is not legal for replace. - rewriter.InsertBefore(contextToReplace.start.TokenIndex, replacementArgument); - } - else - { - rewriter.Replace(contextToReplace, replacementArgument); - } - } - } - - private static void AdjustSignatures(ReorderParametersModel model, IRewriteSession rewriteSession) - { - if (!model.Parameters.Any()) - { - return; - } - - var rewriter = rewriteSession.CheckOutModuleRewriter(model.TargetDeclaration.QualifiedModuleName); - var parameterList = model.Parameters[0].Declaration.Context.GetAncestor(); - var newIndices = NewIndicesOfParameterIndices(model); - - ReorderParameters(parameterList, newIndices, rewriter); - } - - private static void ReorderParameters(VBAParser.ArgListContext parameterList, int[] newIndices, IModuleRewriter rewriter) - { - if (!newIndices.Any()) - { - return; - } - - var parameterContexts = parameterList.arg(); - for(var oldIndex = 0; oldIndex < newIndices.Length; oldIndex++) - { - var newIndex = newIndices[oldIndex]; - - if (oldIndex == newIndex) - { - continue; - } - - var contextToReplace = parameterContexts[newIndex]; - var replacementParameter = parameterContexts[oldIndex].GetText(); - rewriter.Replace(contextToReplace, replacementParameter); - } - } - - private Declaration GetLetterOrSetter(Declaration declaration, DeclarationType declarationType) - { - return _declarationFinderProvider.DeclarationFinder - .UserDeclarations(declarationType) - .FirstOrDefault(item => item.QualifiedModuleName.Equals(declaration.QualifiedModuleName) - && item.IdentifierName == declaration.IdentifierName); - } - - private static ReorderParametersModel ModelForNewTarget(ReorderParametersModel oldModel, Declaration newTarget) - { - var newModel = new ReorderParametersModel(newTarget); - var newParameters = newModel.Parameters; - - var newReorderedParameters = oldModel.Parameters - .Select(param => newParameters[param.Index]) - .ToList(); - if (newReorderedParameters.Count < newParameters.Count) - { - var additionalParameters = newParameters.Skip(newReorderedParameters.Count); - newReorderedParameters.AddRange(additionalParameters); - } - - newModel.Parameters = newReorderedParameters; - return newModel; + _baseRefactoring.Refactor(model); } public static readonly DeclarationType[] ValidDeclarationTypes = diff --git a/RubberduckTests/Commands/RefactorCommands/ReorderParametersCommandTests.cs b/RubberduckTests/Commands/RefactorCommands/ReorderParametersCommandTests.cs index 925b597fa6..b513c13559 100644 --- a/RubberduckTests/Commands/RefactorCommands/ReorderParametersCommandTests.cs +++ b/RubberduckTests/Commands/RefactorCommands/ReorderParametersCommandTests.cs @@ -170,7 +170,8 @@ protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state uiDispatcherMock .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); - var refactoring = new ReorderParametersRefactoring(state, factory, rewritingManager, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); + var baseRefactoring = new ReorderParameterBaseRefactoring(state, rewritingManager); + var refactoring = new ReorderParametersRefactoring(baseRefactoring, state, factory, rewritingManager, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); var notifier = new ReorderParametersFailedNotifier(msgBox); return new RefactorReorderParametersCommand(refactoring, notifier, state, selectionService, selectedDeclarationProvider); } diff --git a/RubberduckTests/Refactoring/ReorderParametersTests.cs b/RubberduckTests/Refactoring/ReorderParametersTests.cs index c291af11cd..ea35734d6f 100644 --- a/RubberduckTests/Refactoring/ReorderParametersTests.cs +++ b/RubberduckTests/Refactoring/ReorderParametersTests.cs @@ -1348,7 +1348,8 @@ protected override IRefactoring TestRefactoring( uiDispatcherMock .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); - return new ReorderParametersRefactoring(state, factory, rewritingManager, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); + var baseRefactoring = new ReorderParameterBaseRefactoring(state, rewritingManager); + return new ReorderParametersRefactoring(baseRefactoring, state, factory, rewritingManager, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); } private static Func ReverseParameters() From dd31347b501dff97e828e8e632bb4e9469621d0a Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Thu, 13 Feb 2020 19:09:31 +0100 Subject: [PATCH 225/461] Split the remaining refactorings, except EncapsulateField --- .../{ => Abstract}/BaseRefactoringBase.cs | 0 .../BaseRefactoringWithSuspensionBase.cs | 55 +++ .../Abstract/CodeOnlyBaseRefactoringBase.cs | 40 +++ .../{ => Abstract}/IBaseRefactoring.cs | 17 +- .../{ => Abstract}/IRefactoring.cs | 0 .../{ => Abstract}/IRefactoringDialog.cs | 0 .../{ => Abstract}/IRefactoringModel.cs | 0 .../{ => Abstract}/IRefactoringPresenter.cs | 0 .../IRefactoringPresenterFactory.cs | 0 .../{ => Abstract}/IRefactoringView.cs | 0 .../{ => Abstract}/IRefactoringViewModel.cs | 0 .../InteractiveRefactoringBase.cs | 0 .../{ => Abstract}/RefactoringBase.cs | 0 .../EncapsulateField/EncapsulateFieldModel.cs | 2 - .../EncapsulateFieldRefactoring.cs | 20 +- .../ExtractInterfaceBaseRefactoring.cs | 102 ++++++ .../ExtractInterfaceRefactoring.cs | 112 +------ ...InterFaceImplementationsBaseRefactoring.cs | 98 ++++++ .../AddInterfaceImplementationsModel.cs | 20 ++ .../ImplementInterfaceBaseRefactoring.cs | 41 +++ .../ImplementInterfaceModel.cs | 16 + .../ImplementInterfaceRefactoring.cs | 113 +------ .../IntroduceFieldBaseRefactoring.cs | 40 +++ .../IntroduceField/IntroduceFieldModel.cs | 14 + .../IntroduceFieldRefactoring.cs | 33 +- .../IntroduceParameterBaseRefactoring.cs | 139 ++++++++ .../IntroduceParameterModel.cs | 16 + .../IntroduceParameterRefactoring.cs | 128 +------ .../MoveCloserToUsageBaseRefactoring.cs | 119 +++++++ .../MoveCloserToUsageModel.cs | 14 + .../MoveCloserToUsageRefactoring.cs | 115 +------ .../RemoveParameterBaseRefactoring.cs | 302 +++++++++++++++++ .../RemoveParametersRefactoring.cs | 314 +---------------- .../Rename/RenameBaseRefactoring.cs | 308 +++++++++++++++++ .../Rename/RenameRefactoring.cs | 315 +----------------- .../CodeExplorer/MockedCodeExplorer.cs | 7 +- .../ExtractInterfaceCommandTests.cs | 5 +- .../ImplementInterfaceCommandTests.cs | 5 +- .../IntroduceFieldCommandTests.cs | 3 +- .../IntroduceParameterCommandTests.cs | 3 +- .../MoveCloserToUsageCommandTests.cs | 3 +- .../RemoveParametersCommandTests.cs | 3 +- .../MoveFieldCloserToUsageQuickFixTests.cs | 3 +- .../RemoveUnusedParameterQuickFixTests.cs | 3 +- .../Refactoring/ExtractInterfaceTests.cs | 5 +- .../Refactoring/ImplementInterfaceTests.cs | 5 +- .../Refactoring/IntroduceFieldTests.cs | 3 +- .../Refactoring/IntroduceParameterTests.cs | 3 +- .../Refactoring/MoveCloserToUsageTests.cs | 3 +- .../Refactoring/RemoveParametersTests.cs | 3 +- .../Refactoring/Rename/RenameTests.cs | 3 +- 51 files changed, 1458 insertions(+), 1095 deletions(-) rename Rubberduck.Refactorings/{ => Abstract}/BaseRefactoringBase.cs (100%) create mode 100644 Rubberduck.Refactorings/Abstract/BaseRefactoringWithSuspensionBase.cs create mode 100644 Rubberduck.Refactorings/Abstract/CodeOnlyBaseRefactoringBase.cs rename Rubberduck.Refactorings/{ => Abstract}/IBaseRefactoring.cs (60%) rename Rubberduck.Refactorings/{ => Abstract}/IRefactoring.cs (100%) rename Rubberduck.Refactorings/{ => Abstract}/IRefactoringDialog.cs (100%) rename Rubberduck.Refactorings/{ => Abstract}/IRefactoringModel.cs (100%) rename Rubberduck.Refactorings/{ => Abstract}/IRefactoringPresenter.cs (100%) rename Rubberduck.Refactorings/{ => Abstract}/IRefactoringPresenterFactory.cs (100%) rename Rubberduck.Refactorings/{ => Abstract}/IRefactoringView.cs (100%) rename Rubberduck.Refactorings/{ => Abstract}/IRefactoringViewModel.cs (100%) rename Rubberduck.Refactorings/{ => Abstract}/InteractiveRefactoringBase.cs (100%) rename Rubberduck.Refactorings/{ => Abstract}/RefactoringBase.cs (100%) create mode 100644 Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceBaseRefactoring.cs create mode 100644 Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterFaceImplementationsBaseRefactoring.cs create mode 100644 Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterfaceImplementationsModel.cs create mode 100644 Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceBaseRefactoring.cs create mode 100644 Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceModel.cs create mode 100644 Rubberduck.Refactorings/IntroduceField/IntroduceFieldBaseRefactoring.cs create mode 100644 Rubberduck.Refactorings/IntroduceField/IntroduceFieldModel.cs create mode 100644 Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterBaseRefactoring.cs create mode 100644 Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterModel.cs create mode 100644 Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageBaseRefactoring.cs create mode 100644 Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageModel.cs create mode 100644 Rubberduck.Refactorings/RemoveParameters/RemoveParameterBaseRefactoring.cs create mode 100644 Rubberduck.Refactorings/Rename/RenameBaseRefactoring.cs diff --git a/Rubberduck.Refactorings/BaseRefactoringBase.cs b/Rubberduck.Refactorings/Abstract/BaseRefactoringBase.cs similarity index 100% rename from Rubberduck.Refactorings/BaseRefactoringBase.cs rename to Rubberduck.Refactorings/Abstract/BaseRefactoringBase.cs diff --git a/Rubberduck.Refactorings/Abstract/BaseRefactoringWithSuspensionBase.cs b/Rubberduck.Refactorings/Abstract/BaseRefactoringWithSuspensionBase.cs new file mode 100644 index 0000000000..d31fdfd5e6 --- /dev/null +++ b/Rubberduck.Refactorings/Abstract/BaseRefactoringWithSuspensionBase.cs @@ -0,0 +1,55 @@ +using System.Runtime.ExceptionServices; +using NLog; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.VBA; +using Rubberduck.Refactorings.Exceptions; + +namespace Rubberduck.Refactorings +{ + public abstract class BaseRefactoringWithSuspensionBase : BaseRefactoringBase + where TModel : class, IRefactoringModel + { + private readonly IParseManager _parseManager; + + private readonly Logger _logger; + + protected BaseRefactoringWithSuspensionBase(IParseManager parseManager, IRewritingManager rewritingManager) + : base(rewritingManager) + { + _parseManager = parseManager; + _logger = LogManager.GetLogger(GetType().FullName); + } + + protected abstract bool RequiresSuspension(TModel model); + + public override void Refactor(TModel model) + { + if (RequiresSuspension(model)) + { + RefactorWithSuspendedParser(model); + } + else + { + base.Refactor(model); + } + } + + private void RefactorWithSuspendedParser(TModel model) + { + var suspendResult = _parseManager.OnSuspendParser(this, new[] { ParserState.Ready }, () => base.Refactor(model)); + var suspendOutcome = suspendResult.Outcome; + if (suspendOutcome != SuspensionOutcome.Completed) + { + if ((suspendOutcome == SuspensionOutcome.UnexpectedError || suspendOutcome == SuspensionOutcome.Canceled) + && suspendResult.EncounteredException != null) + { + ExceptionDispatchInfo.Capture(suspendResult.EncounteredException).Throw(); + return; + } + + _logger.Warn($"{GetType().Name} failed because a parser suspension request could not be fulfilled. The request's result was '{suspendResult.ToString()}'."); + throw new SuspendParserFailureException(); + } + } + } +} \ No newline at end of file diff --git a/Rubberduck.Refactorings/Abstract/CodeOnlyBaseRefactoringBase.cs b/Rubberduck.Refactorings/Abstract/CodeOnlyBaseRefactoringBase.cs new file mode 100644 index 0000000000..e3dd336b89 --- /dev/null +++ b/Rubberduck.Refactorings/Abstract/CodeOnlyBaseRefactoringBase.cs @@ -0,0 +1,40 @@ +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.VBA.Parsing; +using Rubberduck.Refactorings.Exceptions; + +namespace Rubberduck.Refactorings +{ + public abstract class CodeOnlyBaseRefactoringBase : ICodeOnlyBaseRefactoring + where TModel : class, IRefactoringModel + { + private readonly IRewritingManager _rewritingManager; + + protected CodeOnlyBaseRefactoringBase(IRewritingManager rewritingManager) + { + _rewritingManager = rewritingManager; + } + + public abstract void Refactor(TModel model, IRewriteSession rewriteSession); + + public virtual void Refactor(TModel model) + { + var rewriteSession = RewriteSession(RewriteSessionCodeKind); + + Refactor(model, rewriteSession); + + if (!rewriteSession.TryRewrite()) + { + throw new RewriteFailedException(rewriteSession); + } + } + + private IExecutableRewriteSession RewriteSession(CodeKind codeKind) + { + return codeKind == CodeKind.AttributesCode + ? _rewritingManager.CheckOutAttributesSession() + : _rewritingManager.CheckOutCodePaneSession(); + } + + protected virtual CodeKind RewriteSessionCodeKind => CodeKind.CodePaneCode; + } +} \ No newline at end of file diff --git a/Rubberduck.Refactorings/IBaseRefactoring.cs b/Rubberduck.Refactorings/Abstract/IBaseRefactoring.cs similarity index 60% rename from Rubberduck.Refactorings/IBaseRefactoring.cs rename to Rubberduck.Refactorings/Abstract/IBaseRefactoring.cs index 666dcfe06e..27fcf699e2 100644 --- a/Rubberduck.Refactorings/IBaseRefactoring.cs +++ b/Rubberduck.Refactorings/Abstract/IBaseRefactoring.cs @@ -1,4 +1,6 @@ -namespace Rubberduck.Refactorings +using Rubberduck.Parsing.Rewriter; + +namespace Rubberduck.Refactorings { /// /// The heart of a refactoring: this part of the refactoring performs the actual transformation of the code once all necessary information has been gathered. @@ -13,7 +15,7 @@ public interface IBaseRefactoring where TModel : class, IRefactoringM void Refactor(TModel model); } - public interface IBaseRefactoringWithPreview : IBaseRefactoring + public interface IRefactoringPreviewProvider where TModel : class, IRefactoringModel { /// @@ -23,4 +25,15 @@ public interface IBaseRefactoringWithPreview : IBaseRefactoringPreview of the refactored code string Preview(TModel model); } + + public interface ICodeOnlyBaseRefactoring : IBaseRefactoring + where TModel : class, IRefactoringModel + { + /// + /// Performs the refactoring according to the model and using the provided rewrite session. + /// + /// The model specifying all parameters of the refactoring + /// Rewrite session used to manipulate the code (Does not get executed.) + void Refactor(TModel model, IRewriteSession rewriteSession); + } } \ No newline at end of file diff --git a/Rubberduck.Refactorings/IRefactoring.cs b/Rubberduck.Refactorings/Abstract/IRefactoring.cs similarity index 100% rename from Rubberduck.Refactorings/IRefactoring.cs rename to Rubberduck.Refactorings/Abstract/IRefactoring.cs diff --git a/Rubberduck.Refactorings/IRefactoringDialog.cs b/Rubberduck.Refactorings/Abstract/IRefactoringDialog.cs similarity index 100% rename from Rubberduck.Refactorings/IRefactoringDialog.cs rename to Rubberduck.Refactorings/Abstract/IRefactoringDialog.cs diff --git a/Rubberduck.Refactorings/IRefactoringModel.cs b/Rubberduck.Refactorings/Abstract/IRefactoringModel.cs similarity index 100% rename from Rubberduck.Refactorings/IRefactoringModel.cs rename to Rubberduck.Refactorings/Abstract/IRefactoringModel.cs diff --git a/Rubberduck.Refactorings/IRefactoringPresenter.cs b/Rubberduck.Refactorings/Abstract/IRefactoringPresenter.cs similarity index 100% rename from Rubberduck.Refactorings/IRefactoringPresenter.cs rename to Rubberduck.Refactorings/Abstract/IRefactoringPresenter.cs diff --git a/Rubberduck.Refactorings/IRefactoringPresenterFactory.cs b/Rubberduck.Refactorings/Abstract/IRefactoringPresenterFactory.cs similarity index 100% rename from Rubberduck.Refactorings/IRefactoringPresenterFactory.cs rename to Rubberduck.Refactorings/Abstract/IRefactoringPresenterFactory.cs diff --git a/Rubberduck.Refactorings/IRefactoringView.cs b/Rubberduck.Refactorings/Abstract/IRefactoringView.cs similarity index 100% rename from Rubberduck.Refactorings/IRefactoringView.cs rename to Rubberduck.Refactorings/Abstract/IRefactoringView.cs diff --git a/Rubberduck.Refactorings/IRefactoringViewModel.cs b/Rubberduck.Refactorings/Abstract/IRefactoringViewModel.cs similarity index 100% rename from Rubberduck.Refactorings/IRefactoringViewModel.cs rename to Rubberduck.Refactorings/Abstract/IRefactoringViewModel.cs diff --git a/Rubberduck.Refactorings/InteractiveRefactoringBase.cs b/Rubberduck.Refactorings/Abstract/InteractiveRefactoringBase.cs similarity index 100% rename from Rubberduck.Refactorings/InteractiveRefactoringBase.cs rename to Rubberduck.Refactorings/Abstract/InteractiveRefactoringBase.cs diff --git a/Rubberduck.Refactorings/RefactoringBase.cs b/Rubberduck.Refactorings/Abstract/RefactoringBase.cs similarity index 100% rename from Rubberduck.Refactorings/RefactoringBase.cs rename to Rubberduck.Refactorings/Abstract/RefactoringBase.cs diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs index 53ea4f2a76..bdc19145c6 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldModel.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Refactorings.EncapsulateField.Extensions; using Rubberduck.VBEditor; namespace Rubberduck.Refactorings.EncapsulateField diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index b9c754c43b..79eb9ae826 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -1,5 +1,4 @@ using System.Linq; -using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.UIContext; @@ -8,9 +7,7 @@ using Rubberduck.VBEditor; using Rubberduck.SmartIndenter; using Rubberduck.VBEditor.Utility; -using System.Collections.Generic; using System; -using Rubberduck.Refactorings.EncapsulateField.Extensions; namespace Rubberduck.Refactorings.EncapsulateField { @@ -30,7 +27,6 @@ public class EncapsulateFieldRefactoring : InteractiveRefactoringBase c.Declaration == target); selected.EncapsulateFlag = true; @@ -115,7 +115,7 @@ private string PreviewRewrite(EncapsulateFieldModel model) previewSession = RefactorRewrite(model, previewSession, true); - return previewSession.CreatePreview(_targetQMN); + return previewSession.CreatePreview(model.QualifiedModuleName); } private IEncapsulateFieldRewriteSession RefactorRewrite(EncapsulateFieldModel model, IEncapsulateFieldRewriteSession refactorRewriteSession, bool asPreview = false) diff --git a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceBaseRefactoring.cs b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceBaseRefactoring.cs new file mode 100644 index 0000000000..d77d08bc93 --- /dev/null +++ b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceBaseRefactoring.cs @@ -0,0 +1,102 @@ +using System; +using System.Linq; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.Refactorings.AddInterfaceImplementations; +using Rubberduck.VBEditor.SafeComWrappers; + +namespace Rubberduck.Refactorings.ExtractInterface +{ + public class ExtractInterfaceBaseRefactoring : BaseRefactoringWithSuspensionBase + { + private readonly ICodeOnlyBaseRefactoring _addImplementationsRefactoring; + private readonly IDeclarationFinderProvider _declarationFinderProvider; + + public ExtractInterfaceBaseRefactoring( + AddInterFaceImplementationsBaseRefactoring addImplementationsRefactoring, + IDeclarationFinderProvider declarationFinderProvider, + IParseManager parseManager, + IRewritingManager rewritingManager) + : base(parseManager, rewritingManager) + { + _addImplementationsRefactoring = addImplementationsRefactoring; + _declarationFinderProvider = declarationFinderProvider; + } + + protected override bool RequiresSuspension(ExtractInterfaceModel model) + { + return true; + } + + protected override void Refactor(ExtractInterfaceModel model, IRewriteSession rewriteSession) + { + AddInterface(model, rewriteSession); + } + + private void AddInterface(ExtractInterfaceModel model, IRewriteSession rewriteSession) + { + var targetProject = model.TargetDeclaration.Project; + if (targetProject == null) + { + return; //The target project is not available. + } + + AddInterfaceClass(model.TargetDeclaration, model.InterfaceName, GetInterfaceModuleBody(model)); + + var rewriter = rewriteSession.CheckOutModuleRewriter(model.TargetDeclaration.QualifiedModuleName); + + var firstNonFieldMember = _declarationFinderProvider.DeclarationFinder.Members(model.TargetDeclaration) + .OrderBy(o => o.Selection) + .First(m => ExtractInterfaceModel.MemberTypes.Contains(m.DeclarationType)); + rewriter.InsertBefore(firstNonFieldMember.Context.Start.TokenIndex, $"Implements {model.InterfaceName}{Environment.NewLine}{Environment.NewLine}"); + + AddInterfaceMembersToClass(model, rewriteSession); + } + + private void AddInterfaceClass(Declaration implementingClass, string interfaceName, string interfaceBody) + { + var targetProject = implementingClass.Project; + using (var components = targetProject.VBComponents) + { + using (var interfaceComponent = components.Add(ComponentType.ClassModule)) + { + using (var interfaceModule = interfaceComponent.CodeModule) + { + interfaceComponent.Name = interfaceName; + + var optionPresent = interfaceModule.CountOfLines > 1; + if (!optionPresent) + { + interfaceModule.InsertLines(1, $"{Tokens.Option} {Tokens.Explicit}{Environment.NewLine}"); + } + interfaceModule.InsertLines(3, interfaceBody); + } + } + } + } + + private void AddInterfaceMembersToClass(ExtractInterfaceModel model, IRewriteSession rewriteSession) + { + var targetModule = model.TargetDeclaration.QualifiedModuleName; + var interfaceName = model.InterfaceName; + var membersToImplement = model.SelectedMembers.Select(m => m.Member).ToList(); + + var addMembersModel = new AddInterfaceImplementationsModel(targetModule, interfaceName, membersToImplement); + _addImplementationsRefactoring.Refactor(addMembersModel, rewriteSession); + } + + private static string GetInterfaceModuleBody(ExtractInterfaceModel model) + { + return string.Join(Environment.NewLine, model.SelectedMembers.Select(m => m.Body)); + } + + private static readonly DeclarationType[] ModuleTypes = + { + DeclarationType.ClassModule, + DeclarationType.Document, + DeclarationType.UserForm + }; + } +} \ No newline at end of file diff --git a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs index 6745a264e8..fc4c22f781 100644 --- a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs +++ b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs @@ -1,7 +1,4 @@ -using System; -using System.Linq; -using System.Runtime.ExceptionServices; -using NLog; +using System.Linq; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Rewriter; @@ -9,37 +6,36 @@ using Rubberduck.Parsing.UIContext; using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings.Exceptions; -using Rubberduck.Refactorings.ImplementInterface; using Rubberduck.VBEditor; -using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.Utility; namespace Rubberduck.Refactorings.ExtractInterface { public class ExtractInterfaceRefactoring : InteractiveRefactoringBase { + private readonly IBaseRefactoring _baseRefactoring; private readonly IDeclarationFinderProvider _declarationFinderProvider; - private readonly IParseManager _parseManager; - - private readonly ImplementInterfaceRefactoring _implementInterfaceRefactoring; - - private readonly Logger _logger = LogManager.GetCurrentClassLogger(); public ExtractInterfaceRefactoring( + ExtractInterfaceBaseRefactoring baseRefactoring, IDeclarationFinderProvider declarationFinderProvider, - IParseManager parseManager, IRefactoringPresenterFactory factory, IRewritingManager rewritingManager, ISelectionProvider selectionProvider, IUiDispatcher uiDispatcher) :base(rewritingManager, selectionProvider, factory, uiDispatcher) { + _baseRefactoring = baseRefactoring; _declarationFinderProvider = declarationFinderProvider; - _parseManager = parseManager; - - _implementInterfaceRefactoring = new ImplementInterfaceRefactoring(_declarationFinderProvider, RewritingManager, SelectionProvider); } + private static readonly DeclarationType[] ModuleTypes = + { + DeclarationType.ClassModule, + DeclarationType.Document, + DeclarationType.UserForm + }; + protected override Declaration FindTargetDeclaration(QualifiedSelection targetSelection) { var candidates = _declarationFinderProvider.DeclarationFinder @@ -67,93 +63,9 @@ protected override ExtractInterfaceModel InitializeModel(Declaration target) protected override void RefactorImpl(ExtractInterfaceModel model) { - AddInterfaceWithSuspendedParser(model); - } - - private void AddInterfaceWithSuspendedParser(ExtractInterfaceModel model) - { - //We need to suspend here since adding the interface and rewriting will both trigger a reparse. - var suspendResult = _parseManager.OnSuspendParser(this, new[] {ParserState.Ready}, () => AddInterface(model)); - var suspendOutcome = suspendResult.Outcome; - if (suspendOutcome != SuspensionOutcome.Completed) - { - if ((suspendOutcome == SuspensionOutcome.UnexpectedError || suspendOutcome == SuspensionOutcome.Canceled) - && suspendResult.EncounteredException != null) - { - ExceptionDispatchInfo.Capture(suspendResult.EncounteredException).Throw(); - return; - } - - _logger.Warn($"{nameof(AddInterface)} failed because a parser suspension request could not be fulfilled. The request's result was '{suspendResult.ToString()}'."); - throw new SuspendParserFailureException(); - } + _baseRefactoring.Refactor(model); } - private void AddInterface(ExtractInterfaceModel model) - { - var targetProject = model.TargetDeclaration.Project; - if (targetProject == null) - { - return; //The target project is not available. - } - - AddInterfaceClass(model.TargetDeclaration, model.InterfaceName, GetInterfaceModuleBody(model)); - - var rewriteSession = RewritingManager.CheckOutCodePaneSession(); - var rewriter = rewriteSession.CheckOutModuleRewriter(model.TargetDeclaration.QualifiedModuleName); - - var firstNonFieldMember = _declarationFinderProvider.DeclarationFinder.Members(model.TargetDeclaration) - .OrderBy(o => o.Selection) - .First(m => ExtractInterfaceModel.MemberTypes.Contains(m.DeclarationType)); - rewriter.InsertBefore(firstNonFieldMember.Context.Start.TokenIndex, $"Implements {model.InterfaceName}{Environment.NewLine}{Environment.NewLine}"); - - AddInterfaceMembersToClass(model, rewriter); - - if (!rewriteSession.TryRewrite()) - { - throw new RewriteFailedException(rewriteSession); - } - } - - private void AddInterfaceClass(Declaration implementingClass, string interfaceName, string interfaceBody) - { - var targetProject = implementingClass.Project; - using (var components = targetProject.VBComponents) - { - using (var interfaceComponent = components.Add(ComponentType.ClassModule)) - { - using (var interfaceModule = interfaceComponent.CodeModule) - { - interfaceComponent.Name = interfaceName; - - var optionPresent = interfaceModule.CountOfLines > 1; - if (!optionPresent) - { - interfaceModule.InsertLines(1, $"{Tokens.Option} {Tokens.Explicit}{Environment.NewLine}"); - } - interfaceModule.InsertLines(3, interfaceBody); - } - } - } - } - - private void AddInterfaceMembersToClass(ExtractInterfaceModel model, IModuleRewriter rewriter) - { - _implementInterfaceRefactoring.Refactor(model.SelectedMembers.Select(m => m.Member).ToList(), rewriter, model.InterfaceName); - } - - private string GetInterfaceModuleBody(ExtractInterfaceModel model) - { - return string.Join(Environment.NewLine, model.SelectedMembers.Select(m => m.Body)); - } - - private static readonly DeclarationType[] ModuleTypes = - { - DeclarationType.ClassModule, - DeclarationType.Document, - DeclarationType.UserForm - }; - //TODO: Redesign how refactoring commands are wired up to make this a responsibility of the command again. public bool CanExecute(RubberduckParserState state, QualifiedModuleName qualifiedName) { diff --git a/Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterFaceImplementationsBaseRefactoring.cs b/Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterFaceImplementationsBaseRefactoring.cs new file mode 100644 index 0000000000..4736157a82 --- /dev/null +++ b/Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterFaceImplementationsBaseRefactoring.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Refactorings.ImplementInterface; + +namespace Rubberduck.Refactorings.AddInterfaceImplementations +{ + public class AddInterFaceImplementationsBaseRefactoring : CodeOnlyBaseRefactoringBase + { + private const string MemberBody = " Err.Raise 5 'TODO implement interface member"; + + public AddInterFaceImplementationsBaseRefactoring(IRewritingManager rewritingManager) + : base(rewritingManager) + {} + + public override void Refactor(AddInterfaceImplementationsModel model, IRewriteSession rewriteSession) + { + var rewriter = rewriteSession.CheckOutModuleRewriter(model.TargetModule); + AddItems(model.Members, rewriter, model.InterfaceName); + } + + private void AddItems(IEnumerable missingMembers, IModuleRewriter rewriter, string interfaceName) + { + var missingMembersText = missingMembers + .Aggregate(string.Empty, (current, member) => current + Environment.NewLine + GetInterfaceMember(member, interfaceName)); + + rewriter.InsertAfter(rewriter.TokenStream.Size, Environment.NewLine + missingMembersText); + } + + private string GetInterfaceMember(Declaration member, string interfaceName) + { + var template = string.Join(Environment.NewLine, Tokens.Private + " {0}{1} {2}{3}", MemberBody, Tokens.End + " {0}", string.Empty); + var signature = $"{interfaceName}_{member.IdentifierName}({string.Join(", ", GetParameters(member))})"; + var asType = $" {Tokens.As} {member.AsTypeName}"; + + switch (member.DeclarationType) + { + case DeclarationType.Procedure: + return string.Format(template, Tokens.Sub, string.Empty, signature, string.Empty); + case DeclarationType.Function: + return string.Format(template, Tokens.Function, string.Empty, signature, asType); + case DeclarationType.PropertyGet: + return string.Format(template, Tokens.Property, $" {Tokens.Get}", signature, asType); + case DeclarationType.PropertyLet: + return string.Format(template, Tokens.Property, $" {Tokens.Let}", signature, string.Empty); + case DeclarationType.PropertySet: + return string.Format(template, Tokens.Property, $" {Tokens.Set}", signature, string.Empty); + case DeclarationType.Variable: + var members = new List + { + string.Format(template, Tokens.Property, $" {Tokens.Get}", $"{interfaceName}_{member.IdentifierName}()", asType) + }; + + if (member.AsTypeName.Equals(Tokens.Variant) || !member.IsObject) + { + members.Add(string.Format(template, Tokens.Property, $" {Tokens.Let}", signature, string.Empty)); + } + + if (member.AsTypeName.Equals(Tokens.Variant) || member.IsObject) + { + members.Add(string.Format(template, Tokens.Property, $" {Tokens.Set}", signature, string.Empty)); + } + + return string.Join(Environment.NewLine, members); + } + + return string.Empty; + } + + private IEnumerable GetParameters(Declaration member) + { + if (member.DeclarationType == DeclarationType.Variable) + { + return new List + { + new Parameter + { + Accessibility = Tokens.ByVal, + Name = "rhs", + AsTypeName = member.AsTypeName + } + }; + } + + return ((ModuleBodyElementDeclaration)member).Parameters.Select(p => new Parameter + { + Accessibility = ((VBAParser.ArgContext)p.Context).BYVAL() != null + ? Tokens.ByVal + : Tokens.ByRef, + Name = p.IdentifierName, + AsTypeName = p.AsTypeName + }); + } + } +} \ No newline at end of file diff --git a/Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterfaceImplementationsModel.cs b/Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterfaceImplementationsModel.cs new file mode 100644 index 0000000000..98beb472ce --- /dev/null +++ b/Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterfaceImplementationsModel.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using Rubberduck.Parsing.Symbols; +using Rubberduck.VBEditor; + +namespace Rubberduck.Refactorings.AddInterfaceImplementations +{ + public class AddInterfaceImplementationsModel : IRefactoringModel + { + public QualifiedModuleName TargetModule { get; } + public string InterfaceName { get; } + public IList Members { get; } + + public AddInterfaceImplementationsModel(QualifiedModuleName targetModule, string interfaceName, IList members) + { + TargetModule = targetModule; + InterfaceName = interfaceName; + Members = members; + } + } +} \ No newline at end of file diff --git a/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceBaseRefactoring.cs b/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceBaseRefactoring.cs new file mode 100644 index 0000000000..abfb361559 --- /dev/null +++ b/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceBaseRefactoring.cs @@ -0,0 +1,41 @@ +using System.Linq; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Refactorings.AddInterfaceImplementations; + +namespace Rubberduck.Refactorings.ImplementInterface +{ + public class ImplementInterfaceBaseRefactoring : BaseRefactoringBase + { + private readonly ICodeOnlyBaseRefactoring _addImplementationsRefactoring; + + public ImplementInterfaceBaseRefactoring( + AddInterFaceImplementationsBaseRefactoring addImplementationsRefactoring, + IRewritingManager rewritingManager) + : base(rewritingManager) + { + _addImplementationsRefactoring = addImplementationsRefactoring; + } + + protected override void Refactor(ImplementInterfaceModel model, IRewriteSession rewriteSession) + { + ImplementMissingMembers(model.TargetInterface, model.TargetClass, rewriteSession); + } + + private void ImplementMissingMembers(ModuleDeclaration targetInterface, ModuleDeclaration targetClass, IRewriteSession rewriteSession) + { + var implemented = targetClass.Members + .Where(decl => decl is ModuleBodyElementDeclaration member && ReferenceEquals(member.InterfaceImplemented, targetInterface)) + .Cast() + .Select(member => member.InterfaceMemberImplemented).ToList(); + + var interfaceMembers = targetInterface.Members.OrderBy(member => member.Selection.StartLine) + .ThenBy(member => member.Selection.StartColumn); + + var nonImplementedMembers = interfaceMembers.Where(member => !implemented.Contains(member)); + + var addMembersModel = new AddInterfaceImplementationsModel(targetClass.QualifiedModuleName, targetInterface.IdentifierName, nonImplementedMembers.ToList()); + _addImplementationsRefactoring.Refactor(addMembersModel, rewriteSession); + } + } +} \ No newline at end of file diff --git a/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceModel.cs b/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceModel.cs new file mode 100644 index 0000000000..055204c19e --- /dev/null +++ b/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceModel.cs @@ -0,0 +1,16 @@ +using Rubberduck.Parsing.Symbols; + +namespace Rubberduck.Refactorings.ImplementInterface +{ + public class ImplementInterfaceModel : IRefactoringModel + { + public ClassModuleDeclaration TargetInterface { get; } + public ClassModuleDeclaration TargetClass { get; } + + public ImplementInterfaceModel(ClassModuleDeclaration targetInterface, ClassModuleDeclaration targetClass) + { + TargetInterface = targetInterface; + TargetClass = targetClass; + } + } +} \ No newline at end of file diff --git a/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceRefactoring.cs b/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceRefactoring.cs index 0a80552b8b..2a967ecbbd 100644 --- a/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceRefactoring.cs +++ b/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceRefactoring.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; @@ -14,16 +13,17 @@ namespace Rubberduck.Refactorings.ImplementInterface { public class ImplementInterfaceRefactoring : RefactoringBase { + private readonly IBaseRefactoring _baseRefactoring; private readonly IDeclarationFinderProvider _declarationFinderProvider; - private const string MemberBody = " Err.Raise 5 'TODO implement interface member"; - public ImplementInterfaceRefactoring( + ImplementInterfaceBaseRefactoring baseRefactoring, IDeclarationFinderProvider declarationFinderProvider, IRewritingManager rewritingManager, ISelectionProvider selectionProvider) :base(rewritingManager, selectionProvider) { + _baseRefactoring = baseRefactoring; _declarationFinderProvider = declarationFinderProvider; } @@ -60,116 +60,23 @@ public override void Refactor(QualifiedSelection target) throw new InvalidTargetDeclarationException(targetModule); } - var rewriteSession = RewritingManager.CheckOutCodePaneSession(); - var rewriter = rewriteSession.CheckOutModuleRewriter(targetClass.QualifiedModuleName); - ImplementMissingMembers(targetInterface, targetClass, rewriter); - if (!rewriteSession.TryRewrite()) - { - throw new RewriteFailedException(rewriteSession); - } + var model = Model(targetInterface, targetClass); + _baseRefactoring.Refactor(model); } - protected override Declaration FindTargetDeclaration(QualifiedSelection targetSelection) + private static ImplementInterfaceModel Model(ClassModuleDeclaration targetInterface, ClassModuleDeclaration targetClass) { - throw new NotSupportedException(); + return new ImplementInterfaceModel(targetInterface, targetClass); } - public override void Refactor(Declaration target) + protected override Declaration FindTargetDeclaration(QualifiedSelection targetSelection) { throw new NotSupportedException(); } - internal void Refactor(List members, IModuleRewriter rewriter, string interfaceName) - { - AddItems(members, rewriter, interfaceName); - } - - private void ImplementMissingMembers(ModuleDeclaration targetInterface, ModuleDeclaration targetClass, IModuleRewriter rewriter) - { - var implemented = targetClass.Members - .Where(decl => decl is ModuleBodyElementDeclaration member && ReferenceEquals(member.InterfaceImplemented, targetInterface)) - .Cast() - .Select(member => member.InterfaceMemberImplemented).ToList(); - - var interfaceMembers = targetInterface.Members.OrderBy(member => member.Selection.StartLine) - .ThenBy(member => member.Selection.StartColumn); - - var nonImplementedMembers = interfaceMembers.Where(member => !implemented.Contains(member)); - - AddItems(nonImplementedMembers, rewriter, targetInterface.IdentifierName); - } - - private void AddItems(IEnumerable missingMembers, IModuleRewriter rewriter, string interfaceName) - { - var missingMembersText = missingMembers.Aggregate(string.Empty, - (current, member) => current + Environment.NewLine + GetInterfaceMember(member, interfaceName)); - - rewriter.InsertAfter(rewriter.TokenStream.Size, Environment.NewLine + missingMembersText); - } - - private string GetInterfaceMember(Declaration member, string interfaceName) - { - var template = string.Join(Environment.NewLine, Tokens.Private + " {0}{1} {2}{3}", MemberBody, Tokens.End + " {0}", string.Empty); - var signature = $"{interfaceName}_{member.IdentifierName}({string.Join(", ", GetParameters(member))})"; - var asType = $" {Tokens.As} {member.AsTypeName}"; - - switch (member.DeclarationType) - { - case DeclarationType.Procedure: - return string.Format(template, Tokens.Sub, string.Empty, signature, string.Empty); - case DeclarationType.Function: - return string.Format(template, Tokens.Function, string.Empty, signature, asType); - case DeclarationType.PropertyGet: - return string.Format(template, Tokens.Property, $" {Tokens.Get}", signature, asType); - case DeclarationType.PropertyLet: - return string.Format(template, Tokens.Property, $" {Tokens.Let}", signature, string.Empty); - case DeclarationType.PropertySet: - return string.Format(template, Tokens.Property, $" {Tokens.Set}", signature, string.Empty); - case DeclarationType.Variable: - var members = new List - { - string.Format(template, Tokens.Property, $" {Tokens.Get}", $"{interfaceName}_{member.IdentifierName}()", asType) - }; - - if (member.AsTypeName.Equals(Tokens.Variant) || !member.IsObject) - { - members.Add(string.Format(template, Tokens.Property, $" {Tokens.Let}", signature, string.Empty)); - } - - if (member.AsTypeName.Equals(Tokens.Variant) || member.IsObject) - { - members.Add(string.Format(template, Tokens.Property, $" {Tokens.Set}", signature, string.Empty)); - } - - return string.Join(Environment.NewLine, members); - } - - return string.Empty; - } - - private IEnumerable GetParameters(Declaration member) + public override void Refactor(Declaration target) { - if (member.DeclarationType == DeclarationType.Variable) - { - return new List - { - new Parameter - { - Accessibility = Tokens.ByVal, - Name = "rhs", - AsTypeName = member.AsTypeName - } - }; - } - - return ((ModuleBodyElementDeclaration) member).Parameters.Select(p => new Parameter - { - Accessibility = ((VBAParser.ArgContext) p.Context).BYVAL() != null - ? Tokens.ByVal - : Tokens.ByRef, - Name = p.IdentifierName, - AsTypeName = p.AsTypeName - }); + throw new NotSupportedException(); } } } diff --git a/Rubberduck.Refactorings/IntroduceField/IntroduceFieldBaseRefactoring.cs b/Rubberduck.Refactorings/IntroduceField/IntroduceFieldBaseRefactoring.cs new file mode 100644 index 0000000000..edcfbacd63 --- /dev/null +++ b/Rubberduck.Refactorings/IntroduceField/IntroduceFieldBaseRefactoring.cs @@ -0,0 +1,40 @@ +using System; +using System.Linq; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; + +namespace Rubberduck.Refactorings.IntroduceField +{ + public class IntroduceFieldBaseRefactoring : BaseRefactoringBase + { + private readonly IDeclarationFinderProvider _declarationFinderProvider; + + public IntroduceFieldBaseRefactoring(IDeclarationFinderProvider declarationFinderProvider, + IRewritingManager rewritingManager) + : base(rewritingManager) + { + _declarationFinderProvider = declarationFinderProvider; + } + + protected override void Refactor(IntroduceFieldModel model, IRewriteSession rewriteSession) + { + var target = model.Target; + var rewriter = rewriteSession.CheckOutModuleRewriter(target.QualifiedModuleName); + rewriter.Remove(target); + AddField(rewriter, target); + } + + private void AddField(IModuleRewriter rewriter, Declaration target) + { + var content = $"{Tokens.Private} {target.IdentifierName} {Tokens.As} {target.AsTypeName}{Environment.NewLine}"; + var members = _declarationFinderProvider.DeclarationFinder + .Members(target.QualifiedName.QualifiedModuleName, DeclarationType.Member) + .OrderBy(item => item.Selection); + + var firstMember = members.FirstOrDefault(); + rewriter.InsertBefore(firstMember?.Context.Start.TokenIndex ?? 0, content); + } + } +} \ No newline at end of file diff --git a/Rubberduck.Refactorings/IntroduceField/IntroduceFieldModel.cs b/Rubberduck.Refactorings/IntroduceField/IntroduceFieldModel.cs new file mode 100644 index 0000000000..a95bbc5f16 --- /dev/null +++ b/Rubberduck.Refactorings/IntroduceField/IntroduceFieldModel.cs @@ -0,0 +1,14 @@ +using Rubberduck.Parsing.Symbols; + +namespace Rubberduck.Refactorings.IntroduceField +{ + public class IntroduceFieldModel : IRefactoringModel + { + public Declaration Target { get; } + + public IntroduceFieldModel(Declaration target) + { + Target = target; + } + } +} \ No newline at end of file diff --git a/Rubberduck.Refactorings/IntroduceField/IntroduceFieldRefactoring.cs b/Rubberduck.Refactorings/IntroduceField/IntroduceFieldRefactoring.cs index 60b8639cb6..f7063e82d4 100644 --- a/Rubberduck.Refactorings/IntroduceField/IntroduceFieldRefactoring.cs +++ b/Rubberduck.Refactorings/IntroduceField/IntroduceFieldRefactoring.cs @@ -1,7 +1,4 @@ -using System; -using System.Linq; -using Rubberduck.Common; -using Rubberduck.Parsing.Grammar; +using System.Linq; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; @@ -14,17 +11,17 @@ namespace Rubberduck.Refactorings.IntroduceField { public class IntroduceFieldRefactoring : RefactoringBase { - private readonly IDeclarationFinderProvider _declarationFinderProvider; + private readonly IBaseRefactoring _baseRefactoring; private readonly ISelectedDeclarationProvider _selectedDeclarationProvider; public IntroduceFieldRefactoring( - IDeclarationFinderProvider declarationFinderProvider, + IntroduceFieldBaseRefactoring baseRefactoring, IRewritingManager rewritingManager, ISelectionProvider selectionProvider, ISelectedDeclarationProvider selectedDeclarationProvider) :base(rewritingManager, selectionProvider) { - _declarationFinderProvider = declarationFinderProvider; + _baseRefactoring = baseRefactoring; _selectedDeclarationProvider = selectedDeclarationProvider; } @@ -62,27 +59,13 @@ public override void Refactor(Declaration target) private void PromoteVariable(Declaration target) { - var rewriteSession = RewritingManager.CheckOutCodePaneSession(); - var rewriter = rewriteSession.CheckOutModuleRewriter(target.QualifiedModuleName); - - rewriter.Remove(target); - AddField(rewriter, target); - - if (!rewriteSession.TryRewrite()) - { - throw new RewriteFailedException(rewriteSession); - } + var model = Model(target); + _baseRefactoring.Refactor(model); } - private void AddField(IModuleRewriter rewriter, Declaration target) + private static IntroduceFieldModel Model(Declaration target) { - var content = $"{Tokens.Private} {target.IdentifierName} {Tokens.As} {target.AsTypeName}{Environment.NewLine}"; - var members = _declarationFinderProvider.DeclarationFinder.Members(target.QualifiedName.QualifiedModuleName) - .Where(item => item.DeclarationType.HasFlag(DeclarationType.Member)) - .OrderBy(item => item.Selection); - - var firstMember = members.FirstOrDefault(); - rewriter.InsertBefore(firstMember?.Context.Start.TokenIndex ?? 0, content); + return new IntroduceFieldModel(target); } } } diff --git a/Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterBaseRefactoring.cs b/Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterBaseRefactoring.cs new file mode 100644 index 0000000000..ea5e2b07a9 --- /dev/null +++ b/Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterBaseRefactoring.cs @@ -0,0 +1,139 @@ +using System.Collections.Generic; +using System.Linq; +using Rubberduck.Parsing; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; + +namespace Rubberduck.Refactorings.IntroduceParameter +{ + public class IntroduceParameterBaseRefactoring : BaseRefactoringBase + { + private readonly IDeclarationFinderProvider _declarationFinderProvider; + + public IntroduceParameterBaseRefactoring(IDeclarationFinderProvider declarationFinderProvider, IRewritingManager rewritingManager) + : base(rewritingManager) + { + _declarationFinderProvider = declarationFinderProvider; + } + + protected override void Refactor(IntroduceParameterModel model, IRewriteSession rewriteSession) + { + var target = model.Target; + UpdateSignature(target, model.EnclosingMember, rewriteSession); + RemoveTarget(target, rewriteSession); + } + + private static void RemoveTarget(Declaration target, IRewriteSession rewriteSession) + { + var rewriter = rewriteSession.CheckOutModuleRewriter(target.QualifiedModuleName); + rewriter.Remove(target); + } + + private void UpdateSignature(Declaration targetVariable, ModuleBodyElementDeclaration enclosingMember, IRewriteSession rewriteSession) + { + var paramList = enclosingMember.Context.GetChild(); + + if (enclosingMember.DeclarationType.HasFlag(DeclarationType.Property)) + { + UpdateProperties(enclosingMember, targetVariable, rewriteSession); + } + else + { + AddParameter(enclosingMember, targetVariable, paramList, rewriteSession); + } + + var interfaceImplementation = enclosingMember.InterfaceMemberImplemented; + + if (interfaceImplementation == null) + { + return; + } + + UpdateSignature(interfaceImplementation, targetVariable, rewriteSession); + + var interfaceImplementations = _declarationFinderProvider.DeclarationFinder.FindInterfaceImplementationMembers(enclosingMember.InterfaceMemberImplemented) + .Where(member => !ReferenceEquals(member, enclosingMember)); + + foreach (var implementation in interfaceImplementations) + { + UpdateSignature(implementation, targetVariable, rewriteSession); + } + } + + private void UpdateSignature(Declaration targetMethod, Declaration targetVariable, IRewriteSession rewriteSession) + { + var proc = (dynamic)targetMethod.Context; + var paramList = (VBAParser.ArgListContext)proc.argList(); + AddParameter(targetMethod, targetVariable, paramList, rewriteSession); + } + + private void AddParameter(Declaration targetMethod, Declaration targetVariable, VBAParser.ArgListContext paramList, IRewriteSession rewriteSession) + { + var rewriter = rewriteSession.CheckOutModuleRewriter(targetMethod.QualifiedModuleName); + + var argList = paramList.arg(); + var newParameter = $"{Tokens.ByVal} {targetVariable.IdentifierName} {Tokens.As} {targetVariable.AsTypeName}"; + + if (!argList.Any()) + { + rewriter.InsertBefore(paramList.RPAREN().Symbol.TokenIndex, newParameter); + } + else if (targetMethod.DeclarationType != DeclarationType.PropertyLet && + targetMethod.DeclarationType != DeclarationType.PropertySet) + { + rewriter.InsertBefore(paramList.RPAREN().Symbol.TokenIndex, $", {newParameter}"); + } + else + { + var lastParam = argList.Last(); + rewriter.InsertBefore(lastParam.Start.TokenIndex, $"{newParameter}, "); + } + } + + private void UpdateProperties(Declaration knownProperty, Declaration targetVariable, IRewriteSession rewriteSession) + { + var declarationFinder = _declarationFinderProvider.DeclarationFinder; + + var propertyGet = declarationFinder.UserDeclarations(DeclarationType.PropertyGet) + .FirstOrDefault(d => + d.QualifiedModuleName.Equals(knownProperty.QualifiedModuleName) + && d.IdentifierName == knownProperty.IdentifierName); + + var propertyLet = declarationFinder.UserDeclarations(DeclarationType.PropertyLet) + .FirstOrDefault(d => + d.QualifiedModuleName.Equals(knownProperty.QualifiedModuleName) + && d.IdentifierName == knownProperty.IdentifierName); + + var propertySet = declarationFinder.UserDeclarations(DeclarationType.PropertySet) + .FirstOrDefault(d => + d.QualifiedModuleName.Equals(knownProperty.QualifiedModuleName) + && d.IdentifierName == knownProperty.IdentifierName); + + var properties = new List(); + + if (propertyGet != null) + { + properties.Add(propertyGet); + } + + if (propertyLet != null) + { + properties.Add(propertyLet); + } + + if (propertySet != null) + { + properties.Add(propertySet); + } + + foreach (var property in + properties.OrderByDescending(o => o.Selection.StartLine) + .ThenByDescending(t => t.Selection.StartColumn)) + { + UpdateSignature(property, targetVariable, rewriteSession); + } + } + } +} \ No newline at end of file diff --git a/Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterModel.cs b/Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterModel.cs new file mode 100644 index 0000000000..507b4f2c5f --- /dev/null +++ b/Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterModel.cs @@ -0,0 +1,16 @@ +using Rubberduck.Parsing.Symbols; + +namespace Rubberduck.Refactorings.IntroduceParameter +{ + public class IntroduceParameterModel : IRefactoringModel + { + public Declaration Target { get; } + public ModuleBodyElementDeclaration EnclosingMember { get; } + + public IntroduceParameterModel(Declaration target, ModuleBodyElementDeclaration enclosingMember) + { + Target = target; + EnclosingMember = enclosingMember; + } + } +} \ No newline at end of file diff --git a/Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterRefactoring.cs b/Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterRefactoring.cs index dc3e26d41b..d5ba1f8dea 100644 --- a/Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterRefactoring.cs +++ b/Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterRefactoring.cs @@ -16,19 +16,19 @@ namespace Rubberduck.Refactorings.IntroduceParameter { public class IntroduceParameterRefactoring : RefactoringBase { - private readonly IDeclarationFinderProvider _declarationFinderProvider; + private readonly IBaseRefactoring _baseRefactoring; private readonly ISelectedDeclarationProvider _selectedDeclarationProvider; private readonly IMessageBox _messageBox; public IntroduceParameterRefactoring( - IDeclarationFinderProvider declarationFinderProvider, + IntroduceParameterBaseRefactoring baseRefactoring, IMessageBox messageBox, IRewritingManager rewritingManager, ISelectionProvider selectionProvider, ISelectedDeclarationProvider selectedDeclarationProvider) :base(rewritingManager, selectionProvider) { - _declarationFinderProvider = declarationFinderProvider; + _baseRefactoring = baseRefactoring; _selectedDeclarationProvider = selectedDeclarationProvider; _messageBox = messageBox; } @@ -72,16 +72,14 @@ private void PromoteVariable(Declaration target) return; } - var rewriteSession = RewritingManager.CheckOutCodePaneSession(); - var rewriter = rewriteSession.CheckOutModuleRewriter(target.QualifiedModuleName); - - UpdateSignature(target, rewriteSession); - rewriter.Remove(target); + var model = Model(target); + _baseRefactoring.Refactor(model); + } - if (!rewriteSession.TryRewrite()) - { - throw new RewriteFailedException(rewriteSession); - } + private IntroduceParameterModel Model(Declaration target) + { + var enclosingMember = _selectedDeclarationProvider.SelectedMember(target.QualifiedSelection); + return new IntroduceParameterModel(target, enclosingMember); } private bool PromptIfMethodImplementsInterface(Declaration targetVariable) @@ -106,111 +104,5 @@ private bool PromptIfMethodImplementsInterface(Declaration targetVariable) return _messageBox.Question(message, RubberduckUI.IntroduceParameter_Caption); } - - private void UpdateSignature(Declaration targetVariable, IRewriteSession rewriteSession) - { - var functionDeclaration = _selectedDeclarationProvider.SelectedMember(targetVariable.QualifiedSelection); - var paramList = functionDeclaration.Context.GetChild(); - - if (functionDeclaration.DeclarationType.HasFlag(DeclarationType.Property)) - { - UpdateProperties(functionDeclaration, targetVariable, rewriteSession); - } - else - { - AddParameter(functionDeclaration, targetVariable, paramList, rewriteSession); - } - - var interfaceImplementation = functionDeclaration.InterfaceMemberImplemented; - - if (interfaceImplementation == null) - { - return; - } - - UpdateSignature(interfaceImplementation, targetVariable, rewriteSession); - - var interfaceImplementations = _declarationFinderProvider.DeclarationFinder.FindInterfaceImplementationMembers(functionDeclaration.InterfaceMemberImplemented) - .Where(member => !ReferenceEquals(member, functionDeclaration)); - - foreach (var implementation in interfaceImplementations) - { - UpdateSignature(implementation, targetVariable, rewriteSession); - } - } - - private void UpdateSignature(Declaration targetMethod, Declaration targetVariable, IRewriteSession rewriteSession) - { - var proc = (dynamic) targetMethod.Context; - var paramList = (VBAParser.ArgListContext) proc.argList(); - AddParameter(targetMethod, targetVariable, paramList, rewriteSession); - } - - private void AddParameter(Declaration targetMethod, Declaration targetVariable, VBAParser.ArgListContext paramList, IRewriteSession rewriteSession) - { - var rewriter = rewriteSession.CheckOutModuleRewriter(targetMethod.QualifiedModuleName); - - var argList = paramList.arg(); - var newParameter = $"{Tokens.ByVal} {targetVariable.IdentifierName} {Tokens.As} {targetVariable.AsTypeName}"; - - if (!argList.Any()) - { - rewriter.InsertBefore(paramList.RPAREN().Symbol.TokenIndex, newParameter); - } - else if (targetMethod.DeclarationType != DeclarationType.PropertyLet && - targetMethod.DeclarationType != DeclarationType.PropertySet) - { - rewriter.InsertBefore(paramList.RPAREN().Symbol.TokenIndex, $", {newParameter}"); - } - else - { - var lastParam = argList.Last(); - rewriter.InsertBefore(lastParam.Start.TokenIndex, $"{newParameter}, "); - } - } - - private void UpdateProperties(Declaration knownProperty, Declaration targetVariable, IRewriteSession rewriteSession) - { - var declarationFinder = _declarationFinderProvider.DeclarationFinder; - - var propertyGet = declarationFinder.UserDeclarations(DeclarationType.PropertyGet) - .FirstOrDefault(d => - d.QualifiedModuleName.Equals(knownProperty.QualifiedModuleName) - && d.IdentifierName == knownProperty.IdentifierName); - - var propertyLet = declarationFinder.UserDeclarations(DeclarationType.PropertyLet) - .FirstOrDefault(d => - d.QualifiedModuleName.Equals(knownProperty.QualifiedModuleName) - && d.IdentifierName == knownProperty.IdentifierName); - - var propertySet = declarationFinder.UserDeclarations(DeclarationType.PropertySet) - .FirstOrDefault(d => - d.QualifiedModuleName.Equals(knownProperty.QualifiedModuleName) - && d.IdentifierName == knownProperty.IdentifierName); - - var properties = new List(); - - if (propertyGet != null) - { - properties.Add(propertyGet); - } - - if (propertyLet != null) - { - properties.Add(propertyLet); - } - - if (propertySet != null) - { - properties.Add(propertySet); - } - - foreach (var property in - properties.OrderByDescending(o => o.Selection.StartLine) - .ThenByDescending(t => t.Selection.StartColumn)) - { - UpdateSignature(property, targetVariable, rewriteSession); - } - } } } diff --git a/Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageBaseRefactoring.cs b/Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageBaseRefactoring.cs new file mode 100644 index 0000000000..dd533a2a81 --- /dev/null +++ b/Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageBaseRefactoring.cs @@ -0,0 +1,119 @@ +using System; +using System.Linq; +using Rubberduck.Parsing; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; + +namespace Rubberduck.Refactorings.MoveCloserToUsage +{ + public class MoveCloserToUsageBaseRefactoring : BaseRefactoringBase + { + public MoveCloserToUsageBaseRefactoring(IRewritingManager rewritingManager) + : base(rewritingManager) + {} + + protected override void Refactor(MoveCloserToUsageModel model, IRewriteSession rewriteSession) + { + var target = model.Target; + InsertNewDeclaration(target, rewriteSession); + RemoveOldDeclaration(target, rewriteSession); + UpdateQualifiedCalls(target, rewriteSession); + } + + private void InsertNewDeclaration(Declaration target, IRewriteSession rewriteSession) + { + var subscripts = target.Context.GetDescendent()?.GetText() ?? string.Empty; + var identifier = target.IsArray ? $"{target.IdentifierName}({subscripts})" : target.IdentifierName; + + var newVariable = target.AsTypeContext is null + ? $"{Tokens.Dim} {identifier} {Tokens.As} {Tokens.Variant}" + : $"{Tokens.Dim} {identifier} {Tokens.As} {(target.IsSelfAssigned ? Tokens.New + " " : string.Empty)}{target.AsTypeNameWithoutArrayDesignator}"; + + var firstReference = target.References.OrderBy(r => r.Selection.StartLine).First(); + + var enclosingBlockStatement = firstReference.Context.GetAncestor(); + var insertionIndex = enclosingBlockStatement.Start.TokenIndex; + var insertCode = PaddedDeclaration(newVariable, enclosingBlockStatement); + + var rewriter = rewriteSession.CheckOutModuleRewriter(firstReference.QualifiedModuleName); + rewriter.InsertBefore(insertionIndex, insertCode); + } + + private string PaddedDeclaration(string declarationText, VBAParser.BlockStmtContext blockStmtContext) + { + if (blockStmtContext.TryGetPrecedingContext(out VBAParser.IndividualNonEOFEndOfStatementContext precedingEndOfStatement)) + { + if (precedingEndOfStatement.COLON() != null) + { + //You have been asking for it! + return $"{declarationText} : "; + } + + var labelContext = blockStmtContext.statementLabelDefinition(); + if (labelContext != null) + { + var labelAsSpace = new string(' ', labelContext.GetText().Length); + return $"{labelAsSpace}{blockStmtContext.whiteSpace()?.GetText()}{declarationText}{Environment.NewLine}"; + } + + var precedingWhitespaces = precedingEndOfStatement.whiteSpace(); + if (precedingWhitespaces != null && precedingWhitespaces.Length > 0) + { + return $"{declarationText}{Environment.NewLine}{precedingWhitespaces[0]?.GetText()}"; + } + + return $"{declarationText}{Environment.NewLine}"; + } + //This is the very first statement. In the context of this refactoring, this should not happen since we move a declaration into or inside a method. + //We will handle this edge-case nonetheless and return the result with the proper indentation for this special case. + if (blockStmtContext.TryGetPrecedingContext(out VBAParser.WhiteSpaceContext startingWhitespace)) + { + return $"{declarationText}{Environment.NewLine}{startingWhitespace?.GetText()}"; + } + + return $"{declarationText}{Environment.NewLine}"; + } + + private void RemoveOldDeclaration(Declaration target, IRewriteSession rewriteSession) + { + var rewriter = rewriteSession.CheckOutModuleRewriter(target.QualifiedModuleName); + rewriter.Remove(target); + } + + private void UpdateQualifiedCalls(Declaration target, IRewriteSession rewriteSession) + { + var references = target.References.ToList(); + var rewriter = rewriteSession.CheckOutModuleRewriter(references.First().QualifiedModuleName); + foreach (var reference in references) + { + MakeReferenceUnqualified(target, reference, rewriter); + } + } + + private void MakeReferenceUnqualified(Declaration target, IdentifierReference reference, IModuleRewriter rewriter) + { + var memberAccessContext = reference.Context.GetAncestor(); + if (memberAccessContext == null) + { + return; + } + + // member access might be to something unrelated to the rewritten target. + // check we're not accidentally overwriting some other member-access who just happens to be a parent context + if (memberAccessContext.unrestrictedIdentifier()?.GetText() != target.IdentifierName) + { + return; + } + var qualification = memberAccessContext.lExpression().GetText(); + if (!qualification.Equals(target.ComponentName, StringComparison.InvariantCultureIgnoreCase) + && !qualification.Equals(target.ProjectName, StringComparison.InvariantCultureIgnoreCase) + && !qualification.Equals($"{target.QualifiedModuleName.ProjectName}.{target.ComponentName}", StringComparison.InvariantCultureIgnoreCase)) + { + return; + } + + rewriter.Replace(memberAccessContext, reference.IdentifierName); + } + } +} \ No newline at end of file diff --git a/Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageModel.cs b/Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageModel.cs new file mode 100644 index 0000000000..333b0d8c57 --- /dev/null +++ b/Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageModel.cs @@ -0,0 +1,14 @@ +using Rubberduck.Parsing.Symbols; + +namespace Rubberduck.Refactorings.MoveCloserToUsage +{ + public class MoveCloserToUsageModel : IRefactoringModel + { + public Declaration Target { get; } + + public MoveCloserToUsageModel(Declaration target) + { + Target = target; + } + } +} \ No newline at end of file diff --git a/Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageRefactoring.cs b/Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageRefactoring.cs index 97db69f054..c4db966096 100644 --- a/Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageRefactoring.cs +++ b/Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageRefactoring.cs @@ -1,8 +1,4 @@ -using System; -using System.Linq; -using Rubberduck.Common; -using Rubberduck.Parsing; -using Rubberduck.Parsing.Grammar; +using System.Linq; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; @@ -15,16 +11,19 @@ namespace Rubberduck.Refactorings.MoveCloserToUsage { public class MoveCloserToUsageRefactoring : RefactoringBase { + private readonly IBaseRefactoring _baseRefactoring; private readonly IDeclarationFinderProvider _declarationFinderProvider; private readonly ISelectedDeclarationProvider _selectedDeclarationProvider; public MoveCloserToUsageRefactoring( + MoveCloserToUsageBaseRefactoring baseRefactoring, IDeclarationFinderProvider declarationFinderProvider, IRewritingManager rewritingManager, ISelectionProvider selectionProvider, ISelectedDeclarationProvider selectedDeclarationProvider) :base(rewritingManager, selectionProvider) { + _baseRefactoring = baseRefactoring; _declarationFinderProvider = declarationFinderProvider; _selectedDeclarationProvider = selectedDeclarationProvider; } @@ -181,113 +180,17 @@ private void CheckThatThereIsNoOtherSameNameDeclarationInScopeInReferencingMetho { throw new TargetDeclarationConflictsWithPreexistingDeclaration(target, conflictingSameNameDeclarationWithModuleScope); } - } - - private void MoveCloserToUsage(Declaration target) - { - var rewriteSession = RewritingManager.CheckOutCodePaneSession(); - InsertNewDeclaration(target, rewriteSession); - RemoveOldDeclaration(target, rewriteSession); - UpdateQualifiedCalls(target, rewriteSession); - if (!rewriteSession.TryRewrite()) - { - throw new RewriteFailedException(rewriteSession); - } } - private void InsertNewDeclaration(Declaration target, IRewriteSession rewriteSession) + private MoveCloserToUsageModel Model(Declaration target) { - var subscripts = target.Context.GetDescendent()?.GetText() ?? string.Empty; - var identifier = target.IsArray ? $"{target.IdentifierName}({subscripts})" : target.IdentifierName; - - var newVariable = target.AsTypeContext is null - ? $"{Tokens.Dim} {identifier} {Tokens.As} {Tokens.Variant}" - : $"{Tokens.Dim} {identifier} {Tokens.As} {(target.IsSelfAssigned ? Tokens.New + " " : string.Empty)}{target.AsTypeNameWithoutArrayDesignator}"; - - var firstReference = target.References.OrderBy(r => r.Selection.StartLine).First(); - - var enclosingBlockStatement = firstReference.Context.GetAncestor(); - var insertionIndex = enclosingBlockStatement.Start.TokenIndex; - var insertCode = PaddedDeclaration(newVariable, enclosingBlockStatement); - - var rewriter = rewriteSession.CheckOutModuleRewriter(firstReference.QualifiedModuleName); - rewriter.InsertBefore(insertionIndex, insertCode); - } - - private string PaddedDeclaration(string declarationText, VBAParser.BlockStmtContext blockStmtContext) - { - if (blockStmtContext.TryGetPrecedingContext(out VBAParser.IndividualNonEOFEndOfStatementContext precedingEndOfStatement)) - { - if (precedingEndOfStatement.COLON() != null) - { - //You have been asking for it! - return $"{declarationText} : "; - } - - var labelContext = blockStmtContext.statementLabelDefinition(); - if (labelContext != null) - { - var labelAsSpace = new string(' ', labelContext.GetText().Length); - return $"{labelAsSpace}{blockStmtContext.whiteSpace()?.GetText()}{declarationText}{Environment.NewLine}"; - } - - var precedingWhitespaces = precedingEndOfStatement.whiteSpace(); - if (precedingWhitespaces != null && precedingWhitespaces.Length > 0) - { - return $"{declarationText}{Environment.NewLine}{precedingWhitespaces[0]?.GetText()}"; - } - - return $"{declarationText}{Environment.NewLine}"; - } - //This is the very first statement. In the context of this refactoring, this should not happen since we move a declaration into or inside a method. - //We will handle this edge-case nonetheless and return the result with the proper indentation for this special case. - if (blockStmtContext.TryGetPrecedingContext(out VBAParser.WhiteSpaceContext startingWhitespace)) - { - return $"{declarationText}{Environment.NewLine}{startingWhitespace?.GetText()}"; - } - - return $"{declarationText}{Environment.NewLine}"; + return new MoveCloserToUsageModel(target); } - private void RemoveOldDeclaration(Declaration target, IRewriteSession rewriteSession) - { - var rewriter = rewriteSession.CheckOutModuleRewriter(target.QualifiedModuleName); - rewriter.Remove(target); - } - - private void UpdateQualifiedCalls(Declaration target, IRewriteSession rewriteSession) - { - var references = target.References.ToList(); - var rewriter = rewriteSession.CheckOutModuleRewriter(references.First().QualifiedModuleName); - foreach (var reference in references) - { - MakeReferenceUnqualified(target, reference, rewriter); - } - } - - private void MakeReferenceUnqualified(Declaration target, IdentifierReference reference, IModuleRewriter rewriter) + private void MoveCloserToUsage(Declaration target) { - var memberAccessContext = reference.Context.GetAncestor(); - if (memberAccessContext == null) - { - return; - } - - // member access might be to something unrelated to the rewritten target. - // check we're not accidentally overwriting some other member-access who just happens to be a parent context - if (memberAccessContext.unrestrictedIdentifier()?.GetText() != target.IdentifierName) - { - return; - } - var qualification = memberAccessContext.lExpression().GetText(); - if (!qualification.Equals(target.ComponentName, StringComparison.InvariantCultureIgnoreCase) - && !qualification.Equals(target.ProjectName, StringComparison.InvariantCultureIgnoreCase) - && !qualification.Equals($"{target.QualifiedModuleName.ProjectName}.{target.ComponentName}", StringComparison.InvariantCultureIgnoreCase)) - { - return; - } - - rewriter.Replace(memberAccessContext, reference.IdentifierName); + var model = Model(target); + _baseRefactoring.Refactor(model); } } } diff --git a/Rubberduck.Refactorings/RemoveParameters/RemoveParameterBaseRefactoring.cs b/Rubberduck.Refactorings/RemoveParameters/RemoveParameterBaseRefactoring.cs new file mode 100644 index 0000000000..1c8c4ea32c --- /dev/null +++ b/Rubberduck.Refactorings/RemoveParameters/RemoveParameterBaseRefactoring.cs @@ -0,0 +1,302 @@ +using System.Collections.Generic; +using System.Linq; +using Antlr4.Runtime; +using Antlr4.Runtime.Misc; +using Rubberduck.Parsing; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.VBEditor; +using Rubberduck.VBEditor.Extensions; + +namespace Rubberduck.Refactorings.RemoveParameters +{ + public class RemoveParameterBaseRefactoring : BaseRefactoringBase + { + private readonly IDeclarationFinderProvider _declarationFinderProvider; + + public RemoveParameterBaseRefactoring(IDeclarationFinderProvider declarationFinderProvider, IRewritingManager rewritingManager) + : base(rewritingManager) + { + _declarationFinderProvider = declarationFinderProvider; + } + + protected override void Refactor(RemoveParametersModel model, IRewriteSession rewriteSession) + { + AdjustReferences(model, rewriteSession); + AdjustSignatures(model, rewriteSession); + + // if we are adjusting a property getter, check if we need to adjust the letter/setter too + if (model.TargetDeclaration.DeclarationType == DeclarationType.PropertyGet) + { + var setter = GetLetterOrSetter(model.TargetDeclaration, DeclarationType.PropertySet); + if (setter != null) + { + var setterModel = ModelForNewTarget(model, setter); + Refactor(setterModel, rewriteSession); + } + + var letter = GetLetterOrSetter(model.TargetDeclaration, DeclarationType.PropertyLet); + if (letter != null) + { + var letterModel = ModelForNewTarget(model, letter); + Refactor(letterModel, rewriteSession); + } + } + + var eventImplementations = _declarationFinderProvider.DeclarationFinder + .FindEventHandlers(model.TargetDeclaration); + + foreach (var eventImplementation in eventImplementations) + { + var eventImplementationModel = ModelForNewTarget(model, eventImplementation); + AdjustReferences(eventImplementationModel, rewriteSession); + AdjustSignatures(eventImplementationModel, rewriteSession); + } + + var interfaceImplementations = _declarationFinderProvider.DeclarationFinder + .FindInterfaceImplementationMembers(model.TargetDeclaration); + + foreach (var interfaceImplementation in interfaceImplementations) + { + var interfaceImplementationModel = ModelForNewTarget(model, interfaceImplementation); + AdjustReferences(interfaceImplementationModel, rewriteSession); + AdjustSignatures(interfaceImplementationModel, rewriteSession); + } + } + + private static void AdjustReferences(RemoveParametersModel model, IRewriteSession rewriteSession) + { + var parametersToRemove = model.RemoveParameters + .Select(parameter => parameter.Declaration) + .ToList(); + var argumentReferences = ArgumentReferencesByLocation(parametersToRemove); + + foreach (var (module, moduleArgumentReferences) in argumentReferences) + { + AdjustReferences(module, moduleArgumentReferences, rewriteSession); + } + } + + private static Dictionary>> ArgumentReferencesByLocation(ICollection parameters) + { + return parameters + .SelectMany(parameterDeclaration => parameterDeclaration.ArgumentReferences) + .GroupBy(argumentReference => argumentReference.QualifiedModuleName) + .ToDictionary( + grouping => grouping.Key, + grouping => grouping + .GroupBy(reference => reference.ArgumentListSelection) + .ToDictionary(group => group.Key, group => group.ToList())); + } + + private static void AdjustReferences( + QualifiedModuleName module, + Dictionary> argumentReferences, + IRewriteSession rewriteSession) + { + var rewriter = rewriteSession.CheckOutModuleRewriter(module); + foreach (var (argumentListSelection, sameArgumentListReferences) in argumentReferences) + { + //This happens for (with) dictionary access expressions only. + if (argumentListSelection.Equals(Selection.Empty)) + { + foreach (var dictionaryAccessArgument in sameArgumentListReferences) + { + ReplaceDictionaryAccess(dictionaryAccessArgument, rewriter); + } + + continue; + } + + AdjustReferences(sameArgumentListReferences, rewriter); + } + } + + private static void ReplaceDictionaryAccess(ArgumentReference dictionaryAccessArgument, IModuleRewriter rewriter) + { + //TODO: Deal with WithDictionaryAccessExprContexts. + //This should best be handled by extracting a refactoring out of the ExpandBangNotationQuickFix and + //using it here to expand the dictionary access for both kinds of dictionary access expression. + var dictionaryAccess = dictionaryAccessArgument?.Context?.Parent as VBAParser.DictionaryAccessExprContext; + + if (dictionaryAccess == null) + { + return; + } + + var startTokenIndex = dictionaryAccess.dictionaryAccess().start.TokenIndex; + var stopTokenIndex = dictionaryAccess.unrestrictedIdentifier().stop.TokenIndex; + const string replacementString = "()"; + rewriter.Replace(new Interval(startTokenIndex, stopTokenIndex), replacementString); + } + + private static void AdjustReferences(IReadOnlyCollection argumentReferences, IModuleRewriter rewriter) + { + if (!argumentReferences.Any()) + { + return; + } + + var argumentIndicesToRemove = argumentReferences.Select(argumentReference => argumentReference.ArgumentPosition); + var argumentIndexRangesToRemove = IndexRanges(argumentIndicesToRemove); + var argumentList = argumentReferences.First().ArgumentListContext; + + var adjustedArgumentIndexRangesToRemove = WithTrailingMissingArguments(argumentIndexRangesToRemove, argumentList); + + + foreach (var (startIndex, stopIndex) in adjustedArgumentIndexRangesToRemove) + { + RemoveArgumentRange(startIndex, stopIndex, argumentList, rewriter); + } + } + + private static IEnumerable<(int startIndex, int stopIndex)> IndexRanges(IEnumerable indices) + { + var sortedIndices = indices.OrderBy(num => num).ToList(); + var ranges = new List<(int startIndex, int stopIndex)>(); + int startIndex = -10; + int stopIndex = -10; + foreach (var currentIndex in sortedIndices) + { + if (currentIndex == stopIndex + 1) + { + stopIndex = currentIndex; + } + else + { + if (startIndex >= 0) + { + ranges.Add((startIndex, stopIndex)); + } + + startIndex = currentIndex; + stopIndex = currentIndex; + } + } + + if (startIndex >= 0) + { + ranges.Add((startIndex, stopIndex)); + } + + return ranges; + } + + private static IEnumerable<(int startIndex, int stopIndex)> WithTrailingMissingArguments( + IEnumerable<(int startIndex, int stopIndex)> argumentRanges, + VBAParser.ArgumentListContext argumentList) + { + var arguments = argumentList.argument(); + var numberOfArguments = arguments.Length; + + var argumentRangesInDescendingOrder = argumentRanges.OrderByDescending(range => range.stopIndex).ToList(); + if (argumentRangesInDescendingOrder[0].stopIndex != numberOfArguments - 1) + { + return argumentRangesInDescendingOrder; + } + + var currentRangeIndex = 0; + var currentStartIndex = argumentRangesInDescendingOrder[0].startIndex; + while (currentStartIndex > 0) + { + if (currentRangeIndex + 1 < argumentRangesInDescendingOrder.Count + && currentStartIndex - 1 == argumentRangesInDescendingOrder[currentRangeIndex + 1].stopIndex) + { + currentRangeIndex++; + currentStartIndex = argumentRangesInDescendingOrder[currentRangeIndex].startIndex; + } + else if (arguments[currentStartIndex - 1]?.missingArgument() != null) + { + currentStartIndex--; + } + else + { + break; + } + } + + var newRanges = new List<(int startIndex, int stopIndex)> { (currentStartIndex, numberOfArguments - 1) }; + newRanges.AddRange(argumentRangesInDescendingOrder.Skip(currentRangeIndex + 1)); + return newRanges; + } + + private static void RemoveArgumentRange( + int startArgumentIndex, + int stopArgumentIndex, + VBAParser.ArgumentListContext argumentList, + IModuleRewriter rewriter) + { + var (startTokenIndex, stopTokenIndex) = TokenIndexRange(startArgumentIndex, stopArgumentIndex, argumentList.argument()); + rewriter.RemoveRange(startTokenIndex, stopTokenIndex); + } + + private static (int startTokenIndex, int stopTokenIndex) TokenIndexRange( + int startIndex, + int stopIndex, + IReadOnlyList contexts) + { + int startTokenIndex; + int stopTokenIndex; + + if (stopIndex == contexts.Count - 1) + { + startTokenIndex = startIndex == 0 + ? contexts[0].Start.TokenIndex + : contexts[startIndex - 1].Stop.TokenIndex + 1; + stopTokenIndex = contexts[stopIndex].Stop.TokenIndex; + return (startTokenIndex, stopTokenIndex); + } + + startTokenIndex = contexts[startIndex].Start.TokenIndex; + stopTokenIndex = contexts[stopIndex + 1].Start.TokenIndex - 1; + return (startTokenIndex, stopTokenIndex); + } + + private static void AdjustSignatures(RemoveParametersModel model, IRewriteSession rewriteSession) + { + var rewriter = rewriteSession.CheckOutModuleRewriter(model.TargetDeclaration.QualifiedModuleName); + + var parameterIndicesToRemove = model.RemoveParameters + .Select(param => model.Parameters.IndexOf(param)); + var parameterRangesToRemove = IndexRanges(parameterIndicesToRemove); + + var argList = model.Parameters.First().Declaration.Context.GetAncestor(); + + foreach (var (startIndex, stopIndex) in parameterRangesToRemove) + { + RemoveParameterRange(startIndex, stopIndex, argList, rewriter); + } + } + + private static void RemoveParameterRange( + int startArgumentIndex, + int stopArgumentIndex, + VBAParser.ArgListContext argList, + IModuleRewriter rewriter) + { + var (startTokenIndex, stopTokenIndex) = TokenIndexRange(startArgumentIndex, stopArgumentIndex, argList.arg()); + rewriter.RemoveRange(startTokenIndex, stopTokenIndex); + } + + private Declaration GetLetterOrSetter(Declaration declaration, DeclarationType declarationType) + { + return _declarationFinderProvider.DeclarationFinder + .UserDeclarations(declarationType) + .FirstOrDefault(item => item.QualifiedModuleName.Equals(declaration.QualifiedModuleName) + && item.IdentifierName == declaration.IdentifierName); + } + + private static RemoveParametersModel ModelForNewTarget(RemoveParametersModel oldModel, Declaration newTarget) + { + var newModel = new RemoveParametersModel(newTarget); + var toRemoveIndices = oldModel.RemoveParameters.Select(param => oldModel.Parameters.IndexOf(param)); + var newToRemoveParams = toRemoveIndices + .Select(index => newModel.Parameters[index]) + .ToList(); + newModel.RemoveParameters = newToRemoveParams; + return newModel; + } + } +} \ No newline at end of file diff --git a/Rubberduck.Refactorings/RemoveParameters/RemoveParametersRefactoring.cs b/Rubberduck.Refactorings/RemoveParameters/RemoveParametersRefactoring.cs index f96d98b7d7..902c65be7b 100644 --- a/Rubberduck.Refactorings/RemoveParameters/RemoveParametersRefactoring.cs +++ b/Rubberduck.Refactorings/RemoveParameters/RemoveParametersRefactoring.cs @@ -1,9 +1,4 @@ -using System.Collections.Generic; -using System.Linq; -using Antlr4.Runtime; -using Antlr4.Runtime.Misc; -using Rubberduck.Parsing; -using Rubberduck.Parsing.Grammar; +using System.Linq; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.UIContext; @@ -11,17 +6,18 @@ using Rubberduck.Refactorings.Exceptions; using Rubberduck.Refactorings.Exceptions.RemoveParameter; using Rubberduck.VBEditor; -using Rubberduck.VBEditor.Extensions; using Rubberduck.VBEditor.Utility; namespace Rubberduck.Refactorings.RemoveParameters { public class RemoveParametersRefactoring : InteractiveRefactoringBase { + private readonly IBaseRefactoring _baseRefactoring; private readonly IDeclarationFinderProvider _declarationFinderProvider; private readonly ISelectedDeclarationProvider _selectedDeclarationProvider; public RemoveParametersRefactoring( + RemoveParameterBaseRefactoring baseRefactoring, IDeclarationFinderProvider declarationFinderProvider, IRefactoringPresenterFactory factory, IRewritingManager rewritingManager, @@ -30,6 +26,7 @@ public RemoveParametersRefactoring( IUiDispatcher uiDispatcher) :base(rewritingManager, selectionProvider, factory, uiDispatcher) { + _baseRefactoring = baseRefactoring; _declarationFinderProvider = declarationFinderProvider; _selectedDeclarationProvider = selectedDeclarationProvider; } @@ -137,7 +134,12 @@ private RemoveParametersModel ResolvedGetterTarget(RemoveParametersModel model) protected override void RefactorImpl(RemoveParametersModel model) { - RemoveParameters(model); + if (model.TargetDeclaration == null) + { + throw new TargetDeclarationIsNullException(); + } + + _baseRefactoring.Refactor(model); } public void QuickFix(QualifiedSelection selection) @@ -160,301 +162,7 @@ public void QuickFix(QualifiedSelection selection) } model.RemoveParameters.Add(target); - RemoveParameters(model); - } - - private void RemoveParameters(RemoveParametersModel model) - { - if (model.TargetDeclaration == null) - { - throw new TargetDeclarationIsNullException(); - } - - var rewriteSession = RewritingManager.CheckOutCodePaneSession(); - - RemoveParameters(model, rewriteSession); - - if (!rewriteSession.TryRewrite()) - { - throw new RewriteFailedException(rewriteSession); - } - } - - private void RemoveParameters(RemoveParametersModel model, IRewriteSession rewriteSession) - { - AdjustReferences(model, rewriteSession); - AdjustSignatures(model, rewriteSession); - - // if we are adjusting a property getter, check if we need to adjust the letter/setter too - if (model.TargetDeclaration.DeclarationType == DeclarationType.PropertyGet) - { - var setter = GetLetterOrSetter(model.TargetDeclaration, DeclarationType.PropertySet); - if (setter != null) - { - var setterModel = ModelForNewTarget(model, setter); - RemoveParameters(setterModel, rewriteSession); - } - - var letter = GetLetterOrSetter(model.TargetDeclaration, DeclarationType.PropertyLet); - if (letter != null) - { - var letterModel = ModelForNewTarget(model, letter); - RemoveParameters(letterModel, rewriteSession); - } - } - - var eventImplementations = _declarationFinderProvider.DeclarationFinder - .FindEventHandlers(model.TargetDeclaration); - - foreach (var eventImplementation in eventImplementations) - { - var eventImplementationModel = ModelForNewTarget(model, eventImplementation); - AdjustReferences(eventImplementationModel, rewriteSession); - AdjustSignatures(eventImplementationModel, rewriteSession); - } - - var interfaceImplementations = _declarationFinderProvider.DeclarationFinder - .FindInterfaceImplementationMembers(model.TargetDeclaration); - - foreach (var interfaceImplementation in interfaceImplementations) - { - var interfaceImplementationModel = ModelForNewTarget(model, interfaceImplementation); - AdjustReferences(interfaceImplementationModel, rewriteSession); - AdjustSignatures(interfaceImplementationModel, rewriteSession); - } - } - - private static void AdjustReferences(RemoveParametersModel model, IRewriteSession rewriteSession) - { - var parametersToRemove = model.RemoveParameters - .Select(parameter => parameter.Declaration) - .ToList(); - var argumentReferences = ArgumentReferencesByLocation(parametersToRemove); - - foreach (var (module, moduleArgumentReferences) in argumentReferences) - { - AdjustReferences(module, moduleArgumentReferences, rewriteSession); - } - } - - private static Dictionary>> ArgumentReferencesByLocation(ICollection parameters) - { - return parameters - .SelectMany(parameterDeclaration => parameterDeclaration.ArgumentReferences) - .GroupBy(argumentReference => argumentReference.QualifiedModuleName) - .ToDictionary( - grouping => grouping.Key, - grouping => grouping - .GroupBy(reference => reference.ArgumentListSelection) - .ToDictionary(group => group.Key, group => group.ToList())); - } - - private static void AdjustReferences( - QualifiedModuleName module, - Dictionary> argumentReferences, - IRewriteSession rewriteSession) - { - var rewriter = rewriteSession.CheckOutModuleRewriter(module); - foreach (var (argumentListSelection, sameArgumentListReferences) in argumentReferences) - { - //This happens for (with) dictionary access expressions only. - if (argumentListSelection.Equals(Selection.Empty)) - { - foreach (var dictionaryAccessArgument in sameArgumentListReferences) - { - ReplaceDictionaryAccess(dictionaryAccessArgument, rewriter); - } - - continue; - } - - AdjustReferences(sameArgumentListReferences, rewriter); - } - } - - private static void ReplaceDictionaryAccess(ArgumentReference dictionaryAccessArgument, IModuleRewriter rewriter) - { - //TODO: Deal with WithDictionaryAccessExprContexts. - //This should best be handled by extracting a refactoring out of the ExpandBangNotationQuickFix and - //using it here to expand the dictionary access for both kinds of dictionary access expression. - var dictionaryAccess = dictionaryAccessArgument?.Context?.Parent as VBAParser.DictionaryAccessExprContext; - - if (dictionaryAccess == null) - { - return; - } - - var startTokenIndex = dictionaryAccess.dictionaryAccess().start.TokenIndex; - var stopTokenIndex = dictionaryAccess.unrestrictedIdentifier().stop.TokenIndex; - const string replacementString = "()"; - rewriter.Replace(new Interval(startTokenIndex, stopTokenIndex), replacementString); - } - - private static void AdjustReferences(IReadOnlyCollection argumentReferences, IModuleRewriter rewriter) - { - if (!argumentReferences.Any()) - { - return; - } - - var argumentIndicesToRemove = argumentReferences.Select(argumentReference => argumentReference.ArgumentPosition); - var argumentIndexRangesToRemove = IndexRanges(argumentIndicesToRemove); - var argumentList = argumentReferences.First().ArgumentListContext; - - var adjustedArgumentIndexRangesToRemove = WithTrailingMissingArguments(argumentIndexRangesToRemove, argumentList); - - - foreach (var (startIndex, stopIndex) in adjustedArgumentIndexRangesToRemove) - { - RemoveArgumentRange(startIndex, stopIndex, argumentList, rewriter); - } - } - - private static IEnumerable<(int startIndex, int stopIndex)> IndexRanges(IEnumerable indices) - { - var sortedIndices = indices.OrderBy(num => num).ToList(); - var ranges = new List<(int startIndex, int stopIndex)>(); - int startIndex = -10; - int stopIndex = -10; - foreach(var currentIndex in sortedIndices) - { - if (currentIndex == stopIndex + 1) - { - stopIndex = currentIndex; - } - else - { - if (startIndex >= 0) - { - ranges.Add((startIndex, stopIndex)); - } - - startIndex = currentIndex; - stopIndex = currentIndex; - } - } - - if (startIndex >= 0) - { - ranges.Add((startIndex, stopIndex)); - } - - return ranges; - } - - private static IEnumerable<(int startIndex, int stopIndex)> WithTrailingMissingArguments( - IEnumerable<(int startIndex, int stopIndex)> argumentRanges, - VBAParser.ArgumentListContext argumentList) - { - var arguments = argumentList.argument(); - var numberOfArguments = arguments.Length; - - var argumentRangesInDescendingOrder = argumentRanges.OrderByDescending(range => range.stopIndex).ToList(); - if (argumentRangesInDescendingOrder[0].stopIndex != numberOfArguments - 1) - { - return argumentRangesInDescendingOrder; - } - - var currentRangeIndex = 0; - var currentStartIndex = argumentRangesInDescendingOrder[0].startIndex; - while(currentStartIndex > 0) - { - if (currentRangeIndex + 1 < argumentRangesInDescendingOrder.Count - && currentStartIndex - 1 == argumentRangesInDescendingOrder[currentRangeIndex + 1].stopIndex) - { - currentRangeIndex++; - currentStartIndex = argumentRangesInDescendingOrder[currentRangeIndex].startIndex; - } - else if (arguments[currentStartIndex - 1]?.missingArgument() != null) - { - currentStartIndex--; - } - else - { - break; - } - } - - var newRanges = new List<(int startIndex, int stopIndex)> {(currentStartIndex, numberOfArguments -1)}; - newRanges.AddRange(argumentRangesInDescendingOrder.Skip(currentRangeIndex + 1)); - return newRanges; - } - - private static void RemoveArgumentRange( - int startArgumentIndex, - int stopArgumentIndex, - VBAParser.ArgumentListContext argumentList, - IModuleRewriter rewriter) - { - var (startTokenIndex, stopTokenIndex) = TokenIndexRange(startArgumentIndex, stopArgumentIndex, argumentList.argument()); - rewriter.RemoveRange(startTokenIndex, stopTokenIndex); - } - - private static (int startTokenIndex, int stopTokenIndex) TokenIndexRange( - int startIndex, - int stopIndex, - IReadOnlyList contexts) - { - int startTokenIndex; - int stopTokenIndex; - - if (stopIndex == contexts.Count - 1) - { - startTokenIndex = startIndex == 0 - ? contexts[0].Start.TokenIndex - : contexts[startIndex - 1].Stop.TokenIndex + 1; - stopTokenIndex = contexts[stopIndex].Stop.TokenIndex; - return (startTokenIndex, stopTokenIndex); - } - - startTokenIndex = contexts[startIndex].Start.TokenIndex; - stopTokenIndex = contexts[stopIndex + 1].Start.TokenIndex - 1; - return (startTokenIndex, stopTokenIndex); - } - - private static void AdjustSignatures(RemoveParametersModel model, IRewriteSession rewriteSession) - { - var rewriter = rewriteSession.CheckOutModuleRewriter(model.TargetDeclaration.QualifiedModuleName); - - var parameterIndicesToRemove = model.RemoveParameters - .Select(param => model.Parameters.IndexOf(param)); - var parameterRangesToRemove = IndexRanges(parameterIndicesToRemove); - - var argList = model.Parameters.First().Declaration.Context.GetAncestor(); - - foreach (var (startIndex, stopIndex) in parameterRangesToRemove) - { - RemoveParameterRange(startIndex, stopIndex, argList, rewriter); - } - } - - private static void RemoveParameterRange( - int startArgumentIndex, - int stopArgumentIndex, - VBAParser.ArgListContext argList, - IModuleRewriter rewriter) - { - var (startTokenIndex, stopTokenIndex) = TokenIndexRange(startArgumentIndex, stopArgumentIndex, argList.arg()); - rewriter.RemoveRange(startTokenIndex, stopTokenIndex); - } - - private Declaration GetLetterOrSetter(Declaration declaration, DeclarationType declarationType) - { - return _declarationFinderProvider.DeclarationFinder - .UserDeclarations(declarationType) - .FirstOrDefault(item => item.QualifiedModuleName.Equals(declaration.QualifiedModuleName) - && item.IdentifierName == declaration.IdentifierName); - } - - private static RemoveParametersModel ModelForNewTarget(RemoveParametersModel oldModel, Declaration newTarget) - { - var newModel = new RemoveParametersModel(newTarget); - var toRemoveIndices = oldModel.RemoveParameters.Select(param => oldModel.Parameters.IndexOf(param)); - var newToRemoveParams = toRemoveIndices - .Select(index => newModel.Parameters[index]) - .ToList(); - newModel.RemoveParameters = newToRemoveParams; - return newModel; + _baseRefactoring.Refactor(model); } public static readonly DeclarationType[] ValidDeclarationTypes = diff --git a/Rubberduck.Refactorings/Rename/RenameBaseRefactoring.cs b/Rubberduck.Refactorings/Rename/RenameBaseRefactoring.cs new file mode 100644 index 0000000000..373c96c894 --- /dev/null +++ b/Rubberduck.Refactorings/Rename/RenameBaseRefactoring.cs @@ -0,0 +1,308 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using Rubberduck.Parsing; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.VBEditor.ComManagement; +using Rubberduck.VBEditor.SafeComWrappers; + +namespace Rubberduck.Refactorings.Rename +{ + public class RenameBaseRefactoring : BaseRefactoringWithSuspensionBase + { + private const string AppendUnderscoreFormat = "{0}_"; + private const string PrependUnderscoreFormat = "_{0}"; + + private readonly IDeclarationFinderProvider _declarationFinderProvider; + private readonly IProjectsProvider _projectsProvider; + private readonly IDictionary> _renameActions; + + public RenameBaseRefactoring( + IDeclarationFinderProvider declarationFinderProvider, + IProjectsProvider projectsProvider, + IParseManager parserManager, + IRewritingManager rewritingManager) + : base(parserManager, rewritingManager) + { + _declarationFinderProvider = declarationFinderProvider; + _projectsProvider = projectsProvider; + + _renameActions = new Dictionary> + { + {DeclarationType.Member, RenameMember}, + {DeclarationType.Parameter, RenameParameter}, + {DeclarationType.Event, RenameEvent}, + {DeclarationType.Variable, RenameVariable}, + {DeclarationType.Module, RenameModule}, + {DeclarationType.Project, RenameProject} + }; + } + + protected override bool RequiresSuspension(RenameModel model) + { + //The parser needs to be suspended during the refactoring of a component because the VBE API object rename causes a separate reparse. + var targetType = model.Target.DeclarationType; + return targetType.HasFlag(DeclarationType.Module) + || targetType.HasFlag(DeclarationType.Project); + } + + protected override void Refactor(RenameModel model, IRewriteSession rewriteSession) + { + Debug.Assert(!model.NewName.Equals(model.Target.IdentifierName, StringComparison.InvariantCultureIgnoreCase), + $"input validation fail: New Name equals Original Name ({model.Target.IdentifierName})"); + + var actionKeys = _renameActions.Keys.Where(decType => model.Target.DeclarationType.HasFlag(decType)).ToList(); + if (actionKeys.Any()) + { + Debug.Assert(actionKeys.Count == 1, $"{actionKeys.Count} Rename Actions have flag '{model.Target.DeclarationType.ToString()}'"); + _renameActions[actionKeys.FirstOrDefault()](model, rewriteSession); + } + else + { + RenameStandardElements(model.Target, model.NewName, rewriteSession); + } + } + + private void RenameMember(RenameModel model, IRewriteSession rewriteSession) + { + if (model.Target.DeclarationType.HasFlag(DeclarationType.Property)) + { + var members = _declarationFinderProvider.DeclarationFinder.MatchName(model.Target.IdentifierName) + .Where(item => item.ProjectId == model.Target.ProjectId + && item.ComponentName == model.Target.ComponentName + && item.DeclarationType.HasFlag(DeclarationType.Property)); + + foreach (var member in members) + { + RenameStandardElements(member, model.NewName, rewriteSession); + } + } + else + { + RenameStandardElements(model.Target, model.NewName, rewriteSession); + } + + if (!model.IsInterfaceMemberRename) + { + return; + } + + var implementations = _declarationFinderProvider.DeclarationFinder.FindAllInterfaceImplementingMembers() + .Where(impl => ReferenceEquals(model.Target.ParentDeclaration, impl.InterfaceImplemented) + && impl.InterfaceMemberImplemented.IdentifierName.Equals(model.Target.IdentifierName)); + + RenameDefinedFormatMembers(model, implementations.ToList(), PrependUnderscoreFormat, rewriteSession); + } + + private void RenameParameter(RenameModel model, IRewriteSession rewriteSession) + { + if (model.Target.ParentDeclaration.DeclarationType.HasFlag(DeclarationType.Property)) + { + var parameters = _declarationFinderProvider.DeclarationFinder.MatchName(model.Target.IdentifierName).Where(param => + param.ParentDeclaration.DeclarationType.HasFlag(DeclarationType.Property) + && param.DeclarationType == DeclarationType.Parameter + && param.ParentDeclaration.IdentifierName.Equals(model.Target.ParentDeclaration.IdentifierName) + && param.ParentDeclaration.ParentScopeDeclaration.Equals(model.Target.ParentDeclaration.ParentScopeDeclaration)); + + foreach (var param in parameters) + { + RenameStandardElements(param, model.NewName, rewriteSession); + } + } + else + { + RenameStandardElements(model.Target, model.NewName, rewriteSession); + } + } + + private void RenameEvent(RenameModel model, IRewriteSession rewriteSession) + { + RenameStandardElements(model.Target, model.NewName, rewriteSession); + + var withEventsDeclarations = _declarationFinderProvider.DeclarationFinder.UserDeclarations(DeclarationType.Variable) + .Where(varDec => varDec.IsWithEvents && varDec.AsTypeName.Equals(model.Target.ParentDeclaration.IdentifierName)); + + var eventHandlers = withEventsDeclarations.SelectMany(we => _declarationFinderProvider.DeclarationFinder.FindHandlersForWithEventsField(we)); + RenameDefinedFormatMembers(model, eventHandlers.ToList(), PrependUnderscoreFormat, rewriteSession); + } + + private void RenameVariable(RenameModel model, IRewriteSession rewriteSession) + { + if ((model.Target.Accessibility == Accessibility.Public || + model.Target.Accessibility == Accessibility.Implicit) + && model.Target.ParentDeclaration is ClassModuleDeclaration classDeclaration + && classDeclaration.Subtypes.Any()) + { + RenameMember(model, rewriteSession); + } + else if (model.Target.DeclarationType.HasFlag(DeclarationType.Control)) + { + var component = _projectsProvider.Component(model.Target.QualifiedName.QualifiedModuleName); + using (var controls = component.Controls) + { + using (var control = controls.SingleOrDefault(item => item.Name == model.Target.IdentifierName)) + { + Debug.Assert(control != null, + $"input validation fail: unable to locate '{model.Target.IdentifierName}' in Controls collection"); + + control.Name = model.NewName; + } + } + RenameReferences(model.Target, model.NewName, rewriteSession); + var controlEventHandlers = FindEventHandlersForControl(model.Target); + RenameDefinedFormatMembers(model, controlEventHandlers.ToList(), AppendUnderscoreFormat, rewriteSession); + } + else + { + RenameStandardElements(model.Target, model.NewName, rewriteSession); + if (model.Target.IsWithEvents) + { + var eventHandlers = _declarationFinderProvider.DeclarationFinder.FindHandlersForWithEventsField(model.Target); + RenameDefinedFormatMembers(model, eventHandlers.ToList(), AppendUnderscoreFormat, rewriteSession); + } + } + } + + private void RenameModule(RenameModel model, IRewriteSession rewriteSession) + { + RenameReferences(model.Target, model.NewName, rewriteSession); + + if (model.Target.DeclarationType.HasFlag(DeclarationType.ClassModule)) + { + foreach (var reference in model.Target.References) + { + var ctxt = reference.Context.GetAncestor(); + if (ctxt != null) + { + RenameDefinedFormatMembers(model, _declarationFinderProvider.DeclarationFinder.FindInterfaceMembersForImplementsContext(ctxt).ToList(), AppendUnderscoreFormat, rewriteSession); + } + } + } + + var component = _projectsProvider.Component(model.Target.QualifiedName.QualifiedModuleName); + switch (component.Type) + { + case ComponentType.Document: + { + using (var properties = component.Properties) + using (var property = properties["_CodeName"]) + { + property.Value = model.NewName; + } + break; + } + case ComponentType.UserForm: + case ComponentType.VBForm: + case ComponentType.MDIForm: + { + using (var properties = component.Properties) + using (var property = properties["Caption"]) + { + if ((string)property.Value == model.Target.IdentifierName) + { + property.Value = model.NewName; + } + component.Name = model.NewName; + } + break; + } + default: + { + using (var vbe = component.VBE) + { + if (vbe.Kind == VBEKind.Hosted) + { + // VBA - rename code module + using (var codeModule = component.CodeModule) + { + Debug.Assert(!codeModule.IsWrappingNullReference, + "input validation fail: Attempting to rename an ICodeModule wrapping a null reference"); + codeModule.Name = model.NewName; + } + } + else + { + // VB6 - rename component + component.Name = model.NewName; + } + } + break; + } + } + } + + //TODO: Implement renaming references to the project in code. + private void RenameProject(RenameModel model, IRewriteSession rewriteSession) + { + var project = _projectsProvider.Project(model.Target.ProjectId); + + if (project != null) + { + project.Name = model.NewName; + } + } + + private void RenameDefinedFormatMembers(RenameModel model, IReadOnlyCollection members, string underscoreFormat, IRewriteSession rewriteSession) + { + if (!members.Any()) { return; } + + var targetFragment = string.Format(underscoreFormat, model.Target.IdentifierName); + var replacementFragment = string.Format(underscoreFormat, model.NewName); + foreach (var member in members) + { + var newMemberName = member.IdentifierName.Replace(targetFragment, replacementFragment); + RenameStandardElements(member, newMemberName, rewriteSession); + } + } + + private void RenameStandardElements(Declaration target, string newName, IRewriteSession rewriteSession) + { + RenameReferences(target, newName, rewriteSession); + RenameDeclaration(target, newName, rewriteSession); + } + + private void RenameReferences(Declaration target, string newName, IRewriteSession rewriteSession) + { + var modules = target.References + .Where(reference => + reference.Context.GetText() != "Me" + && !reference.IsArrayAccess + && !reference.IsDefaultMemberAccess) + .GroupBy(r => r.QualifiedModuleName); + + foreach (var grouping in modules) + { + var rewriter = rewriteSession.CheckOutModuleRewriter(grouping.Key); + foreach (var reference in grouping) + { + rewriter.Replace(reference.Context, newName); + } + } + } + + private void RenameDeclaration(Declaration target, string newName, IRewriteSession rewriteSession) + { + var rewriter = rewriteSession.CheckOutModuleRewriter(target.QualifiedName.QualifiedModuleName); + + if (target.Context is IIdentifierContext context) + { + rewriter.Replace(context.IdentifierTokens, newName); + } + } + + private IEnumerable FindEventHandlersForControl(Declaration control) + { + if (control != null && control.DeclarationType.HasFlag(DeclarationType.Control)) + { + return _declarationFinderProvider.DeclarationFinder.FindEventHandlers() + .Where(ev => ev.Scope.StartsWith($"{control.ParentScope}.{control.IdentifierName}_")); + } + + return Enumerable.Empty(); + } + } +} \ No newline at end of file diff --git a/Rubberduck.Refactorings/Rename/RenameRefactoring.cs b/Rubberduck.Refactorings/Rename/RenameRefactoring.cs index 27c7d5508e..4aae96677a 100644 --- a/Rubberduck.Refactorings/Rename/RenameRefactoring.cs +++ b/Rubberduck.Refactorings/Rename/RenameRefactoring.cs @@ -1,62 +1,39 @@ using System.Linq; -using Rubberduck.Parsing; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor; -using System; -using System.Diagnostics; using System.Collections.Generic; -using System.Runtime.ExceptionServices; -using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Rewriter; using Rubberduck.Refactorings.Exceptions; using Rubberduck.Refactorings.Exceptions.Rename; using Rubberduck.VBEditor.ComManagement; -using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.Utility; -using NLog; using Rubberduck.Parsing.UIContext; namespace Rubberduck.Refactorings.Rename { public class RenameRefactoring : InteractiveRefactoringBase { - private const string AppendUnderscoreFormat = "{0}_"; - private const string PrependUnderscoreFormat = "_{0}"; - + private readonly IBaseRefactoring _baseRefactoring; private readonly IDeclarationFinderProvider _declarationFinderProvider; private readonly ISelectedDeclarationProvider _selectedDeclarationProvider; private readonly IProjectsProvider _projectsProvider; - private readonly IDictionary> _renameActions; - - private readonly IParseManager _parseManager; - private readonly Logger _logger = LogManager.GetCurrentClassLogger(); public RenameRefactoring( + RenameBaseRefactoring baseRefactoring, IRefactoringPresenterFactory factory, IDeclarationFinderProvider declarationFinderProvider, IProjectsProvider projectsProvider, IRewritingManager rewritingManager, ISelectionProvider selectionProvider, ISelectedDeclarationProvider selectedDeclarationProvider, - IParseManager parseManager, IUiDispatcher uiDispatcher) - :base(rewritingManager, selectionProvider, factory, uiDispatcher) + : base(rewritingManager, selectionProvider, factory, uiDispatcher) { + _baseRefactoring = baseRefactoring; _declarationFinderProvider = declarationFinderProvider; _selectedDeclarationProvider = selectedDeclarationProvider; _projectsProvider = projectsProvider; - _parseManager = parseManager; - - _renameActions = new Dictionary> - { - {DeclarationType.Member, RenameMember}, - {DeclarationType.Parameter, RenameParameter}, - {DeclarationType.Event, RenameEvent}, - {DeclarationType.Variable, RenameVariable}, - {DeclarationType.Module, RenameModule}, - {DeclarationType.Project, RenameProject} - }; } protected override Declaration FindTargetDeclaration(QualifiedSelection targetSelection) @@ -80,43 +57,7 @@ protected override RenameModel InitializeModel(Declaration target) protected override void RefactorImpl(RenameModel model) { - if (model.Target.DeclarationType.HasFlag(DeclarationType.Module) - || model.Target.DeclarationType.HasFlag(DeclarationType.Project)) - { - //The parser needs to be suspended during the refactoring of a component because the VBE API object rename causes a separate reparse. - RenameRefactorWithSuspendedParser(model); - return; - } - - RenameRefactor(model); - } - - private void RenameRefactorWithSuspendedParser(RenameModel model) - { - var suspendResult = _parseManager.OnSuspendParser(this, new[] { ParserState.Ready }, () => RenameRefactor(model)); - var suspendOutcome = suspendResult.Outcome; - if (suspendOutcome != SuspensionOutcome.Completed) - { - if ((suspendOutcome == SuspensionOutcome.UnexpectedError || suspendOutcome == SuspensionOutcome.Canceled) - && suspendResult.EncounteredException != null) - { - ExceptionDispatchInfo.Capture(suspendResult.EncounteredException).Throw(); - return; - } - - _logger.Warn($"{nameof(RenameRefactor)} failed because a parser suspension request could not be fulfilled. The request's result was '{suspendResult.ToString()}'."); - throw new SuspendParserFailureException(); - } - } - - private void RenameRefactor(RenameModel model) - { - var rewriteSession = RewritingManager.CheckOutCodePaneSession(); - Rename(model, rewriteSession); - if (!rewriteSession.TryRewrite()) - { - throw new RewriteFailedException(rewriteSession); - } + _baseRefactoring.Refactor(model); } private RenameModel DeriveTarget(RenameModel model) @@ -239,7 +180,7 @@ private RenameModel ResolveEventHandlerToUserEvent(RenameModel model) return null; } - private RenameModel ResolveRenameTargetIfInterfaceImplementationSelected(RenameModel model) + private static RenameModel ResolveRenameTargetIfInterfaceImplementationSelected(RenameModel model) { var userTarget = model.InitialTarget; @@ -257,250 +198,6 @@ private RenameModel ResolveRenameTargetIfInterfaceImplementationSelected(RenameM return null; } - private void Rename(RenameModel model, IRewriteSession rewriteSession) - { - Debug.Assert(!model.NewName.Equals(model.Target.IdentifierName, StringComparison.InvariantCultureIgnoreCase), - $"input validation fail: New Name equals Original Name ({model.Target.IdentifierName})"); - - var actionKeys = _renameActions.Keys.Where(decType => model.Target.DeclarationType.HasFlag(decType)).ToList(); - if (actionKeys.Any()) - { - Debug.Assert(actionKeys.Count == 1, $"{actionKeys.Count} Rename Actions have flag '{model.Target.DeclarationType.ToString()}'"); - _renameActions[actionKeys.FirstOrDefault()](model, rewriteSession); - } - else - { - RenameStandardElements(model.Target, model.NewName, rewriteSession); - } - } - - private void RenameMember(RenameModel model, IRewriteSession rewriteSession) - { - if (model.Target.DeclarationType.HasFlag(DeclarationType.Property)) - { - var members = _declarationFinderProvider.DeclarationFinder.MatchName(model.Target.IdentifierName) - .Where(item => item.ProjectId == model.Target.ProjectId - && item.ComponentName == model.Target.ComponentName - && item.DeclarationType.HasFlag(DeclarationType.Property)); - - foreach (var member in members) - { - RenameStandardElements(member, model.NewName, rewriteSession); - } - } - else - { - RenameStandardElements(model.Target, model.NewName, rewriteSession); - } - - if (!model.IsInterfaceMemberRename) - { - return; - } - - var implementations = _declarationFinderProvider.DeclarationFinder.FindAllInterfaceImplementingMembers() - .Where(impl => ReferenceEquals(model.Target.ParentDeclaration, impl.InterfaceImplemented) - && impl.InterfaceMemberImplemented.IdentifierName.Equals(model.Target.IdentifierName)); - - RenameDefinedFormatMembers(model, implementations.ToList(), PrependUnderscoreFormat, rewriteSession); - } - - private void RenameParameter(RenameModel model, IRewriteSession rewriteSession) - { - if (model.Target.ParentDeclaration.DeclarationType.HasFlag(DeclarationType.Property)) - { - var parameters = _declarationFinderProvider.DeclarationFinder.MatchName(model.Target.IdentifierName).Where(param => - param.ParentDeclaration.DeclarationType.HasFlag(DeclarationType.Property) - && param.DeclarationType == DeclarationType.Parameter - && param.ParentDeclaration.IdentifierName.Equals(model.Target.ParentDeclaration.IdentifierName) - && param.ParentDeclaration.ParentScopeDeclaration.Equals(model.Target.ParentDeclaration.ParentScopeDeclaration)); - - foreach (var param in parameters) - { - RenameStandardElements(param, model.NewName, rewriteSession); - } - } - else - { - RenameStandardElements(model.Target, model.NewName, rewriteSession); - } - } - - private void RenameEvent(RenameModel model, IRewriteSession rewriteSession) - { - RenameStandardElements(model.Target, model.NewName, rewriteSession); - - var withEventsDeclarations = _declarationFinderProvider.DeclarationFinder.UserDeclarations(DeclarationType.Variable) - .Where(varDec => varDec.IsWithEvents && varDec.AsTypeName.Equals(model.Target.ParentDeclaration.IdentifierName)); - - var eventHandlers = withEventsDeclarations.SelectMany(we => _declarationFinderProvider.DeclarationFinder.FindHandlersForWithEventsField(we)); - RenameDefinedFormatMembers(model, eventHandlers.ToList(), PrependUnderscoreFormat, rewriteSession); - } - - private void RenameVariable(RenameModel model, IRewriteSession rewriteSession) - { - if ((model.Target.Accessibility == Accessibility.Public || - model.Target.Accessibility == Accessibility.Implicit) - && model.Target.ParentDeclaration is ClassModuleDeclaration classDeclaration - && classDeclaration.Subtypes.Any()) - { - RenameMember(model, rewriteSession); - } - else if (model.Target.DeclarationType.HasFlag(DeclarationType.Control)) - { - var component = _projectsProvider.Component(model.Target.QualifiedName.QualifiedModuleName); - using (var controls = component.Controls) - { - using (var control = controls.SingleOrDefault(item => item.Name == model.Target.IdentifierName)) - { - Debug.Assert(control != null, - $"input validation fail: unable to locate '{model.Target.IdentifierName}' in Controls collection"); - - control.Name = model.NewName; - } - } - RenameReferences(model.Target, model.NewName, rewriteSession); - var controlEventHandlers = FindEventHandlersForControl(model.Target); - RenameDefinedFormatMembers(model, controlEventHandlers.ToList(), AppendUnderscoreFormat, rewriteSession); - } - else - { - RenameStandardElements(model.Target, model.NewName, rewriteSession); - if (model.Target.IsWithEvents) - { - var eventHandlers = _declarationFinderProvider.DeclarationFinder.FindHandlersForWithEventsField(model.Target); - RenameDefinedFormatMembers(model, eventHandlers.ToList(), AppendUnderscoreFormat, rewriteSession); - } - } - } - - private void RenameModule(RenameModel model, IRewriteSession rewriteSession) - { - RenameReferences(model.Target, model.NewName, rewriteSession); - - if (model.Target.DeclarationType.HasFlag(DeclarationType.ClassModule)) - { - foreach (var reference in model.Target.References) - { - var ctxt = reference.Context.GetAncestor(); - if (ctxt != null) - { - RenameDefinedFormatMembers(model, _declarationFinderProvider.DeclarationFinder.FindInterfaceMembersForImplementsContext(ctxt).ToList(), AppendUnderscoreFormat, rewriteSession); - } - } - } - - var component = _projectsProvider.Component(model.Target.QualifiedName.QualifiedModuleName); - switch (component.Type) - { - case ComponentType.Document: - { - using (var properties = component.Properties) - using (var property = properties["_CodeName"]) - { - property.Value = model.NewName; - } - break; - } - case ComponentType.UserForm: - case ComponentType.VBForm: - case ComponentType.MDIForm: - { - using (var properties = component.Properties) - using (var property = properties["Caption"]) - { - if ((string)property.Value == model.Target.IdentifierName) - { - property.Value = model.NewName; - } - component.Name = model.NewName; - } - break; - } - default: - { - using (var vbe = component.VBE) - { - if (vbe.Kind == VBEKind.Hosted) - { - // VBA - rename code module - using (var codeModule = component.CodeModule) - { - Debug.Assert(!codeModule.IsWrappingNullReference, - "input validation fail: Attempting to rename an ICodeModule wrapping a null reference"); - codeModule.Name = model.NewName; - } - } - else - { - // VB6 - rename component - component.Name = model.NewName; - } - } - break; - } - } - } - - //TODO: Implement renaming references to the project in code. - private void RenameProject(RenameModel model, IRewriteSession rewriteSession) - { - var project = _projectsProvider.Project(model.Target.ProjectId); - - if (project != null) - { - project.Name = model.NewName; - } - } - - private void RenameDefinedFormatMembers(RenameModel model, IReadOnlyCollection members, string underscoreFormat, IRewriteSession rewriteSession) - { - if (!members.Any()) { return; } - - var targetFragment = string.Format(underscoreFormat, model.Target.IdentifierName); - var replacementFragment = string.Format(underscoreFormat, model.NewName); - foreach (var member in members) - { - var newMemberName = member.IdentifierName.Replace(targetFragment, replacementFragment); - RenameStandardElements(member, newMemberName, rewriteSession); - } - } - - private void RenameStandardElements(Declaration target, string newName, IRewriteSession rewriteSession) - { - RenameReferences(target, newName, rewriteSession); - RenameDeclaration(target, newName, rewriteSession); - } - - private void RenameReferences(Declaration target, string newName, IRewriteSession rewriteSession) - { - var modules = target.References - .Where(reference => - reference.Context.GetText() != "Me" - && !reference.IsArrayAccess - && !reference.IsDefaultMemberAccess) - .GroupBy(r => r.QualifiedModuleName); - - foreach (var grouping in modules) - { - var rewriter = rewriteSession.CheckOutModuleRewriter(grouping.Key); - foreach (var reference in grouping) - { - rewriter.Replace(reference.Context, newName); - } - } - } - - private void RenameDeclaration(Declaration target, string newName, IRewriteSession rewriteSession) - { - var rewriter = rewriteSession.CheckOutModuleRewriter(target.QualifiedName.QualifiedModuleName); - - if (target.Context is IIdentifierContext context) - { - rewriter.Replace(context.IdentifierTokens, newName); - } - } - private IEnumerable FindEventHandlersForControl(Declaration control) { if (control != null && control.DeclarationType.HasFlag(DeclarationType.Control)) diff --git a/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs b/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs index c3a44ae97d..2ae5e22bff 100644 --- a/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs +++ b/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs @@ -18,6 +18,8 @@ using Rubberduck.Parsing.UIContext; using Rubberduck.SettingsProvider; using Rubberduck.Interaction; +using Rubberduck.Refactorings.AddInterfaceImplementations; +using Rubberduck.Refactorings.ExtractInterface; using Rubberduck.UI.Command.ComCommands; using Rubberduck.UI.UnitTesting.ComCommands; using Rubberduck.UnitTesting; @@ -501,9 +503,10 @@ public MockedCodeExplorer ImplementIndenterCommand() public MockedCodeExplorer ImplementExtractInterfaceCommand() { + var addImplementationsBaseRefactoring = new AddInterFaceImplementationsBaseRefactoring(null); + var extractInterfaceBaseRefactoring = new ExtractInterfaceBaseRefactoring(addImplementationsBaseRefactoring, State, State, null); ViewModel.CodeExplorerExtractInterfaceCommand = new CodeExplorerExtractInterfaceCommand( - new Rubberduck.Refactorings.ExtractInterface.ExtractInterfaceRefactoring( - State, State, null, null, null, _uiDispatcher.Object), + new ExtractInterfaceRefactoring(extractInterfaceBaseRefactoring, State, null, null, null, _uiDispatcher.Object), State, null, VbeEvents.Object); return this; } diff --git a/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs b/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs index e89b5293d4..aa6a67b7a2 100644 --- a/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs +++ b/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs @@ -6,6 +6,7 @@ using Rubberduck.Parsing.UIContext; using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings; +using Rubberduck.Refactorings.AddInterfaceImplementations; using Rubberduck.Refactorings.ExtractInterface; using Rubberduck.UI.Command; using Rubberduck.UI.Command.Refactorings; @@ -170,7 +171,9 @@ protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state uiDispatcherMock .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); - var refactoring = new ExtractInterfaceRefactoring(state, state, factory, rewritingManager, selectionService, uiDispatcherMock.Object); + var addImplementationsBaseRefactoring = new AddInterFaceImplementationsBaseRefactoring(rewritingManager); + var baseRefactoring = new ExtractInterfaceBaseRefactoring(addImplementationsBaseRefactoring, state, state, rewritingManager); + var refactoring = new ExtractInterfaceRefactoring(baseRefactoring, state, factory, rewritingManager, selectionService, uiDispatcherMock.Object); 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 d441f11a63..1230baf014 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.AddInterfaceImplementations; using Rubberduck.Refactorings.ImplementInterface; using Rubberduck.UI.Command; using Rubberduck.UI.Command.Refactorings; @@ -56,7 +57,9 @@ public void ImplementInterface_CanExecute_ImplementsInterfaceSelected() protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state, IRewritingManager rewritingManager, ISelectionService selectionService) { var msgBox = new Mock().Object; - var refactoring = new ImplementInterfaceRefactoring(state, rewritingManager, selectionService); + var addImplementationsBaseRefactoring = new AddInterFaceImplementationsBaseRefactoring(rewritingManager); + var baseRefactoring = new ImplementInterfaceBaseRefactoring(addImplementationsBaseRefactoring, rewritingManager); + var refactoring = new ImplementInterfaceRefactoring(baseRefactoring, state, rewritingManager, selectionService); var notifier = new ImplementInterfaceFailedNotifier(msgBox); return new RefactorImplementInterfaceCommand(refactoring, notifier, state, selectionService); } diff --git a/RubberduckTests/Commands/RefactorCommands/IntroduceFieldCommandTests.cs b/RubberduckTests/Commands/RefactorCommands/IntroduceFieldCommandTests.cs index c079114409..f554640c48 100644 --- a/RubberduckTests/Commands/RefactorCommands/IntroduceFieldCommandTests.cs +++ b/RubberduckTests/Commands/RefactorCommands/IntroduceFieldCommandTests.cs @@ -43,7 +43,8 @@ protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state { var msgBox = new Mock().Object; var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); - var refactoring = new IntroduceFieldRefactoring(state, rewritingManager, selectionService, selectedDeclarationProvider); + var baseRefactoring = new IntroduceFieldBaseRefactoring(state, rewritingManager); + var refactoring = new IntroduceFieldRefactoring(baseRefactoring, rewritingManager, selectionService, selectedDeclarationProvider); var notifier = new IntroduceFieldFailedNotifier(msgBox); return new RefactorIntroduceFieldCommand(refactoring, notifier, state, selectionService, selectedDeclarationProvider); } diff --git a/RubberduckTests/Commands/RefactorCommands/IntroduceParameterCommandTests.cs b/RubberduckTests/Commands/RefactorCommands/IntroduceParameterCommandTests.cs index ca6a5988b9..cf6313d9b1 100644 --- a/RubberduckTests/Commands/RefactorCommands/IntroduceParameterCommandTests.cs +++ b/RubberduckTests/Commands/RefactorCommands/IntroduceParameterCommandTests.cs @@ -44,7 +44,8 @@ protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state { var msgBox = new Mock().Object; var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); - var refactoring = new IntroduceParameterRefactoring(state, msgBox, rewritingManager, selectionService, selectedDeclarationProvider); + var baseRefactoring = new IntroduceParameterBaseRefactoring(state, rewritingManager); + var refactoring = new IntroduceParameterRefactoring(baseRefactoring, msgBox, rewritingManager, selectionService, selectedDeclarationProvider); var notifier = new IntroduceParameterFailedNotifier(msgBox); return new RefactorIntroduceParameterCommand(refactoring, notifier, state, selectionService, selectedDeclarationProvider); } diff --git a/RubberduckTests/Commands/RefactorCommands/MoveCloserToUsageCommandTests.cs b/RubberduckTests/Commands/RefactorCommands/MoveCloserToUsageCommandTests.cs index 5db0d76d0e..5c88e397dd 100644 --- a/RubberduckTests/Commands/RefactorCommands/MoveCloserToUsageCommandTests.cs +++ b/RubberduckTests/Commands/RefactorCommands/MoveCloserToUsageCommandTests.cs @@ -98,7 +98,8 @@ protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state { var msgBox = new Mock().Object; var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); - var refactoring = new MoveCloserToUsageRefactoring(state, rewritingManager, selectionService, selectedDeclarationProvider); + var baseRefactoring = new MoveCloserToUsageBaseRefactoring(rewritingManager); + var refactoring = new MoveCloserToUsageRefactoring(baseRefactoring, state, rewritingManager, selectionService, selectedDeclarationProvider); var notifier = new MoveCloserToUsageFailedNotifier(msgBox); var selectedDeclarationService = new SelectedDeclarationProvider(selectionService, state); return new RefactorMoveCloserToUsageCommand(refactoring, notifier, state, selectionService, selectedDeclarationService); diff --git a/RubberduckTests/Commands/RefactorCommands/RemoveParametersCommandTests.cs b/RubberduckTests/Commands/RefactorCommands/RemoveParametersCommandTests.cs index 6fdbf761e3..1b99afd10a 100644 --- a/RubberduckTests/Commands/RefactorCommands/RemoveParametersCommandTests.cs +++ b/RubberduckTests/Commands/RefactorCommands/RemoveParametersCommandTests.cs @@ -170,7 +170,8 @@ protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state uiDispatcherMock .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); - var refactoring = new RemoveParametersRefactoring(state, factory, rewritingManager, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); + var baseRefactoring = new RemoveParameterBaseRefactoring(state, rewritingManager); + var refactoring = new RemoveParametersRefactoring(baseRefactoring, state, factory, rewritingManager, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); var notifier = new RemoveParameterFailedNotifier(msgBox); return new RefactorRemoveParametersCommand(refactoring, notifier, state, selectionService, selectedDeclarationProvider); } diff --git a/RubberduckTests/QuickFixes/MoveFieldCloserToUsageQuickFixTests.cs b/RubberduckTests/QuickFixes/MoveFieldCloserToUsageQuickFixTests.cs index 26fde3264e..31b9adf32b 100644 --- a/RubberduckTests/QuickFixes/MoveFieldCloserToUsageQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/MoveFieldCloserToUsageQuickFixTests.cs @@ -128,7 +128,8 @@ private string ApplyQuickFixToFirstInspectionResult(string inputCode) var rewriteSession = rewritingManager.CheckOutCodePaneSession(); var selectionService = MockedSelectionService(); var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); - var refactoring = new MoveCloserToUsageRefactoring(state, rewritingManager, selectionService, selectedDeclarationProvider); + var baseRefactoring = new MoveCloserToUsageBaseRefactoring(rewritingManager); + var refactoring = new MoveCloserToUsageRefactoring(baseRefactoring, state, rewritingManager, selectionService, selectedDeclarationProvider); var quickFix = new MoveFieldCloserToUsageQuickFix(refactoring); quickFix.Fix(resultToFix, rewriteSession); diff --git a/RubberduckTests/QuickFixes/RemoveUnusedParameterQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveUnusedParameterQuickFixTests.cs index a8e9349396..752edd3186 100644 --- a/RubberduckTests/QuickFixes/RemoveUnusedParameterQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveUnusedParameterQuickFixTests.cs @@ -47,7 +47,8 @@ Private Sub Foo() uiDispatcherMock .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); - var refactoring = new RemoveParametersRefactoring(state, factory, rewritingManager, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); + var baseRefactoring = new RemoveParameterBaseRefactoring(state, rewritingManager); + var refactoring = new RemoveParametersRefactoring(baseRefactoring, state, factory, rewritingManager, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); new RemoveUnusedParameterQuickFix(refactoring) .Fix(inspectionResults.First(), rewriteSession); Assert.AreEqual(expectedCode, component.CodeModule.Content()); diff --git a/RubberduckTests/Refactoring/ExtractInterfaceTests.cs b/RubberduckTests/Refactoring/ExtractInterfaceTests.cs index 3bf77e6f66..2cdffe9a7e 100644 --- a/RubberduckTests/Refactoring/ExtractInterfaceTests.cs +++ b/RubberduckTests/Refactoring/ExtractInterfaceTests.cs @@ -8,6 +8,7 @@ using Rubberduck.Parsing.UIContext; using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings; +using Rubberduck.Refactorings.AddInterfaceImplementations; using Rubberduck.Refactorings.Exceptions; using Rubberduck.Refactorings.ExtractInterface; using Rubberduck.VBEditor; @@ -424,7 +425,9 @@ protected override IRefactoring TestRefactoring(IRewritingManager rewritingManag uiDispatcherMock .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); - return new ExtractInterfaceRefactoring(state, state, factory, rewritingManager, selectionService, uiDispatcherMock.Object); + var addImplementationsBaseRefactoring = new AddInterFaceImplementationsBaseRefactoring(rewritingManager); + var baseRefactoring = new ExtractInterfaceBaseRefactoring(addImplementationsBaseRefactoring, state, state, rewritingManager); + return new ExtractInterfaceRefactoring(baseRefactoring, state, factory, rewritingManager, selectionService, uiDispatcherMock.Object); } } } \ No newline at end of file diff --git a/RubberduckTests/Refactoring/ImplementInterfaceTests.cs b/RubberduckTests/Refactoring/ImplementInterfaceTests.cs index 8dbbb124ec..e13697b906 100644 --- a/RubberduckTests/Refactoring/ImplementInterfaceTests.cs +++ b/RubberduckTests/Refactoring/ImplementInterfaceTests.cs @@ -5,6 +5,7 @@ using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings; +using Rubberduck.Refactorings.AddInterfaceImplementations; using Rubberduck.Refactorings.Exceptions; using Rubberduck.Refactorings.Exceptions.ImplementInterface; using Rubberduck.Refactorings.ImplementInterface; @@ -910,7 +911,9 @@ End Sub protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, ISelectionService selectionService) { - return new ImplementInterfaceRefactoring(state, rewritingManager, selectionService); + var addImplementationsBaseRefactoring = new AddInterFaceImplementationsBaseRefactoring(rewritingManager); + var baseRefactoring = new ImplementInterfaceBaseRefactoring(addImplementationsBaseRefactoring, rewritingManager); + return new ImplementInterfaceRefactoring(baseRefactoring, state, rewritingManager, selectionService); } } } diff --git a/RubberduckTests/Refactoring/IntroduceFieldTests.cs b/RubberduckTests/Refactoring/IntroduceFieldTests.cs index f4176fb43d..24c60fb422 100644 --- a/RubberduckTests/Refactoring/IntroduceFieldTests.cs +++ b/RubberduckTests/Refactoring/IntroduceFieldTests.cs @@ -350,7 +350,8 @@ Dim bar As Boolean protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, ISelectionService selectionService) { var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); - return new IntroduceFieldRefactoring(state, rewritingManager, selectionService, selectedDeclarationProvider); + var baseRefactoring = new IntroduceFieldBaseRefactoring(state, rewritingManager); + return new IntroduceFieldRefactoring(baseRefactoring, rewritingManager, selectionService, selectedDeclarationProvider); } } } diff --git a/RubberduckTests/Refactoring/IntroduceParameterTests.cs b/RubberduckTests/Refactoring/IntroduceParameterTests.cs index a80c3337e4..57e326a021 100644 --- a/RubberduckTests/Refactoring/IntroduceParameterTests.cs +++ b/RubberduckTests/Refactoring/IntroduceParameterTests.cs @@ -559,7 +559,8 @@ private static IRefactoring TestRefactoring(IRewritingManager rewritingManager, msgBox = new Mock().Object; } var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); - return new IntroduceParameterRefactoring(state, msgBox, rewritingManager, selectionService, selectedDeclarationProvider); + var baseRefactoring = new IntroduceParameterBaseRefactoring(state, rewritingManager); + return new IntroduceParameterRefactoring(baseRefactoring, msgBox, rewritingManager, selectionService, selectedDeclarationProvider); } private IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IMessageBox msgBox = null, QualifiedSelection? initialSelection = null) diff --git a/RubberduckTests/Refactoring/MoveCloserToUsageTests.cs b/RubberduckTests/Refactoring/MoveCloserToUsageTests.cs index 6de5d2ddb2..45fc70abc4 100644 --- a/RubberduckTests/Refactoring/MoveCloserToUsageTests.cs +++ b/RubberduckTests/Refactoring/MoveCloserToUsageTests.cs @@ -1075,7 +1075,8 @@ bar.Add 42 protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, ISelectionService selectionService) { var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); - return new MoveCloserToUsageRefactoring(state, rewritingManager, selectionService, selectedDeclarationProvider); + var baseRefactoring = new MoveCloserToUsageBaseRefactoring(rewritingManager); + return new MoveCloserToUsageRefactoring(baseRefactoring, state, rewritingManager, selectionService, selectedDeclarationProvider); } } } diff --git a/RubberduckTests/Refactoring/RemoveParametersTests.cs b/RubberduckTests/Refactoring/RemoveParametersTests.cs index 43f1973183..b21e42cb32 100644 --- a/RubberduckTests/Refactoring/RemoveParametersTests.cs +++ b/RubberduckTests/Refactoring/RemoveParametersTests.cs @@ -1974,7 +1974,8 @@ protected override IRefactoring TestRefactoring(IRewritingManager rewritingManag uiDispatcherMock .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); - return new RemoveParametersRefactoring(state, factory, rewritingManager, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); + var baseRefactoring = new RemoveParameterBaseRefactoring(state, rewritingManager); + return new RemoveParametersRefactoring(baseRefactoring, state, factory, rewritingManager, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); } } } diff --git a/RubberduckTests/Refactoring/Rename/RenameTests.cs b/RubberduckTests/Refactoring/Rename/RenameTests.cs index 02701260b9..ff93b9c7d7 100644 --- a/RubberduckTests/Refactoring/Rename/RenameTests.cs +++ b/RubberduckTests/Refactoring/Rename/RenameTests.cs @@ -3369,7 +3369,8 @@ protected override IRefactoring TestRefactoring(IRewritingManager rewritingManag uiDispatcherMock .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); - return new RenameRefactoring(factory, state, state?.ProjectsProvider, rewritingManager, selectionService, selectedDeclarationService, state, uiDispatcherMock.Object); + var baseRefactoring = new RenameBaseRefactoring(state, state?.ProjectsProvider, state, rewritingManager); + return new RenameRefactoring(baseRefactoring, factory, state, state?.ProjectsProvider, rewritingManager, selectionService, selectedDeclarationService, uiDispatcherMock.Object); } #endregion From 6f9e34784539f1e6756b08af71945ac3a4d70e73 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Thu, 13 Feb 2020 22:29:48 +0100 Subject: [PATCH 226/461] Remove RewritingManager from RefactoringBase --- .../Root/RubberduckIoCInstaller.cs | 21 +++++++++++++++++-- .../Abstract/InteractiveRefactoringBase.cs | 8 +++---- .../Abstract/RefactoringBase.cs | 7 ++----- .../EncapsulateFieldRefactoring.cs | 8 ++++--- .../ExtractInterfaceRefactoring.cs | 4 +--- .../ImplementInterfaceRefactoring.cs | 4 +--- .../IntroduceFieldRefactoring.cs | 4 +--- .../IntroduceParameterRefactoring.cs | 10 ++------- .../MoveCloserToUsageRefactoring.cs | 6 ++---- .../RemoveParametersRefactoring.cs | 4 +--- .../Rename/RenameRefactoring.cs | 4 +--- .../ReorderParametersRefactoring.cs | 4 +--- .../CodeExplorer/MockedCodeExplorer.cs | 2 +- .../ExtractInterfaceCommandTests.cs | 2 +- .../ImplementInterfaceCommandTests.cs | 2 +- .../IntroduceFieldCommandTests.cs | 2 +- .../IntroduceParameterCommandTests.cs | 2 +- .../MoveCloserToUsageCommandTests.cs | 2 +- .../RemoveParametersCommandTests.cs | 2 +- .../ReorderParametersCommandTests.cs | 2 +- .../MoveFieldCloserToUsageQuickFixTests.cs | 2 +- .../RemoveUnusedParameterQuickFixTests.cs | 2 +- .../Refactoring/ExtractInterfaceTests.cs | 2 +- .../Refactoring/ImplementInterfaceTests.cs | 2 +- .../Refactoring/IntroduceFieldTests.cs | 2 +- .../Refactoring/IntroduceParameterTests.cs | 2 +- .../Refactoring/MoveCloserToUsageTests.cs | 2 +- .../Refactoring/RemoveParametersTests.cs | 2 +- .../Refactoring/Rename/RenameTests.cs | 2 +- .../Refactoring/ReorderParametersTests.cs | 2 +- 30 files changed, 57 insertions(+), 63 deletions(-) diff --git a/Rubberduck.Main/Root/RubberduckIoCInstaller.cs b/Rubberduck.Main/Root/RubberduckIoCInstaller.cs index e66968d120..e968145171 100644 --- a/Rubberduck.Main/Root/RubberduckIoCInstaller.cs +++ b/Rubberduck.Main/Root/RubberduckIoCInstaller.cs @@ -149,6 +149,7 @@ public void Install(IWindsorContainer container, IConfigurationStore store) .LifestyleSingleton()); RegisterSettingsViewModel(container); + RegisterRefactoringPreviewProviders(container); RegisterRefactoringDialogs(container); container.Register(Component.For() @@ -156,8 +157,7 @@ public void Install(IWindsorContainer container, IConfigurationStore store) .LifestyleSingleton()); container.Register(Component.For() .LifestyleSingleton()); - - RegisterRefactoringDialogs(container); + RegisterDockablePresenters(container); RegisterDockableUserControls(container); @@ -715,6 +715,23 @@ private void RegisterSettingsViewModel(IWindsorContainer container) ); } + private void RegisterRefactoringPreviewProviders(IWindsorContainer container) + { + container.Register(Types + .FromAssemblyInThisApplication() + .IncludeNonPublicTypes() + .BasedOn(typeof(IRefactoringPreviewProvider<>)) + .LifestyleSingleton() + .WithServiceSelect((type, types) => + { + var face = type.GetInterfaces().FirstOrDefault(i => + i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IRefactoringPreviewProvider<>)); + + return face == null ? new[] { type } : new[] { type, face }; + }) + ); + } + private void RegisterRefactoringDialogs(IWindsorContainer container) { container.Register(Types diff --git a/Rubberduck.Refactorings/Abstract/InteractiveRefactoringBase.cs b/Rubberduck.Refactorings/Abstract/InteractiveRefactoringBase.cs index e8939954c8..a2bb6e75d4 100644 --- a/Rubberduck.Refactorings/Abstract/InteractiveRefactoringBase.cs +++ b/Rubberduck.Refactorings/Abstract/InteractiveRefactoringBase.cs @@ -1,5 +1,4 @@ -using Rubberduck.Parsing.Rewriter; -using Rubberduck.VBEditor.Utility; +using Rubberduck.VBEditor.Utility; using System; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.UIContext; @@ -13,12 +12,11 @@ public abstract class InteractiveRefactoringBase : Refactori { private readonly Func> _presenterFactory; - protected InteractiveRefactoringBase( - IRewritingManager rewritingManager, + protected InteractiveRefactoringBase( ISelectionProvider selectionProvider, IRefactoringPresenterFactory factory, IUiDispatcher uiDispatcher) - :base(rewritingManager, selectionProvider) + :base(selectionProvider) { Action presenterDisposalAction = (TPresenter presenter) => uiDispatcher.Invoke(() => factory.Release(presenter)); _presenterFactory = ((model) => DisposalActionContainer.Create(factory.Create(model), presenterDisposalAction)); diff --git a/Rubberduck.Refactorings/Abstract/RefactoringBase.cs b/Rubberduck.Refactorings/Abstract/RefactoringBase.cs index 3985a4881c..9fa6d9ef81 100644 --- a/Rubberduck.Refactorings/Abstract/RefactoringBase.cs +++ b/Rubberduck.Refactorings/Abstract/RefactoringBase.cs @@ -1,5 +1,4 @@ -using Rubberduck.Parsing.Rewriter; -using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.Symbols; using Rubberduck.Refactorings.Exceptions; using Rubberduck.VBEditor; using Rubberduck.VBEditor.Utility; @@ -8,12 +7,10 @@ namespace Rubberduck.Refactorings { public abstract class RefactoringBase : IRefactoring { - protected readonly IRewritingManager RewritingManager; protected readonly ISelectionProvider SelectionProvider; - protected RefactoringBase(IRewritingManager rewritingManager, ISelectionProvider selectionProvider) + protected RefactoringBase(ISelectionProvider selectionProvider) { - RewritingManager = rewritingManager; SelectionProvider = selectionProvider; } diff --git a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs index 79eb9ae826..8e8efbe774 100644 --- a/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs +++ b/Rubberduck.Refactorings/EncapsulateField/EncapsulateFieldRefactoring.cs @@ -27,6 +27,7 @@ public class EncapsulateFieldRefactoring : InteractiveRefactoringBase userInteraction) @@ -99,7 +101,7 @@ protected override EncapsulateFieldModel InitializeModel(Declaration target) protected override void RefactorImpl(EncapsulateFieldModel model) { - var refactorRewriteSession = new EncapsulateFieldRewriteSession(RewritingManager.CheckOutCodePaneSession()) as IEncapsulateFieldRewriteSession; + var refactorRewriteSession = new EncapsulateFieldRewriteSession(_rewritingManager.CheckOutCodePaneSession()) as IEncapsulateFieldRewriteSession; refactorRewriteSession = RefactorRewrite(model, refactorRewriteSession); @@ -111,7 +113,7 @@ protected override void RefactorImpl(EncapsulateFieldModel model) private string PreviewRewrite(EncapsulateFieldModel model) { - var previewSession = new EncapsulateFieldRewriteSession(RewritingManager.CheckOutCodePaneSession()) as IEncapsulateFieldRewriteSession; ; + var previewSession = new EncapsulateFieldRewriteSession(_rewritingManager.CheckOutCodePaneSession()) as IEncapsulateFieldRewriteSession; ; previewSession = RefactorRewrite(model, previewSession, true); diff --git a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs index fc4c22f781..20b910e12d 100644 --- a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs +++ b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs @@ -1,7 +1,6 @@ using System.Linq; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.UIContext; using Rubberduck.Parsing.VBA; @@ -20,10 +19,9 @@ public ExtractInterfaceRefactoring( ExtractInterfaceBaseRefactoring baseRefactoring, IDeclarationFinderProvider declarationFinderProvider, IRefactoringPresenterFactory factory, - IRewritingManager rewritingManager, ISelectionProvider selectionProvider, IUiDispatcher uiDispatcher) - :base(rewritingManager, selectionProvider, factory, uiDispatcher) + :base(selectionProvider, factory, uiDispatcher) { _baseRefactoring = baseRefactoring; _declarationFinderProvider = declarationFinderProvider; diff --git a/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceRefactoring.cs b/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceRefactoring.cs index 2a967ecbbd..387001c227 100644 --- a/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceRefactoring.cs +++ b/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceRefactoring.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings.Exceptions; @@ -19,9 +18,8 @@ public class ImplementInterfaceRefactoring : RefactoringBase public ImplementInterfaceRefactoring( ImplementInterfaceBaseRefactoring baseRefactoring, IDeclarationFinderProvider declarationFinderProvider, - IRewritingManager rewritingManager, ISelectionProvider selectionProvider) - :base(rewritingManager, selectionProvider) + :base(selectionProvider) { _baseRefactoring = baseRefactoring; _declarationFinderProvider = declarationFinderProvider; diff --git a/Rubberduck.Refactorings/IntroduceField/IntroduceFieldRefactoring.cs b/Rubberduck.Refactorings/IntroduceField/IntroduceFieldRefactoring.cs index f7063e82d4..f6a2b46b23 100644 --- a/Rubberduck.Refactorings/IntroduceField/IntroduceFieldRefactoring.cs +++ b/Rubberduck.Refactorings/IntroduceField/IntroduceFieldRefactoring.cs @@ -1,5 +1,4 @@ using System.Linq; -using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings.Exceptions; @@ -16,10 +15,9 @@ public class IntroduceFieldRefactoring : RefactoringBase public IntroduceFieldRefactoring( IntroduceFieldBaseRefactoring baseRefactoring, - IRewritingManager rewritingManager, ISelectionProvider selectionProvider, ISelectedDeclarationProvider selectedDeclarationProvider) - :base(rewritingManager, selectionProvider) + :base(selectionProvider) { _baseRefactoring = baseRefactoring; _selectedDeclarationProvider = selectedDeclarationProvider; diff --git a/Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterRefactoring.cs b/Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterRefactoring.cs index d5ba1f8dea..bf83202cd1 100644 --- a/Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterRefactoring.cs +++ b/Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterRefactoring.cs @@ -1,9 +1,4 @@ -using System.Collections.Generic; -using System.Linq; -using Rubberduck.Interaction; -using Rubberduck.Parsing; -using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Rewriter; +using Rubberduck.Interaction; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings.Exceptions; @@ -23,10 +18,9 @@ public class IntroduceParameterRefactoring : RefactoringBase public IntroduceParameterRefactoring( IntroduceParameterBaseRefactoring baseRefactoring, IMessageBox messageBox, - IRewritingManager rewritingManager, ISelectionProvider selectionProvider, ISelectedDeclarationProvider selectedDeclarationProvider) - :base(rewritingManager, selectionProvider) + :base(selectionProvider) { _baseRefactoring = baseRefactoring; _selectedDeclarationProvider = selectedDeclarationProvider; diff --git a/Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageRefactoring.cs b/Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageRefactoring.cs index c4db966096..b5bce9aaca 100644 --- a/Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageRefactoring.cs +++ b/Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageRefactoring.cs @@ -1,5 +1,4 @@ using System.Linq; -using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Refactorings.Exceptions; @@ -17,11 +16,10 @@ public class MoveCloserToUsageRefactoring : RefactoringBase public MoveCloserToUsageRefactoring( MoveCloserToUsageBaseRefactoring baseRefactoring, - IDeclarationFinderProvider declarationFinderProvider, - IRewritingManager rewritingManager, + IDeclarationFinderProvider declarationFinderProvider, ISelectionProvider selectionProvider, ISelectedDeclarationProvider selectedDeclarationProvider) - :base(rewritingManager, selectionProvider) + :base(selectionProvider) { _baseRefactoring = baseRefactoring; _declarationFinderProvider = declarationFinderProvider; diff --git a/Rubberduck.Refactorings/RemoveParameters/RemoveParametersRefactoring.cs b/Rubberduck.Refactorings/RemoveParameters/RemoveParametersRefactoring.cs index 902c65be7b..b021ebbe86 100644 --- a/Rubberduck.Refactorings/RemoveParameters/RemoveParametersRefactoring.cs +++ b/Rubberduck.Refactorings/RemoveParameters/RemoveParametersRefactoring.cs @@ -1,5 +1,4 @@ using System.Linq; -using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.UIContext; using Rubberduck.Parsing.VBA; @@ -20,11 +19,10 @@ public RemoveParametersRefactoring( RemoveParameterBaseRefactoring baseRefactoring, IDeclarationFinderProvider declarationFinderProvider, IRefactoringPresenterFactory factory, - IRewritingManager rewritingManager, ISelectionProvider selectionProvider, ISelectedDeclarationProvider selectedDeclarationProvider, IUiDispatcher uiDispatcher) - :base(rewritingManager, selectionProvider, factory, uiDispatcher) + :base(selectionProvider, factory, uiDispatcher) { _baseRefactoring = baseRefactoring; _declarationFinderProvider = declarationFinderProvider; diff --git a/Rubberduck.Refactorings/Rename/RenameRefactoring.cs b/Rubberduck.Refactorings/Rename/RenameRefactoring.cs index 4aae96677a..2e50009c82 100644 --- a/Rubberduck.Refactorings/Rename/RenameRefactoring.cs +++ b/Rubberduck.Refactorings/Rename/RenameRefactoring.cs @@ -3,7 +3,6 @@ using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor; using System.Collections.Generic; -using Rubberduck.Parsing.Rewriter; using Rubberduck.Refactorings.Exceptions; using Rubberduck.Refactorings.Exceptions.Rename; using Rubberduck.VBEditor.ComManagement; @@ -24,11 +23,10 @@ public RenameRefactoring( IRefactoringPresenterFactory factory, IDeclarationFinderProvider declarationFinderProvider, IProjectsProvider projectsProvider, - IRewritingManager rewritingManager, ISelectionProvider selectionProvider, ISelectedDeclarationProvider selectedDeclarationProvider, IUiDispatcher uiDispatcher) - : base(rewritingManager, selectionProvider, factory, uiDispatcher) + : base(selectionProvider, factory, uiDispatcher) { _baseRefactoring = baseRefactoring; _declarationFinderProvider = declarationFinderProvider; diff --git a/Rubberduck.Refactorings/ReorderParameters/ReorderParametersRefactoring.cs b/Rubberduck.Refactorings/ReorderParameters/ReorderParametersRefactoring.cs index dd471bc2e1..627ca0dc95 100644 --- a/Rubberduck.Refactorings/ReorderParameters/ReorderParametersRefactoring.cs +++ b/Rubberduck.Refactorings/ReorderParameters/ReorderParametersRefactoring.cs @@ -1,6 +1,5 @@ using Rubberduck.Parsing.Symbols; using Rubberduck.VBEditor; -using Rubberduck.Parsing.Rewriter; using System.Linq; using Rubberduck.Parsing.UIContext; using Rubberduck.Parsing.VBA; @@ -19,11 +18,10 @@ public ReorderParametersRefactoring( ReorderParameterBaseRefactoring baseRefactoring, IDeclarationFinderProvider declarationFinderProvider, IRefactoringPresenterFactory factory, - IRewritingManager rewritingManager, ISelectionProvider selectionProvider, ISelectedDeclarationProvider selectedDeclarationProvider, IUiDispatcher uiDispatcher) - :base(rewritingManager, selectionProvider, factory, uiDispatcher) + :base(selectionProvider, factory, uiDispatcher) { _baseRefactoring = baseRefactoring; _declarationFinderProvider = declarationFinderProvider; diff --git a/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs b/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs index 2ae5e22bff..b9c870fa55 100644 --- a/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs +++ b/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs @@ -506,7 +506,7 @@ public MockedCodeExplorer ImplementExtractInterfaceCommand() var addImplementationsBaseRefactoring = new AddInterFaceImplementationsBaseRefactoring(null); var extractInterfaceBaseRefactoring = new ExtractInterfaceBaseRefactoring(addImplementationsBaseRefactoring, State, State, null); ViewModel.CodeExplorerExtractInterfaceCommand = new CodeExplorerExtractInterfaceCommand( - new ExtractInterfaceRefactoring(extractInterfaceBaseRefactoring, State, null, null, null, _uiDispatcher.Object), + new ExtractInterfaceRefactoring(extractInterfaceBaseRefactoring, State, null, null, _uiDispatcher.Object), State, null, VbeEvents.Object); return this; } diff --git a/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs b/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs index aa6a67b7a2..b30e49c7c3 100644 --- a/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs +++ b/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs @@ -173,7 +173,7 @@ protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state .Callback((Action action) => action.Invoke()); var addImplementationsBaseRefactoring = new AddInterFaceImplementationsBaseRefactoring(rewritingManager); var baseRefactoring = new ExtractInterfaceBaseRefactoring(addImplementationsBaseRefactoring, state, state, rewritingManager); - var refactoring = new ExtractInterfaceRefactoring(baseRefactoring, state, factory, rewritingManager, selectionService, uiDispatcherMock.Object); + var refactoring = new ExtractInterfaceRefactoring(baseRefactoring, state, factory, selectionService, uiDispatcherMock.Object); 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 1230baf014..159289498a 100644 --- a/RubberduckTests/Commands/RefactorCommands/ImplementInterfaceCommandTests.cs +++ b/RubberduckTests/Commands/RefactorCommands/ImplementInterfaceCommandTests.cs @@ -59,7 +59,7 @@ protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state var msgBox = new Mock().Object; var addImplementationsBaseRefactoring = new AddInterFaceImplementationsBaseRefactoring(rewritingManager); var baseRefactoring = new ImplementInterfaceBaseRefactoring(addImplementationsBaseRefactoring, rewritingManager); - var refactoring = new ImplementInterfaceRefactoring(baseRefactoring, state, rewritingManager, selectionService); + var refactoring = new ImplementInterfaceRefactoring(baseRefactoring, state, selectionService); var notifier = new ImplementInterfaceFailedNotifier(msgBox); return new RefactorImplementInterfaceCommand(refactoring, notifier, state, selectionService); } diff --git a/RubberduckTests/Commands/RefactorCommands/IntroduceFieldCommandTests.cs b/RubberduckTests/Commands/RefactorCommands/IntroduceFieldCommandTests.cs index f554640c48..524e47671f 100644 --- a/RubberduckTests/Commands/RefactorCommands/IntroduceFieldCommandTests.cs +++ b/RubberduckTests/Commands/RefactorCommands/IntroduceFieldCommandTests.cs @@ -44,7 +44,7 @@ protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state var msgBox = new Mock().Object; var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); var baseRefactoring = new IntroduceFieldBaseRefactoring(state, rewritingManager); - var refactoring = new IntroduceFieldRefactoring(baseRefactoring, rewritingManager, selectionService, selectedDeclarationProvider); + var refactoring = new IntroduceFieldRefactoring(baseRefactoring, selectionService, selectedDeclarationProvider); var notifier = new IntroduceFieldFailedNotifier(msgBox); return new RefactorIntroduceFieldCommand(refactoring, notifier, state, selectionService, selectedDeclarationProvider); } diff --git a/RubberduckTests/Commands/RefactorCommands/IntroduceParameterCommandTests.cs b/RubberduckTests/Commands/RefactorCommands/IntroduceParameterCommandTests.cs index cf6313d9b1..363cfe6b49 100644 --- a/RubberduckTests/Commands/RefactorCommands/IntroduceParameterCommandTests.cs +++ b/RubberduckTests/Commands/RefactorCommands/IntroduceParameterCommandTests.cs @@ -45,7 +45,7 @@ protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state var msgBox = new Mock().Object; var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); var baseRefactoring = new IntroduceParameterBaseRefactoring(state, rewritingManager); - var refactoring = new IntroduceParameterRefactoring(baseRefactoring, msgBox, rewritingManager, selectionService, selectedDeclarationProvider); + var refactoring = new IntroduceParameterRefactoring(baseRefactoring, msgBox, selectionService, selectedDeclarationProvider); var notifier = new IntroduceParameterFailedNotifier(msgBox); return new RefactorIntroduceParameterCommand(refactoring, notifier, state, selectionService, selectedDeclarationProvider); } diff --git a/RubberduckTests/Commands/RefactorCommands/MoveCloserToUsageCommandTests.cs b/RubberduckTests/Commands/RefactorCommands/MoveCloserToUsageCommandTests.cs index 5c88e397dd..864a93f99c 100644 --- a/RubberduckTests/Commands/RefactorCommands/MoveCloserToUsageCommandTests.cs +++ b/RubberduckTests/Commands/RefactorCommands/MoveCloserToUsageCommandTests.cs @@ -99,7 +99,7 @@ protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state var msgBox = new Mock().Object; var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); var baseRefactoring = new MoveCloserToUsageBaseRefactoring(rewritingManager); - var refactoring = new MoveCloserToUsageRefactoring(baseRefactoring, state, rewritingManager, selectionService, selectedDeclarationProvider); + var refactoring = new MoveCloserToUsageRefactoring(baseRefactoring, state, selectionService, selectedDeclarationProvider); var notifier = new MoveCloserToUsageFailedNotifier(msgBox); var selectedDeclarationService = new SelectedDeclarationProvider(selectionService, state); return new RefactorMoveCloserToUsageCommand(refactoring, notifier, state, selectionService, selectedDeclarationService); diff --git a/RubberduckTests/Commands/RefactorCommands/RemoveParametersCommandTests.cs b/RubberduckTests/Commands/RefactorCommands/RemoveParametersCommandTests.cs index 1b99afd10a..77efcd58cd 100644 --- a/RubberduckTests/Commands/RefactorCommands/RemoveParametersCommandTests.cs +++ b/RubberduckTests/Commands/RefactorCommands/RemoveParametersCommandTests.cs @@ -171,7 +171,7 @@ protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); var baseRefactoring = new RemoveParameterBaseRefactoring(state, rewritingManager); - var refactoring = new RemoveParametersRefactoring(baseRefactoring, state, factory, rewritingManager, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); + var refactoring = new RemoveParametersRefactoring(baseRefactoring, state, factory, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); var notifier = new RemoveParameterFailedNotifier(msgBox); return new RefactorRemoveParametersCommand(refactoring, notifier, state, selectionService, selectedDeclarationProvider); } diff --git a/RubberduckTests/Commands/RefactorCommands/ReorderParametersCommandTests.cs b/RubberduckTests/Commands/RefactorCommands/ReorderParametersCommandTests.cs index b513c13559..41c18a7498 100644 --- a/RubberduckTests/Commands/RefactorCommands/ReorderParametersCommandTests.cs +++ b/RubberduckTests/Commands/RefactorCommands/ReorderParametersCommandTests.cs @@ -171,7 +171,7 @@ protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); var baseRefactoring = new ReorderParameterBaseRefactoring(state, rewritingManager); - var refactoring = new ReorderParametersRefactoring(baseRefactoring, state, factory, rewritingManager, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); + var refactoring = new ReorderParametersRefactoring(baseRefactoring, state, factory, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); var notifier = new ReorderParametersFailedNotifier(msgBox); return new RefactorReorderParametersCommand(refactoring, notifier, state, selectionService, selectedDeclarationProvider); } diff --git a/RubberduckTests/QuickFixes/MoveFieldCloserToUsageQuickFixTests.cs b/RubberduckTests/QuickFixes/MoveFieldCloserToUsageQuickFixTests.cs index 31b9adf32b..8949312e0b 100644 --- a/RubberduckTests/QuickFixes/MoveFieldCloserToUsageQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/MoveFieldCloserToUsageQuickFixTests.cs @@ -129,7 +129,7 @@ private string ApplyQuickFixToFirstInspectionResult(string inputCode) var selectionService = MockedSelectionService(); var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); var baseRefactoring = new MoveCloserToUsageBaseRefactoring(rewritingManager); - var refactoring = new MoveCloserToUsageRefactoring(baseRefactoring, state, rewritingManager, selectionService, selectedDeclarationProvider); + var refactoring = new MoveCloserToUsageRefactoring(baseRefactoring, state, selectionService, selectedDeclarationProvider); var quickFix = new MoveFieldCloserToUsageQuickFix(refactoring); quickFix.Fix(resultToFix, rewriteSession); diff --git a/RubberduckTests/QuickFixes/RemoveUnusedParameterQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveUnusedParameterQuickFixTests.cs index 752edd3186..fc21642964 100644 --- a/RubberduckTests/QuickFixes/RemoveUnusedParameterQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveUnusedParameterQuickFixTests.cs @@ -48,7 +48,7 @@ Private Sub Foo() .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); var baseRefactoring = new RemoveParameterBaseRefactoring(state, rewritingManager); - var refactoring = new RemoveParametersRefactoring(baseRefactoring, state, factory, rewritingManager, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); + var refactoring = new RemoveParametersRefactoring(baseRefactoring, state, factory, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); new RemoveUnusedParameterQuickFix(refactoring) .Fix(inspectionResults.First(), rewriteSession); Assert.AreEqual(expectedCode, component.CodeModule.Content()); diff --git a/RubberduckTests/Refactoring/ExtractInterfaceTests.cs b/RubberduckTests/Refactoring/ExtractInterfaceTests.cs index 2cdffe9a7e..98cf880f72 100644 --- a/RubberduckTests/Refactoring/ExtractInterfaceTests.cs +++ b/RubberduckTests/Refactoring/ExtractInterfaceTests.cs @@ -427,7 +427,7 @@ protected override IRefactoring TestRefactoring(IRewritingManager rewritingManag .Callback((Action action) => action.Invoke()); var addImplementationsBaseRefactoring = new AddInterFaceImplementationsBaseRefactoring(rewritingManager); var baseRefactoring = new ExtractInterfaceBaseRefactoring(addImplementationsBaseRefactoring, state, state, rewritingManager); - return new ExtractInterfaceRefactoring(baseRefactoring, state, factory, rewritingManager, selectionService, uiDispatcherMock.Object); + return new ExtractInterfaceRefactoring(baseRefactoring, state, factory, selectionService, uiDispatcherMock.Object); } } } \ No newline at end of file diff --git a/RubberduckTests/Refactoring/ImplementInterfaceTests.cs b/RubberduckTests/Refactoring/ImplementInterfaceTests.cs index e13697b906..e4a80a2ecd 100644 --- a/RubberduckTests/Refactoring/ImplementInterfaceTests.cs +++ b/RubberduckTests/Refactoring/ImplementInterfaceTests.cs @@ -913,7 +913,7 @@ protected override IRefactoring TestRefactoring(IRewritingManager rewritingManag { var addImplementationsBaseRefactoring = new AddInterFaceImplementationsBaseRefactoring(rewritingManager); var baseRefactoring = new ImplementInterfaceBaseRefactoring(addImplementationsBaseRefactoring, rewritingManager); - return new ImplementInterfaceRefactoring(baseRefactoring, state, rewritingManager, selectionService); + return new ImplementInterfaceRefactoring(baseRefactoring, state, selectionService); } } } diff --git a/RubberduckTests/Refactoring/IntroduceFieldTests.cs b/RubberduckTests/Refactoring/IntroduceFieldTests.cs index 24c60fb422..9676e8f174 100644 --- a/RubberduckTests/Refactoring/IntroduceFieldTests.cs +++ b/RubberduckTests/Refactoring/IntroduceFieldTests.cs @@ -351,7 +351,7 @@ protected override IRefactoring TestRefactoring(IRewritingManager rewritingManag { var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); var baseRefactoring = new IntroduceFieldBaseRefactoring(state, rewritingManager); - return new IntroduceFieldRefactoring(baseRefactoring, rewritingManager, selectionService, selectedDeclarationProvider); + return new IntroduceFieldRefactoring(baseRefactoring, selectionService, selectedDeclarationProvider); } } } diff --git a/RubberduckTests/Refactoring/IntroduceParameterTests.cs b/RubberduckTests/Refactoring/IntroduceParameterTests.cs index 57e326a021..97419367c3 100644 --- a/RubberduckTests/Refactoring/IntroduceParameterTests.cs +++ b/RubberduckTests/Refactoring/IntroduceParameterTests.cs @@ -560,7 +560,7 @@ private static IRefactoring TestRefactoring(IRewritingManager rewritingManager, } var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); var baseRefactoring = new IntroduceParameterBaseRefactoring(state, rewritingManager); - return new IntroduceParameterRefactoring(baseRefactoring, msgBox, rewritingManager, selectionService, selectedDeclarationProvider); + return new IntroduceParameterRefactoring(baseRefactoring, msgBox, selectionService, selectedDeclarationProvider); } private IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IMessageBox msgBox = null, QualifiedSelection? initialSelection = null) diff --git a/RubberduckTests/Refactoring/MoveCloserToUsageTests.cs b/RubberduckTests/Refactoring/MoveCloserToUsageTests.cs index 45fc70abc4..3ec996a1c7 100644 --- a/RubberduckTests/Refactoring/MoveCloserToUsageTests.cs +++ b/RubberduckTests/Refactoring/MoveCloserToUsageTests.cs @@ -1076,7 +1076,7 @@ protected override IRefactoring TestRefactoring(IRewritingManager rewritingManag { var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); var baseRefactoring = new MoveCloserToUsageBaseRefactoring(rewritingManager); - return new MoveCloserToUsageRefactoring(baseRefactoring, state, rewritingManager, selectionService, selectedDeclarationProvider); + return new MoveCloserToUsageRefactoring(baseRefactoring, state, selectionService, selectedDeclarationProvider); } } } diff --git a/RubberduckTests/Refactoring/RemoveParametersTests.cs b/RubberduckTests/Refactoring/RemoveParametersTests.cs index b21e42cb32..69221e7ed9 100644 --- a/RubberduckTests/Refactoring/RemoveParametersTests.cs +++ b/RubberduckTests/Refactoring/RemoveParametersTests.cs @@ -1975,7 +1975,7 @@ protected override IRefactoring TestRefactoring(IRewritingManager rewritingManag .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); var baseRefactoring = new RemoveParameterBaseRefactoring(state, rewritingManager); - return new RemoveParametersRefactoring(baseRefactoring, state, factory, rewritingManager, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); + return new RemoveParametersRefactoring(baseRefactoring, state, factory, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); } } } diff --git a/RubberduckTests/Refactoring/Rename/RenameTests.cs b/RubberduckTests/Refactoring/Rename/RenameTests.cs index ff93b9c7d7..5936bb8884 100644 --- a/RubberduckTests/Refactoring/Rename/RenameTests.cs +++ b/RubberduckTests/Refactoring/Rename/RenameTests.cs @@ -3370,7 +3370,7 @@ protected override IRefactoring TestRefactoring(IRewritingManager rewritingManag .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); var baseRefactoring = new RenameBaseRefactoring(state, state?.ProjectsProvider, state, rewritingManager); - return new RenameRefactoring(baseRefactoring, factory, state, state?.ProjectsProvider, rewritingManager, selectionService, selectedDeclarationService, uiDispatcherMock.Object); + return new RenameRefactoring(baseRefactoring, factory, state, state?.ProjectsProvider, selectionService, selectedDeclarationService, uiDispatcherMock.Object); } #endregion diff --git a/RubberduckTests/Refactoring/ReorderParametersTests.cs b/RubberduckTests/Refactoring/ReorderParametersTests.cs index ea35734d6f..437ac3db5e 100644 --- a/RubberduckTests/Refactoring/ReorderParametersTests.cs +++ b/RubberduckTests/Refactoring/ReorderParametersTests.cs @@ -1349,7 +1349,7 @@ protected override IRefactoring TestRefactoring( .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); var baseRefactoring = new ReorderParameterBaseRefactoring(state, rewritingManager); - return new ReorderParametersRefactoring(baseRefactoring, state, factory, rewritingManager, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); + return new ReorderParametersRefactoring(baseRefactoring, state, factory, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); } private static Func ReverseParameters() From eb8dd7b3e8452127ae91c2b8c3abfc629db197af Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Fri, 14 Feb 2020 00:42:02 +0100 Subject: [PATCH 227/461] Add MoveToFolderBaseRefactoring Also adds BaseRefactoringTestBase to support testing the base refactorings in separation from the full implementations of IRefactoring. --- .../Annotations/Concrete/FolderAnnotation.cs | 7 +- .../MoveToFolderBaseRefactoring.cs | 63 ++++++++++++++++ .../MoveToFolder/MoveToFolderModel.cs | 16 ++++ .../Refactoring/BaseRefactoringTestBase.cs | 62 ++++++++++++++++ .../Refactoring/MoveToFolderTests.cs | 74 +++++++++++++++++++ 5 files changed, 216 insertions(+), 6 deletions(-) create mode 100644 Rubberduck.Refactorings/MoveToFolder/MoveToFolderBaseRefactoring.cs create mode 100644 Rubberduck.Refactorings/MoveToFolder/MoveToFolderModel.cs create mode 100644 RubberduckTests/Refactoring/BaseRefactoringTestBase.cs create mode 100644 RubberduckTests/Refactoring/MoveToFolderTests.cs diff --git a/Rubberduck.Parsing/Annotations/Concrete/FolderAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/FolderAnnotation.cs index 85bcc0c611..52cddc53c4 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/FolderAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/FolderAnnotation.cs @@ -1,9 +1,4 @@ -using Rubberduck.VBEditor; -using System.Collections.Generic; -using System.Linq; -using Rubberduck.Parsing.Grammar; - -namespace Rubberduck.Parsing.Annotations +namespace Rubberduck.Parsing.Annotations { /// /// Used for specifying the Code Explorer folder a appears under. diff --git a/Rubberduck.Refactorings/MoveToFolder/MoveToFolderBaseRefactoring.cs b/Rubberduck.Refactorings/MoveToFolder/MoveToFolderBaseRefactoring.cs new file mode 100644 index 0000000000..1e851ee159 --- /dev/null +++ b/Rubberduck.Refactorings/MoveToFolder/MoveToFolderBaseRefactoring.cs @@ -0,0 +1,63 @@ +using System.Collections.Generic; +using System.Linq; +using Rubberduck.Common; +using Rubberduck.Parsing.Annotations; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.VBA; + +namespace Rubberduck.Refactorings.MoveToFolder +{ + public class MoveToFolderBaseRefactoring : CodeOnlyBaseRefactoringBase + { + private readonly IAnnotationUpdater _annotationUpdater; + + public MoveToFolderBaseRefactoring( + IRewritingManager rewritingManager, + IAnnotationUpdater annotationUpdater) + : base(rewritingManager) + { + _annotationUpdater = annotationUpdater; + } + + public override void Refactor(MoveToFolderModel model, IRewriteSession rewriteSession) + { + var oldFolderAnnotation = model.Target.Annotations.FirstOrDefault(pta => pta.Annotation is FolderAnnotation); + if (oldFolderAnnotation != null) + { + UpdateFolderAnnotation(model, oldFolderAnnotation, rewriteSession); + } + else + { + AddFolderAnnotation(model, rewriteSession); + } + } + + private void UpdateFolderAnnotation(MoveToFolderModel model, IParseTreeAnnotation oldPta, IRewriteSession rewriteSession) + { + var oldFolderName = oldPta.AnnotationArguments.FirstOrDefault(); + if (oldFolderName == null || oldFolderName.Equals(model.TargetFolder)) + { + return; + } + + var (annotation, annotationValues) = NewAnnotation(model.TargetFolder); + + _annotationUpdater.UpdateAnnotation(rewriteSession, oldPta, annotation, annotationValues); + } + + private static (IAnnotation annotation, IReadOnlyList annotationArguments) NewAnnotation(string targetFolder) + { + var annotation = new FolderAnnotation(); + var annotationValues = new List { targetFolder.EnQuote() }; + + return (annotation, annotationValues); + } + + private void AddFolderAnnotation(MoveToFolderModel model, IRewriteSession rewriteSession) + { + var (annotation, annotationValues) = NewAnnotation(model.TargetFolder); + + _annotationUpdater.AddAnnotation(rewriteSession, model.Target, annotation, annotationValues); + } + } +} \ No newline at end of file diff --git a/Rubberduck.Refactorings/MoveToFolder/MoveToFolderModel.cs b/Rubberduck.Refactorings/MoveToFolder/MoveToFolderModel.cs new file mode 100644 index 0000000000..4dea0dfe63 --- /dev/null +++ b/Rubberduck.Refactorings/MoveToFolder/MoveToFolderModel.cs @@ -0,0 +1,16 @@ +using Rubberduck.Parsing.Symbols; + +namespace Rubberduck.Refactorings.MoveToFolder +{ + public class MoveToFolderModel : IRefactoringModel + { + public ModuleDeclaration Target { get; } + public string TargetFolder { get; } + + public MoveToFolderModel(ModuleDeclaration target, string targetFolder) + { + Target = target; + TargetFolder = targetFolder; + } + } +} \ No newline at end of file diff --git a/RubberduckTests/Refactoring/BaseRefactoringTestBase.cs b/RubberduckTests/Refactoring/BaseRefactoringTestBase.cs new file mode 100644 index 0000000000..7f7136258b --- /dev/null +++ b/RubberduckTests/Refactoring/BaseRefactoringTestBase.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.VBA; +using Rubberduck.Refactorings; +using Rubberduck.VBEditor; +using Rubberduck.VBEditor.SafeComWrappers; +using Rubberduck.VBEditor.SafeComWrappers.Abstract; +using RubberduckTests.Mocks; + +namespace RubberduckTests.Refactoring +{ + public abstract class BaseRefactoringTestBase + where TModel : class, IRefactoringModel + { + + protected string RefactoredCode(string code, Func modelBuilder) + { + var vbe = TestVbe(code, out _); + var componentName = vbe.SelectedVBComponent.Name; + var refactored = RefactoredCode(vbe, modelBuilder); + return refactored[componentName]; + } + + protected IDictionary RefactoredCode(Func modelBuilder, params (string componentName, string content, ComponentType componentType)[] modules) + { + var vbe = TestVbe(modules); + return RefactoredCode(vbe, modelBuilder); + } + + protected IDictionary RefactoredCode(IVBE vbe, Func modelBuilder) + { + var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe); + using (state) + { + var baseRefactoring = TestBaseRefactoring(state, rewritingManager); + var model = modelBuilder(state); + + baseRefactoring.Refactor(model); + + return vbe.ActiveVBProject.VBComponents + .ToDictionary(component => component.Name, component => component.CodeModule.Content()); + } + } + + protected abstract IBaseRefactoring TestBaseRefactoring( + RubberduckParserState state, + IRewritingManager rewritingManager + ); + + protected virtual IVBE TestVbe(string content, out IVBComponent component, Selection? selection = null) + { + return MockVbeBuilder.BuildFromSingleStandardModule(content, out component, selection ?? default).Object; + } + + protected virtual IVBE TestVbe(params (string componentName, string content, ComponentType componentType)[] modules) + { + return MockVbeBuilder.BuildFromModules(modules).Object; + } + } +} \ No newline at end of file diff --git a/RubberduckTests/Refactoring/MoveToFolderTests.cs b/RubberduckTests/Refactoring/MoveToFolderTests.cs new file mode 100644 index 0000000000..8b775b4a9f --- /dev/null +++ b/RubberduckTests/Refactoring/MoveToFolderTests.cs @@ -0,0 +1,74 @@ +using System; +using System.Linq; +using NUnit.Framework; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.Refactorings; +using Rubberduck.Refactorings.MoveToFolder; + +namespace RubberduckTests.Refactoring +{ + [TestFixture] + public class MoveToFolderTests : BaseRefactoringTestBase + { + [Test] + [Category("Refactorings")] + public void MoveToFolderBaseRefactoring_NoAnnotation() + { + const string code = @" +Public Sub Foo() +End Sub +"; + const string expectedCode = @"'@Folder ""MyNewFolder.MySubFolder"" + +Public Sub Foo() +End Sub +"; + Func modelBuilder = (state) => + { + var module = state.DeclarationFinder + .UserDeclarations(DeclarationType.ProceduralModule) + .Single() as ModuleDeclaration; + return new MoveToFolderModel(module, "MyNewFolder.MySubFolder"); + }; + + var refactoredCode = RefactoredCode(code, modelBuilder); + + Assert.AreEqual(expectedCode, refactoredCode); + } + + [Test] + [Category("Refactorings")] + public void MoveToFolderBaseRefactoring_UpdateAnnotation() + { + const string code = @" +'@Folder(""MyOldFolder.MyOldSubfolder.SubSub"") +Public Sub Foo() +End Sub +"; + const string expectedCode = @" +'@Folder ""MyNewFolder.MySubFolder"" +Public Sub Foo() +End Sub +"; + Func modelBuilder = (state) => + { + var module = state.DeclarationFinder + .UserDeclarations(DeclarationType.ProceduralModule) + .Single() as ModuleDeclaration; + return new MoveToFolderModel(module, "MyNewFolder.MySubFolder"); + }; + + var refactoredCode = RefactoredCode(code, modelBuilder); + + Assert.AreEqual(expectedCode, refactoredCode); + } + + protected override IBaseRefactoring TestBaseRefactoring(RubberduckParserState state, IRewritingManager rewritingManager) + { + var annotationUpdater = new AnnotationUpdater(); + return new MoveToFolderBaseRefactoring(rewritingManager, annotationUpdater); + } + } +} \ No newline at end of file From d26eef58ededf9e71c1ce71ab9a26520c7e8e07a Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sun, 16 Feb 2020 21:42:09 +0100 Subject: [PATCH 228/461] Enhance Implements positioning in ExtractInterfaceRefactoring The implements statement is now placed right below the last already existing one or, in case there is none, below the last Option statement or, in case there is none, at the start of the module. --- .../ExtractInterfaceBaseRefactoring.cs | 67 ++++- .../Refactoring/ExtractInterfaceTests.cs | 228 +++++++++++++++++- 2 files changed, 282 insertions(+), 13 deletions(-) diff --git a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceBaseRefactoring.cs b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceBaseRefactoring.cs index d77d08bc93..4bbd504304 100644 --- a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceBaseRefactoring.cs +++ b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceBaseRefactoring.cs @@ -1,9 +1,12 @@ using System; using System.Linq; +using Antlr4.Runtime; +using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.Parsing; using Rubberduck.Refactorings.AddInterfaceImplementations; using Rubberduck.VBEditor.SafeComWrappers; @@ -12,17 +15,17 @@ namespace Rubberduck.Refactorings.ExtractInterface public class ExtractInterfaceBaseRefactoring : BaseRefactoringWithSuspensionBase { private readonly ICodeOnlyBaseRefactoring _addImplementationsRefactoring; - private readonly IDeclarationFinderProvider _declarationFinderProvider; + private readonly IParseTreeProvider _parseTreeProvider; public ExtractInterfaceBaseRefactoring( AddInterFaceImplementationsBaseRefactoring addImplementationsRefactoring, - IDeclarationFinderProvider declarationFinderProvider, + IParseTreeProvider parseTreeProvider, IParseManager parseManager, IRewritingManager rewritingManager) : base(parseManager, rewritingManager) { _addImplementationsRefactoring = addImplementationsRefactoring; - _declarationFinderProvider = declarationFinderProvider; + _parseTreeProvider = parseTreeProvider; } protected override bool RequiresSuspension(ExtractInterfaceModel model) @@ -44,14 +47,7 @@ private void AddInterface(ExtractInterfaceModel model, IRewriteSession rewriteSe } AddInterfaceClass(model.TargetDeclaration, model.InterfaceName, GetInterfaceModuleBody(model)); - - var rewriter = rewriteSession.CheckOutModuleRewriter(model.TargetDeclaration.QualifiedModuleName); - - var firstNonFieldMember = _declarationFinderProvider.DeclarationFinder.Members(model.TargetDeclaration) - .OrderBy(o => o.Selection) - .First(m => ExtractInterfaceModel.MemberTypes.Contains(m.DeclarationType)); - rewriter.InsertBefore(firstNonFieldMember.Context.Start.TokenIndex, $"Implements {model.InterfaceName}{Environment.NewLine}{Environment.NewLine}"); - + AddImplementsStatement(model, rewriteSession); AddInterfaceMembersToClass(model, rewriteSession); } @@ -77,6 +73,55 @@ private void AddInterfaceClass(Declaration implementingClass, string interfaceNa } } + private void AddImplementsStatement(ExtractInterfaceModel model, IRewriteSession rewriteSession) + { + var rewriter = rewriteSession.CheckOutModuleRewriter(model.TargetDeclaration.QualifiedModuleName); + + var implementsStatement = $"Implements {model.InterfaceName}"; + + var (insertionIndex, isImplementsStatement) = InsertionIndex(model); + + if (insertionIndex == -1) + { + rewriter.InsertBefore(0, $"{implementsStatement}{Environment.NewLine}{Environment.NewLine}"); + } + else + { + rewriter.InsertAfter(insertionIndex, $"{Environment.NewLine}{(isImplementsStatement ? string.Empty : Environment.NewLine)}{implementsStatement}"); + } + } + + private (int index, bool isImplementsStatement) InsertionIndex(ExtractInterfaceModel model) + { + var tree = (ParserRuleContext)_parseTreeProvider.GetParseTree(model.TargetDeclaration.QualifiedModuleName, CodeKind.CodePaneCode); + + var moduleDeclarations = tree.GetDescendent(); + if (moduleDeclarations == null) + { + return (-1, false); + } + + var lastImplementsStatement = moduleDeclarations + .GetDescendents() + .LastOrDefault(); + if (lastImplementsStatement != null) + { + return (lastImplementsStatement.Stop.TokenIndex, true); + } + + var lastOptionStatement = moduleDeclarations + .GetDescendents() + .LastOrDefault(); + if (lastOptionStatement != null) + { + return (lastOptionStatement.Stop.TokenIndex, false); + } + + return (-1, false); + } + + + private void AddInterfaceMembersToClass(ExtractInterfaceModel model, IRewriteSession rewriteSession) { var targetModule = model.TargetDeclaration.QualifiedModuleName; diff --git a/RubberduckTests/Refactoring/ExtractInterfaceTests.cs b/RubberduckTests/Refactoring/ExtractInterfaceTests.cs index 98cf880f72..68c3a544ed 100644 --- a/RubberduckTests/Refactoring/ExtractInterfaceTests.cs +++ b/RubberduckTests/Refactoring/ExtractInterfaceTests.cs @@ -152,8 +152,8 @@ Public Property Set Buzz(value) var selection = new Selection(1, 23, 1, 27); //Expectation - const string expectedCode = @" -Implements IClass + const string expectedCode = @"Implements IClass + Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) End Sub @@ -419,6 +419,230 @@ End Sub Assert.AreEqual(expectedInterfaceCode, actualInterfaceCode); } + [Test] + [Category("Refactorings")] + [Category("Extract Interface")] + public void ExtractInterfaceRefactoring_BelowLastImplementStatement() + { + //Input + const string inputCode = + @" + +Option Explicit + +Implements Interface1 + + +Implements Interface2 + + + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub"; + var selection = new Selection(1, 23, 1, 27); + + //Expectation + const string expectedCode = + @" + +Option Explicit + +Implements Interface1 + + +Implements Interface2 +Implements IClass + + + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub + +Private Sub IClass_Foo(ByVal arg1 As Integer, ByVal arg2 As String) + Err.Raise 5 'TODO implement interface member +End Sub +"; + + const string expectedInterfaceCode = + @"Option Explicit + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub + +"; + Func presenterAction = model => + { + foreach (var interfaceMember in model.Members) + { + interfaceMember.IsSelected = true; + } + + return model; + }; + + var actualCode = RefactoredCode("Class", selection, presenterAction, null, false, + ("Class", inputCode, ComponentType.ClassModule), + ("Interface1", string.Empty, ComponentType.ClassModule), + ("Interface2", string.Empty, ComponentType.ClassModule)); + Assert.AreEqual(expectedCode, actualCode["Class"]); + var actualInterfaceCode = actualCode[actualCode.Keys.Single(componentName => !new[]{"Class", "Interface1", "Interface2"}.Contains(componentName))]; + Assert.AreEqual(expectedInterfaceCode, actualInterfaceCode); + } + + [Test] + [Category("Refactorings")] + [Category("Extract Interface")] + public void ExtractInterfaceRefactoring_BelowLastOptionStatement() + { + //Input + const string inputCode = + @" + +Option Explicit + + + +Option Base 1 + + + + + +Private bar As Variant + + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub"; + var selection = new Selection(1, 23, 1, 27); + + //Expectation + const string expectedCode = + @" + +Option Explicit + + + +Option Base 1 + +Implements IClass + + + + + +Private bar As Variant + + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub + +Private Sub IClass_Foo(ByVal arg1 As Integer, ByVal arg2 As String) + Err.Raise 5 'TODO implement interface member +End Sub +"; + + const string expectedInterfaceCode = + @"Option Explicit + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub + +"; + Func presenterAction = model => + { + foreach (var interfaceMember in model.Members) + { + interfaceMember.IsSelected = true; + } + + return model; + }; + + var actualCode = RefactoredCode("Class", selection, presenterAction, null, false, + ("Class", inputCode, ComponentType.ClassModule)); + Assert.AreEqual(expectedCode, actualCode["Class"]); + var actualInterfaceCode = actualCode[actualCode.Keys.Single(componentName => !componentName.Equals("Class"))]; + Assert.AreEqual(expectedInterfaceCode, actualInterfaceCode); + } + + [Test] + [Category("Refactorings")] + [Category("Extract Interface")] + public void ExtractInterfaceRefactoring_AtTopOfModule() + { + //Input + const string inputCode = + @" + + + + + + + + + + + +Private bar As Variant + + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub"; + var selection = new Selection(1, 23, 1, 27); + + //Expectation + const string expectedCode = + @"Implements IClass + + + + + + + + + + + + + +Private bar As Variant + + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub + +Private Sub IClass_Foo(ByVal arg1 As Integer, ByVal arg2 As String) + Err.Raise 5 'TODO implement interface member +End Sub +"; + + const string expectedInterfaceCode = + @"Option Explicit + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub + +"; + Func presenterAction = model => + { + foreach (var interfaceMember in model.Members) + { + interfaceMember.IsSelected = true; + } + + return model; + }; + + var actualCode = RefactoredCode("Class", selection, presenterAction, null, false, + ("Class", inputCode, ComponentType.ClassModule)); + Assert.AreEqual(expectedCode, actualCode["Class"]); + var actualInterfaceCode = actualCode[actualCode.Keys.Single(componentName => !componentName.Equals("Class"))]; + Assert.AreEqual(expectedInterfaceCode, actualInterfaceCode); + } + protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) { var uiDispatcherMock = new Mock(); From 6efdf2445c67fb4eafe6acf28a8dbb847adc0433 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Mon, 17 Feb 2020 01:13:57 +0100 Subject: [PATCH 229/461] Remove Declaration.Project --- .../ReferenceReconciler.cs | 14 +++- .../Formatters/DeclarationFormatter.cs | 2 +- .../CodeExplorerProjectViewModel.cs | 27 ++++++- .../CodeExplorer/CodeExplorerViewModel.cs | 9 +-- .../AddRemoveReferencesPresenterFactory.cs | 25 ++++-- .../Commands/AddClassModuleCommand.cs | 8 +- .../Commands/AddComponentCommand.cs | 12 ++- .../Commands/AddMDIFormCommand.cs | 15 +++- .../Commands/AddPropertyPageCommand.cs | 8 +- .../Commands/AddStdModuleCommand.cs | 7 +- .../Commands/AddTemplateCommand.cs | 11 ++- .../Commands/AddTestComponentCommand.cs | 19 +++-- .../Commands/AddUserControlCommand.cs | 7 +- .../Commands/AddUserDocumentCommand.cs | 7 +- .../Commands/AddUserFormCommand.cs | 7 +- .../CodeExplorer/Commands/AddVBFormCommand.cs | 7 +- .../UI/CodeExplorer/Commands/ImportCommand.cs | 7 +- .../Commands/OpenProjectPropertiesCommand.cs | 14 +++- .../Commands/SetAsStartupProjectCommand.cs | 33 +++++--- .../Command/ComCommands/ExportAllCommand.cs | 25 ++++-- .../ComCommands/AddTestModuleCommand.cs | 9 ++- Rubberduck.Parsing/Symbols/Declaration.cs | 8 -- .../Symbols/ProjectDeclaration.cs | 11 +-- .../ExtractInterfaceRefactoring.cs | 14 ++-- .../UnitTesting/TestEngine.cs | 16 ++-- .../AddRemoveReferencesSetup.cs | 42 +++++++--- .../ReferenceReconcilerTests.cs | 21 ++--- .../CodeExplorerProjectViewModelTests.cs | 81 +++++++++++-------- .../CodeExplorer/CodeExplorerTestSetup.cs | 8 +- .../CodeExplorer/MockedCodeExplorer.cs | 28 ++++--- .../Commands/ExportAllCommandTests.cs | 18 +++-- .../ExtractInterfaceCommandTests.cs | 2 +- .../Commands/UnitTestCommandTests.cs | 2 +- RubberduckTests/Grammar/ResolverTests.cs | 15 ++-- .../Refactoring/ExtractInterfaceTests.cs | 2 +- .../UnitTesting/MockedTestEngine.cs | 10 ++- 36 files changed, 366 insertions(+), 185 deletions(-) diff --git a/Rubberduck.Core/AddRemoveReferences/ReferenceReconciler.cs b/Rubberduck.Core/AddRemoveReferences/ReferenceReconciler.cs index 9fabded063..a7d37c5b94 100644 --- a/Rubberduck.Core/AddRemoveReferences/ReferenceReconciler.cs +++ b/Rubberduck.Core/AddRemoveReferences/ReferenceReconciler.cs @@ -8,6 +8,7 @@ using Rubberduck.Settings; using Rubberduck.SettingsProvider; using Rubberduck.UI.AddRemoveReferences; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.SafeComWrappers.Abstract; namespace Rubberduck.AddRemoveReferences @@ -29,15 +30,18 @@ public class ReferenceReconciler : IReferenceReconciler private readonly IMessageBox _messageBox; private readonly IConfigurationService _settings; private readonly IComLibraryProvider _libraryProvider; + private readonly IProjectsProvider _projectsProvider; public ReferenceReconciler( IMessageBox messageBox, IConfigurationService settings, - IComLibraryProvider libraryProvider) + IComLibraryProvider libraryProvider, + IProjectsProvider projectsProvider) { _messageBox = messageBox; _settings = settings; _libraryProvider = libraryProvider; + _projectsProvider = projectsProvider; } public List ReconcileReferences(IAddRemoveReferencesModel model) @@ -58,12 +62,18 @@ public List ReconcileReferences(IAddRemoveReferencesModel model, return new List(); } + var project = _projectsProvider.Project(model.Project.ProjectId); + + if (project == null) + { + return new List(); + } + var selected = allReferences.Where(reference => !reference.IsBuiltIn && reference.Priority.HasValue) .ToDictionary(reference => reference.FullPath); var output = selected.Values.Where(reference => reference.IsBuiltIn).ToList(); - var project = model.Project.Project; using (var references = project.References) { foreach (var reference in references) diff --git a/Rubberduck.Core/Formatters/DeclarationFormatter.cs b/Rubberduck.Core/Formatters/DeclarationFormatter.cs index 0f299e473a..4b0e9b3b42 100644 --- a/Rubberduck.Core/Formatters/DeclarationFormatter.cs +++ b/Rubberduck.Core/Formatters/DeclarationFormatter.cs @@ -21,7 +21,7 @@ public object[] ToArray() public string ToClipboardString() { return string.Format(RubberduckUI.CodeExplorer_IExportable_DeclarationFormat, - _declaration.Project.Name, + _declaration.ProjectName, _declaration.CustomFolder, _declaration.ComponentName, _declaration.DeclarationType, diff --git a/Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerProjectViewModel.cs b/Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerProjectViewModel.cs index 4bd9d35960..1fa758a01f 100644 --- a/Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerProjectViewModel.cs +++ b/Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerProjectViewModel.cs @@ -22,7 +22,13 @@ public class CodeExplorerProjectViewModel : CodeExplorerItemViewModel private readonly IVBE _vbe; - public CodeExplorerProjectViewModel(Declaration project, ref List declarations, RubberduckParserState state, IVBE vbe, bool references = true) : base(null, project) + public CodeExplorerProjectViewModel( + Declaration project, + ref List declarations, + RubberduckParserState state, + IVBE vbe, + bool references = true) + : base(null, project) { State = state; _vbe = vbe; @@ -47,7 +53,13 @@ public override FontWeight FontWeight { get { - if (_vbe.Kind == VBEKind.Hosted || Declaration.Project == null) + if (_vbe.Kind == VBEKind.Hosted || Declaration == null) + { + return base.FontWeight; + } + + var project = State.ProjectsProvider.Project(Declaration.ProjectId); + if (project == null) { return base.FontWeight; } @@ -55,7 +67,9 @@ public override FontWeight FontWeight using (var vbProjects = _vbe.VBProjects) using (var startProject = vbProjects?.StartProject) { - return Declaration.Project.Equals(startProject) ? FontWeights.Bold : base.FontWeight; + return project.Equals(startProject) + ? FontWeights.Bold + : base.FontWeight; } } } @@ -139,7 +153,12 @@ private void SynchronizeReferences() private List GetProjectReferenceModels() { - var project = Declaration?.Project; + if (Declaration == null) + { + return new List(); + } + + var project = State.ProjectsProvider.Project(Declaration.ProjectId); if (project == null) { return new List(); diff --git a/Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerViewModel.cs b/Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerViewModel.cs index ce4c19fc20..31c3c33708 100644 --- a/Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerViewModel.cs +++ b/Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerViewModel.cs @@ -13,7 +13,6 @@ using Rubberduck.UI.Command; using Rubberduck.VBEditor.SafeComWrappers; using System.Windows; -using System.Windows.Forms; using System.Windows.Input; using Rubberduck.Parsing.UIContext; using Rubberduck.Templates; @@ -305,12 +304,12 @@ private void ParserState_ModuleStateChanged(object sender, ParseProgressEventArg return; } - var componentProject = _state.ProjectsProvider.Project(e.Module.ProjectId); + var componentProjectId = e.Module.ProjectId; var module = Projects.OfType() - .FirstOrDefault(p => p.Declaration.Project?.Equals(componentProject) ?? false)?.Children - .OfType().FirstOrDefault(component => - component.QualifiedSelection?.QualifiedName.Equals(e.Module) ?? false); + .FirstOrDefault(p => p.Declaration?.ProjectId.Equals(componentProjectId) ?? false)?.Children + .OfType() + .FirstOrDefault(component => component.QualifiedSelection?.QualifiedName.Equals(e.Module) ?? false); if (module == null) { diff --git a/Rubberduck.Core/UI/AddRemoveReferences/AddRemoveReferencesPresenterFactory.cs b/Rubberduck.Core/UI/AddRemoveReferences/AddRemoveReferencesPresenterFactory.cs index 00478c8f6a..78f4944404 100644 --- a/Rubberduck.Core/UI/AddRemoveReferences/AddRemoveReferencesPresenterFactory.cs +++ b/Rubberduck.Core/UI/AddRemoveReferences/AddRemoveReferencesPresenterFactory.cs @@ -10,6 +10,7 @@ using Rubberduck.Settings; using Rubberduck.SettingsProvider; using Rubberduck.VBEditor; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; @@ -17,7 +18,7 @@ namespace Rubberduck.UI.AddRemoveReferences { public interface IAddRemoveReferencesPresenterFactory { - AddRemoveReferencesPresenter Create(ProjectDeclaration project); + AddRemoveReferencesPresenter Create(ProjectDeclaration projectDeclaration); } public class AddRemoveReferencesPresenterFactory : IAddRemoveReferencesPresenterFactory @@ -31,13 +32,15 @@ public class AddRemoveReferencesPresenterFactory : IAddRemoveReferencesPresenter private readonly IRegisteredLibraryFinderService _finder; private readonly IReferenceReconciler _reconciler; private readonly IFileSystemBrowserFactory _browser; + private readonly IProjectsProvider _projectsProvider; public AddRemoveReferencesPresenterFactory(IVBE vbe, RubberduckParserState state, IConfigurationService settingsProvider, IRegisteredLibraryFinderService finder, IReferenceReconciler reconciler, - IFileSystemBrowserFactory browser) + IFileSystemBrowserFactory browser, + IProjectsProvider projectsProvider) { _vbe = vbe; _state = state; @@ -45,11 +48,19 @@ public AddRemoveReferencesPresenterFactory(IVBE vbe, _finder = finder; _reconciler = reconciler; _browser = browser; + _projectsProvider = projectsProvider; } - public AddRemoveReferencesPresenter Create(ProjectDeclaration project) + public AddRemoveReferencesPresenter Create(ProjectDeclaration projectDeclaration) { - if (project is null) + if (projectDeclaration is null) + { + return null; + } + + var project = _projectsProvider.Project(projectDeclaration.ProjectId); + + if (project == null) { return null; } @@ -75,7 +86,7 @@ public AddRemoveReferencesPresenter Create(ProjectDeclaration project) } var models = new Dictionary(); - using (var references = project.Project?.References) + using (var references = project.References) { if (references is null) { @@ -101,7 +112,7 @@ public AddRemoveReferencesPresenter Create(ProjectDeclaration project) : new ReferenceModel(reference, priority++); adding.IsUsed = adding.IsBuiltIn || - _state.DeclarationFinder.IsReferenceUsedInProject(project, + _state.DeclarationFinder.IsReferenceUsedInProject(projectDeclaration, adding.ToReferenceInfo()); models.Add(libraryId, adding); @@ -117,7 +128,7 @@ public AddRemoveReferencesPresenter Create(ProjectDeclaration project) } var settings = _settings.Read(); - model = new AddRemoveReferencesModel(_state, project, models.Values, settings); + model = new AddRemoveReferencesModel(_state, projectDeclaration, models.Values, settings); if (AddRemoveReferencesViewModel.HostHasProjects) { model.References.AddRange(GetUserProjectFolderModels(model.Settings).Where(proj => diff --git a/Rubberduck.Core/UI/CodeExplorer/Commands/AddClassModuleCommand.cs b/Rubberduck.Core/UI/CodeExplorer/Commands/AddClassModuleCommand.cs index 4626f436f9..144b49b048 100644 --- a/Rubberduck.Core/UI/CodeExplorer/Commands/AddClassModuleCommand.cs +++ b/Rubberduck.Core/UI/CodeExplorer/Commands/AddClassModuleCommand.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.Events; using Rubberduck.VBEditor.SafeComWrappers; @@ -7,8 +8,11 @@ namespace Rubberduck.UI.CodeExplorer.Commands public class AddClassModuleCommand : AddComponentCommandBase { public AddClassModuleCommand( - ICodeExplorerAddComponentService addComponentService, IVbeEvents vbeEvents) - : base(addComponentService, vbeEvents) { } + ICodeExplorerAddComponentService addComponentService, + IVbeEvents vbeEvents, + IProjectsProvider projectsProvider) + : base(addComponentService, vbeEvents, projectsProvider) + {} public override IEnumerable AllowableProjectTypes => ProjectTypes.All; diff --git a/Rubberduck.Core/UI/CodeExplorer/Commands/AddComponentCommand.cs b/Rubberduck.Core/UI/CodeExplorer/Commands/AddComponentCommand.cs index adee198f77..2d9a2262d9 100644 --- a/Rubberduck.Core/UI/CodeExplorer/Commands/AddComponentCommand.cs +++ b/Rubberduck.Core/UI/CodeExplorer/Commands/AddComponentCommand.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Runtime.InteropServices; using Rubberduck.Navigation.CodeExplorer; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.Events; using Rubberduck.VBEditor.SafeComWrappers; @@ -19,12 +20,16 @@ public abstract class AddComponentCommandBase : CodeExplorerCommandBase }; private readonly ICodeExplorerAddComponentService _addComponentService; + private readonly IProjectsProvider _projectsProvider; protected AddComponentCommandBase( - ICodeExplorerAddComponentService addComponentService, IVbeEvents vbeEvents) + ICodeExplorerAddComponentService addComponentService, + IVbeEvents vbeEvents, + IProjectsProvider projectsProvider) : base(vbeEvents) { _addComponentService = addComponentService; + _projectsProvider = projectsProvider; AddToCanExecuteEvaluation(SpecialEvaluateCanExecute); } @@ -50,8 +55,9 @@ private bool SpecialEvaluateCanExecute(object parameter) try { - var project = node.Declaration.Project; - return AllowableProjectTypes.Contains(project.Type); + var project = _projectsProvider.Project(node.Declaration.ProjectId); + return project != null + && AllowableProjectTypes.Contains(project.Type); } catch (COMException) { diff --git a/Rubberduck.Core/UI/CodeExplorer/Commands/AddMDIFormCommand.cs b/Rubberduck.Core/UI/CodeExplorer/Commands/AddMDIFormCommand.cs index 9b2248ecaa..3e895ef720 100644 --- a/Rubberduck.Core/UI/CodeExplorer/Commands/AddMDIFormCommand.cs +++ b/Rubberduck.Core/UI/CodeExplorer/Commands/AddMDIFormCommand.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using Rubberduck.Navigation.CodeExplorer; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.Events; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; @@ -12,10 +13,16 @@ public class AddMDIFormCommand : AddComponentCommandBase { private static readonly ProjectType[] Types = { ProjectType.StandardExe, ProjectType.ActiveXExe }; + private readonly IProjectsProvider _projectsProvider; + public AddMDIFormCommand( - ICodeExplorerAddComponentService addComponentService, IVbeEvents vbeEvents) - : base(addComponentService, vbeEvents) + ICodeExplorerAddComponentService addComponentService, + IVbeEvents vbeEvents, + IProjectsProvider projectsProvider) + : base(addComponentService, vbeEvents, projectsProvider) { + _projectsProvider = projectsProvider; + AddToCanExecuteEvaluation(SpecialEvaluateCanExecute); } @@ -30,7 +37,9 @@ private bool SpecialEvaluateCanExecute(object parameter) return false; } - var project = node.Declaration?.Project; + var project = node.Declaration != null + ? _projectsProvider.Project(node.Declaration.ProjectId) + : null; return EvaluateCanExecuteForProject(project); } diff --git a/Rubberduck.Core/UI/CodeExplorer/Commands/AddPropertyPageCommand.cs b/Rubberduck.Core/UI/CodeExplorer/Commands/AddPropertyPageCommand.cs index 4da33f28c1..8a813e094b 100644 --- a/Rubberduck.Core/UI/CodeExplorer/Commands/AddPropertyPageCommand.cs +++ b/Rubberduck.Core/UI/CodeExplorer/Commands/AddPropertyPageCommand.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.Events; using Rubberduck.VBEditor.SafeComWrappers; @@ -7,8 +8,11 @@ namespace Rubberduck.UI.CodeExplorer.Commands public class AddPropertyPageCommand : AddComponentCommandBase { public AddPropertyPageCommand( - ICodeExplorerAddComponentService addComponentService, IVbeEvents vbeEvents) - : base(addComponentService, vbeEvents) { } + ICodeExplorerAddComponentService addComponentService, + IVbeEvents vbeEvents, + IProjectsProvider projectsProvider) + : base(addComponentService, vbeEvents, projectsProvider) + {} public override IEnumerable AllowableProjectTypes => ProjectTypes.VB6; diff --git a/Rubberduck.Core/UI/CodeExplorer/Commands/AddStdModuleCommand.cs b/Rubberduck.Core/UI/CodeExplorer/Commands/AddStdModuleCommand.cs index 75fb2cdf62..d6334dcfed 100644 --- a/Rubberduck.Core/UI/CodeExplorer/Commands/AddStdModuleCommand.cs +++ b/Rubberduck.Core/UI/CodeExplorer/Commands/AddStdModuleCommand.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.Events; using Rubberduck.VBEditor.SafeComWrappers; @@ -7,8 +8,10 @@ namespace Rubberduck.UI.CodeExplorer.Commands public class AddStdModuleCommand : AddComponentCommandBase { public AddStdModuleCommand( - ICodeExplorerAddComponentService addComponentService, IVbeEvents vbeEvents) - : base(addComponentService, vbeEvents) + ICodeExplorerAddComponentService addComponentService, + IVbeEvents vbeEvents, + IProjectsProvider projectsProvider) + : base(addComponentService, vbeEvents, projectsProvider) { } public override IEnumerable AllowableProjectTypes => ProjectTypes.All; diff --git a/Rubberduck.Core/UI/CodeExplorer/Commands/AddTemplateCommand.cs b/Rubberduck.Core/UI/CodeExplorer/Commands/AddTemplateCommand.cs index 33b25dcd82..80e2813423 100644 --- a/Rubberduck.Core/UI/CodeExplorer/Commands/AddTemplateCommand.cs +++ b/Rubberduck.Core/UI/CodeExplorer/Commands/AddTemplateCommand.cs @@ -6,6 +6,7 @@ using Rubberduck.Templates; using Rubberduck.VBEditor.Events; using Rubberduck.UI.Command; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.SafeComWrappers; namespace Rubberduck.UI.CodeExplorer.Commands @@ -30,15 +31,18 @@ public class AddTemplateCommand : CodeExplorerCommandBase private readonly ITemplateProvider _provider; private readonly ICodeExplorerAddComponentService _addComponentService; + private readonly IProjectsProvider _projectsProvider; public AddTemplateCommand( ICodeExplorerAddComponentService addComponentService, ITemplateProvider provider, - IVbeEvents vbeEvents) + IVbeEvents vbeEvents, + IProjectsProvider projectsProvider) : base(vbeEvents) { _provider = provider; _addComponentService = addComponentService; + _projectsProvider = projectsProvider; AddToCanExecuteEvaluation(SpecialEvaluateCanExecute); } @@ -75,8 +79,9 @@ private bool EvaluateCanExecute(ICodeExplorerNode node) return false; } - var project = node.Declaration.Project; - return AllowableProjectTypes.Contains(project.Type); + var project = _projectsProvider.Project(node.Declaration.ProjectId); + return project != null + && AllowableProjectTypes.Contains(project.Type); } protected override void OnExecute(object parameter) diff --git a/Rubberduck.Core/UI/CodeExplorer/Commands/AddTestComponentCommand.cs b/Rubberduck.Core/UI/CodeExplorer/Commands/AddTestComponentCommand.cs index 074f62ea4e..d39e334057 100644 --- a/Rubberduck.Core/UI/CodeExplorer/Commands/AddTestComponentCommand.cs +++ b/Rubberduck.Core/UI/CodeExplorer/Commands/AddTestComponentCommand.cs @@ -6,6 +6,7 @@ using Rubberduck.Parsing.VBA; using Rubberduck.UI.UnitTesting.ComCommands; using Rubberduck.UnitTesting.CodeGeneration; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.Events; using Rubberduck.VBEditor.SafeComWrappers.Abstract; @@ -21,13 +22,17 @@ public class AddTestComponentCommand : AddTestModuleCommand typeof(CodeExplorerMemberViewModel) }; + private readonly IProjectsProvider _projectsProvider; + public AddTestComponentCommand( IVBE vbe, RubberduckParserState state, ITestCodeGenerator codeGenerator, - IVbeEvents vbeEvents) - : base(vbe, state, codeGenerator, vbeEvents) + IVbeEvents vbeEvents, + IProjectsProvider projectsProvider) + : base(vbe, state, codeGenerator, vbeEvents, projectsProvider) { + _projectsProvider = projectsProvider; AddToCanExecuteEvaluation(SpecialEvaluateCanExecute); } @@ -39,8 +44,8 @@ private bool SpecialEvaluateCanExecute(object parameter) } Declaration declaration; - if (ApplicableNodes.Contains(parameter.GetType()) && - parameter is CodeExplorerItemViewModel node) + if (ApplicableNodes.Contains(parameter.GetType()) + && parameter is CodeExplorerItemViewModel node) { declaration = node.Declaration; } @@ -53,9 +58,13 @@ private bool SpecialEvaluateCanExecute(object parameter) return false; } + var project = declaration != null + ? _projectsProvider.Project(declaration.ProjectId) + : null; + try { - return declaration?.Project != null || Vbe.ProjectsCount != 1; + return project != null || Vbe.ProjectsCount != 1; } catch (COMException) { diff --git a/Rubberduck.Core/UI/CodeExplorer/Commands/AddUserControlCommand.cs b/Rubberduck.Core/UI/CodeExplorer/Commands/AddUserControlCommand.cs index d88e32654d..bb20d0036b 100644 --- a/Rubberduck.Core/UI/CodeExplorer/Commands/AddUserControlCommand.cs +++ b/Rubberduck.Core/UI/CodeExplorer/Commands/AddUserControlCommand.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.Events; using Rubberduck.VBEditor.SafeComWrappers; @@ -7,8 +8,10 @@ namespace Rubberduck.UI.CodeExplorer.Commands public class AddUserControlCommand : AddComponentCommandBase { public AddUserControlCommand( - ICodeExplorerAddComponentService addComponentService, IVbeEvents vbeEvents) - : base(addComponentService, vbeEvents) + ICodeExplorerAddComponentService addComponentService, + IVbeEvents vbeEvents, + IProjectsProvider projectsProvider) + : base(addComponentService, vbeEvents, projectsProvider) { } public override IEnumerable AllowableProjectTypes => ProjectTypes.VB6; diff --git a/Rubberduck.Core/UI/CodeExplorer/Commands/AddUserDocumentCommand.cs b/Rubberduck.Core/UI/CodeExplorer/Commands/AddUserDocumentCommand.cs index d88f145530..3cd0bddc13 100644 --- a/Rubberduck.Core/UI/CodeExplorer/Commands/AddUserDocumentCommand.cs +++ b/Rubberduck.Core/UI/CodeExplorer/Commands/AddUserDocumentCommand.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.Events; using Rubberduck.VBEditor.SafeComWrappers; @@ -9,8 +10,10 @@ public class AddUserDocumentCommand : AddComponentCommandBase private static readonly ProjectType[] Types = { ProjectType.ActiveXExe, ProjectType.ActiveXDll }; public AddUserDocumentCommand( - ICodeExplorerAddComponentService addComponentService, IVbeEvents vbeEvents) - : base(addComponentService, vbeEvents) + ICodeExplorerAddComponentService addComponentService, + IVbeEvents vbeEvents, + IProjectsProvider projectsProvider) + : base(addComponentService, vbeEvents, projectsProvider) { } public override IEnumerable AllowableProjectTypes => Types; diff --git a/Rubberduck.Core/UI/CodeExplorer/Commands/AddUserFormCommand.cs b/Rubberduck.Core/UI/CodeExplorer/Commands/AddUserFormCommand.cs index 57fd03a0f6..2bdca1a93d 100644 --- a/Rubberduck.Core/UI/CodeExplorer/Commands/AddUserFormCommand.cs +++ b/Rubberduck.Core/UI/CodeExplorer/Commands/AddUserFormCommand.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.Events; using Rubberduck.VBEditor.SafeComWrappers; @@ -7,8 +8,10 @@ namespace Rubberduck.UI.CodeExplorer.Commands public class AddUserFormCommand : AddComponentCommandBase { public AddUserFormCommand( - ICodeExplorerAddComponentService addComponentService, IVbeEvents vbeEvents) - : base(addComponentService, vbeEvents) + ICodeExplorerAddComponentService addComponentService, + IVbeEvents vbeEvents, + IProjectsProvider projectsProvider) + : base(addComponentService, vbeEvents, projectsProvider) { } public override IEnumerable AllowableProjectTypes => ProjectTypes.VBA; diff --git a/Rubberduck.Core/UI/CodeExplorer/Commands/AddVBFormCommand.cs b/Rubberduck.Core/UI/CodeExplorer/Commands/AddVBFormCommand.cs index 6cdc942a06..e95a31c5d5 100644 --- a/Rubberduck.Core/UI/CodeExplorer/Commands/AddVBFormCommand.cs +++ b/Rubberduck.Core/UI/CodeExplorer/Commands/AddVBFormCommand.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.Events; using Rubberduck.VBEditor.SafeComWrappers; @@ -9,8 +10,10 @@ namespace Rubberduck.UI.CodeExplorer.Commands public class AddVBFormCommand : AddComponentCommandBase { public AddVBFormCommand( - ICodeExplorerAddComponentService addComponentService, IVbeEvents vbeEvents) - : base(addComponentService, vbeEvents) + ICodeExplorerAddComponentService addComponentService, + IVbeEvents vbeEvents, + IProjectsProvider projectsProvider) + : base(addComponentService, vbeEvents, projectsProvider) { } public override IEnumerable AllowableProjectTypes => ProjectTypes.VB6; diff --git a/Rubberduck.Core/UI/CodeExplorer/Commands/ImportCommand.cs b/Rubberduck.Core/UI/CodeExplorer/Commands/ImportCommand.cs index eed039d51c..7327f39adc 100644 --- a/Rubberduck.Core/UI/CodeExplorer/Commands/ImportCommand.cs +++ b/Rubberduck.Core/UI/CodeExplorer/Commands/ImportCommand.cs @@ -102,9 +102,12 @@ private bool ThereIsAValidActiveProject() return (targetProject, targetProject != null); } - private static IVBProject TargetProjectFromParameter(object parameter) + private IVBProject TargetProjectFromParameter(object parameter) { - return (parameter as CodeExplorerItemViewModel)?.Declaration?.Project; + var declaration = (parameter as CodeExplorerItemViewModel)?.Declaration; + return declaration != null + ? _projectsProvider.Project(declaration.ProjectId) + : null; } private IVBProject TargetProjectFromVbe() diff --git a/Rubberduck.Core/UI/CodeExplorer/Commands/OpenProjectPropertiesCommand.cs b/Rubberduck.Core/UI/CodeExplorer/Commands/OpenProjectPropertiesCommand.cs index d72a15df3a..0a7bd86816 100644 --- a/Rubberduck.Core/UI/CodeExplorer/Commands/OpenProjectPropertiesCommand.cs +++ b/Rubberduck.Core/UI/CodeExplorer/Commands/OpenProjectPropertiesCommand.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Runtime.InteropServices; using Rubberduck.Navigation.CodeExplorer; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.Events; using Rubberduck.VBEditor.SafeComWrappers.Abstract; @@ -18,13 +19,16 @@ public class OpenProjectPropertiesCommand : CodeExplorerCommandBase }; private readonly IVBE _vbe; + private readonly IProjectsProvider _projectsProvider; public OpenProjectPropertiesCommand( IVBE vbe, - IVbeEvents vbeEvents) + IVbeEvents vbeEvents, + IProjectsProvider projectsProvider) : base(vbeEvents) { _vbe = vbe; + _projectsProvider = projectsProvider; AddToCanExecuteEvaluation(SpecialEvaluateCanExecute); } @@ -67,7 +71,13 @@ protected override void OnExecute(object parameter) return; } - var nodeProject = node.Declaration?.Project; + var nodeProjectId = node.Declaration?.ProjectId; + if (nodeProjectId == null) + { + return; + } + + var nodeProject = _projectsProvider.Project(nodeProjectId); if (nodeProject == null) { return; //The project declaration has been disposed, i.e. the project has been removed already. diff --git a/Rubberduck.Core/UI/CodeExplorer/Commands/SetAsStartupProjectCommand.cs b/Rubberduck.Core/UI/CodeExplorer/Commands/SetAsStartupProjectCommand.cs index 1bdd20afaf..38e8f24b22 100644 --- a/Rubberduck.Core/UI/CodeExplorer/Commands/SetAsStartupProjectCommand.cs +++ b/Rubberduck.Core/UI/CodeExplorer/Commands/SetAsStartupProjectCommand.cs @@ -4,6 +4,7 @@ using System.Runtime.InteropServices; using Rubberduck.Navigation.CodeExplorer; using Rubberduck.Parsing.VBA; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.Events; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; @@ -16,15 +17,18 @@ public class SetAsStartupProjectCommand : CodeExplorerCommandBase private readonly IVBE _vbe; private readonly RubberduckParserState _parserState; + private readonly IProjectsProvider _projectsProvider; public SetAsStartupProjectCommand( IVBE vbe, RubberduckParserState parserState, - IVbeEvents vbeEvents) + IVbeEvents vbeEvents, + IProjectsProvider projectsProvider) : base(vbeEvents) { _vbe = vbe; _parserState = parserState; + _projectsProvider = projectsProvider; AddToCanExecuteEvaluation(SpecialEvaluateCanExecute); } @@ -35,10 +39,16 @@ private bool SpecialEvaluateCanExecute(object parameter) { try { - if (!(parameter is CodeExplorerProjectViewModel node) || - !(node.Declaration?.Project is IVBProject project) || - !ProjectTypes.VB6.Contains(project.Type) || - _vbe.ProjectsCount <= 1) + if (!(parameter is CodeExplorerProjectViewModel node) + || node.Declaration == null + || _vbe.ProjectsCount <= 1) + { + return false; + } + + var project = _projectsProvider.Project(node.Declaration.ProjectId); + if (project == null + || !ProjectTypes.VB6.Contains(project.Type)) { return false; } @@ -57,16 +67,21 @@ private bool SpecialEvaluateCanExecute(object parameter) protected override void OnExecute(object parameter) { - if (!CanExecute(parameter) || - !(parameter is CodeExplorerProjectViewModel node)) + if (!CanExecute(parameter) + || !(parameter is CodeExplorerProjectViewModel node) + || node.Declaration == null) { return; } - try + var project = _projectsProvider.Project(node.Declaration.ProjectId); + if (project == null) { - var project = node.Declaration.Project; + return; + } + try + { using (var vbProjects = _vbe.VBProjects) { vbProjects.StartProject = project; diff --git a/Rubberduck.Core/UI/Command/ComCommands/ExportAllCommand.cs b/Rubberduck.Core/UI/Command/ComCommands/ExportAllCommand.cs index 21c777cc98..40937c6fd1 100644 --- a/Rubberduck.Core/UI/Command/ComCommands/ExportAllCommand.cs +++ b/Rubberduck.Core/UI/Command/ComCommands/ExportAllCommand.cs @@ -2,6 +2,7 @@ using System.Windows.Forms; using Rubberduck.Navigation.CodeExplorer; using Rubberduck.Resources; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.Events; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; @@ -12,15 +13,18 @@ public class ExportAllCommand : ComCommandBase { private readonly IVBE _vbe; private readonly IFileSystemBrowserFactory _factory; + private readonly IProjectsProvider _projectsProvider; public ExportAllCommand( IVBE vbe, IFileSystemBrowserFactory folderBrowserFactory, - IVbeEvents vbeEvents) + IVbeEvents vbeEvents, + IProjectsProvider projectsProvider) : base(vbeEvents) { _vbe = vbe; _factory = folderBrowserFactory; + _projectsProvider = projectsProvider; AddToCanExecuteEvaluation(SpecialEvaluateCanExecute); } @@ -32,7 +36,8 @@ private bool SpecialEvaluateCanExecute(object parameter) return false; } - if (!(parameter is CodeExplorerProjectViewModel) && parameter is CodeExplorerItemViewModel) + if (!(parameter is CodeExplorerProjectViewModel) + && parameter is CodeExplorerItemViewModel) { return false; } @@ -40,7 +45,10 @@ private bool SpecialEvaluateCanExecute(object parameter) switch (parameter) { case CodeExplorerProjectViewModel projectNode: - return Evaluate(projectNode.Declaration.Project); + var nodeProject = projectNode.Declaration != null + ? _projectsProvider.Project(projectNode.Declaration.ProjectId) + : null; + return Evaluate(nodeProject); case IVBProject project: return Evaluate(project); } @@ -69,8 +77,15 @@ protected override void OnExecute(object parameter) { switch (parameter) { - case CodeExplorerProjectViewModel projectNode when projectNode.Declaration.Project != null: - Export(projectNode.Declaration.Project); + case CodeExplorerProjectViewModel projectNode: + var nodeProject = projectNode.Declaration != null + ? _projectsProvider.Project(projectNode.Declaration.ProjectId) + : null; + if (nodeProject == null) + { + return; + } + Export(nodeProject); break; case IVBProject vbproject: Export(vbproject); diff --git a/Rubberduck.Core/UI/UnitTesting/ComCommands/AddTestModuleCommand.cs b/Rubberduck.Core/UI/UnitTesting/ComCommands/AddTestModuleCommand.cs index 3fbeb65fd0..d41f04c719 100644 --- a/Rubberduck.Core/UI/UnitTesting/ComCommands/AddTestModuleCommand.cs +++ b/Rubberduck.Core/UI/UnitTesting/ComCommands/AddTestModuleCommand.cs @@ -3,6 +3,7 @@ using Rubberduck.Parsing.VBA; using Rubberduck.UI.Command.ComCommands; using Rubberduck.UnitTesting.CodeGeneration; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.Events; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; @@ -17,17 +18,20 @@ public class AddTestModuleCommand : ComCommandBase { private readonly RubberduckParserState _state; private readonly ITestCodeGenerator _codeGenerator; + private readonly IProjectsProvider _projectsProvider; public AddTestModuleCommand( IVBE vbe, RubberduckParserState state, ITestCodeGenerator codeGenerator, - IVbeEvents vbeEvents) + IVbeEvents vbeEvents, + IProjectsProvider projectsProvider) : base(vbeEvents) { Vbe = vbe; _state = state; _codeGenerator = codeGenerator; + _projectsProvider = projectsProvider; AddToCanExecuteEvaluation(SpecialEvaluateCanExecute); } @@ -78,7 +82,8 @@ protected override void OnExecute(object parameter) _codeGenerator.AddTestModuleToProject(project); break; case Declaration declaration when parameterIsModuleDeclaration: - _codeGenerator.AddTestModuleToProject(declaration.Project, declaration); + var declarationProject = _projectsProvider.Project(declaration.ProjectId); + _codeGenerator.AddTestModuleToProject(declarationProject, declaration); break; default: using (var project = GetProject()) diff --git a/Rubberduck.Parsing/Symbols/Declaration.cs b/Rubberduck.Parsing/Symbols/Declaration.cs index 0660e56110..8c109f603e 100644 --- a/Rubberduck.Parsing/Symbols/Declaration.cs +++ b/Rubberduck.Parsing/Symbols/Declaration.cs @@ -414,14 +414,6 @@ public void AddReference( public QualifiedSelection QualifiedSelection => new QualifiedSelection(QualifiedName.QualifiedModuleName, Selection); - /// - /// Gets a reference to the VBProject the declaration is made in. - /// - /// - /// This property is intended to differenciate identically-named VBProjects. - /// - public virtual IVBProject Project => ParentDeclaration.Project; - /// /// Gets a unique identifier for the VBProject the declaration is made in. /// diff --git a/Rubberduck.Parsing/Symbols/ProjectDeclaration.cs b/Rubberduck.Parsing/Symbols/ProjectDeclaration.cs index c9f8b69299..13ef5e1795 100644 --- a/Rubberduck.Parsing/Symbols/ProjectDeclaration.cs +++ b/Rubberduck.Parsing/Symbols/ProjectDeclaration.cs @@ -10,6 +10,7 @@ namespace Rubberduck.Parsing.Symbols public sealed class ProjectDeclaration : Declaration, IDisposable { private readonly List _projectReferences; + private readonly IVBProject _project; public ProjectDeclaration( QualifiedMemberName qualifiedName, @@ -57,15 +58,6 @@ public IReadOnlyList ProjectReferences } } - private readonly IVBProject _project; - /// - /// Gets a reference to the VBProject the declaration is made in. - /// - /// - /// This property is intended to differenciate identically-named VBProjects. - /// - public override IVBProject Project => IsDisposed ? null : _project; - public void AddProjectReference(string referencedProjectId, int priority) { if (_projectReferences.Any(p => p.ReferencedProjectId == referencedProjectId)) @@ -98,7 +90,6 @@ public override string ProjectDisplayName } } - public bool IsDisposed { get; private set; } public void Dispose() diff --git a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs index 6745a264e8..08a18c1090 100644 --- a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs +++ b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs @@ -11,7 +11,9 @@ using Rubberduck.Refactorings.Exceptions; using Rubberduck.Refactorings.ImplementInterface; using Rubberduck.VBEditor; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.SafeComWrappers; +using Rubberduck.VBEditor.SafeComWrappers.Abstract; using Rubberduck.VBEditor.Utility; namespace Rubberduck.Refactorings.ExtractInterface @@ -20,6 +22,7 @@ public class ExtractInterfaceRefactoring : InteractiveRefactoringBase _knownOutcomes = new Dictionary(); private List _lastRun = new List(); @@ -53,7 +55,8 @@ public TestEngine( IVBEInteraction declarationRunner, ITypeLibWrapperProvider wrapperProvider, IUiDispatcher uiDispatcher, - IVBE vbe) + IVBE vbe, + IProjectsProvider projectsProvider) { Debug.WriteLine("TestEngine created."); _state = state; @@ -62,6 +65,7 @@ public TestEngine( _wrapperProvider = wrapperProvider; _uiDispatcher = uiDispatcher; _vbe = vbe; + _projectsProvider = projectsProvider; _state.StateChanged += StateChangedHandler; } @@ -209,11 +213,11 @@ private void EnsureRubberduckIsReferencedForEarlyBoundTests() .Where(member => member.AsTypeName == "Rubberduck.PermissiveAssertClass" || member.AsTypeName == "Rubberduck.AssertClass") .Select(member => member.ProjectId) - .ToHashSet(); - var projectsUsingAddInLibrary = _state.DeclarationFinder - .UserDeclarations(DeclarationType.Project) - .Where(declaration => projectIdsOfMembersUsingAddInLibrary.Contains(declaration.ProjectId)) - .Select(declaration => declaration.Project); + .Distinct(); + + var projectsUsingAddInLibrary = projectIdsOfMembersUsingAddInLibrary + .Select(projectId => _projectsProvider.Project(projectId)) + .Where(project => project != null); foreach (var project in projectsUsingAddInLibrary) { diff --git a/RubberduckTests/AddRemoveReferences/AddRemoveReferencesSetup.cs b/RubberduckTests/AddRemoveReferences/AddRemoveReferencesSetup.cs index c8741d823d..3db9a0f7e7 100644 --- a/RubberduckTests/AddRemoveReferences/AddRemoveReferencesSetup.cs +++ b/RubberduckTests/AddRemoveReferences/AddRemoveReferencesSetup.cs @@ -14,6 +14,7 @@ using Rubberduck.UI; using Rubberduck.UI.AddRemoveReferences; using Rubberduck.VBEditor; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; using RubberduckTests.Mocks; @@ -112,17 +113,31 @@ public static Mock> GetMockReferenceSet public static ReferenceReconciler ArrangeReferenceReconciler(ReferenceSettings settings = null) { - return ArrangeReferenceReconciler(settings, out _, out _); + return ArrangeReferenceReconciler(settings, null, out _, out _); + } + + public static ReferenceReconciler ArrangeReferenceReconciler(IProjectsProvider projectsProvider, ReferenceSettings settings = null) + { + return ArrangeReferenceReconciler(settings, projectsProvider, out _, out _); + } + + public static ReferenceReconciler ArrangeReferenceReconciler( + ReferenceSettings settings, + out Mock messageBox, + out Mock libraryProvider) + { + return ArrangeReferenceReconciler(settings, null, out messageBox, out libraryProvider); } public static ReferenceReconciler ArrangeReferenceReconciler( ReferenceSettings settings, + IProjectsProvider projectsprovider, out Mock messageBox, out Mock libraryProvider) { messageBox = new Mock(); libraryProvider = new Mock(); - return new ReferenceReconciler(messageBox.Object, GetReferenceSettingsProvider(settings), libraryProvider.Object); + return new ReferenceReconciler(messageBox.Object, GetReferenceSettingsProvider(settings), libraryProvider.Object, projectsprovider); } public static void SetupIComLibraryProvider(Mock provider, ReferenceInfo reference, string path, string description = "") @@ -164,10 +179,10 @@ public static Mock ArrangeAddRemoveReferencesModel(Li public static ProjectDeclaration ArrangeMocksAndGetProject() { - return ArrangeMocksAndGetProject(out _, out _); + return ArrangeMocksAndGetProject(out _, out _, out _); } - public static ProjectDeclaration ArrangeMocksAndGetProject(out MockProjectBuilder projectBuilder, out Mock references) + public static ProjectDeclaration ArrangeMocksAndGetProject(out MockProjectBuilder projectBuilder, out Mock references, out IProjectsProvider projectsProvider) { var builder = new MockVbeBuilder(); @@ -183,8 +198,14 @@ public static ProjectDeclaration ArrangeMocksAndGetProject(out MockProjectBuilde builder.AddProject(projectBuilder.Build()); - var parser = MockParser.CreateAndParse(builder.Build().Object); - return parser.AllUserDeclarations.OfType().Single(); + var state = MockParser.CreateAndParse(builder.Build().Object); + + projectsProvider = state.ProjectsProvider; + + return state.DeclarationFinder + .UserDeclarations(DeclarationType.Project) + .OfType() + .Single(); } public static Mock ArrangeParsedAddRemoveReferencesModel( @@ -192,9 +213,10 @@ public static Mock ArrangeParsedAddRemoveReferencesMo List output, List registered, out Mock references, - out MockProjectBuilder projectBuilder) + out MockProjectBuilder projectBuilder, + out IProjectsProvider projectsProvider) { - var declaration = ArrangeMocksAndGetProject(out projectBuilder, out references); + var declaration = ArrangeMocksAndGetProject(out projectBuilder, out references, out projectsProvider); var model = ArrangeAddRemoveReferencesModel(input, output, GetDefaultReferenceSettings()); model.Setup(m => m.Project).Returns(declaration); @@ -233,7 +255,7 @@ public static AddRemoveReferencesViewModel ArrangeViewModel( { var registered = LibraryReferenceInfoList.Select(reference => new ReferenceModel(reference, ReferenceKind.TypeLibrary)).ToList(); - var declaration = ArrangeMocksAndGetProject(out _, out var references); + var declaration = ArrangeMocksAndGetProject(out _, out var references, out var projectsProvider); var settings = GetNonDefaultReferenceSettings(); var priority = 1; @@ -258,7 +280,7 @@ public static AddRemoveReferencesViewModel ArrangeViewModel( } var model = new AddRemoveReferencesModel(null, declaration, allReferences, settings); - var reconciler = ArrangeReferenceReconciler(settings, out _, out libraryProvider); + var reconciler = ArrangeReferenceReconciler(settings, projectsProvider, out _, out libraryProvider); browserFactory = new Mock(); return new AddRemoveReferencesViewModel(model, reconciler, browserFactory.Object); diff --git a/RubberduckTests/AddRemoveReferences/ReferenceReconcilerTests.cs b/RubberduckTests/AddRemoveReferences/ReferenceReconcilerTests.cs index 23c98d9ea6..0bb6ede375 100644 --- a/RubberduckTests/AddRemoveReferences/ReferenceReconcilerTests.cs +++ b/RubberduckTests/AddRemoveReferences/ReferenceReconcilerTests.cs @@ -332,8 +332,8 @@ public void TryAddReferenceReferenceModel_ReturnsNullOnThrow() [Category("AddRemoveReferences")] public void ReconcileReferences_ReturnsEmptyWithoutNewReferences() { - var model = AddRemoveReferencesSetup.ArrangeParsedAddRemoveReferencesModel(null, null, null, out _, out _); - var reconciler = AddRemoveReferencesSetup.ArrangeReferenceReconciler(); + var model = AddRemoveReferencesSetup.ArrangeParsedAddRemoveReferencesModel(null, null, null, out _, out _, out var projectsProvider); + var reconciler = AddRemoveReferencesSetup.ArrangeReferenceReconciler(projectsProvider); var output = reconciler.ReconcileReferences(model.Object); @@ -344,8 +344,8 @@ public void ReconcileReferences_ReturnsEmptyWithoutNewReferences() [Category("AddRemoveReferences")] public void ReconcileReferencesOverload_ReturnsEmptyWithoutNewReferences() { - var model = AddRemoveReferencesSetup.ArrangeParsedAddRemoveReferencesModel(null, null, null, out _, out _); - var reconciler = AddRemoveReferencesSetup.ArrangeReferenceReconciler(); + var model = AddRemoveReferencesSetup.ArrangeParsedAddRemoveReferencesModel(null, null, null, out _, out _, out var projectsProvider); + var reconciler = AddRemoveReferencesSetup.ArrangeReferenceReconciler(projectsProvider); var output = reconciler.ReconcileReferences(model.Object, null); Assert.IsEmpty(output); @@ -358,8 +358,8 @@ public void ReconcileReferences_UpdatesSettingsPinned() var newReferences = AddRemoveReferencesSetup.LibraryReferenceInfoList .Select(reference => new ReferenceModel(reference, ReferenceKind.TypeLibrary)).ToList(); - var model = AddRemoveReferencesSetup.ArrangeParsedAddRemoveReferencesModel(null, newReferences, null, out _, out _); - var reconciler = AddRemoveReferencesSetup.ArrangeReferenceReconciler(); + var model = AddRemoveReferencesSetup.ArrangeParsedAddRemoveReferencesModel(null, newReferences, null, out _, out _, out var projectsProvider); + var reconciler = AddRemoveReferencesSetup.ArrangeReferenceReconciler(projectsProvider); var pinned = newReferences.First(); pinned.IsPinned = true; @@ -377,8 +377,9 @@ public void ReconcileReferences_AllReferencesAreAdded() var newReferences = AddRemoveReferencesSetup.LibraryReferenceInfoList .Select(reference => new ReferenceModel(reference, ReferenceKind.TypeLibrary)).ToList(); - var model = AddRemoveReferencesSetup.ArrangeParsedAddRemoveReferencesModel(newReferences, newReferences, newReferences, out var references, out var builder); - var reconciler = AddRemoveReferencesSetup.ArrangeReferenceReconciler(); + var model = AddRemoveReferencesSetup.ArrangeParsedAddRemoveReferencesModel(newReferences, newReferences, newReferences, out var references, out var builder, out var projectsProvider); + + var reconciler = AddRemoveReferencesSetup.ArrangeReferenceReconciler(projectsProvider); var priority = references.Object.Count; foreach (var item in newReferences) @@ -398,8 +399,8 @@ public void ReconcileReferences_AllReferencesAreAdded() public void ReconcileReferences_RemoveNotCalledOnBuiltIn() { var registered = AddRemoveReferencesSetup.DummyReferencesList; - var model = AddRemoveReferencesSetup.ArrangeParsedAddRemoveReferencesModel(registered, registered, registered, out var references, out _); - var reconciler = AddRemoveReferencesSetup.ArrangeReferenceReconciler(); + var model = AddRemoveReferencesSetup.ArrangeParsedAddRemoveReferencesModel(registered, registered, registered, out var references, out _, out var projectsProvider); + var reconciler = AddRemoveReferencesSetup.ArrangeReferenceReconciler(projectsProvider); var vba = references.Object.First(lib => lib.Name.Equals("VBA")); var excel = references.Object.First(lib => lib.Name.Equals("Excel")); diff --git a/RubberduckTests/CodeExplorer/CodeExplorerProjectViewModelTests.cs b/RubberduckTests/CodeExplorer/CodeExplorerProjectViewModelTests.cs index feed5398d0..c366e4ec75 100644 --- a/RubberduckTests/CodeExplorer/CodeExplorerProjectViewModelTests.cs +++ b/RubberduckTests/CodeExplorer/CodeExplorerProjectViewModelTests.cs @@ -1,9 +1,11 @@ using System.Collections.Generic; using NUnit.Framework; using System.Linq; +using System.Runtime.InteropServices; using Rubberduck.AddRemoveReferences; using Rubberduck.Parsing.Symbols; using Rubberduck.Navigation.CodeExplorer; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; @@ -419,18 +421,21 @@ public void Synchronize_SetsDeclarationNull_DeclarationsForDifferentProject() [TestCase(false, true, TestName = "Constructor_CreatesReferenceFolders_ProjectsOnly")] public void Constructor_CreatesReferenceFolders(bool libraries, bool projects) { - var declarations = CodeExplorerTestSetup.GetProjectDeclarationsWithReferences(libraries, projects); - var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); + var declarations = CodeExplorerTestSetup.GetProjectDeclarationsWithReferences(libraries, projects, out var state); + using (state) + { + var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); - var libraryFolder = project.Children.OfType() - .SingleOrDefault(folder => folder.ReferenceKind == ReferenceKind.TypeLibrary); - var projectFolder = project.Children.OfType() - .SingleOrDefault(folder => folder.ReferenceKind == ReferenceKind.Project); + var libraryFolder = project.Children.OfType() + .SingleOrDefault(folder => folder.ReferenceKind == ReferenceKind.TypeLibrary); + var projectFolder = project.Children.OfType() + .SingleOrDefault(folder => folder.ReferenceKind == ReferenceKind.Project); - Assert.AreEqual(libraries, libraryFolder != null); - Assert.AreEqual(projects, projectFolder != null); + Assert.AreEqual(libraries, libraryFolder != null); + Assert.AreEqual(projects, projectFolder != null); + } } [Test] @@ -441,18 +446,21 @@ public void Constructor_CreatesReferenceFolders(bool libraries, bool projects) [TestCase(false, true, TestName = "Synchronize_ReferenceFolders_NoChanges_ProjectsOnly")] public void Synchronize_ReferenceFolders_NoChanges(bool libraries, bool projects) { - var declarations = CodeExplorerTestSetup.GetProjectDeclarationsWithReferences(libraries, projects); - var updates = declarations.ToList(); - var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); + var declarations = CodeExplorerTestSetup.GetProjectDeclarationsWithReferences(libraries, projects, out var state); + using (state) + { + var updates = declarations.ToList(); + var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); - var expected = GetReferencesFromProjectDeclaration(projectDeclaration).Select(reference => reference.Name).ToList(); + var expected = GetReferencesFromProjectDeclaration(projectDeclaration, state.ProjectsProvider).Select(reference => reference.Name).ToList(); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); - project.Synchronize(ref updates); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); + project.Synchronize(ref updates); - var actual = GetReferencesFromProjectViewModel(project).OrderBy(reference => reference.Priority).Select(reference => reference.Name); + var actual = GetReferencesFromProjectViewModel(project).OrderBy(reference => reference.Priority).Select(reference => reference.Name); - Assert.IsTrue(expected.SequenceEqual(actual)); + Assert.IsTrue(expected.SequenceEqual(actual)); + } } [Test] @@ -463,27 +471,30 @@ public void Synchronize_ReferenceFolders_NoChanges(bool libraries, bool projects [TestCase(true, true, TestName = "Synchronize_ReferenceFolderRemoved_Both")] public void Synchronize_ReferenceFolderRemoved(bool libraries, bool projects) { - var declarations = CodeExplorerTestSetup.GetProjectDeclarationsWithReferences(libraries, projects); - var updates = declarations.ToList(); - var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); + var declarations = CodeExplorerTestSetup.GetProjectDeclarationsWithReferences(libraries, projects, out var state); + using (state) + { + var updates = declarations.ToList(); + var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); - var references = projectDeclaration.Project.References; - foreach (var reference in references.ToList()) - { - references.Remove(reference); - } + var references = state.ProjectsProvider.Project(projectDeclaration.ProjectId).References; + foreach (var reference in references.ToList()) + { + references.Remove(reference); + } - project.Synchronize(ref updates); + project.Synchronize(ref updates); - var libraryFolder = project.Children.OfType() - .SingleOrDefault(folder => folder.ReferenceKind == ReferenceKind.TypeLibrary); - var projectFolder = project.Children.OfType() - .SingleOrDefault(folder => folder.ReferenceKind == ReferenceKind.Project); + var libraryFolder = project.Children.OfType() + .SingleOrDefault(folder => folder.ReferenceKind == ReferenceKind.TypeLibrary); + var projectFolder = project.Children.OfType() + .SingleOrDefault(folder => folder.ReferenceKind == ReferenceKind.Project); - Assert.IsNull(libraryFolder); - Assert.IsNull(projectFolder); + Assert.IsNull(libraryFolder); + Assert.IsNull(projectFolder); + } } private static List GetReferencesFromProjectViewModel(ICodeExplorerNode viewModel) @@ -496,9 +507,9 @@ private static List GetReferencesFromProjectViewModel(ICodeExplo .ToList(); } - private static List GetReferencesFromProjectDeclaration(Declaration project) + private static List GetReferencesFromProjectDeclaration(Declaration project, IProjectsProvider projectsProvider) { - return project.Project.References.ToList(); + return projectsProvider.Project(project.ProjectId).References.ToList(); } } } diff --git a/RubberduckTests/CodeExplorer/CodeExplorerTestSetup.cs b/RubberduckTests/CodeExplorer/CodeExplorerTestSetup.cs index 0c443e3466..f43324d2d6 100644 --- a/RubberduckTests/CodeExplorer/CodeExplorerTestSetup.cs +++ b/RubberduckTests/CodeExplorer/CodeExplorerTestSetup.cs @@ -5,6 +5,8 @@ using RubberduckTests.Mocks; using System.Collections.Generic; using System.Linq; +using Rubberduck.Parsing.VBA; +using Rubberduck.UI.Command.MenuItems.ParentMenus; using Rubberduck.VBEditor.SafeComWrappers.Abstract; using RubberduckTests.AddRemoveReferences; @@ -173,7 +175,7 @@ static CodeExplorerTestSetup() ProjectTwo = parser.AllUserDeclarations.ToList(); } - public static List GetProjectDeclarationsWithReferences(bool libraries, bool projects) + public static List GetProjectDeclarationsWithReferences(bool libraries, bool projects, out RubberduckParserState state) { var builder = new MockVbeBuilder(); @@ -197,8 +199,8 @@ public static List GetProjectDeclarationsWithReferences(bool librar } builder.AddProject(project.Build()); - var parser = MockParser.CreateAndParse(builder.Build().Object); - return parser.AllUserDeclarations.ToList(); + state = MockParser.CreateAndParse(builder.Build().Object); + return state.AllUserDeclarations.ToList(); } public static List GetAllChildDeclarations(this ICodeExplorerNode node) diff --git a/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs b/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs index c3a44ae97d..370385bf01 100644 --- a/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs +++ b/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs @@ -210,7 +210,7 @@ private void SetupViewModelAndParse() public MockedCodeExplorer ImplementAddStdModuleCommand() { - ViewModel.AddStdModuleCommand = new AddStdModuleCommand(AddComponentService(), VbeEvents.Object); + ViewModel.AddStdModuleCommand = new AddStdModuleCommand(AddComponentService(), VbeEvents.Object, State.ProjectsProvider); return this; } @@ -234,7 +234,7 @@ public void ExecuteAddStdModuleCommand() public MockedCodeExplorer ImplementAddClassModuleCommand() { - ViewModel.AddClassModuleCommand = new AddClassModuleCommand(AddComponentService(), VbeEvents.Object); + ViewModel.AddClassModuleCommand = new AddClassModuleCommand(AddComponentService(), VbeEvents.Object, State.ProjectsProvider); return this; } @@ -249,7 +249,7 @@ public void ExecuteAddClassModuleCommand() public MockedCodeExplorer ImplementAddUserFormCommand() { - ViewModel.AddUserFormCommand = new AddUserFormCommand(AddComponentService(), VbeEvents.Object); + ViewModel.AddUserFormCommand = new AddUserFormCommand(AddComponentService(), VbeEvents.Object, State.ProjectsProvider); return this; } @@ -264,7 +264,7 @@ public void ExecuteAddUserFormCommand() public MockedCodeExplorer ImplementAddVbFormCommand() { - ViewModel.AddVBFormCommand = new AddVBFormCommand(AddComponentService(), VbeEvents.Object); + ViewModel.AddVBFormCommand = new AddVBFormCommand(AddComponentService(), VbeEvents.Object, State.ProjectsProvider); return this; } @@ -279,7 +279,7 @@ public void ExecuteAddVbFormCommand() public MockedCodeExplorer ImplementAddMdiFormCommand() { - ViewModel.AddMDIFormCommand = new AddMDIFormCommand(AddComponentService(), VbeEvents.Object); + ViewModel.AddMDIFormCommand = new AddMDIFormCommand(AddComponentService(), VbeEvents.Object, State.ProjectsProvider); return this; } @@ -294,7 +294,7 @@ public void ExecuteAddMdiFormCommand() public MockedCodeExplorer ImplementAddUserControlCommand() { - ViewModel.AddUserControlCommand = new AddUserControlCommand(AddComponentService(), VbeEvents.Object); + ViewModel.AddUserControlCommand = new AddUserControlCommand(AddComponentService(), VbeEvents.Object, State.ProjectsProvider); return this; } @@ -309,7 +309,7 @@ public void ExecuteAddUserControlCommand() public MockedCodeExplorer ImplementAddPropertyPageCommand() { - ViewModel.AddPropertyPageCommand = new AddPropertyPageCommand(AddComponentService(), VbeEvents.Object); + ViewModel.AddPropertyPageCommand = new AddPropertyPageCommand(AddComponentService(), VbeEvents.Object, State.ProjectsProvider); return this; } @@ -324,7 +324,7 @@ public void ExecuteAddPropertyPageCommand() public MockedCodeExplorer ImplementAddUserDocumentCommand() { - ViewModel.AddUserDocumentCommand = new AddUserDocumentCommand(AddComponentService(), VbeEvents.Object); + ViewModel.AddUserDocumentCommand = new AddUserDocumentCommand(AddComponentService(), VbeEvents.Object, State.ProjectsProvider); return this; } @@ -341,7 +341,7 @@ public MockedCodeExplorer ImplementAddTestModuleCommand() { var indenter = new Indenter(null, () => IndenterSettingsTests.GetMockIndenterSettings()); var codeGenerator = new TestCodeGenerator(Vbe.Object, State, MessageBox.Object, _interaction.Object, _unitTestSettingsProvider.Object, indenter, null); - ViewModel.AddTestModuleCommand = new AddTestComponentCommand(Vbe.Object, State, codeGenerator, VbeEvents.Object); + ViewModel.AddTestModuleCommand = new AddTestComponentCommand(Vbe.Object, State, codeGenerator, VbeEvents.Object, State.ProjectsProvider); return this; } @@ -450,7 +450,7 @@ public void ExecuteExportAllCommand() public MockedCodeExplorer ImplementExportAllCommand() { - ViewModel.ExportAllCommand = new ExportAllCommand(Vbe.Object, BrowserFactory.Object, VbeEvents.Object); + ViewModel.ExportAllCommand = new ExportAllCommand(Vbe.Object, BrowserFactory.Object, VbeEvents.Object, State.ProjectsProvider); return this; } @@ -503,7 +503,13 @@ public MockedCodeExplorer ImplementExtractInterfaceCommand() { ViewModel.CodeExplorerExtractInterfaceCommand = new CodeExplorerExtractInterfaceCommand( new Rubberduck.Refactorings.ExtractInterface.ExtractInterfaceRefactoring( - State, State, null, null, null, _uiDispatcher.Object), + State, + State, + null, + null, + null, + _uiDispatcher.Object, + State.ProjectsProvider), State, null, VbeEvents.Object); return this; } diff --git a/RubberduckTests/Commands/ExportAllCommandTests.cs b/RubberduckTests/Commands/ExportAllCommandTests.cs index b22107ba4d..87ba12c04f 100644 --- a/RubberduckTests/Commands/ExportAllCommandTests.cs +++ b/RubberduckTests/Commands/ExportAllCommandTests.cs @@ -6,6 +6,7 @@ using RubberduckTests.Mocks; using System.Linq; using System.Windows.Forms; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.Events; using Rubberduck.VBEditor.SafeComWrappers.Abstract; @@ -409,16 +410,21 @@ public void ExportAllCommand_Execute_PassedIVBProject_MultipleProjects_BrowserCa project2.Verify(m => m.ExportSourceFiles(_path), Times.Never); } - private static ExportAllCommand ArrangeExportAllCommand(Mock vbe, - Mock mockFolderBrowserFactory) + private static ExportAllCommand ArrangeExportAllCommand( + Mock vbe, + Mock mockFolderBrowserFactory, + IProjectsProvider projectsProvider = null) { - return ArrangeExportAllCommand(vbe, mockFolderBrowserFactory, MockVbeEvents.CreateMockVbeEvents(vbe)); + return ArrangeExportAllCommand(vbe, mockFolderBrowserFactory, MockVbeEvents.CreateMockVbeEvents(vbe), projectsProvider); } - private static ExportAllCommand ArrangeExportAllCommand(Mock vbe, - Mock mockFolderBrowserFactory, Mock vbeEvents) + private static ExportAllCommand ArrangeExportAllCommand( + Mock vbe, + Mock mockFolderBrowserFactory, + Mock vbeEvents, + IProjectsProvider projectsProvider) { - return new ExportAllCommand(vbe.Object, mockFolderBrowserFactory.Object, vbeEvents.Object); + return new ExportAllCommand(vbe.Object, mockFolderBrowserFactory.Object, vbeEvents.Object, projectsProvider); } } } diff --git a/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs b/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs index e89b5293d4..9a01a37a1c 100644 --- a/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs +++ b/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs @@ -170,7 +170,7 @@ protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state uiDispatcherMock .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); - var refactoring = new ExtractInterfaceRefactoring(state, state, factory, rewritingManager, selectionService, uiDispatcherMock.Object); + var refactoring = new ExtractInterfaceRefactoring(state, state, factory, rewritingManager, selectionService, uiDispatcherMock.Object, state.ProjectsProvider); var notifier = new ExtractInterfaceFailedNotifier(msgBox); return new RefactorExtractInterfaceCommand(refactoring, notifier, state, selectionService); } diff --git a/RubberduckTests/Commands/UnitTestCommandTests.cs b/RubberduckTests/Commands/UnitTestCommandTests.cs index 567c69d048..28ad0d3285 100644 --- a/RubberduckTests/Commands/UnitTestCommandTests.cs +++ b/RubberduckTests/Commands/UnitTestCommandTests.cs @@ -475,7 +475,7 @@ private AddTestModuleCommand ArrangeAddTestModuleCommand(Mock vbe, Rubberd // TODO: Remove the temporal copuling with other Arrange* private AddTestModuleCommand ArrangeAddTestModuleCommand(Mock vbe, RubberduckParserState state, ITestCodeGenerator generator, Mock vbeEvents) { - return new AddTestModuleCommand(vbe.Object, state, ArrangeCodeGenerator(vbe.Object, state), vbeEvents.Object); + return new AddTestModuleCommand(vbe.Object, state, ArrangeCodeGenerator(vbe.Object, state), vbeEvents.Object, state.ProjectsProvider); } // TODO: Remove the temporal coupling with other Arrange* diff --git a/RubberduckTests/Grammar/ResolverTests.cs b/RubberduckTests/Grammar/ResolverTests.cs index 6e5da78a69..1967c22c15 100644 --- a/RubberduckTests/Grammar/ResolverTests.cs +++ b/RubberduckTests/Grammar/ResolverTests.cs @@ -1495,10 +1495,11 @@ End Sub using (var state = Resolve(code)) { - var declaration = state.AllUserDeclarations.Single(item => - item.DeclarationType == DeclarationType.UserDefinedType); + var declaration = state.DeclarationFinder + .UserDeclarations(DeclarationType.UserDefinedType) + .Single(); - if (declaration.Project.Name != declaration.IdentifierName) + if (Declaration.GetProjectParent(declaration).IdentifierName != declaration.IdentifierName) { Assert.Inconclusive("UDT should be named after project."); } @@ -1534,7 +1535,7 @@ End Sub var declaration = state.AllUserDeclarations.Single(item => item.DeclarationType == DeclarationType.UserDefinedType); - if (declaration.Project.Name != declaration.IdentifierName) + if (Declaration.GetProjectParent(declaration).IdentifierName != declaration.IdentifierName) { Assert.Inconclusive("UDT should be named after project."); } @@ -1568,7 +1569,7 @@ End Sub var declaration = state.AllUserDeclarations.Single(item => item.DeclarationType == DeclarationType.Variable); - if (declaration.Project.Name != declaration.AsTypeName) + if (Declaration.GetProjectParent(declaration).IdentifierName != declaration.AsTypeName) { Assert.Inconclusive("variable should be named after project."); } @@ -1636,7 +1637,7 @@ End Sub var declaration = state.AllUserDeclarations.Single(item => item.DeclarationType == DeclarationType.UserDefinedTypeMember && item.IdentifierName == "Foo" - && item.AsTypeName == item.Project.Name + && item.AsTypeName == Declaration.GetProjectParent(item).IdentifierName && item.IdentifierName == item.ParentDeclaration.IdentifierName); var usages = declaration.References.Where(item => @@ -1857,7 +1858,7 @@ End Sub var declaration = state.AllUserDeclarations.Single(item => item.DeclarationType == DeclarationType.Project - && item.IdentifierName == item.Project.Name); + && item.IdentifierName == Declaration.GetProjectParent(item).IdentifierName); var usages = declaration.References.Where(item => item.ParentScoping.IdentifierName == "DoSomething"); diff --git a/RubberduckTests/Refactoring/ExtractInterfaceTests.cs b/RubberduckTests/Refactoring/ExtractInterfaceTests.cs index 3bf77e6f66..4d10444c02 100644 --- a/RubberduckTests/Refactoring/ExtractInterfaceTests.cs +++ b/RubberduckTests/Refactoring/ExtractInterfaceTests.cs @@ -424,7 +424,7 @@ protected override IRefactoring TestRefactoring(IRewritingManager rewritingManag uiDispatcherMock .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); - return new ExtractInterfaceRefactoring(state, state, factory, rewritingManager, selectionService, uiDispatcherMock.Object); + return new ExtractInterfaceRefactoring(state, state, factory, rewritingManager, selectionService, uiDispatcherMock.Object, state.ProjectsProvider); } } } \ No newline at end of file diff --git a/RubberduckTests/UnitTesting/MockedTestEngine.cs b/RubberduckTests/UnitTesting/MockedTestEngine.cs index f2eed867b9..be856070b2 100644 --- a/RubberduckTests/UnitTesting/MockedTestEngine.cs +++ b/RubberduckTests/UnitTesting/MockedTestEngine.cs @@ -8,6 +8,7 @@ using Rubberduck.Parsing.UIContext; using Rubberduck.Parsing.VBA; using Rubberduck.UnitTesting; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.ComManagement.TypeLibs.Abstract; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; @@ -74,7 +75,7 @@ public MockedTestEngine(string testModuleCode) : this() Vbe = builder.Build(); ParserState = MockParser.Create(Vbe.Object).State; - TestEngine = new SynchronouslySuspendingTestEngine(ParserState, _fakesFactory.Object, VbeInteraction.Object, WrapperProvider.Object, Dispatcher.Object, Vbe.Object); + TestEngine = new SynchronouslySuspendingTestEngine(ParserState, _fakesFactory.Object, VbeInteraction.Object, WrapperProvider.Object, Dispatcher.Object, Vbe.Object, ParserState.ProjectsProvider); } public MockedTestEngine(IReadOnlyList moduleNames, IReadOnlyList methodCounts) : this() @@ -97,7 +98,7 @@ public MockedTestEngine(IReadOnlyList moduleNames, IReadOnlyList me project.AddProjectToVbeBuilder(); Vbe = builder.Build(); ParserState = MockParser.Create(Vbe.Object).State; - TestEngine = new SynchronouslySuspendingTestEngine(ParserState, _fakesFactory.Object, VbeInteraction.Object, WrapperProvider.Object, Dispatcher.Object, Vbe.Object); + TestEngine = new SynchronouslySuspendingTestEngine(ParserState, _fakesFactory.Object, VbeInteraction.Object, WrapperProvider.Object, Dispatcher.Object, Vbe.Object, ParserState.ProjectsProvider); } public MockedTestEngine(int testMethodCount) @@ -267,8 +268,9 @@ public SynchronouslySuspendingTestEngine( IVBEInteraction declarationRunner, ITypeLibWrapperProvider wrapperProvider, IUiDispatcher uiDispatcher, - IVBE vbe) - : base(state, fakesFactory, declarationRunner, wrapperProvider, uiDispatcher, vbe) + IVBE vbe, + IProjectsProvider projectsProvider) + : base(state, fakesFactory, declarationRunner, wrapperProvider, uiDispatcher, vbe, projectsProvider) { _state = state; } From 8a310792cf0989233ebb79cc7dc4313857ec7bc8 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Mon, 17 Feb 2020 01:19:47 +0100 Subject: [PATCH 230/461] Use IProjectsProvider in ExtractInterfaceBaseRefactoring --- .../ExtractInterfaceBaseRefactoring.cs | 16 +++++++++------- .../CodeExplorer/MockedCodeExplorer.cs | 2 +- .../ExtractInterfaceCommandTests.cs | 2 +- .../Refactoring/ExtractInterfaceTests.cs | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceBaseRefactoring.cs b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceBaseRefactoring.cs index 4bbd504304..2dcdc511d9 100644 --- a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceBaseRefactoring.cs +++ b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceBaseRefactoring.cs @@ -8,7 +8,9 @@ using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.Parsing; using Rubberduck.Refactorings.AddInterfaceImplementations; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.SafeComWrappers; +using Rubberduck.VBEditor.SafeComWrappers.Abstract; namespace Rubberduck.Refactorings.ExtractInterface { @@ -16,16 +18,19 @@ public class ExtractInterfaceBaseRefactoring : BaseRefactoringWithSuspensionBase { private readonly ICodeOnlyBaseRefactoring _addImplementationsRefactoring; private readonly IParseTreeProvider _parseTreeProvider; + private readonly IProjectsProvider _projectsProvider; public ExtractInterfaceBaseRefactoring( AddInterFaceImplementationsBaseRefactoring addImplementationsRefactoring, IParseTreeProvider parseTreeProvider, IParseManager parseManager, - IRewritingManager rewritingManager) + IRewritingManager rewritingManager, + IProjectsProvider projectsProvider) : base(parseManager, rewritingManager) { _addImplementationsRefactoring = addImplementationsRefactoring; _parseTreeProvider = parseTreeProvider; + _projectsProvider = projectsProvider; } protected override bool RequiresSuspension(ExtractInterfaceModel model) @@ -40,20 +45,19 @@ protected override void Refactor(ExtractInterfaceModel model, IRewriteSession re private void AddInterface(ExtractInterfaceModel model, IRewriteSession rewriteSession) { - var targetProject = model.TargetDeclaration.Project; + var targetProject = _projectsProvider.Project(model.TargetDeclaration.ProjectId); if (targetProject == null) { return; //The target project is not available. } - AddInterfaceClass(model.TargetDeclaration, model.InterfaceName, GetInterfaceModuleBody(model)); + AddInterfaceClass(targetProject, model.InterfaceName, GetInterfaceModuleBody(model)); AddImplementsStatement(model, rewriteSession); AddInterfaceMembersToClass(model, rewriteSession); } - private void AddInterfaceClass(Declaration implementingClass, string interfaceName, string interfaceBody) + private void AddInterfaceClass(IVBProject targetProject, string interfaceName, string interfaceBody) { - var targetProject = implementingClass.Project; using (var components = targetProject.VBComponents) { using (var interfaceComponent = components.Add(ComponentType.ClassModule)) @@ -120,8 +124,6 @@ private void AddImplementsStatement(ExtractInterfaceModel model, IRewriteSession return (-1, false); } - - private void AddInterfaceMembersToClass(ExtractInterfaceModel model, IRewriteSession rewriteSession) { var targetModule = model.TargetDeclaration.QualifiedModuleName; diff --git a/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs b/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs index b9c870fa55..0bcece1ef4 100644 --- a/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs +++ b/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs @@ -504,7 +504,7 @@ public MockedCodeExplorer ImplementIndenterCommand() public MockedCodeExplorer ImplementExtractInterfaceCommand() { var addImplementationsBaseRefactoring = new AddInterFaceImplementationsBaseRefactoring(null); - var extractInterfaceBaseRefactoring = new ExtractInterfaceBaseRefactoring(addImplementationsBaseRefactoring, State, State, null); + var extractInterfaceBaseRefactoring = new ExtractInterfaceBaseRefactoring(addImplementationsBaseRefactoring, State, State, null, State.ProjectsProvider); ViewModel.CodeExplorerExtractInterfaceCommand = new CodeExplorerExtractInterfaceCommand( new ExtractInterfaceRefactoring(extractInterfaceBaseRefactoring, State, null, null, _uiDispatcher.Object), State, null, VbeEvents.Object); diff --git a/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs b/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs index b30e49c7c3..14b18823a6 100644 --- a/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs +++ b/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs @@ -172,7 +172,7 @@ protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); var addImplementationsBaseRefactoring = new AddInterFaceImplementationsBaseRefactoring(rewritingManager); - var baseRefactoring = new ExtractInterfaceBaseRefactoring(addImplementationsBaseRefactoring, state, state, rewritingManager); + var baseRefactoring = new ExtractInterfaceBaseRefactoring(addImplementationsBaseRefactoring, state, state, rewritingManager, state.ProjectsProvider); var refactoring = new ExtractInterfaceRefactoring(baseRefactoring, state, factory, selectionService, uiDispatcherMock.Object); var notifier = new ExtractInterfaceFailedNotifier(msgBox); return new RefactorExtractInterfaceCommand(refactoring, notifier, state, selectionService); diff --git a/RubberduckTests/Refactoring/ExtractInterfaceTests.cs b/RubberduckTests/Refactoring/ExtractInterfaceTests.cs index 68c3a544ed..f14742913b 100644 --- a/RubberduckTests/Refactoring/ExtractInterfaceTests.cs +++ b/RubberduckTests/Refactoring/ExtractInterfaceTests.cs @@ -650,7 +650,7 @@ protected override IRefactoring TestRefactoring(IRewritingManager rewritingManag .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); var addImplementationsBaseRefactoring = new AddInterFaceImplementationsBaseRefactoring(rewritingManager); - var baseRefactoring = new ExtractInterfaceBaseRefactoring(addImplementationsBaseRefactoring, state, state, rewritingManager); + var baseRefactoring = new ExtractInterfaceBaseRefactoring(addImplementationsBaseRefactoring, state, state, rewritingManager, state.ProjectsProvider); return new ExtractInterfaceRefactoring(baseRefactoring, state, factory, selectionService, uiDispatcherMock.Object); } } From 166ddf635f19614cdad32d7ace69a3bb36a57609 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Mon, 17 Feb 2020 01:37:24 +0100 Subject: [PATCH 231/461] Rename IBaseRefactoring to IRefactoringAction Also renames all corresponding classes. --- ...oringBase.cs => CodeOnlyRefactoringActionBase.cs} | 4 ++-- .../{IBaseRefactoring.cs => IRefactoringAction.cs} | 4 ++-- ...seRefactoringBase.cs => RefactoringActionBase.cs} | 4 ++-- ...ionBase.cs => RefactoringActionWithSuspension.cs} | 4 ++-- .../ExtractInterface/ExtractInterfaceRefactoring.cs | 8 ++++---- ...oring.cs => ExtractInterfaceRefactoringAction.cs} | 12 ++++++------ ... AddInterfaceImplementationsRefactoringAction.cs} | 4 ++-- .../ImplementInterfaceRefactoring.cs | 8 ++++---- ...ing.cs => ImplementInterfaceRefactoringAction.cs} | 12 ++++++------ .../IntroduceField/IntroduceFieldRefactoring.cs | 8 ++++---- ...ctoring.cs => IntroduceFieldRefactoringAction.cs} | 4 ++-- .../IntroduceParameterRefactoring.cs | 8 ++++---- ...ing.cs => IntroduceParameterRefactoringAction.cs} | 4 ++-- .../MoveCloserToUsageRefactoring.cs | 8 ++++---- ...ring.cs => MoveCloserToUsageRefactoringAction.cs} | 4 ++-- ...factoring.cs => MoveToFolderRefactoringAction.cs} | 4 ++-- ...toring.cs => RemoveParameterRefactoringAction.cs} | 4 ++-- .../RemoveParameters/RemoveParametersRefactoring.cs | 10 +++++----- Rubberduck.Refactorings/Rename/RenameRefactoring.cs | 8 ++++---- ...BaseRefactoring.cs => RenameRefactoringAction.cs} | 4 ++-- ...oring.cs => ReorderParameterRefactoringAction.cs} | 4 ++-- .../ReorderParametersRefactoring.cs | 8 ++++---- RubberduckTests/CodeExplorer/MockedCodeExplorer.cs | 4 ++-- .../RefactorCommands/ExtractInterfaceCommandTests.cs | 4 ++-- .../ImplementInterfaceCommandTests.cs | 4 ++-- .../RefactorCommands/IntroduceFieldCommandTests.cs | 2 +- .../IntroduceParameterCommandTests.cs | 2 +- .../MoveCloserToUsageCommandTests.cs | 2 +- .../RefactorCommands/RemoveParametersCommandTests.cs | 2 +- .../ReorderParametersCommandTests.cs | 2 +- .../MoveFieldCloserToUsageQuickFixTests.cs | 2 +- .../QuickFixes/RemoveUnusedParameterQuickFixTests.cs | 2 +- .../Refactoring/BaseRefactoringTestBase.cs | 2 +- RubberduckTests/Refactoring/ExtractInterfaceTests.cs | 4 ++-- .../Refactoring/ImplementInterfaceTests.cs | 4 ++-- RubberduckTests/Refactoring/IntroduceFieldTests.cs | 2 +- .../Refactoring/IntroduceParameterTests.cs | 2 +- .../Refactoring/MoveCloserToUsageTests.cs | 2 +- RubberduckTests/Refactoring/MoveToFolderTests.cs | 4 ++-- RubberduckTests/Refactoring/RemoveParametersTests.cs | 2 +- RubberduckTests/Refactoring/Rename/RenameTests.cs | 2 +- .../Refactoring/ReorderParametersTests.cs | 2 +- 42 files changed, 95 insertions(+), 95 deletions(-) rename Rubberduck.Refactorings/Abstract/{CodeOnlyBaseRefactoringBase.cs => CodeOnlyRefactoringActionBase.cs} (85%) rename Rubberduck.Refactorings/Abstract/{IBaseRefactoring.cs => IRefactoringAction.cs} (90%) rename Rubberduck.Refactorings/Abstract/{BaseRefactoringBase.cs => RefactoringActionBase.cs} (87%) rename Rubberduck.Refactorings/Abstract/{BaseRefactoringWithSuspensionBase.cs => RefactoringActionWithSuspension.cs} (89%) rename Rubberduck.Refactorings/ExtractInterface/{ExtractInterfaceBaseRefactoring.cs => ExtractInterfaceRefactoringAction.cs} (90%) rename Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/{AddInterFaceImplementationsBaseRefactoring.cs => AddInterfaceImplementationsRefactoringAction.cs} (94%) rename Rubberduck.Refactorings/ImplementInterface/{ImplementInterfaceBaseRefactoring.cs => ImplementInterfaceRefactoringAction.cs} (72%) rename Rubberduck.Refactorings/IntroduceField/{IntroduceFieldBaseRefactoring.cs => IntroduceFieldRefactoringAction.cs} (87%) rename Rubberduck.Refactorings/IntroduceParameter/{IntroduceParameterBaseRefactoring.cs => IntroduceParameterRefactoringAction.cs} (95%) rename Rubberduck.Refactorings/MoveCloserToUsage/{MoveCloserToUsageBaseRefactoring.cs => MoveCloserToUsageRefactoringAction.cs} (96%) rename Rubberduck.Refactorings/MoveToFolder/{MoveToFolderBaseRefactoring.cs => MoveToFolderRefactoringAction.cs} (93%) rename Rubberduck.Refactorings/RemoveParameters/{RemoveParameterBaseRefactoring.cs => RemoveParameterRefactoringAction.cs} (98%) rename Rubberduck.Refactorings/Rename/{RenameBaseRefactoring.cs => RenameRefactoringAction.cs} (99%) rename Rubberduck.Refactorings/ReorderParameters/{ReorderParameterBaseRefactoring.cs => ReorderParameterRefactoringAction.cs} (98%) diff --git a/Rubberduck.Refactorings/Abstract/CodeOnlyBaseRefactoringBase.cs b/Rubberduck.Refactorings/Abstract/CodeOnlyRefactoringActionBase.cs similarity index 85% rename from Rubberduck.Refactorings/Abstract/CodeOnlyBaseRefactoringBase.cs rename to Rubberduck.Refactorings/Abstract/CodeOnlyRefactoringActionBase.cs index e3dd336b89..e1db929c6c 100644 --- a/Rubberduck.Refactorings/Abstract/CodeOnlyBaseRefactoringBase.cs +++ b/Rubberduck.Refactorings/Abstract/CodeOnlyRefactoringActionBase.cs @@ -4,12 +4,12 @@ namespace Rubberduck.Refactorings { - public abstract class CodeOnlyBaseRefactoringBase : ICodeOnlyBaseRefactoring + public abstract class CodeOnlyRefactoringActionBase : ICodeOnlyRefactoringAction where TModel : class, IRefactoringModel { private readonly IRewritingManager _rewritingManager; - protected CodeOnlyBaseRefactoringBase(IRewritingManager rewritingManager) + protected CodeOnlyRefactoringActionBase(IRewritingManager rewritingManager) { _rewritingManager = rewritingManager; } diff --git a/Rubberduck.Refactorings/Abstract/IBaseRefactoring.cs b/Rubberduck.Refactorings/Abstract/IRefactoringAction.cs similarity index 90% rename from Rubberduck.Refactorings/Abstract/IBaseRefactoring.cs rename to Rubberduck.Refactorings/Abstract/IRefactoringAction.cs index 27fcf699e2..764bd601b8 100644 --- a/Rubberduck.Refactorings/Abstract/IBaseRefactoring.cs +++ b/Rubberduck.Refactorings/Abstract/IRefactoringAction.cs @@ -6,7 +6,7 @@ namespace Rubberduck.Refactorings /// The heart of a refactoring: this part of the refactoring performs the actual transformation of the code once all necessary information has been gathered. /// /// The model used by the refactoring containing all information needed to specify what to do. - public interface IBaseRefactoring where TModel : class, IRefactoringModel + public interface IRefactoringAction where TModel : class, IRefactoringModel { /// /// Performs the actual refactoring based on the parameters specified in the model. @@ -26,7 +26,7 @@ public interface IRefactoringPreviewProvider string Preview(TModel model); } - public interface ICodeOnlyBaseRefactoring : IBaseRefactoring + public interface ICodeOnlyRefactoringAction : IRefactoringAction where TModel : class, IRefactoringModel { /// diff --git a/Rubberduck.Refactorings/Abstract/BaseRefactoringBase.cs b/Rubberduck.Refactorings/Abstract/RefactoringActionBase.cs similarity index 87% rename from Rubberduck.Refactorings/Abstract/BaseRefactoringBase.cs rename to Rubberduck.Refactorings/Abstract/RefactoringActionBase.cs index d64dbd0aaf..f9b62dd432 100644 --- a/Rubberduck.Refactorings/Abstract/BaseRefactoringBase.cs +++ b/Rubberduck.Refactorings/Abstract/RefactoringActionBase.cs @@ -4,12 +4,12 @@ namespace Rubberduck.Refactorings { - public abstract class BaseRefactoringBase : IBaseRefactoring + public abstract class RefactoringActionBase : IRefactoringAction where TModel : class, IRefactoringModel { private readonly IRewritingManager _rewritingManager; - protected BaseRefactoringBase(IRewritingManager rewritingManager) + protected RefactoringActionBase(IRewritingManager rewritingManager) { _rewritingManager = rewritingManager; } diff --git a/Rubberduck.Refactorings/Abstract/BaseRefactoringWithSuspensionBase.cs b/Rubberduck.Refactorings/Abstract/RefactoringActionWithSuspension.cs similarity index 89% rename from Rubberduck.Refactorings/Abstract/BaseRefactoringWithSuspensionBase.cs rename to Rubberduck.Refactorings/Abstract/RefactoringActionWithSuspension.cs index d31fdfd5e6..8ffb588cef 100644 --- a/Rubberduck.Refactorings/Abstract/BaseRefactoringWithSuspensionBase.cs +++ b/Rubberduck.Refactorings/Abstract/RefactoringActionWithSuspension.cs @@ -6,14 +6,14 @@ namespace Rubberduck.Refactorings { - public abstract class BaseRefactoringWithSuspensionBase : BaseRefactoringBase + public abstract class RefactoringActionWithSuspension : RefactoringActionBase where TModel : class, IRefactoringModel { private readonly IParseManager _parseManager; private readonly Logger _logger; - protected BaseRefactoringWithSuspensionBase(IParseManager parseManager, IRewritingManager rewritingManager) + protected RefactoringActionWithSuspension(IParseManager parseManager, IRewritingManager rewritingManager) : base(rewritingManager) { _parseManager = parseManager; diff --git a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs index 20b910e12d..6c545f2fb8 100644 --- a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs +++ b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs @@ -12,18 +12,18 @@ namespace Rubberduck.Refactorings.ExtractInterface { public class ExtractInterfaceRefactoring : InteractiveRefactoringBase { - private readonly IBaseRefactoring _baseRefactoring; + private readonly IRefactoringAction _refactoringAction; private readonly IDeclarationFinderProvider _declarationFinderProvider; public ExtractInterfaceRefactoring( - ExtractInterfaceBaseRefactoring baseRefactoring, + ExtractInterfaceRefactoringAction refactoringAction, IDeclarationFinderProvider declarationFinderProvider, IRefactoringPresenterFactory factory, ISelectionProvider selectionProvider, IUiDispatcher uiDispatcher) :base(selectionProvider, factory, uiDispatcher) { - _baseRefactoring = baseRefactoring; + _refactoringAction = refactoringAction; _declarationFinderProvider = declarationFinderProvider; } @@ -61,7 +61,7 @@ protected override ExtractInterfaceModel InitializeModel(Declaration target) protected override void RefactorImpl(ExtractInterfaceModel model) { - _baseRefactoring.Refactor(model); + _refactoringAction.Refactor(model); } //TODO: Redesign how refactoring commands are wired up to make this a responsibility of the command again. diff --git a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceBaseRefactoring.cs b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoringAction.cs similarity index 90% rename from Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceBaseRefactoring.cs rename to Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoringAction.cs index 2dcdc511d9..c3fa031284 100644 --- a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceBaseRefactoring.cs +++ b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoringAction.cs @@ -14,21 +14,21 @@ namespace Rubberduck.Refactorings.ExtractInterface { - public class ExtractInterfaceBaseRefactoring : BaseRefactoringWithSuspensionBase + public class ExtractInterfaceRefactoringAction : RefactoringActionWithSuspension { - private readonly ICodeOnlyBaseRefactoring _addImplementationsRefactoring; + private readonly ICodeOnlyRefactoringAction _addImplementationsRefactoringAction; private readonly IParseTreeProvider _parseTreeProvider; private readonly IProjectsProvider _projectsProvider; - public ExtractInterfaceBaseRefactoring( - AddInterFaceImplementationsBaseRefactoring addImplementationsRefactoring, + public ExtractInterfaceRefactoringAction( + AddInterfaceImplementationsRefactoringAction addImplementationsRefactoringAction, IParseTreeProvider parseTreeProvider, IParseManager parseManager, IRewritingManager rewritingManager, IProjectsProvider projectsProvider) : base(parseManager, rewritingManager) { - _addImplementationsRefactoring = addImplementationsRefactoring; + _addImplementationsRefactoringAction = addImplementationsRefactoringAction; _parseTreeProvider = parseTreeProvider; _projectsProvider = projectsProvider; } @@ -131,7 +131,7 @@ private void AddInterfaceMembersToClass(ExtractInterfaceModel model, IRewriteSes var membersToImplement = model.SelectedMembers.Select(m => m.Member).ToList(); var addMembersModel = new AddInterfaceImplementationsModel(targetModule, interfaceName, membersToImplement); - _addImplementationsRefactoring.Refactor(addMembersModel, rewriteSession); + _addImplementationsRefactoringAction.Refactor(addMembersModel, rewriteSession); } private static string GetInterfaceModuleBody(ExtractInterfaceModel model) diff --git a/Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterFaceImplementationsBaseRefactoring.cs b/Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterfaceImplementationsRefactoringAction.cs similarity index 94% rename from Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterFaceImplementationsBaseRefactoring.cs rename to Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterfaceImplementationsRefactoringAction.cs index 4736157a82..4277dc0886 100644 --- a/Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterFaceImplementationsBaseRefactoring.cs +++ b/Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterfaceImplementationsRefactoringAction.cs @@ -8,11 +8,11 @@ namespace Rubberduck.Refactorings.AddInterfaceImplementations { - public class AddInterFaceImplementationsBaseRefactoring : CodeOnlyBaseRefactoringBase + public class AddInterfaceImplementationsRefactoringAction : CodeOnlyRefactoringActionBase { private const string MemberBody = " Err.Raise 5 'TODO implement interface member"; - public AddInterFaceImplementationsBaseRefactoring(IRewritingManager rewritingManager) + public AddInterfaceImplementationsRefactoringAction(IRewritingManager rewritingManager) : base(rewritingManager) {} diff --git a/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceRefactoring.cs b/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceRefactoring.cs index 387001c227..716f14ba04 100644 --- a/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceRefactoring.cs +++ b/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceRefactoring.cs @@ -12,16 +12,16 @@ namespace Rubberduck.Refactorings.ImplementInterface { public class ImplementInterfaceRefactoring : RefactoringBase { - private readonly IBaseRefactoring _baseRefactoring; + private readonly IRefactoringAction _refactoringAction; private readonly IDeclarationFinderProvider _declarationFinderProvider; public ImplementInterfaceRefactoring( - ImplementInterfaceBaseRefactoring baseRefactoring, + ImplementInterfaceRefactoringAction refactoringAction, IDeclarationFinderProvider declarationFinderProvider, ISelectionProvider selectionProvider) :base(selectionProvider) { - _baseRefactoring = baseRefactoring; + _refactoringAction = refactoringAction; _declarationFinderProvider = declarationFinderProvider; } @@ -59,7 +59,7 @@ public override void Refactor(QualifiedSelection target) } var model = Model(targetInterface, targetClass); - _baseRefactoring.Refactor(model); + _refactoringAction.Refactor(model); } private static ImplementInterfaceModel Model(ClassModuleDeclaration targetInterface, ClassModuleDeclaration targetClass) diff --git a/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceBaseRefactoring.cs b/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceRefactoringAction.cs similarity index 72% rename from Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceBaseRefactoring.cs rename to Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceRefactoringAction.cs index abfb361559..397d2390a6 100644 --- a/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceBaseRefactoring.cs +++ b/Rubberduck.Refactorings/ImplementInterface/ImplementInterfaceRefactoringAction.cs @@ -5,16 +5,16 @@ namespace Rubberduck.Refactorings.ImplementInterface { - public class ImplementInterfaceBaseRefactoring : BaseRefactoringBase + public class ImplementInterfaceRefactoringAction : RefactoringActionBase { - private readonly ICodeOnlyBaseRefactoring _addImplementationsRefactoring; + private readonly ICodeOnlyRefactoringAction _addImplementationsRefactoringAction; - public ImplementInterfaceBaseRefactoring( - AddInterFaceImplementationsBaseRefactoring addImplementationsRefactoring, + public ImplementInterfaceRefactoringAction( + AddInterfaceImplementationsRefactoringAction addImplementationsRefactoringAction, IRewritingManager rewritingManager) : base(rewritingManager) { - _addImplementationsRefactoring = addImplementationsRefactoring; + _addImplementationsRefactoringAction = addImplementationsRefactoringAction; } protected override void Refactor(ImplementInterfaceModel model, IRewriteSession rewriteSession) @@ -35,7 +35,7 @@ private void ImplementMissingMembers(ModuleDeclaration targetInterface, ModuleDe var nonImplementedMembers = interfaceMembers.Where(member => !implemented.Contains(member)); var addMembersModel = new AddInterfaceImplementationsModel(targetClass.QualifiedModuleName, targetInterface.IdentifierName, nonImplementedMembers.ToList()); - _addImplementationsRefactoring.Refactor(addMembersModel, rewriteSession); + _addImplementationsRefactoringAction.Refactor(addMembersModel, rewriteSession); } } } \ No newline at end of file diff --git a/Rubberduck.Refactorings/IntroduceField/IntroduceFieldRefactoring.cs b/Rubberduck.Refactorings/IntroduceField/IntroduceFieldRefactoring.cs index f6a2b46b23..6a5782a62f 100644 --- a/Rubberduck.Refactorings/IntroduceField/IntroduceFieldRefactoring.cs +++ b/Rubberduck.Refactorings/IntroduceField/IntroduceFieldRefactoring.cs @@ -10,16 +10,16 @@ namespace Rubberduck.Refactorings.IntroduceField { public class IntroduceFieldRefactoring : RefactoringBase { - private readonly IBaseRefactoring _baseRefactoring; + private readonly IRefactoringAction _refactoringAction; private readonly ISelectedDeclarationProvider _selectedDeclarationProvider; public IntroduceFieldRefactoring( - IntroduceFieldBaseRefactoring baseRefactoring, + IntroduceFieldRefactoringAction refactoringAction, ISelectionProvider selectionProvider, ISelectedDeclarationProvider selectedDeclarationProvider) :base(selectionProvider) { - _baseRefactoring = baseRefactoring; + _refactoringAction = refactoringAction; _selectedDeclarationProvider = selectedDeclarationProvider; } @@ -58,7 +58,7 @@ public override void Refactor(Declaration target) private void PromoteVariable(Declaration target) { var model = Model(target); - _baseRefactoring.Refactor(model); + _refactoringAction.Refactor(model); } private static IntroduceFieldModel Model(Declaration target) diff --git a/Rubberduck.Refactorings/IntroduceField/IntroduceFieldBaseRefactoring.cs b/Rubberduck.Refactorings/IntroduceField/IntroduceFieldRefactoringAction.cs similarity index 87% rename from Rubberduck.Refactorings/IntroduceField/IntroduceFieldBaseRefactoring.cs rename to Rubberduck.Refactorings/IntroduceField/IntroduceFieldRefactoringAction.cs index edcfbacd63..a36ca2e5cc 100644 --- a/Rubberduck.Refactorings/IntroduceField/IntroduceFieldBaseRefactoring.cs +++ b/Rubberduck.Refactorings/IntroduceField/IntroduceFieldRefactoringAction.cs @@ -7,11 +7,11 @@ namespace Rubberduck.Refactorings.IntroduceField { - public class IntroduceFieldBaseRefactoring : BaseRefactoringBase + public class IntroduceFieldRefactoringAction : RefactoringActionBase { private readonly IDeclarationFinderProvider _declarationFinderProvider; - public IntroduceFieldBaseRefactoring(IDeclarationFinderProvider declarationFinderProvider, + public IntroduceFieldRefactoringAction(IDeclarationFinderProvider declarationFinderProvider, IRewritingManager rewritingManager) : base(rewritingManager) { diff --git a/Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterRefactoring.cs b/Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterRefactoring.cs index bf83202cd1..55476dc64d 100644 --- a/Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterRefactoring.cs +++ b/Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterRefactoring.cs @@ -11,18 +11,18 @@ namespace Rubberduck.Refactorings.IntroduceParameter { public class IntroduceParameterRefactoring : RefactoringBase { - private readonly IBaseRefactoring _baseRefactoring; + private readonly IRefactoringAction _refactoringAction; private readonly ISelectedDeclarationProvider _selectedDeclarationProvider; private readonly IMessageBox _messageBox; public IntroduceParameterRefactoring( - IntroduceParameterBaseRefactoring baseRefactoring, + IntroduceParameterRefactoringAction refactoringAction, IMessageBox messageBox, ISelectionProvider selectionProvider, ISelectedDeclarationProvider selectedDeclarationProvider) :base(selectionProvider) { - _baseRefactoring = baseRefactoring; + _refactoringAction = refactoringAction; _selectedDeclarationProvider = selectedDeclarationProvider; _messageBox = messageBox; } @@ -67,7 +67,7 @@ private void PromoteVariable(Declaration target) } var model = Model(target); - _baseRefactoring.Refactor(model); + _refactoringAction.Refactor(model); } private IntroduceParameterModel Model(Declaration target) diff --git a/Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterBaseRefactoring.cs b/Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterRefactoringAction.cs similarity index 95% rename from Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterBaseRefactoring.cs rename to Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterRefactoringAction.cs index ea5e2b07a9..c512c7f4c5 100644 --- a/Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterBaseRefactoring.cs +++ b/Rubberduck.Refactorings/IntroduceParameter/IntroduceParameterRefactoringAction.cs @@ -8,11 +8,11 @@ namespace Rubberduck.Refactorings.IntroduceParameter { - public class IntroduceParameterBaseRefactoring : BaseRefactoringBase + public class IntroduceParameterRefactoringAction : RefactoringActionBase { private readonly IDeclarationFinderProvider _declarationFinderProvider; - public IntroduceParameterBaseRefactoring(IDeclarationFinderProvider declarationFinderProvider, IRewritingManager rewritingManager) + public IntroduceParameterRefactoringAction(IDeclarationFinderProvider declarationFinderProvider, IRewritingManager rewritingManager) : base(rewritingManager) { _declarationFinderProvider = declarationFinderProvider; diff --git a/Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageRefactoring.cs b/Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageRefactoring.cs index b5bce9aaca..acbbfd3104 100644 --- a/Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageRefactoring.cs +++ b/Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageRefactoring.cs @@ -10,18 +10,18 @@ namespace Rubberduck.Refactorings.MoveCloserToUsage { public class MoveCloserToUsageRefactoring : RefactoringBase { - private readonly IBaseRefactoring _baseRefactoring; + private readonly IRefactoringAction _refactoringAction; private readonly IDeclarationFinderProvider _declarationFinderProvider; private readonly ISelectedDeclarationProvider _selectedDeclarationProvider; public MoveCloserToUsageRefactoring( - MoveCloserToUsageBaseRefactoring baseRefactoring, + MoveCloserToUsageRefactoringAction refactoringAction, IDeclarationFinderProvider declarationFinderProvider, ISelectionProvider selectionProvider, ISelectedDeclarationProvider selectedDeclarationProvider) :base(selectionProvider) { - _baseRefactoring = baseRefactoring; + _refactoringAction = refactoringAction; _declarationFinderProvider = declarationFinderProvider; _selectedDeclarationProvider = selectedDeclarationProvider; } @@ -188,7 +188,7 @@ private MoveCloserToUsageModel Model(Declaration target) private void MoveCloserToUsage(Declaration target) { var model = Model(target); - _baseRefactoring.Refactor(model); + _refactoringAction.Refactor(model); } } } diff --git a/Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageBaseRefactoring.cs b/Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageRefactoringAction.cs similarity index 96% rename from Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageBaseRefactoring.cs rename to Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageRefactoringAction.cs index dd533a2a81..d300472735 100644 --- a/Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageBaseRefactoring.cs +++ b/Rubberduck.Refactorings/MoveCloserToUsage/MoveCloserToUsageRefactoringAction.cs @@ -7,9 +7,9 @@ namespace Rubberduck.Refactorings.MoveCloserToUsage { - public class MoveCloserToUsageBaseRefactoring : BaseRefactoringBase + public class MoveCloserToUsageRefactoringAction : RefactoringActionBase { - public MoveCloserToUsageBaseRefactoring(IRewritingManager rewritingManager) + public MoveCloserToUsageRefactoringAction(IRewritingManager rewritingManager) : base(rewritingManager) {} diff --git a/Rubberduck.Refactorings/MoveToFolder/MoveToFolderBaseRefactoring.cs b/Rubberduck.Refactorings/MoveToFolder/MoveToFolderRefactoringAction.cs similarity index 93% rename from Rubberduck.Refactorings/MoveToFolder/MoveToFolderBaseRefactoring.cs rename to Rubberduck.Refactorings/MoveToFolder/MoveToFolderRefactoringAction.cs index 1e851ee159..5214491832 100644 --- a/Rubberduck.Refactorings/MoveToFolder/MoveToFolderBaseRefactoring.cs +++ b/Rubberduck.Refactorings/MoveToFolder/MoveToFolderRefactoringAction.cs @@ -7,11 +7,11 @@ namespace Rubberduck.Refactorings.MoveToFolder { - public class MoveToFolderBaseRefactoring : CodeOnlyBaseRefactoringBase + public class MoveToFolderRefactoringAction : CodeOnlyRefactoringActionBase { private readonly IAnnotationUpdater _annotationUpdater; - public MoveToFolderBaseRefactoring( + public MoveToFolderRefactoringAction( IRewritingManager rewritingManager, IAnnotationUpdater annotationUpdater) : base(rewritingManager) diff --git a/Rubberduck.Refactorings/RemoveParameters/RemoveParameterBaseRefactoring.cs b/Rubberduck.Refactorings/RemoveParameters/RemoveParameterRefactoringAction.cs similarity index 98% rename from Rubberduck.Refactorings/RemoveParameters/RemoveParameterBaseRefactoring.cs rename to Rubberduck.Refactorings/RemoveParameters/RemoveParameterRefactoringAction.cs index 1c8c4ea32c..3880ee08e3 100644 --- a/Rubberduck.Refactorings/RemoveParameters/RemoveParameterBaseRefactoring.cs +++ b/Rubberduck.Refactorings/RemoveParameters/RemoveParameterRefactoringAction.cs @@ -12,11 +12,11 @@ namespace Rubberduck.Refactorings.RemoveParameters { - public class RemoveParameterBaseRefactoring : BaseRefactoringBase + public class RemoveParameterRefactoringAction : RefactoringActionBase { private readonly IDeclarationFinderProvider _declarationFinderProvider; - public RemoveParameterBaseRefactoring(IDeclarationFinderProvider declarationFinderProvider, IRewritingManager rewritingManager) + public RemoveParameterRefactoringAction(IDeclarationFinderProvider declarationFinderProvider, IRewritingManager rewritingManager) : base(rewritingManager) { _declarationFinderProvider = declarationFinderProvider; diff --git a/Rubberduck.Refactorings/RemoveParameters/RemoveParametersRefactoring.cs b/Rubberduck.Refactorings/RemoveParameters/RemoveParametersRefactoring.cs index b021ebbe86..f8f448b497 100644 --- a/Rubberduck.Refactorings/RemoveParameters/RemoveParametersRefactoring.cs +++ b/Rubberduck.Refactorings/RemoveParameters/RemoveParametersRefactoring.cs @@ -11,12 +11,12 @@ namespace Rubberduck.Refactorings.RemoveParameters { public class RemoveParametersRefactoring : InteractiveRefactoringBase { - private readonly IBaseRefactoring _baseRefactoring; + private readonly IRefactoringAction _refactoringAction; private readonly IDeclarationFinderProvider _declarationFinderProvider; private readonly ISelectedDeclarationProvider _selectedDeclarationProvider; public RemoveParametersRefactoring( - RemoveParameterBaseRefactoring baseRefactoring, + RemoveParameterRefactoringAction refactoringAction, IDeclarationFinderProvider declarationFinderProvider, IRefactoringPresenterFactory factory, ISelectionProvider selectionProvider, @@ -24,7 +24,7 @@ public RemoveParametersRefactoring( IUiDispatcher uiDispatcher) :base(selectionProvider, factory, uiDispatcher) { - _baseRefactoring = baseRefactoring; + _refactoringAction = refactoringAction; _declarationFinderProvider = declarationFinderProvider; _selectedDeclarationProvider = selectedDeclarationProvider; } @@ -137,7 +137,7 @@ protected override void RefactorImpl(RemoveParametersModel model) throw new TargetDeclarationIsNullException(); } - _baseRefactoring.Refactor(model); + _refactoringAction.Refactor(model); } public void QuickFix(QualifiedSelection selection) @@ -160,7 +160,7 @@ public void QuickFix(QualifiedSelection selection) } model.RemoveParameters.Add(target); - _baseRefactoring.Refactor(model); + _refactoringAction.Refactor(model); } public static readonly DeclarationType[] ValidDeclarationTypes = diff --git a/Rubberduck.Refactorings/Rename/RenameRefactoring.cs b/Rubberduck.Refactorings/Rename/RenameRefactoring.cs index 2e50009c82..c154d7b0df 100644 --- a/Rubberduck.Refactorings/Rename/RenameRefactoring.cs +++ b/Rubberduck.Refactorings/Rename/RenameRefactoring.cs @@ -13,13 +13,13 @@ namespace Rubberduck.Refactorings.Rename { public class RenameRefactoring : InteractiveRefactoringBase { - private readonly IBaseRefactoring _baseRefactoring; + private readonly IRefactoringAction _refactoringAction; private readonly IDeclarationFinderProvider _declarationFinderProvider; private readonly ISelectedDeclarationProvider _selectedDeclarationProvider; private readonly IProjectsProvider _projectsProvider; public RenameRefactoring( - RenameBaseRefactoring baseRefactoring, + RenameRefactoringAction refactoringAction, IRefactoringPresenterFactory factory, IDeclarationFinderProvider declarationFinderProvider, IProjectsProvider projectsProvider, @@ -28,7 +28,7 @@ public RenameRefactoring( IUiDispatcher uiDispatcher) : base(selectionProvider, factory, uiDispatcher) { - _baseRefactoring = baseRefactoring; + _refactoringAction = refactoringAction; _declarationFinderProvider = declarationFinderProvider; _selectedDeclarationProvider = selectedDeclarationProvider; _projectsProvider = projectsProvider; @@ -55,7 +55,7 @@ protected override RenameModel InitializeModel(Declaration target) protected override void RefactorImpl(RenameModel model) { - _baseRefactoring.Refactor(model); + _refactoringAction.Refactor(model); } private RenameModel DeriveTarget(RenameModel model) diff --git a/Rubberduck.Refactorings/Rename/RenameBaseRefactoring.cs b/Rubberduck.Refactorings/Rename/RenameRefactoringAction.cs similarity index 99% rename from Rubberduck.Refactorings/Rename/RenameBaseRefactoring.cs rename to Rubberduck.Refactorings/Rename/RenameRefactoringAction.cs index 373c96c894..e8d14c792a 100644 --- a/Rubberduck.Refactorings/Rename/RenameBaseRefactoring.cs +++ b/Rubberduck.Refactorings/Rename/RenameRefactoringAction.cs @@ -12,7 +12,7 @@ namespace Rubberduck.Refactorings.Rename { - public class RenameBaseRefactoring : BaseRefactoringWithSuspensionBase + public class RenameRefactoringAction : RefactoringActionWithSuspension { private const string AppendUnderscoreFormat = "{0}_"; private const string PrependUnderscoreFormat = "_{0}"; @@ -21,7 +21,7 @@ public class RenameBaseRefactoring : BaseRefactoringWithSuspensionBase> _renameActions; - public RenameBaseRefactoring( + public RenameRefactoringAction( IDeclarationFinderProvider declarationFinderProvider, IProjectsProvider projectsProvider, IParseManager parserManager, diff --git a/Rubberduck.Refactorings/ReorderParameters/ReorderParameterBaseRefactoring.cs b/Rubberduck.Refactorings/ReorderParameters/ReorderParameterRefactoringAction.cs similarity index 98% rename from Rubberduck.Refactorings/ReorderParameters/ReorderParameterBaseRefactoring.cs rename to Rubberduck.Refactorings/ReorderParameters/ReorderParameterRefactoringAction.cs index 3fe1c5ad33..a4be3877df 100644 --- a/Rubberduck.Refactorings/ReorderParameters/ReorderParameterBaseRefactoring.cs +++ b/Rubberduck.Refactorings/ReorderParameters/ReorderParameterRefactoringAction.cs @@ -12,11 +12,11 @@ namespace Rubberduck.Refactorings.ReorderParameters { - public class ReorderParameterBaseRefactoring : BaseRefactoringBase + public class ReorderParameterRefactoringAction : RefactoringActionBase { private readonly IDeclarationFinderProvider _declarationFinderProvider; - public ReorderParameterBaseRefactoring(IDeclarationFinderProvider declarationFinderProvider, IRewritingManager rewritingManager) + public ReorderParameterRefactoringAction(IDeclarationFinderProvider declarationFinderProvider, IRewritingManager rewritingManager) : base(rewritingManager) { _declarationFinderProvider = declarationFinderProvider; diff --git a/Rubberduck.Refactorings/ReorderParameters/ReorderParametersRefactoring.cs b/Rubberduck.Refactorings/ReorderParameters/ReorderParametersRefactoring.cs index 627ca0dc95..650cdff144 100644 --- a/Rubberduck.Refactorings/ReorderParameters/ReorderParametersRefactoring.cs +++ b/Rubberduck.Refactorings/ReorderParameters/ReorderParametersRefactoring.cs @@ -12,10 +12,10 @@ public class ReorderParametersRefactoring : InteractiveRefactoringBase _baseRefactoring; + private readonly IRefactoringAction _refactoringAction; public ReorderParametersRefactoring( - ReorderParameterBaseRefactoring baseRefactoring, + ReorderParameterRefactoringAction refactoringAction, IDeclarationFinderProvider declarationFinderProvider, IRefactoringPresenterFactory factory, ISelectionProvider selectionProvider, @@ -23,7 +23,7 @@ public ReorderParametersRefactoring( IUiDispatcher uiDispatcher) :base(selectionProvider, factory, uiDispatcher) { - _baseRefactoring = baseRefactoring; + _refactoringAction = refactoringAction; _declarationFinderProvider = declarationFinderProvider; _selectedDeclarationProvider = selectedDeclarationProvider; } @@ -131,7 +131,7 @@ private ReorderParametersModel ResolvedGetterTarget(ReorderParametersModel model protected override void RefactorImpl(ReorderParametersModel model) { - _baseRefactoring.Refactor(model); + _refactoringAction.Refactor(model); } public static readonly DeclarationType[] ValidDeclarationTypes = diff --git a/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs b/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs index 0bcece1ef4..6371f8354e 100644 --- a/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs +++ b/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs @@ -503,8 +503,8 @@ public MockedCodeExplorer ImplementIndenterCommand() public MockedCodeExplorer ImplementExtractInterfaceCommand() { - var addImplementationsBaseRefactoring = new AddInterFaceImplementationsBaseRefactoring(null); - var extractInterfaceBaseRefactoring = new ExtractInterfaceBaseRefactoring(addImplementationsBaseRefactoring, State, State, null, State.ProjectsProvider); + var addImplementationsBaseRefactoring = new AddInterfaceImplementationsRefactoringAction(null); + var extractInterfaceBaseRefactoring = new ExtractInterfaceRefactoringAction(addImplementationsBaseRefactoring, State, State, null, State.ProjectsProvider); ViewModel.CodeExplorerExtractInterfaceCommand = new CodeExplorerExtractInterfaceCommand( new ExtractInterfaceRefactoring(extractInterfaceBaseRefactoring, State, null, null, _uiDispatcher.Object), State, null, VbeEvents.Object); diff --git a/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs b/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs index 14b18823a6..e0efee80fe 100644 --- a/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs +++ b/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs @@ -171,8 +171,8 @@ protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state uiDispatcherMock .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); - var addImplementationsBaseRefactoring = new AddInterFaceImplementationsBaseRefactoring(rewritingManager); - var baseRefactoring = new ExtractInterfaceBaseRefactoring(addImplementationsBaseRefactoring, state, state, rewritingManager, state.ProjectsProvider); + var addImplementationsBaseRefactoring = new AddInterfaceImplementationsRefactoringAction(rewritingManager); + var baseRefactoring = new ExtractInterfaceRefactoringAction(addImplementationsBaseRefactoring, state, state, rewritingManager, state.ProjectsProvider); var refactoring = new ExtractInterfaceRefactoring(baseRefactoring, state, factory, selectionService, uiDispatcherMock.Object); 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 159289498a..a37e3cea0f 100644 --- a/RubberduckTests/Commands/RefactorCommands/ImplementInterfaceCommandTests.cs +++ b/RubberduckTests/Commands/RefactorCommands/ImplementInterfaceCommandTests.cs @@ -57,8 +57,8 @@ 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 AddInterFaceImplementationsBaseRefactoring(rewritingManager); - var baseRefactoring = new ImplementInterfaceBaseRefactoring(addImplementationsBaseRefactoring, rewritingManager); + var addImplementationsBaseRefactoring = new AddInterfaceImplementationsRefactoringAction(rewritingManager); + var baseRefactoring = new ImplementInterfaceRefactoringAction(addImplementationsBaseRefactoring, rewritingManager); var refactoring = new ImplementInterfaceRefactoring(baseRefactoring, state, selectionService); var notifier = new ImplementInterfaceFailedNotifier(msgBox); return new RefactorImplementInterfaceCommand(refactoring, notifier, state, selectionService); diff --git a/RubberduckTests/Commands/RefactorCommands/IntroduceFieldCommandTests.cs b/RubberduckTests/Commands/RefactorCommands/IntroduceFieldCommandTests.cs index 524e47671f..572fad5c29 100644 --- a/RubberduckTests/Commands/RefactorCommands/IntroduceFieldCommandTests.cs +++ b/RubberduckTests/Commands/RefactorCommands/IntroduceFieldCommandTests.cs @@ -43,7 +43,7 @@ protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state { var msgBox = new Mock().Object; var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); - var baseRefactoring = new IntroduceFieldBaseRefactoring(state, rewritingManager); + var baseRefactoring = new IntroduceFieldRefactoringAction(state, rewritingManager); var refactoring = new IntroduceFieldRefactoring(baseRefactoring, selectionService, selectedDeclarationProvider); var notifier = new IntroduceFieldFailedNotifier(msgBox); return new RefactorIntroduceFieldCommand(refactoring, notifier, state, selectionService, selectedDeclarationProvider); diff --git a/RubberduckTests/Commands/RefactorCommands/IntroduceParameterCommandTests.cs b/RubberduckTests/Commands/RefactorCommands/IntroduceParameterCommandTests.cs index 363cfe6b49..0f90cb2896 100644 --- a/RubberduckTests/Commands/RefactorCommands/IntroduceParameterCommandTests.cs +++ b/RubberduckTests/Commands/RefactorCommands/IntroduceParameterCommandTests.cs @@ -44,7 +44,7 @@ protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state { var msgBox = new Mock().Object; var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); - var baseRefactoring = new IntroduceParameterBaseRefactoring(state, rewritingManager); + var baseRefactoring = new IntroduceParameterRefactoringAction(state, rewritingManager); var refactoring = new IntroduceParameterRefactoring(baseRefactoring, msgBox, selectionService, selectedDeclarationProvider); var notifier = new IntroduceParameterFailedNotifier(msgBox); return new RefactorIntroduceParameterCommand(refactoring, notifier, state, selectionService, selectedDeclarationProvider); diff --git a/RubberduckTests/Commands/RefactorCommands/MoveCloserToUsageCommandTests.cs b/RubberduckTests/Commands/RefactorCommands/MoveCloserToUsageCommandTests.cs index 864a93f99c..d16642d4e2 100644 --- a/RubberduckTests/Commands/RefactorCommands/MoveCloserToUsageCommandTests.cs +++ b/RubberduckTests/Commands/RefactorCommands/MoveCloserToUsageCommandTests.cs @@ -98,7 +98,7 @@ protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state { var msgBox = new Mock().Object; var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); - var baseRefactoring = new MoveCloserToUsageBaseRefactoring(rewritingManager); + var baseRefactoring = new MoveCloserToUsageRefactoringAction(rewritingManager); var refactoring = new MoveCloserToUsageRefactoring(baseRefactoring, state, selectionService, selectedDeclarationProvider); var notifier = new MoveCloserToUsageFailedNotifier(msgBox); var selectedDeclarationService = new SelectedDeclarationProvider(selectionService, state); diff --git a/RubberduckTests/Commands/RefactorCommands/RemoveParametersCommandTests.cs b/RubberduckTests/Commands/RefactorCommands/RemoveParametersCommandTests.cs index 77efcd58cd..263b0fa7e6 100644 --- a/RubberduckTests/Commands/RefactorCommands/RemoveParametersCommandTests.cs +++ b/RubberduckTests/Commands/RefactorCommands/RemoveParametersCommandTests.cs @@ -170,7 +170,7 @@ protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state uiDispatcherMock .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); - var baseRefactoring = new RemoveParameterBaseRefactoring(state, rewritingManager); + var baseRefactoring = new RemoveParameterRefactoringAction(state, rewritingManager); var refactoring = new RemoveParametersRefactoring(baseRefactoring, state, factory, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); var notifier = new RemoveParameterFailedNotifier(msgBox); return new RefactorRemoveParametersCommand(refactoring, notifier, state, selectionService, selectedDeclarationProvider); diff --git a/RubberduckTests/Commands/RefactorCommands/ReorderParametersCommandTests.cs b/RubberduckTests/Commands/RefactorCommands/ReorderParametersCommandTests.cs index 41c18a7498..78affe3098 100644 --- a/RubberduckTests/Commands/RefactorCommands/ReorderParametersCommandTests.cs +++ b/RubberduckTests/Commands/RefactorCommands/ReorderParametersCommandTests.cs @@ -170,7 +170,7 @@ protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state uiDispatcherMock .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); - var baseRefactoring = new ReorderParameterBaseRefactoring(state, rewritingManager); + var baseRefactoring = new ReorderParameterRefactoringAction(state, rewritingManager); var refactoring = new ReorderParametersRefactoring(baseRefactoring, state, factory, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); var notifier = new ReorderParametersFailedNotifier(msgBox); return new RefactorReorderParametersCommand(refactoring, notifier, state, selectionService, selectedDeclarationProvider); diff --git a/RubberduckTests/QuickFixes/MoveFieldCloserToUsageQuickFixTests.cs b/RubberduckTests/QuickFixes/MoveFieldCloserToUsageQuickFixTests.cs index 8949312e0b..05cf7a7885 100644 --- a/RubberduckTests/QuickFixes/MoveFieldCloserToUsageQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/MoveFieldCloserToUsageQuickFixTests.cs @@ -128,7 +128,7 @@ private string ApplyQuickFixToFirstInspectionResult(string inputCode) var rewriteSession = rewritingManager.CheckOutCodePaneSession(); var selectionService = MockedSelectionService(); var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); - var baseRefactoring = new MoveCloserToUsageBaseRefactoring(rewritingManager); + var baseRefactoring = new MoveCloserToUsageRefactoringAction(rewritingManager); var refactoring = new MoveCloserToUsageRefactoring(baseRefactoring, state, selectionService, selectedDeclarationProvider); var quickFix = new MoveFieldCloserToUsageQuickFix(refactoring); diff --git a/RubberduckTests/QuickFixes/RemoveUnusedParameterQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveUnusedParameterQuickFixTests.cs index fc21642964..64e32163ba 100644 --- a/RubberduckTests/QuickFixes/RemoveUnusedParameterQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveUnusedParameterQuickFixTests.cs @@ -47,7 +47,7 @@ Private Sub Foo() uiDispatcherMock .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); - var baseRefactoring = new RemoveParameterBaseRefactoring(state, rewritingManager); + var baseRefactoring = new RemoveParameterRefactoringAction(state, rewritingManager); var refactoring = new RemoveParametersRefactoring(baseRefactoring, state, factory, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); new RemoveUnusedParameterQuickFix(refactoring) .Fix(inspectionResults.First(), rewriteSession); diff --git a/RubberduckTests/Refactoring/BaseRefactoringTestBase.cs b/RubberduckTests/Refactoring/BaseRefactoringTestBase.cs index 7f7136258b..20489509e2 100644 --- a/RubberduckTests/Refactoring/BaseRefactoringTestBase.cs +++ b/RubberduckTests/Refactoring/BaseRefactoringTestBase.cs @@ -44,7 +44,7 @@ protected IDictionary RefactoredCode(IVBE vbe, Func TestBaseRefactoring( + protected abstract IRefactoringAction TestBaseRefactoring( RubberduckParserState state, IRewritingManager rewritingManager ); diff --git a/RubberduckTests/Refactoring/ExtractInterfaceTests.cs b/RubberduckTests/Refactoring/ExtractInterfaceTests.cs index f14742913b..0936181e53 100644 --- a/RubberduckTests/Refactoring/ExtractInterfaceTests.cs +++ b/RubberduckTests/Refactoring/ExtractInterfaceTests.cs @@ -649,8 +649,8 @@ protected override IRefactoring TestRefactoring(IRewritingManager rewritingManag uiDispatcherMock .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); - var addImplementationsBaseRefactoring = new AddInterFaceImplementationsBaseRefactoring(rewritingManager); - var baseRefactoring = new ExtractInterfaceBaseRefactoring(addImplementationsBaseRefactoring, state, state, rewritingManager, state.ProjectsProvider); + var addImplementationsBaseRefactoring = new AddInterfaceImplementationsRefactoringAction(rewritingManager); + var baseRefactoring = new ExtractInterfaceRefactoringAction(addImplementationsBaseRefactoring, state, state, rewritingManager, state?.ProjectsProvider); return new ExtractInterfaceRefactoring(baseRefactoring, state, factory, selectionService, uiDispatcherMock.Object); } } diff --git a/RubberduckTests/Refactoring/ImplementInterfaceTests.cs b/RubberduckTests/Refactoring/ImplementInterfaceTests.cs index e4a80a2ecd..f7ed1f7433 100644 --- a/RubberduckTests/Refactoring/ImplementInterfaceTests.cs +++ b/RubberduckTests/Refactoring/ImplementInterfaceTests.cs @@ -911,8 +911,8 @@ End Sub protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, ISelectionService selectionService) { - var addImplementationsBaseRefactoring = new AddInterFaceImplementationsBaseRefactoring(rewritingManager); - var baseRefactoring = new ImplementInterfaceBaseRefactoring(addImplementationsBaseRefactoring, rewritingManager); + var addImplementationsBaseRefactoring = new AddInterfaceImplementationsRefactoringAction(rewritingManager); + var baseRefactoring = new ImplementInterfaceRefactoringAction(addImplementationsBaseRefactoring, rewritingManager); return new ImplementInterfaceRefactoring(baseRefactoring, state, selectionService); } } diff --git a/RubberduckTests/Refactoring/IntroduceFieldTests.cs b/RubberduckTests/Refactoring/IntroduceFieldTests.cs index 9676e8f174..d397820801 100644 --- a/RubberduckTests/Refactoring/IntroduceFieldTests.cs +++ b/RubberduckTests/Refactoring/IntroduceFieldTests.cs @@ -350,7 +350,7 @@ Dim bar As Boolean protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, ISelectionService selectionService) { var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); - var baseRefactoring = new IntroduceFieldBaseRefactoring(state, rewritingManager); + var baseRefactoring = new IntroduceFieldRefactoringAction(state, rewritingManager); return new IntroduceFieldRefactoring(baseRefactoring, selectionService, selectedDeclarationProvider); } } diff --git a/RubberduckTests/Refactoring/IntroduceParameterTests.cs b/RubberduckTests/Refactoring/IntroduceParameterTests.cs index 97419367c3..99b93cdbde 100644 --- a/RubberduckTests/Refactoring/IntroduceParameterTests.cs +++ b/RubberduckTests/Refactoring/IntroduceParameterTests.cs @@ -559,7 +559,7 @@ private static IRefactoring TestRefactoring(IRewritingManager rewritingManager, msgBox = new Mock().Object; } var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); - var baseRefactoring = new IntroduceParameterBaseRefactoring(state, rewritingManager); + var baseRefactoring = new IntroduceParameterRefactoringAction(state, rewritingManager); return new IntroduceParameterRefactoring(baseRefactoring, msgBox, selectionService, selectedDeclarationProvider); } diff --git a/RubberduckTests/Refactoring/MoveCloserToUsageTests.cs b/RubberduckTests/Refactoring/MoveCloserToUsageTests.cs index 3ec996a1c7..adf8b51c61 100644 --- a/RubberduckTests/Refactoring/MoveCloserToUsageTests.cs +++ b/RubberduckTests/Refactoring/MoveCloserToUsageTests.cs @@ -1075,7 +1075,7 @@ bar.Add 42 protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, ISelectionService selectionService) { var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state); - var baseRefactoring = new MoveCloserToUsageBaseRefactoring(rewritingManager); + var baseRefactoring = new MoveCloserToUsageRefactoringAction(rewritingManager); return new MoveCloserToUsageRefactoring(baseRefactoring, state, selectionService, selectedDeclarationProvider); } } diff --git a/RubberduckTests/Refactoring/MoveToFolderTests.cs b/RubberduckTests/Refactoring/MoveToFolderTests.cs index 8b775b4a9f..7cb8bc0f54 100644 --- a/RubberduckTests/Refactoring/MoveToFolderTests.cs +++ b/RubberduckTests/Refactoring/MoveToFolderTests.cs @@ -65,10 +65,10 @@ End Sub Assert.AreEqual(expectedCode, refactoredCode); } - protected override IBaseRefactoring TestBaseRefactoring(RubberduckParserState state, IRewritingManager rewritingManager) + protected override IRefactoringAction TestBaseRefactoring(RubberduckParserState state, IRewritingManager rewritingManager) { var annotationUpdater = new AnnotationUpdater(); - return new MoveToFolderBaseRefactoring(rewritingManager, annotationUpdater); + return new MoveToFolderRefactoringAction(rewritingManager, annotationUpdater); } } } \ No newline at end of file diff --git a/RubberduckTests/Refactoring/RemoveParametersTests.cs b/RubberduckTests/Refactoring/RemoveParametersTests.cs index 69221e7ed9..b8dd10ac56 100644 --- a/RubberduckTests/Refactoring/RemoveParametersTests.cs +++ b/RubberduckTests/Refactoring/RemoveParametersTests.cs @@ -1974,7 +1974,7 @@ protected override IRefactoring TestRefactoring(IRewritingManager rewritingManag uiDispatcherMock .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); - var baseRefactoring = new RemoveParameterBaseRefactoring(state, rewritingManager); + var baseRefactoring = new RemoveParameterRefactoringAction(state, rewritingManager); return new RemoveParametersRefactoring(baseRefactoring, state, factory, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); } } diff --git a/RubberduckTests/Refactoring/Rename/RenameTests.cs b/RubberduckTests/Refactoring/Rename/RenameTests.cs index 5936bb8884..e9a4515a3a 100644 --- a/RubberduckTests/Refactoring/Rename/RenameTests.cs +++ b/RubberduckTests/Refactoring/Rename/RenameTests.cs @@ -3369,7 +3369,7 @@ protected override IRefactoring TestRefactoring(IRewritingManager rewritingManag uiDispatcherMock .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); - var baseRefactoring = new RenameBaseRefactoring(state, state?.ProjectsProvider, state, rewritingManager); + var baseRefactoring = new RenameRefactoringAction(state, state?.ProjectsProvider, state, rewritingManager); return new RenameRefactoring(baseRefactoring, factory, state, state?.ProjectsProvider, selectionService, selectedDeclarationService, uiDispatcherMock.Object); } diff --git a/RubberduckTests/Refactoring/ReorderParametersTests.cs b/RubberduckTests/Refactoring/ReorderParametersTests.cs index 437ac3db5e..9a704fb13a 100644 --- a/RubberduckTests/Refactoring/ReorderParametersTests.cs +++ b/RubberduckTests/Refactoring/ReorderParametersTests.cs @@ -1348,7 +1348,7 @@ protected override IRefactoring TestRefactoring( uiDispatcherMock .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); - var baseRefactoring = new ReorderParameterBaseRefactoring(state, rewritingManager); + var baseRefactoring = new ReorderParameterRefactoringAction(state, rewritingManager); return new ReorderParametersRefactoring(baseRefactoring, state, factory, selectionService, selectedDeclarationProvider, uiDispatcherMock.Object); } From 115f2e9a99db6eb1a455a17c08e28f61401fa5ed Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Mon, 17 Feb 2020 20:34:55 +0100 Subject: [PATCH 232/461] Split RenameRefactoringAction into a part that requires suspension and one that does not This allows to reuse the part not requiring suspension inside other refactoring actions and in refactoring preview providers. There is some code duplication between the two parts, but I chose not to split them until a third version arises. --- ...eCodeDefinedIdentifierRefactoringAction.cs | 213 ++++++++++++ ...nameComponentOrProjectRefactoringAction.cs | 178 ++++++++++ .../Rename/RenameRefactoringAction.cs | 305 +----------------- .../Refactoring/Rename/RenameTests.cs | 4 +- 4 files changed, 411 insertions(+), 289 deletions(-) create mode 100644 Rubberduck.Refactorings/Rename/RenameCodeDefinedIdentifierRefactoringAction.cs create mode 100644 Rubberduck.Refactorings/Rename/RenameComponentOrProjectRefactoringAction.cs diff --git a/Rubberduck.Refactorings/Rename/RenameCodeDefinedIdentifierRefactoringAction.cs b/Rubberduck.Refactorings/Rename/RenameCodeDefinedIdentifierRefactoringAction.cs new file mode 100644 index 0000000000..e1f97be882 --- /dev/null +++ b/Rubberduck.Refactorings/Rename/RenameCodeDefinedIdentifierRefactoringAction.cs @@ -0,0 +1,213 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.VBEditor.ComManagement; + +namespace Rubberduck.Refactorings.Rename +{ + public class RenameCodeDefinedIdentifierRefactoringAction : CodeOnlyRefactoringActionBase + { + private const string AppendUnderscoreFormat = "{0}_"; + private const string PrependUnderscoreFormat = "_{0}"; + + private readonly IDeclarationFinderProvider _declarationFinderProvider; + private readonly IProjectsProvider _projectsProvider; + private readonly IDictionary> _renameActions; + + public RenameCodeDefinedIdentifierRefactoringAction( + IDeclarationFinderProvider declarationFinderProvider, + IProjectsProvider projectsProvider, + IRewritingManager rewritingManager) + : base(rewritingManager) + { + _declarationFinderProvider = declarationFinderProvider; + _projectsProvider = projectsProvider; + + _renameActions = new Dictionary> + { + {DeclarationType.Member, RenameMember}, + {DeclarationType.Parameter, RenameParameter}, + {DeclarationType.Event, RenameEvent}, + {DeclarationType.Variable, RenameVariable} + }; + } + + public override void Refactor(RenameModel model, IRewriteSession rewriteSession) + { + var actionKeys = _renameActions.Keys.Where(decType => model.Target.DeclarationType.HasFlag(decType)).ToList(); + if (actionKeys.Any()) + { + Debug.Assert(actionKeys.Count == 1, $"{actionKeys.Count} Rename Actions have flag '{model.Target.DeclarationType.ToString()}'"); + _renameActions[actionKeys.FirstOrDefault()](model, rewriteSession); + } + else + { + RenameStandardElements(model.Target, model.NewName, rewriteSession); + } + } + + private void RenameMember(RenameModel model, IRewriteSession rewriteSession) + { + if (model.Target.DeclarationType.HasFlag(DeclarationType.Property)) + { + var members = _declarationFinderProvider.DeclarationFinder.MatchName(model.Target.IdentifierName) + .Where(item => item.ProjectId == model.Target.ProjectId + && item.ComponentName == model.Target.ComponentName + && item.DeclarationType.HasFlag(DeclarationType.Property)); + + foreach (var member in members) + { + RenameStandardElements(member, model.NewName, rewriteSession); + } + } + else + { + RenameStandardElements(model.Target, model.NewName, rewriteSession); + } + + if (!model.IsInterfaceMemberRename) + { + return; + } + + var implementations = _declarationFinderProvider.DeclarationFinder.FindAllInterfaceImplementingMembers() + .Where(impl => ReferenceEquals(model.Target.ParentDeclaration, impl.InterfaceImplemented) + && impl.InterfaceMemberImplemented.IdentifierName.Equals(model.Target.IdentifierName)); + + RenameDefinedFormatMembers(model, implementations.ToList(), PrependUnderscoreFormat, rewriteSession); + } + + private void RenameParameter(RenameModel model, IRewriteSession rewriteSession) + { + if (model.Target.ParentDeclaration.DeclarationType.HasFlag(DeclarationType.Property)) + { + var parameters = _declarationFinderProvider.DeclarationFinder.MatchName(model.Target.IdentifierName).Where(param => + param.ParentDeclaration.DeclarationType.HasFlag(DeclarationType.Property) + && param.DeclarationType == DeclarationType.Parameter + && param.ParentDeclaration.IdentifierName.Equals(model.Target.ParentDeclaration.IdentifierName) + && param.ParentDeclaration.ParentScopeDeclaration.Equals(model.Target.ParentDeclaration.ParentScopeDeclaration)); + + foreach (var param in parameters) + { + RenameStandardElements(param, model.NewName, rewriteSession); + } + } + else + { + RenameStandardElements(model.Target, model.NewName, rewriteSession); + } + } + + private void RenameEvent(RenameModel model, IRewriteSession rewriteSession) + { + RenameStandardElements(model.Target, model.NewName, rewriteSession); + + var withEventsDeclarations = _declarationFinderProvider.DeclarationFinder.UserDeclarations(DeclarationType.Variable) + .Where(varDec => varDec.IsWithEvents && varDec.AsTypeName.Equals(model.Target.ParentDeclaration.IdentifierName)); + + var eventHandlers = withEventsDeclarations.SelectMany(we => _declarationFinderProvider.DeclarationFinder.FindHandlersForWithEventsField(we)); + RenameDefinedFormatMembers(model, eventHandlers.ToList(), PrependUnderscoreFormat, rewriteSession); + } + + private void RenameVariable(RenameModel model, IRewriteSession rewriteSession) + { + if ((model.Target.Accessibility == Accessibility.Public || + model.Target.Accessibility == Accessibility.Implicit) + && model.Target.ParentDeclaration is ClassModuleDeclaration classDeclaration + && classDeclaration.Subtypes.Any()) + { + RenameMember(model, rewriteSession); + } + else if (model.Target.DeclarationType.HasFlag(DeclarationType.Control)) + { + var component = _projectsProvider.Component(model.Target.QualifiedName.QualifiedModuleName); + using (var controls = component.Controls) + { + using (var control = controls.SingleOrDefault(item => item.Name == model.Target.IdentifierName)) + { + Debug.Assert(control != null, + $"input validation fail: unable to locate '{model.Target.IdentifierName}' in Controls collection"); + + control.Name = model.NewName; + } + } + RenameReferences(model.Target, model.NewName, rewriteSession); + var controlEventHandlers = FindEventHandlersForControl(model.Target); + RenameDefinedFormatMembers(model, controlEventHandlers.ToList(), AppendUnderscoreFormat, rewriteSession); + } + else + { + RenameStandardElements(model.Target, model.NewName, rewriteSession); + if (model.Target.IsWithEvents) + { + var eventHandlers = _declarationFinderProvider.DeclarationFinder.FindHandlersForWithEventsField(model.Target); + RenameDefinedFormatMembers(model, eventHandlers.ToList(), AppendUnderscoreFormat, rewriteSession); + } + } + } + + private void RenameDefinedFormatMembers(RenameModel model, IReadOnlyCollection members, string underscoreFormat, IRewriteSession rewriteSession) + { + if (!members.Any()) { return; } + + var targetFragment = string.Format(underscoreFormat, model.Target.IdentifierName); + var replacementFragment = string.Format(underscoreFormat, model.NewName); + foreach (var member in members) + { + var newMemberName = member.IdentifierName.Replace(targetFragment, replacementFragment); + RenameStandardElements(member, newMemberName, rewriteSession); + } + } + + private void RenameStandardElements(Declaration target, string newName, IRewriteSession rewriteSession) + { + RenameReferences(target, newName, rewriteSession); + RenameDeclaration(target, newName, rewriteSession); + } + + private void RenameReferences(Declaration target, string newName, IRewriteSession rewriteSession) + { + var modules = target.References + .Where(reference => + reference.Context.GetText() != "Me" + && !reference.IsArrayAccess + && !reference.IsDefaultMemberAccess) + .GroupBy(r => r.QualifiedModuleName); + + foreach (var grouping in modules) + { + var rewriter = rewriteSession.CheckOutModuleRewriter(grouping.Key); + foreach (var reference in grouping) + { + rewriter.Replace(reference.Context, newName); + } + } + } + + private void RenameDeclaration(Declaration target, string newName, IRewriteSession rewriteSession) + { + var rewriter = rewriteSession.CheckOutModuleRewriter(target.QualifiedName.QualifiedModuleName); + + if (target.Context is IIdentifierContext context) + { + rewriter.Replace(context.IdentifierTokens, newName); + } + } + + private IEnumerable FindEventHandlersForControl(Declaration control) + { + if (control != null && control.DeclarationType.HasFlag(DeclarationType.Control)) + { + return _declarationFinderProvider.DeclarationFinder.FindEventHandlers() + .Where(ev => ev.Scope.StartsWith($"{control.ParentScope}.{control.IdentifierName}_")); + } + + return Enumerable.Empty(); + } + } +} \ No newline at end of file diff --git a/Rubberduck.Refactorings/Rename/RenameComponentOrProjectRefactoringAction.cs b/Rubberduck.Refactorings/Rename/RenameComponentOrProjectRefactoringAction.cs new file mode 100644 index 0000000000..f85f78ae16 --- /dev/null +++ b/Rubberduck.Refactorings/Rename/RenameComponentOrProjectRefactoringAction.cs @@ -0,0 +1,178 @@ +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using Rubberduck.Parsing; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.VBEditor.ComManagement; +using Rubberduck.VBEditor.SafeComWrappers; + +namespace Rubberduck.Refactorings.Rename +{ + public class RenameComponentOrProjectRefactoringAction : RefactoringActionWithSuspension + { + private const string AppendUnderscoreFormat = "{0}_"; + + private readonly IDeclarationFinderProvider _declarationFinderProvider; + private readonly IProjectsProvider _projectsProvider; + + public RenameComponentOrProjectRefactoringAction( + IDeclarationFinderProvider declarationFinderProvider, + IProjectsProvider projectsProvider, + IParseManager parserManager, + IRewritingManager rewritingManager) + : base(parserManager, rewritingManager) + { + _declarationFinderProvider = declarationFinderProvider; + _projectsProvider = projectsProvider; + } + + protected override bool RequiresSuspension(RenameModel model) + { + //The parser needs to be suspended during the refactoring of a component because the VBE API object rename causes a separate reparse. + return true; + } + + protected override void Refactor(RenameModel model, IRewriteSession rewriteSession) + { + var targetDeclarationType = model.Target.DeclarationType; + if (targetDeclarationType.HasFlag(DeclarationType.Module)) + { + RenameModule(model, rewriteSession); + } + else if (targetDeclarationType.HasFlag(DeclarationType.Project)) + { + RenameProject(model, rewriteSession); + } + } + + private void RenameModule(RenameModel model, IRewriteSession rewriteSession) + { + RenameReferences(model.Target, model.NewName, rewriteSession); + + if (model.Target.DeclarationType.HasFlag(DeclarationType.ClassModule)) + { + foreach (var reference in model.Target.References) + { + var ctxt = reference.Context.GetAncestor(); + if (ctxt != null) + { + RenameDefinedFormatMembers(model, _declarationFinderProvider.DeclarationFinder.FindInterfaceMembersForImplementsContext(ctxt).ToList(), AppendUnderscoreFormat, rewriteSession); + } + } + } + + var component = _projectsProvider.Component(model.Target.QualifiedName.QualifiedModuleName); + switch (component.Type) + { + case ComponentType.Document: + { + using (var properties = component.Properties) + using (var property = properties["_CodeName"]) + { + property.Value = model.NewName; + } + break; + } + case ComponentType.UserForm: + case ComponentType.VBForm: + case ComponentType.MDIForm: + { + using (var properties = component.Properties) + using (var property = properties["Caption"]) + { + if ((string)property.Value == model.Target.IdentifierName) + { + property.Value = model.NewName; + } + component.Name = model.NewName; + } + break; + } + default: + { + using (var vbe = component.VBE) + { + if (vbe.Kind == VBEKind.Hosted) + { + // VBA - rename code module + using (var codeModule = component.CodeModule) + { + Debug.Assert(!codeModule.IsWrappingNullReference, + "input validation fail: Attempting to rename an ICodeModule wrapping a null reference"); + codeModule.Name = model.NewName; + } + } + else + { + // VB6 - rename component + component.Name = model.NewName; + } + } + break; + } + } + } + + //TODO: Implement renaming references to the project in code. + private void RenameProject(RenameModel model, IRewriteSession rewriteSession) + { + var project = _projectsProvider.Project(model.Target.ProjectId); + + if (project != null) + { + project.Name = model.NewName; + } + } + + private void RenameDefinedFormatMembers(RenameModel model, IReadOnlyCollection members, string underscoreFormat, IRewriteSession rewriteSession) + { + if (!members.Any()) { return; } + + var targetFragment = string.Format(underscoreFormat, model.Target.IdentifierName); + var replacementFragment = string.Format(underscoreFormat, model.NewName); + foreach (var member in members) + { + var newMemberName = member.IdentifierName.Replace(targetFragment, replacementFragment); + RenameStandardElements(member, newMemberName, rewriteSession); + } + } + + private void RenameStandardElements(Declaration target, string newName, IRewriteSession rewriteSession) + { + RenameReferences(target, newName, rewriteSession); + RenameDeclaration(target, newName, rewriteSession); + } + + private void RenameReferences(Declaration target, string newName, IRewriteSession rewriteSession) + { + var modules = target.References + .Where(reference => + reference.Context.GetText() != "Me" + && !reference.IsArrayAccess + && !reference.IsDefaultMemberAccess) + .GroupBy(r => r.QualifiedModuleName); + + foreach (var grouping in modules) + { + var rewriter = rewriteSession.CheckOutModuleRewriter(grouping.Key); + foreach (var reference in grouping) + { + rewriter.Replace(reference.Context, newName); + } + } + } + + private void RenameDeclaration(Declaration target, string newName, IRewriteSession rewriteSession) + { + var rewriter = rewriteSession.CheckOutModuleRewriter(target.QualifiedName.QualifiedModuleName); + + if (target.Context is IIdentifierContext context) + { + rewriter.Replace(context.IdentifierTokens, newName); + } + } + } +} \ No newline at end of file diff --git a/Rubberduck.Refactorings/Rename/RenameRefactoringAction.cs b/Rubberduck.Refactorings/Rename/RenameRefactoringAction.cs index e8d14c792a..da734e5ebb 100644 --- a/Rubberduck.Refactorings/Rename/RenameRefactoringAction.cs +++ b/Rubberduck.Refactorings/Rename/RenameRefactoringAction.cs @@ -1,308 +1,37 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using Rubberduck.Parsing; -using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Rewriter; -using Rubberduck.Parsing.Symbols; -using Rubberduck.Parsing.VBA; -using Rubberduck.VBEditor.ComManagement; -using Rubberduck.VBEditor.SafeComWrappers; +using Rubberduck.Parsing.Symbols; namespace Rubberduck.Refactorings.Rename { - public class RenameRefactoringAction : RefactoringActionWithSuspension + public class RenameRefactoringAction : IRefactoringAction { - private const string AppendUnderscoreFormat = "{0}_"; - private const string PrependUnderscoreFormat = "_{0}"; - - private readonly IDeclarationFinderProvider _declarationFinderProvider; - private readonly IProjectsProvider _projectsProvider; - private readonly IDictionary> _renameActions; + private readonly IRefactoringAction _renameComponentOrProjectRefactoringAction; + private readonly IRefactoringAction _renameCodeDefinedIdentifierRefactoringAction; public RenameRefactoringAction( - IDeclarationFinderProvider declarationFinderProvider, - IProjectsProvider projectsProvider, - IParseManager parserManager, - IRewritingManager rewritingManager) - : base(parserManager, rewritingManager) - { - _declarationFinderProvider = declarationFinderProvider; - _projectsProvider = projectsProvider; - - _renameActions = new Dictionary> - { - {DeclarationType.Member, RenameMember}, - {DeclarationType.Parameter, RenameParameter}, - {DeclarationType.Event, RenameEvent}, - {DeclarationType.Variable, RenameVariable}, - {DeclarationType.Module, RenameModule}, - {DeclarationType.Project, RenameProject} - }; - } - - protected override bool RequiresSuspension(RenameModel model) - { - //The parser needs to be suspended during the refactoring of a component because the VBE API object rename causes a separate reparse. - var targetType = model.Target.DeclarationType; - return targetType.HasFlag(DeclarationType.Module) - || targetType.HasFlag(DeclarationType.Project); - } - - protected override void Refactor(RenameModel model, IRewriteSession rewriteSession) - { - Debug.Assert(!model.NewName.Equals(model.Target.IdentifierName, StringComparison.InvariantCultureIgnoreCase), - $"input validation fail: New Name equals Original Name ({model.Target.IdentifierName})"); - - var actionKeys = _renameActions.Keys.Where(decType => model.Target.DeclarationType.HasFlag(decType)).ToList(); - if (actionKeys.Any()) - { - Debug.Assert(actionKeys.Count == 1, $"{actionKeys.Count} Rename Actions have flag '{model.Target.DeclarationType.ToString()}'"); - _renameActions[actionKeys.FirstOrDefault()](model, rewriteSession); - } - else - { - RenameStandardElements(model.Target, model.NewName, rewriteSession); - } - } - - private void RenameMember(RenameModel model, IRewriteSession rewriteSession) - { - if (model.Target.DeclarationType.HasFlag(DeclarationType.Property)) - { - var members = _declarationFinderProvider.DeclarationFinder.MatchName(model.Target.IdentifierName) - .Where(item => item.ProjectId == model.Target.ProjectId - && item.ComponentName == model.Target.ComponentName - && item.DeclarationType.HasFlag(DeclarationType.Property)); - - foreach (var member in members) - { - RenameStandardElements(member, model.NewName, rewriteSession); - } - } - else - { - RenameStandardElements(model.Target, model.NewName, rewriteSession); - } - - if (!model.IsInterfaceMemberRename) - { - return; - } - - var implementations = _declarationFinderProvider.DeclarationFinder.FindAllInterfaceImplementingMembers() - .Where(impl => ReferenceEquals(model.Target.ParentDeclaration, impl.InterfaceImplemented) - && impl.InterfaceMemberImplemented.IdentifierName.Equals(model.Target.IdentifierName)); - - RenameDefinedFormatMembers(model, implementations.ToList(), PrependUnderscoreFormat, rewriteSession); - } - - private void RenameParameter(RenameModel model, IRewriteSession rewriteSession) + RenameComponentOrProjectRefactoringAction renameComponentOrProjectRefactoringAction, + RenameCodeDefinedIdentifierRefactoringAction renameCodeDefinedIdentifierRefactoringAction) { - if (model.Target.ParentDeclaration.DeclarationType.HasFlag(DeclarationType.Property)) - { - var parameters = _declarationFinderProvider.DeclarationFinder.MatchName(model.Target.IdentifierName).Where(param => - param.ParentDeclaration.DeclarationType.HasFlag(DeclarationType.Property) - && param.DeclarationType == DeclarationType.Parameter - && param.ParentDeclaration.IdentifierName.Equals(model.Target.ParentDeclaration.IdentifierName) - && param.ParentDeclaration.ParentScopeDeclaration.Equals(model.Target.ParentDeclaration.ParentScopeDeclaration)); - - foreach (var param in parameters) - { - RenameStandardElements(param, model.NewName, rewriteSession); - } - } - else - { - RenameStandardElements(model.Target, model.NewName, rewriteSession); - } - } - - private void RenameEvent(RenameModel model, IRewriteSession rewriteSession) - { - RenameStandardElements(model.Target, model.NewName, rewriteSession); - - var withEventsDeclarations = _declarationFinderProvider.DeclarationFinder.UserDeclarations(DeclarationType.Variable) - .Where(varDec => varDec.IsWithEvents && varDec.AsTypeName.Equals(model.Target.ParentDeclaration.IdentifierName)); - - var eventHandlers = withEventsDeclarations.SelectMany(we => _declarationFinderProvider.DeclarationFinder.FindHandlersForWithEventsField(we)); - RenameDefinedFormatMembers(model, eventHandlers.ToList(), PrependUnderscoreFormat, rewriteSession); + _renameCodeDefinedIdentifierRefactoringAction = renameCodeDefinedIdentifierRefactoringAction; + _renameComponentOrProjectRefactoringAction = renameComponentOrProjectRefactoringAction; } - private void RenameVariable(RenameModel model, IRewriteSession rewriteSession) + public void Refactor(RenameModel model) { - if ((model.Target.Accessibility == Accessibility.Public || - model.Target.Accessibility == Accessibility.Implicit) - && model.Target.ParentDeclaration is ClassModuleDeclaration classDeclaration - && classDeclaration.Subtypes.Any()) + if (IsComponentOrProjectTarget(model)) { - RenameMember(model, rewriteSession); - } - else if (model.Target.DeclarationType.HasFlag(DeclarationType.Control)) - { - var component = _projectsProvider.Component(model.Target.QualifiedName.QualifiedModuleName); - using (var controls = component.Controls) - { - using (var control = controls.SingleOrDefault(item => item.Name == model.Target.IdentifierName)) - { - Debug.Assert(control != null, - $"input validation fail: unable to locate '{model.Target.IdentifierName}' in Controls collection"); - - control.Name = model.NewName; - } - } - RenameReferences(model.Target, model.NewName, rewriteSession); - var controlEventHandlers = FindEventHandlersForControl(model.Target); - RenameDefinedFormatMembers(model, controlEventHandlers.ToList(), AppendUnderscoreFormat, rewriteSession); + _renameComponentOrProjectRefactoringAction.Refactor(model); } else { - RenameStandardElements(model.Target, model.NewName, rewriteSession); - if (model.Target.IsWithEvents) - { - var eventHandlers = _declarationFinderProvider.DeclarationFinder.FindHandlersForWithEventsField(model.Target); - RenameDefinedFormatMembers(model, eventHandlers.ToList(), AppendUnderscoreFormat, rewriteSession); - } - } - } - - private void RenameModule(RenameModel model, IRewriteSession rewriteSession) - { - RenameReferences(model.Target, model.NewName, rewriteSession); - - if (model.Target.DeclarationType.HasFlag(DeclarationType.ClassModule)) - { - foreach (var reference in model.Target.References) - { - var ctxt = reference.Context.GetAncestor(); - if (ctxt != null) - { - RenameDefinedFormatMembers(model, _declarationFinderProvider.DeclarationFinder.FindInterfaceMembersForImplementsContext(ctxt).ToList(), AppendUnderscoreFormat, rewriteSession); - } - } - } - - var component = _projectsProvider.Component(model.Target.QualifiedName.QualifiedModuleName); - switch (component.Type) - { - case ComponentType.Document: - { - using (var properties = component.Properties) - using (var property = properties["_CodeName"]) - { - property.Value = model.NewName; - } - break; - } - case ComponentType.UserForm: - case ComponentType.VBForm: - case ComponentType.MDIForm: - { - using (var properties = component.Properties) - using (var property = properties["Caption"]) - { - if ((string)property.Value == model.Target.IdentifierName) - { - property.Value = model.NewName; - } - component.Name = model.NewName; - } - break; - } - default: - { - using (var vbe = component.VBE) - { - if (vbe.Kind == VBEKind.Hosted) - { - // VBA - rename code module - using (var codeModule = component.CodeModule) - { - Debug.Assert(!codeModule.IsWrappingNullReference, - "input validation fail: Attempting to rename an ICodeModule wrapping a null reference"); - codeModule.Name = model.NewName; - } - } - else - { - // VB6 - rename component - component.Name = model.NewName; - } - } - break; - } - } - } - - //TODO: Implement renaming references to the project in code. - private void RenameProject(RenameModel model, IRewriteSession rewriteSession) - { - var project = _projectsProvider.Project(model.Target.ProjectId); - - if (project != null) - { - project.Name = model.NewName; - } - } - - private void RenameDefinedFormatMembers(RenameModel model, IReadOnlyCollection members, string underscoreFormat, IRewriteSession rewriteSession) - { - if (!members.Any()) { return; } - - var targetFragment = string.Format(underscoreFormat, model.Target.IdentifierName); - var replacementFragment = string.Format(underscoreFormat, model.NewName); - foreach (var member in members) - { - var newMemberName = member.IdentifierName.Replace(targetFragment, replacementFragment); - RenameStandardElements(member, newMemberName, rewriteSession); - } - } - - private void RenameStandardElements(Declaration target, string newName, IRewriteSession rewriteSession) - { - RenameReferences(target, newName, rewriteSession); - RenameDeclaration(target, newName, rewriteSession); - } - - private void RenameReferences(Declaration target, string newName, IRewriteSession rewriteSession) - { - var modules = target.References - .Where(reference => - reference.Context.GetText() != "Me" - && !reference.IsArrayAccess - && !reference.IsDefaultMemberAccess) - .GroupBy(r => r.QualifiedModuleName); - - foreach (var grouping in modules) - { - var rewriter = rewriteSession.CheckOutModuleRewriter(grouping.Key); - foreach (var reference in grouping) - { - rewriter.Replace(reference.Context, newName); - } + _renameCodeDefinedIdentifierRefactoringAction.Refactor(model); } } - private void RenameDeclaration(Declaration target, string newName, IRewriteSession rewriteSession) - { - var rewriter = rewriteSession.CheckOutModuleRewriter(target.QualifiedName.QualifiedModuleName); - - if (target.Context is IIdentifierContext context) - { - rewriter.Replace(context.IdentifierTokens, newName); - } - } - - private IEnumerable FindEventHandlersForControl(Declaration control) - { - if (control != null && control.DeclarationType.HasFlag(DeclarationType.Control)) - { - return _declarationFinderProvider.DeclarationFinder.FindEventHandlers() - .Where(ev => ev.Scope.StartsWith($"{control.ParentScope}.{control.IdentifierName}_")); - } - - return Enumerable.Empty(); + private static bool IsComponentOrProjectTarget(RenameModel model) + { + var targetType = model.Target.DeclarationType; + return targetType.HasFlag(DeclarationType.Module) + || targetType.HasFlag(DeclarationType.Project); } } } \ No newline at end of file diff --git a/RubberduckTests/Refactoring/Rename/RenameTests.cs b/RubberduckTests/Refactoring/Rename/RenameTests.cs index e9a4515a3a..de3e39a6bf 100644 --- a/RubberduckTests/Refactoring/Rename/RenameTests.cs +++ b/RubberduckTests/Refactoring/Rename/RenameTests.cs @@ -3369,7 +3369,9 @@ protected override IRefactoring TestRefactoring(IRewritingManager rewritingManag uiDispatcherMock .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); - var baseRefactoring = new RenameRefactoringAction(state, state?.ProjectsProvider, state, rewritingManager); + var componentRename = new RenameComponentOrProjectRefactoringAction(state, state?.ProjectsProvider, state, rewritingManager); + var otherRename = new RenameCodeDefinedIdentifierRefactoringAction(state, state?.ProjectsProvider, rewritingManager); + var baseRefactoring = new RenameRefactoringAction(componentRename, otherRename); return new RenameRefactoring(baseRefactoring, factory, state, state?.ProjectsProvider, selectionService, selectedDeclarationService, uiDispatcherMock.Object); } From a4739d388772f8aeebffd3bbc76b81d75c504df9 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Mon, 17 Feb 2020 20:36:08 +0100 Subject: [PATCH 233/461] Introduce wrapper base for IRefactoringPreviewProviders --- .../RefactoringPreviewProviderWrapperBase.cs | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 Rubberduck.Refactorings/Abstract/RefactoringPreviewProviderWrapperBase.cs diff --git a/Rubberduck.Refactorings/Abstract/RefactoringPreviewProviderWrapperBase.cs b/Rubberduck.Refactorings/Abstract/RefactoringPreviewProviderWrapperBase.cs new file mode 100644 index 0000000000..5d4be37753 --- /dev/null +++ b/Rubberduck.Refactorings/Abstract/RefactoringPreviewProviderWrapperBase.cs @@ -0,0 +1,41 @@ +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.VBA.Parsing; +using Rubberduck.VBEditor; + +namespace Rubberduck.Refactorings +{ + public abstract class RefactoringPreviewProviderWrapperBase : IRefactoringPreviewProvider + where TModel : class, IRefactoringModel + { + private readonly IRewritingManager _rewritingManager; + private readonly ICodeOnlyRefactoringAction _refactoringAction; + + protected RefactoringPreviewProviderWrapperBase( + ICodeOnlyRefactoringAction refactoringAction, + IRewritingManager rewritingManager) + { + _refactoringAction = refactoringAction; + _rewritingManager = rewritingManager; + } + + protected abstract QualifiedModuleName ComponentToShow(TModel model); + + public string Preview(TModel model) + { + var rewriteSession = RewriteSession(RewriteSessionCodeKind); + _refactoringAction.Refactor(model, rewriteSession); + var componentToShow = ComponentToShow(model); + var rewriter = rewriteSession.CheckOutModuleRewriter(componentToShow); + return rewriter.GetText(); + } + + private IExecutableRewriteSession RewriteSession(CodeKind codeKind) + { + return codeKind == CodeKind.AttributesCode + ? _rewritingManager.CheckOutAttributesSession() + : _rewritingManager.CheckOutCodePaneSession(); + } + + protected virtual CodeKind RewriteSessionCodeKind => CodeKind.CodePaneCode; + } +} \ No newline at end of file From 7e4c572ea5d915c49c7327c96a6a7438642abbf0 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Mon, 17 Feb 2020 22:23:00 +0100 Subject: [PATCH 234/461] Fix CE tests broken in last commit The problem was that they passed null as the parser state, which caused an NRE with the new setup. --- .../CodeMetrics/CodeMetricsViewModel.cs | 2 +- .../CodeExplorerProjectViewModel.cs | 10 +- .../CodeExplorer/CodeExplorerViewModel.cs | 2 +- .../CodeExplorerCustomFolderViewModelTests.cs | 282 +++++++++++------- .../CodeExplorerProjectViewModelTests.cs | 47 ++- .../CodeExplorer/CodeExplorerTestSetup.cs | 24 +- .../Refactoring/ExtractInterfaceTests.cs | 2 +- 7 files changed, 220 insertions(+), 149 deletions(-) diff --git a/Rubberduck.Core/CodeAnalysis/CodeMetrics/CodeMetricsViewModel.cs b/Rubberduck.Core/CodeAnalysis/CodeMetrics/CodeMetricsViewModel.cs index ed73640a98..2f1ca7d70a 100644 --- a/Rubberduck.Core/CodeAnalysis/CodeMetrics/CodeMetricsViewModel.cs +++ b/Rubberduck.Core/CodeAnalysis/CodeMetrics/CodeMetricsViewModel.cs @@ -84,7 +84,7 @@ private void Synchronize(IEnumerable declarations) foreach (var project in adding) { - var model = new CodeExplorerProjectViewModel(project, ref updates, _state, _vbe, false); + var model = new CodeExplorerProjectViewModel(project, ref updates, _state, _vbe, _state.ProjectsProvider,false); Projects.Add(model); } }).Wait(); diff --git a/Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerProjectViewModel.cs b/Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerProjectViewModel.cs index 1fa758a01f..7bc81c9a2b 100644 --- a/Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerProjectViewModel.cs +++ b/Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerProjectViewModel.cs @@ -5,6 +5,7 @@ using Rubberduck.Navigation.Folders; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; @@ -21,17 +22,20 @@ public class CodeExplorerProjectViewModel : CodeExplorerItemViewModel }; private readonly IVBE _vbe; + private readonly IProjectsProvider _projectsProvider; public CodeExplorerProjectViewModel( Declaration project, ref List declarations, RubberduckParserState state, IVBE vbe, + IProjectsProvider projectsProvider, bool references = true) : base(null, project) { - State = state; + State = state; _vbe = vbe; + _projectsProvider = projectsProvider; ShowReferences = references; SetName(); @@ -58,7 +62,7 @@ public override FontWeight FontWeight return base.FontWeight; } - var project = State.ProjectsProvider.Project(Declaration.ProjectId); + var project = _projectsProvider.Project(Declaration.ProjectId); if (project == null) { return base.FontWeight; @@ -158,7 +162,7 @@ private List GetProjectReferenceModels() return new List(); } - var project = State.ProjectsProvider.Project(Declaration.ProjectId); + var project = _projectsProvider.Project(Declaration.ProjectId); if (project == null) { return new List(); diff --git a/Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerViewModel.cs b/Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerViewModel.cs index 31c3c33708..d832b8f049 100644 --- a/Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerViewModel.cs +++ b/Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerViewModel.cs @@ -286,7 +286,7 @@ private void Synchronize(IEnumerable declarations) foreach (var project in adding) { - var model = new CodeExplorerProjectViewModel(project, ref updates, _state, _vbe) { Filter = Search }; + var model = new CodeExplorerProjectViewModel(project, ref updates, _state, _vbe, _state.ProjectsProvider) { Filter = Search }; Projects.Add(model); } diff --git a/RubberduckTests/CodeExplorer/CodeExplorerCustomFolderViewModelTests.cs b/RubberduckTests/CodeExplorer/CodeExplorerCustomFolderViewModelTests.cs index cef13c6f13..aa6d5caf98 100644 --- a/RubberduckTests/CodeExplorer/CodeExplorerCustomFolderViewModelTests.cs +++ b/RubberduckTests/CodeExplorer/CodeExplorerCustomFolderViewModelTests.cs @@ -22,13 +22,16 @@ public void Constructor_SetsFolderName(object[] parameters) var folderPath = structure.First().Folder; var path = folderPath.Split(FolderExtensions.FolderDelimiter); - var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(structure, out _); - var folder = new CodeExplorerCustomFolderViewModel(null, path.First(), path.First(), null, ref declarations); - - foreach (var name in path) + var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(structure, out _, out var state); + using (state) { - Assert.AreEqual(name, folder.Name); - folder = folder.Children.OfType().FirstOrDefault(); + var folder = new CodeExplorerCustomFolderViewModel(null, path.First(), path.First(), null, ref declarations); + + foreach (var name in path) + { + Assert.AreEqual(name, folder.Name); + folder = folder.Children.OfType().FirstOrDefault(); + } } } @@ -43,14 +46,17 @@ public void Constructor_SetsFullPath(object[] parameters) var folderPath = structure.First().Folder; var path = folderPath.Split(FolderExtensions.FolderDelimiter); - var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(structure, out _); - var folder = new CodeExplorerCustomFolderViewModel(null, path.First(), path.First(), null, ref declarations); - - var depth = 1; - foreach (var _ in path) + var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(structure, out _, out var state); + using (state) { - Assert.AreEqual(string.Join(FolderExtensions.FolderDelimiter.ToString(), path.Take(depth++)), folder.FullPath); - folder = folder.Children.OfType().FirstOrDefault(); + var folder = new CodeExplorerCustomFolderViewModel(null, path.First(), path.First(), null, ref declarations); + + var depth = 1; + foreach (var _ in path) + { + Assert.AreEqual(string.Join(FolderExtensions.FolderDelimiter.ToString(), path.Take(depth++)), folder.FullPath); + folder = folder.Children.OfType().FirstOrDefault(); + } } } @@ -65,13 +71,17 @@ public void Constructor_PanelTitleIsFullPath(object[] parameters) var folderPath = structure.First().Folder; var path = folderPath.Split(FolderExtensions.FolderDelimiter); - var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(structure, out _); - var folder = new CodeExplorerCustomFolderViewModel(null, path.First(), path.First(), null, ref declarations); - - foreach (var _ in path) + var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(structure, out _, out var state); + using (state) { - Assert.AreEqual(folder.FullPath, folder.PanelTitle); - folder = folder.Children.OfType().FirstOrDefault(); + var folder = + new CodeExplorerCustomFolderViewModel(null, path.First(), path.First(), null, ref declarations); + + foreach (var _ in path) + { + Assert.AreEqual(folder.FullPath, folder.PanelTitle); + folder = folder.Children.OfType().FirstOrDefault(); + } } } @@ -86,13 +96,17 @@ public void Constructor_FolderAttributeIsCorrect(object[] parameters) var folderPath = structure.First().Folder; var path = folderPath.Split(FolderExtensions.FolderDelimiter); - var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(structure, out _); - var folder = new CodeExplorerCustomFolderViewModel(null, path.First(), path.First(), null, ref declarations); - - foreach (var _ in path) + var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(structure, out _, out var state); + using (state) { - Assert.AreEqual($"'@Folder(\"{folder.FullPath}\")", folder.FolderAttribute); - folder = folder.Children.OfType().FirstOrDefault(); + var folder = + new CodeExplorerCustomFolderViewModel(null, path.First(), path.First(), null, ref declarations); + + foreach (var _ in path) + { + Assert.AreEqual($"'@Folder(\"{folder.FullPath}\")", folder.FolderAttribute); + folder = folder.Children.OfType().FirstOrDefault(); + } } } @@ -107,13 +121,17 @@ public void Constructor_DescriptionIsFolderAttribute(object[] parameters) var folderPath = structure.First().Folder; var path = folderPath.Split(FolderExtensions.FolderDelimiter); - var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(structure, out _); - var folder = new CodeExplorerCustomFolderViewModel(null, path.First(), path.First(), null, ref declarations); - - foreach (var _ in path) + var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(structure, out _, out var state); + using (state) { - Assert.AreEqual(folder.FolderAttribute, folder.Description); - folder = folder.Children.OfType().FirstOrDefault(); + var folder = + new CodeExplorerCustomFolderViewModel(null, path.First(), path.First(), null, ref declarations); + + foreach (var _ in path) + { + Assert.AreEqual(folder.FolderAttribute, folder.Description); + folder = folder.Children.OfType().FirstOrDefault(); + } } } @@ -128,14 +146,18 @@ public void Constructor_SetsFolderDepth(object[] parameters) var folderPath = structure.First().Folder; var path = folderPath.Split(FolderExtensions.FolderDelimiter); - var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(structure, out _); - var folder = new CodeExplorerCustomFolderViewModel(null, path.First(), path.First(), null, ref declarations); - - var depth = 1; - foreach (var _ in path) + var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(structure, out _, out var state); + using (state) { - Assert.AreEqual(depth++, folder.FolderDepth); - folder = folder.Children.OfType().FirstOrDefault(); + var folder = + new CodeExplorerCustomFolderViewModel(null, path.First(), path.First(), null, ref declarations); + + var depth = 1; + foreach (var _ in path) + { + Assert.AreEqual(depth++, folder.FolderDepth); + folder = folder.Children.OfType().FirstOrDefault(); + } } } @@ -147,17 +169,23 @@ public void FilteredIsTrueForCharactersNotInName() const string folderName = "Asdf"; var testFolder = (Name: CodeExplorerTestSetup.TestModuleName, Folder: folderName); - var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(new List<(string Name, string Folder)> { testFolder }, out _); - var children = declarations.SelectMany(declaration => declaration.IdentifierName.ToCharArray()).Distinct().ToList(); + var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(new List<(string Name, string Folder)> { testFolder }, out _, out var state); + using (state) + { + var children = declarations.SelectMany(declaration => declaration.IdentifierName.ToCharArray()) + .Distinct().ToList(); - var folder = new CodeExplorerCustomFolderViewModel(null, folderName, folderName, null, ref declarations); + var folder = + new CodeExplorerCustomFolderViewModel(null, folderName, folderName, null, ref declarations); - var nonMatching = testCharacters.ToCharArray().Except(folderName.ToLowerInvariant().ToCharArray().Union(children)); + var nonMatching = testCharacters.ToCharArray() + .Except(folderName.ToLowerInvariant().ToCharArray().Union(children)); - foreach (var character in nonMatching.Select(letter => letter.ToString())) - { - folder.Filter = character; - Assert.IsTrue(folder.Filtered); + foreach (var character in nonMatching.Select(letter => letter.ToString())) + { + folder.Filter = character; + Assert.IsTrue(folder.Filtered); + } } } @@ -168,20 +196,24 @@ public void FilteredIsFalseForSubsetsOfName() const string folderName = "Foobar"; var testFolder = (Name: CodeExplorerTestSetup.TestModuleName, Folder: folderName); - var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(new List<(string Name, string Folder)> { testFolder }, out _); + var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(new List<(string Name, string Folder)> { testFolder }, out _, out var state); + using (state) + { - var folder = new CodeExplorerCustomFolderViewModel(null, folderName, folderName, null, ref declarations); + var folder = + new CodeExplorerCustomFolderViewModel(null, folderName, folderName, null, ref declarations); - for (var characters = 1; characters <= folderName.Length; characters++) - { - folder.Filter = folderName.Substring(0, characters); - Assert.IsFalse(folder.Filtered); - } + for (var characters = 1; characters <= folderName.Length; characters++) + { + folder.Filter = folderName.Substring(0, characters); + Assert.IsFalse(folder.Filtered); + } - for (var position = folderName.Length - 2; position > 0; position--) - { - folder.Filter = folderName.Substring(position); - Assert.IsFalse(folder.Filtered); + for (var position = folderName.Length - 2; position > 0; position--) + { + folder.Filter = folderName.Substring(position); + Assert.IsFalse(folder.Filtered); + } } } @@ -192,21 +224,25 @@ public void FilteredIsFalseIfChildMatches() const string folderName = "Foobar"; var testFolder = (Name: CodeExplorerTestSetup.TestModuleName, Folder: folderName); - var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(new List<(string Name, string Folder)> { testFolder }, out _); + var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(new List<(string Name, string Folder)> { testFolder }, out _, out var state); + using (state) + { - var folder = new CodeExplorerCustomFolderViewModel(null, folderName, folderName, null, ref declarations); - var childName = folder.Children.First().Name; + var folder = + new CodeExplorerCustomFolderViewModel(null, folderName, folderName, null, ref declarations); + var childName = folder.Children.First().Name; - for (var characters = 1; characters <= childName.Length; characters++) - { - folder.Filter = childName.Substring(0, characters); - Assert.IsFalse(folder.Filtered); - } + for (var characters = 1; characters <= childName.Length; characters++) + { + folder.Filter = childName.Substring(0, characters); + Assert.IsFalse(folder.Filtered); + } - for (var position = childName.Length - 2; position > 0; position--) - { - folder.Filter = childName.Substring(position); - Assert.IsFalse(folder.Filtered); + for (var position = childName.Length - 2; position > 0; position--) + { + folder.Filter = childName.Substring(position); + Assert.IsFalse(folder.Filtered); + } } } @@ -217,17 +253,21 @@ public void UnfilteredStateIsRestored() const string folderName = "Foobar"; var testFolder = (Name: CodeExplorerTestSetup.TestModuleName, Folder: folderName); - var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(new List<(string Name, string Folder)> { testFolder }, out _); + var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(new List<(string Name, string Folder)> { testFolder }, out _, out var state); + using (state) + { - var folder = new CodeExplorerCustomFolderViewModel(null, folderName, folderName, null, ref declarations); - var childName = folder.Children.First().Name; + var folder = + new CodeExplorerCustomFolderViewModel(null, folderName, folderName, null, ref declarations); + var childName = folder.Children.First().Name; - folder.IsExpanded = false; - folder.Filter = childName; - Assert.IsTrue(folder.IsExpanded); + folder.IsExpanded = false; + folder.Filter = childName; + Assert.IsTrue(folder.IsExpanded); - folder.Filter = string.Empty; - Assert.IsFalse(folder.IsExpanded); + folder.Filter = string.Empty; + Assert.IsFalse(folder.IsExpanded); + } } [Test] @@ -243,14 +283,17 @@ public void SortComparerIsName(CodeExplorerSortOrder order) const string folderName = "Foo"; var testFolder = (Name: CodeExplorerTestSetup.TestModuleName, Folder: folderName); - var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(new List<(string Name, string Folder)> { testFolder }, out _); - - var folder = new CodeExplorerCustomFolderViewModel(null, folderName, folderName, null, ref declarations) + var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(new List<(string Name, string Folder)> { testFolder }, out _, out var state); + using (state) { - SortOrder = order - }; - Assert.AreEqual(CodeExplorerItemComparer.Name.GetType(), folder.SortComparer.GetType()); + var folder = new CodeExplorerCustomFolderViewModel(null, folderName, folderName, null, ref declarations) + { + SortOrder = order + }; + + Assert.AreEqual(CodeExplorerItemComparer.Name.GetType(), folder.SortComparer.GetType()); + } } [Test] @@ -260,14 +303,17 @@ public void ErrorStateCanNotBeSet() const string folderName = "Foo"; var testFolder = (Name: CodeExplorerTestSetup.TestModuleName, Folder: folderName); - var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(new List<(string Name, string Folder)> { testFolder }, out _); - - var folder = new CodeExplorerCustomFolderViewModel(null, folderName, folderName, null, ref declarations) + var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(new List<(string Name, string Folder)> { testFolder }, out _, out var state); + using (state) { - IsErrorState = true - }; - Assert.IsFalse(folder.IsErrorState); + var folder = new CodeExplorerCustomFolderViewModel(null, folderName, folderName, null, ref declarations) + { + IsErrorState = true + }; + + Assert.IsFalse(folder.IsErrorState); + } } [Test] @@ -306,12 +352,18 @@ public void Constructor_CreatesCorrectSubFolderStructure(params object[] paramet var root = structure.First().Folder; var path = root.Split(FolderExtensions.FolderDelimiter); - var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(structure, out var projectDeclaration); - var contents = CodeExplorerProjectViewModel.ExtractTrackedDeclarationsForProject(projectDeclaration, ref declarations); + var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(structure, out var projectDeclaration, out var state); + using (state) + { + var contents = + CodeExplorerProjectViewModel.ExtractTrackedDeclarationsForProject(projectDeclaration, + ref declarations); - var folder = new CodeExplorerCustomFolderViewModel(null, path.First(), path.First(), null, ref contents); + var folder = + new CodeExplorerCustomFolderViewModel(null, path.First(), path.First(), null, ref contents); - AssertFolderStructureIsCorrect(folder, structure); + AssertFolderStructureIsCorrect(folder, structure); + } } [Test] @@ -350,17 +402,23 @@ public void Synchronize_AddedComponent_HasCorrectSubFolderStructure(params objec var root = structure.First().Folder; var path = root.Split(FolderExtensions.FolderDelimiter); - var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(structure, out var projectDeclaration); - var synchronizing = CodeExplorerProjectViewModel.ExtractTrackedDeclarationsForProject(projectDeclaration, ref declarations); - var component = synchronizing.TestComponentDeclarations(structure.Last().Name); - var contents = synchronizing.Except(component).ToList(); + var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(structure, out var projectDeclaration, out var state); + using (state) + { + var synchronizing = + CodeExplorerProjectViewModel.ExtractTrackedDeclarationsForProject(projectDeclaration, + ref declarations); + var component = synchronizing.TestComponentDeclarations(structure.Last().Name); + var contents = synchronizing.Except(component).ToList(); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref contents, null, null); - var folder = project.Children.OfType().Single(item => item.Name.Equals(path.First())); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref contents, state, null, state.ProjectsProvider); + var folder = project.Children.OfType() + .Single(item => item.Name.Equals(path.First())); - project.Synchronize(ref synchronizing); + project.Synchronize(ref synchronizing); - AssertFolderStructureIsCorrect(folder, structure); + AssertFolderStructureIsCorrect(folder, structure); + } } [Test] @@ -399,17 +457,23 @@ public void Synchronize_RemovedComponent_HasCorrectSubFolderStructure(params obj var root = structure.First().Folder; var path = root.Split(FolderExtensions.FolderDelimiter); - var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(structure, out var projectDeclaration); - var contents = CodeExplorerProjectViewModel.ExtractTrackedDeclarationsForProject(projectDeclaration, ref declarations); - var component = contents.TestComponentDeclarations(structure.Last().Name); - var synchronizing = contents.Except(component).ToList(); + var declarations = CodeExplorerTestSetup.TestProjectWithFolderStructure(structure, out var projectDeclaration, out var state); + using (state) + { + var contents = + CodeExplorerProjectViewModel.ExtractTrackedDeclarationsForProject(projectDeclaration, + ref declarations); + var component = contents.TestComponentDeclarations(structure.Last().Name); + var synchronizing = contents.Except(component).ToList(); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref contents, null, null); - var folder = project.Children.OfType().Single(item => item.Name.Equals(path.First())); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref contents, state, null, state.ProjectsProvider); + var folder = project.Children.OfType() + .Single(item => item.Name.Equals(path.First())); - project.Synchronize(ref synchronizing); + project.Synchronize(ref synchronizing); - AssertFolderStructureIsCorrect(folder, structure.Take(structure.Count - 1).ToList()); + AssertFolderStructureIsCorrect(folder, structure.Take(structure.Count - 1).ToList()); + } } private static void AssertFolderStructureIsCorrect(CodeExplorerCustomFolderViewModel underTest, List<(string Name, string Folder)> structure) diff --git a/RubberduckTests/CodeExplorer/CodeExplorerProjectViewModelTests.cs b/RubberduckTests/CodeExplorer/CodeExplorerProjectViewModelTests.cs index c366e4ec75..58a4104434 100644 --- a/RubberduckTests/CodeExplorer/CodeExplorerProjectViewModelTests.cs +++ b/RubberduckTests/CodeExplorer/CodeExplorerProjectViewModelTests.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using NUnit.Framework; using System.Linq; -using System.Runtime.InteropServices; using Rubberduck.AddRemoveReferences; using Rubberduck.Parsing.Symbols; using Rubberduck.Navigation.CodeExplorer; @@ -21,7 +20,7 @@ public void Constructor_SetsDeclaration() var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations; var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null, CodeExplorerTestSetup.ProjectOneProvider); Assert.AreSame(projectDeclaration, project.Declaration); } @@ -33,7 +32,7 @@ public void Constructor_SetsName() var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations; var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null, CodeExplorerTestSetup.ProjectOneProvider); Assert.AreEqual(CodeExplorerTestSetup.TestProjectOneName, project.Name); } @@ -45,7 +44,7 @@ public void Constructor_NameWithSignatureIsSet() var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations; var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null, CodeExplorerTestSetup.ProjectOneProvider); Assert.IsFalse(string.IsNullOrEmpty(project.NameWithSignature)); } @@ -57,7 +56,7 @@ public void Constructor_PanelTitleIsSet() var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations; var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null, CodeExplorerTestSetup.ProjectOneProvider); Assert.IsFalse(string.IsNullOrEmpty(project.PanelTitle)); } @@ -69,7 +68,7 @@ public void Constructor_SetsIsExpandedTrue() var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations; var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null, CodeExplorerTestSetup.ProjectOneProvider); Assert.IsTrue(project.IsExpanded); } @@ -81,7 +80,7 @@ public void Constructor_ToolTipIsSet() var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations; var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null, CodeExplorerTestSetup.ProjectOneProvider); Assert.IsFalse(string.IsNullOrEmpty(project.ToolTip)); } @@ -99,7 +98,7 @@ public void SortComparerIsNodeType(CodeExplorerSortOrder order) var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations; var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null) + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null, CodeExplorerTestSetup.ProjectOneProvider) { SortOrder = order }; @@ -117,7 +116,7 @@ public void IsNotFiltered(string filter) var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations; var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null) + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null, CodeExplorerTestSetup.ProjectOneProvider) { Filter = filter }; @@ -173,7 +172,7 @@ public void Constructor_CreatesDefaultProjectFolder() var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations; var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null, CodeExplorerTestSetup.ProjectOneProvider); var folder = project.Children.OfType().Single(); Assert.AreEqual(projectDeclaration.IdentifierName, folder.Name); @@ -187,7 +186,7 @@ public void Constructor_ClearsDeclarationList() var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); // ReSharper disable once UnusedVariable - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null, CodeExplorerTestSetup.ProjectOneProvider); Assert.AreEqual(0, declarations.Count); } @@ -200,7 +199,7 @@ public void Synchronize_UsesDefaultProjectFolder_NoChanges() var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); var updates = declarations.ToList(); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null, CodeExplorerTestSetup.ProjectOneProvider); project.Synchronize(ref updates); @@ -216,7 +215,7 @@ public void Synchronize_ClearsPassedDeclarationList_NoChanges() var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations; var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null, CodeExplorerTestSetup.ProjectOneProvider); var updates = CodeExplorerTestSetup.TestProjectOneDeclarations; project.Synchronize(ref updates); @@ -230,7 +229,7 @@ public void Synchronize_DoesNotAlterDeclarationList_DifferentProject() var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations; var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null, CodeExplorerTestSetup.ProjectOneProvider); var updates = CodeExplorerTestSetup.TestProjectTwoDeclarations; project.Synchronize(ref updates); @@ -252,7 +251,7 @@ public void Constructor_PlacesAllTrackedDeclarations() var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); var results = declarations.ToList(); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null, CodeExplorerTestSetup.ProjectOneProvider); var expected = CodeExplorerProjectViewModel.ExtractTrackedDeclarationsForProject(projectDeclaration, ref results) @@ -273,7 +272,7 @@ public void Synchronize_PlacesAllTrackedDeclarations_NoChanges() var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations; var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null, CodeExplorerTestSetup.ProjectOneProvider); var updates = CodeExplorerTestSetup.TestProjectOneDeclarations; var results = updates.ToList(); @@ -302,7 +301,7 @@ public void Synchronize_PlacesAllTrackedDeclarations_AddedComponent(string compo var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations .TestProjectWithComponentDeclarations(new[] { component },out var projectDeclaration); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null, CodeExplorerTestSetup.ProjectOneProvider); var updates = CodeExplorerTestSetup.TestProjectOneDeclarations .TestProjectWithComponentDeclarations(new[] { component, added }, out _).ToList(); @@ -335,7 +334,7 @@ public void Synchronize_AddedComponent_SingleProjectFolderExists(string componen var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations .TestProjectWithComponentDeclarations(new[] { component }, out var projectDeclaration); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null, CodeExplorerTestSetup.ProjectOneProvider); var updates = CodeExplorerTestSetup.TestProjectOneDeclarations .TestProjectWithComponentDeclarations(new[] { component, added }, out _); @@ -359,7 +358,7 @@ public void Synchronize_RemovesComponent(string removed) var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations; var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null, CodeExplorerTestSetup.ProjectOneProvider); var updates = CodeExplorerTestSetup.TestProjectOneDeclarations.TestProjectWithComponentRemoved(removed); var expected = updates.Select(declaration => declaration.QualifiedName.ToString()) @@ -382,7 +381,7 @@ public void Synchronize_SetsDeclarationNull_NoDeclarationsForProject() var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations; var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null, CodeExplorerTestSetup.ProjectOneProvider); if (project.Declaration is null) { Assert.Inconclusive("Project declaration is null. Fix test setup and see why no other tests failed."); @@ -401,7 +400,7 @@ public void Synchronize_SetsDeclarationNull_DeclarationsForDifferentProject() var declarations = CodeExplorerTestSetup.TestProjectOneDeclarations; var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null, CodeExplorerTestSetup.ProjectOneProvider); if (project.Declaration is null) { Assert.Inconclusive("Project declaration is null. Fix test setup and see why no other tests failed."); @@ -426,7 +425,7 @@ public void Constructor_CreatesReferenceFolders(bool libraries, bool projects) { var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, state, null, state.ProjectsProvider); var libraryFolder = project.Children.OfType() .SingleOrDefault(folder => folder.ReferenceKind == ReferenceKind.TypeLibrary); @@ -454,7 +453,7 @@ public void Synchronize_ReferenceFolders_NoChanges(bool libraries, bool projects var expected = GetReferencesFromProjectDeclaration(projectDeclaration, state.ProjectsProvider).Select(reference => reference.Name).ToList(); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, state, null, state.ProjectsProvider); project.Synchronize(ref updates); var actual = GetReferencesFromProjectViewModel(project).OrderBy(reference => reference.Priority).Select(reference => reference.Name); @@ -477,7 +476,7 @@ public void Synchronize_ReferenceFolderRemoved(bool libraries, bool projects) var updates = declarations.ToList(); var projectDeclaration = declarations.First(declaration => declaration.DeclarationType == DeclarationType.Project); - var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, null, null); + var project = new CodeExplorerProjectViewModel(projectDeclaration, ref declarations, state, null, state.ProjectsProvider); var references = state.ProjectsProvider.Project(projectDeclaration.ProjectId).References; foreach (var reference in references.ToList()) diff --git a/RubberduckTests/CodeExplorer/CodeExplorerTestSetup.cs b/RubberduckTests/CodeExplorer/CodeExplorerTestSetup.cs index f43324d2d6..8da2ec9e84 100644 --- a/RubberduckTests/CodeExplorer/CodeExplorerTestSetup.cs +++ b/RubberduckTests/CodeExplorer/CodeExplorerTestSetup.cs @@ -6,8 +6,7 @@ using System.Collections.Generic; using System.Linq; using Rubberduck.Parsing.VBA; -using Rubberduck.UI.Command.MenuItems.ParentMenus; -using Rubberduck.VBEditor.SafeComWrappers.Abstract; +using Rubberduck.VBEditor.ComManagement; using RubberduckTests.AddRemoveReferences; namespace RubberduckTests.CodeExplorer @@ -16,7 +15,10 @@ internal static class CodeExplorerTestSetup { private static readonly List ProjectOne; private static readonly List ProjectTwo; - + + public static readonly IProjectsProvider ProjectOneProvider; + public static readonly IProjectsProvider ProjectTwoProvider; + public const string TestProjectOneName = "TestProject1"; public const string TestProjectTwoName = "TestProject2"; public const string TestDocumentName = "TestDocument1"; @@ -117,7 +119,7 @@ public static List TestSubMemberDeclarations(this List { TestUserFormName, ComponentType.UserForm } }; - public static List TestProjectWithFolderStructure(IEnumerable<(string Name, string Folder)> modules, out Declaration projectDeclaration) + public static List TestProjectWithFolderStructure(IEnumerable<(string Name, string Folder)> modules, out Declaration projectDeclaration, out RubberduckParserState state) { var builder = new MockVbeBuilder(); var project = builder.ProjectBuilder(TestProjectOneName, ProjectProtection.Unprotected); @@ -139,8 +141,8 @@ public static List TestProjectWithFolderStructure(IEnumerable<(stri } builder.AddProject(project.Build()); - var parser = MockParser.CreateAndParse(builder.Build().Object); - var output = parser.AllUserDeclarations.ToList(); + state = MockParser.CreateAndParse(builder.Build().Object); + var output = state.AllUserDeclarations.ToList(); projectDeclaration = output.Single(declaration => declaration.DeclarationType == DeclarationType.Project); return output; @@ -158,8 +160,9 @@ static CodeExplorerTestSetup() project.MockUserFormBuilder(TestUserFormName, CodeExplorerTestCode.TestUserFormCode).AddFormToProjectBuilder(); builder.AddProject(project.Build()); - var parser = MockParser.CreateAndParse(builder.Build().Object); - ProjectOne = parser.AllUserDeclarations.ToList(); + var state = MockParser.CreateAndParse(builder.Build().Object); + ProjectOne = state.AllUserDeclarations.ToList(); + ProjectOneProvider = state.ProjectsProvider; builder = new MockVbeBuilder(); @@ -171,8 +174,9 @@ static CodeExplorerTestSetup() project.MockUserFormBuilder(TestUserFormName, CodeExplorerTestCode.TestUserFormCode).AddFormToProjectBuilder(); builder.AddProject(project.Build()); - parser = MockParser.CreateAndParse(builder.Build().Object); - ProjectTwo = parser.AllUserDeclarations.ToList(); + state = MockParser.CreateAndParse(builder.Build().Object); + ProjectTwo = state.AllUserDeclarations.ToList(); + ProjectTwoProvider = state.ProjectsProvider; } public static List GetProjectDeclarationsWithReferences(bool libraries, bool projects, out RubberduckParserState state) diff --git a/RubberduckTests/Refactoring/ExtractInterfaceTests.cs b/RubberduckTests/Refactoring/ExtractInterfaceTests.cs index 4d10444c02..ba1e5a2797 100644 --- a/RubberduckTests/Refactoring/ExtractInterfaceTests.cs +++ b/RubberduckTests/Refactoring/ExtractInterfaceTests.cs @@ -424,7 +424,7 @@ protected override IRefactoring TestRefactoring(IRewritingManager rewritingManag uiDispatcherMock .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); - return new ExtractInterfaceRefactoring(state, state, factory, rewritingManager, selectionService, uiDispatcherMock.Object, state.ProjectsProvider); + return new ExtractInterfaceRefactoring(state, state, factory, rewritingManager, selectionService, uiDispatcherMock.Object, state?.ProjectsProvider); } } } \ No newline at end of file From 156e1b7f01359d76a0d73143ec31d441b7f5b8d9 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Mon, 17 Feb 2020 23:35:48 +0100 Subject: [PATCH 235/461] Remove uses of ProjectDisplayName on ProjectDeclaration except in InspectionResultFormatter The last remaining case is rather complicated. --- .../Formatters/InspectionResultFormatter.cs | 1 - .../CodeExplorerProjectViewModel.cs | 16 +++++++++- .../AddRemoveReferencesPresenterFactory.cs | 2 +- .../AddRemoveReferencesViewModel.cs | 31 ++++++++++++++++--- .../Inspections/InspectionResultsViewModel.cs | 3 +- .../AddRemoveReferencesSetup.cs | 2 +- .../AddRemoveReferencesViewModelTests.cs | 2 +- 7 files changed, 46 insertions(+), 11 deletions(-) diff --git a/Rubberduck.Core/Formatters/InspectionResultFormatter.cs b/Rubberduck.Core/Formatters/InspectionResultFormatter.cs index 139d85ffc6..7fbcc093c4 100644 --- a/Rubberduck.Core/Formatters/InspectionResultFormatter.cs +++ b/Rubberduck.Core/Formatters/InspectionResultFormatter.cs @@ -1,6 +1,5 @@ using Rubberduck.Common; using Rubberduck.Parsing.Inspections.Abstract; -using Rubberduck.Inspections.Abstract; using System.IO; using Rubberduck.Resources.Inspections; diff --git a/Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerProjectViewModel.cs b/Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerProjectViewModel.cs index 7bc81c9a2b..f88c3cd967 100644 --- a/Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerProjectViewModel.cs +++ b/Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerProjectViewModel.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Windows; using Rubberduck.AddRemoveReferences; @@ -193,11 +194,24 @@ private void SetName() _name = Declaration?.IdentifierName ?? string.Empty; // F' the flicker. Digging into the properties has some even more evil side-effects, and is a performance nightmare by comparison. - _displayName = Declaration?.ProjectDisplayName ?? string.Empty; + _displayName = DisplayName(Declaration); OnNameChanged(); } + private string DisplayName(Declaration declaration) + { + if (declaration == null) + { + return string.Empty; + } + + var project = _projectsProvider.Project(declaration.ProjectId); + return project != null + ? project.ProjectDisplayName + : string.Empty; + } + private static readonly List UntrackedTypes = new List { DeclarationType.Parameter, diff --git a/Rubberduck.Core/UI/AddRemoveReferences/AddRemoveReferencesPresenterFactory.cs b/Rubberduck.Core/UI/AddRemoveReferences/AddRemoveReferencesPresenterFactory.cs index 78f4944404..5b01d74bc6 100644 --- a/Rubberduck.Core/UI/AddRemoveReferences/AddRemoveReferencesPresenterFactory.cs +++ b/Rubberduck.Core/UI/AddRemoveReferences/AddRemoveReferencesPresenterFactory.cs @@ -147,7 +147,7 @@ public AddRemoveReferencesPresenter Create(ProjectDeclaration projectDeclaration return (model != null) ? new AddRemoveReferencesPresenter( - new AddRemoveReferencesDialog(new AddRemoveReferencesViewModel(model, _reconciler, _browser))) + new AddRemoveReferencesDialog(new AddRemoveReferencesViewModel(model, _reconciler, _browser, _projectsProvider))) : null; } diff --git a/Rubberduck.Core/UI/AddRemoveReferences/AddRemoveReferencesViewModel.cs b/Rubberduck.Core/UI/AddRemoveReferences/AddRemoveReferencesViewModel.cs index 0aeec16892..c6e7212c3e 100644 --- a/Rubberduck.Core/UI/AddRemoveReferences/AddRemoveReferencesViewModel.cs +++ b/Rubberduck.Core/UI/AddRemoveReferences/AddRemoveReferencesViewModel.cs @@ -13,6 +13,7 @@ using Rubberduck.Resources; using Rubberduck.UI.Command; using Rubberduck.VBEditor; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.SafeComWrappers; namespace Rubberduck.UI.AddRemoveReferences @@ -83,13 +84,19 @@ static AddRemoveReferencesViewModel() private readonly ObservableCollection _available; private readonly ObservableCollection _project; private readonly IReferenceReconciler _reconciler; + private readonly IProjectsProvider _projectsProvider; private readonly IFileSystemBrowserFactory _browser; - public AddRemoveReferencesViewModel(IAddRemoveReferencesModel model, IReferenceReconciler reconciler, IFileSystemBrowserFactory browser) + public AddRemoveReferencesViewModel( + IAddRemoveReferencesModel model, + IReferenceReconciler reconciler, + IFileSystemBrowserFactory browser, + IProjectsProvider projectsProvider) { Model = model; _reconciler = reconciler; _browser = browser; + _projectsProvider = projectsProvider; _available = new ObservableCollection(model.References .Where(reference => !reference.IsReferenced).OrderBy(reference => reference.Description)); @@ -114,9 +121,25 @@ public AddRemoveReferencesViewModel(IAddRemoveReferencesModel model, IReferenceR ApplyCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteApplyCommand, ApplyCanExecute); } - public string ProjectCaption => string.IsNullOrEmpty(Model?.Project?.IdentifierName) - ? RubberduckUI.References_Caption - : string.Format(RubberduckUI.References_CaptionTemplate, Model.Project.ProjectDisplayName); + public string ProjectCaption + { + get + { + if (string.IsNullOrEmpty(Model?.Project?.IdentifierName)) + { + return RubberduckUI.References_Caption; + } + + var project = _projectsProvider.Project(Model.Project.ProjectId); + + if (project == null) + { + return RubberduckUI.References_Caption; + } + + return project.ProjectDisplayName; + } + } /// /// The IAddRemoveReferencesModel for the view. diff --git a/Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs b/Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs index 7297f03439..330170ae58 100644 --- a/Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs +++ b/Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs @@ -20,7 +20,6 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.UIContext; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.VBA.Extensions; using Rubberduck.Settings; using Rubberduck.SettingsProvider; using Rubberduck.UI.Command; @@ -669,7 +668,7 @@ private void ExecuteCopyResultsCommand(object parameter) var resultArray = Results.OfType().Select(result => result.ToArray()).ToArray(); - var resource = resultArray.Count() == 1 + var resource = resultArray.Length == 1 ? Resources.RubberduckUI.CodeInspections_NumberOfIssuesFound_Singular : Resources.RubberduckUI.CodeInspections_NumberOfIssuesFound_Plural; diff --git a/RubberduckTests/AddRemoveReferences/AddRemoveReferencesSetup.cs b/RubberduckTests/AddRemoveReferences/AddRemoveReferencesSetup.cs index 3db9a0f7e7..fcc32202eb 100644 --- a/RubberduckTests/AddRemoveReferences/AddRemoveReferencesSetup.cs +++ b/RubberduckTests/AddRemoveReferences/AddRemoveReferencesSetup.cs @@ -283,7 +283,7 @@ public static AddRemoveReferencesViewModel ArrangeViewModel( var reconciler = ArrangeReferenceReconciler(settings, projectsProvider, out _, out libraryProvider); browserFactory = new Mock(); - return new AddRemoveReferencesViewModel(model, reconciler, browserFactory.Object); + return new AddRemoveReferencesViewModel(model, reconciler, browserFactory.Object, projectsProvider); } public static void SetupMockedOpenDialog(this Mock factory, string filename, DialogResult result) diff --git a/RubberduckTests/AddRemoveReferences/AddRemoveReferencesViewModelTests.cs b/RubberduckTests/AddRemoveReferences/AddRemoveReferencesViewModelTests.cs index df6b8908da..71d153dba6 100644 --- a/RubberduckTests/AddRemoveReferences/AddRemoveReferencesViewModelTests.cs +++ b/RubberduckTests/AddRemoveReferences/AddRemoveReferencesViewModelTests.cs @@ -136,7 +136,7 @@ public void ViewModelFilters_SearchInputFiltersList(string input, int expected) var model = new AddRemoveReferencesModel(null, declaration, SearchReferencesList, settings); var reconciler = AddRemoveReferencesSetup.ArrangeReferenceReconciler(settings); - var viewModel = new AddRemoveReferencesViewModel(model, reconciler, new Mock().Object); + var viewModel = new AddRemoveReferencesViewModel(model, reconciler, new Mock().Object, null); viewModel.SelectedFilter = ReferenceFilter.ComTypes.ToString(); viewModel.Search = input; From c7ac2da07a8857691c358b2fda0a23c170c93675 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Tue, 18 Feb 2020 00:18:35 +0100 Subject: [PATCH 236/461] Remove ProjectDisplayName from ProjectDeclaration This also removes the IVbProject ctor parameter. --- .../Formatters/InspectionResultFormatter.cs | 26 +++---------------- .../Symbols/ProjectDeclaration.cs | 26 ++----------------- .../DeclarationResolveRunnerBase.cs | 2 +- .../Symbols/AccessibilityCheckTests.cs | 2 +- .../Symbols/ClassModuleDeclarationTests.cs | 2 +- .../Symbols/DeclarationFinderTests.cs | 2 +- .../ProceduralModuleDeclarationTests.cs | 2 +- .../Symbols/ProjectDeclarationTests.cs | 2 +- 8 files changed, 12 insertions(+), 52 deletions(-) diff --git a/Rubberduck.Core/Formatters/InspectionResultFormatter.cs b/Rubberduck.Core/Formatters/InspectionResultFormatter.cs index 7fbcc093c4..2cb217665d 100644 --- a/Rubberduck.Core/Formatters/InspectionResultFormatter.cs +++ b/Rubberduck.Core/Formatters/InspectionResultFormatter.cs @@ -8,10 +8,12 @@ namespace Rubberduck.Formatters public class InspectionResultFormatter : IExportable { private readonly IInspectionResult _inspectionResult; + private readonly string _documentName; - public InspectionResultFormatter(IInspectionResult inspectionResult) + public InspectionResultFormatter(IInspectionResult inspectionResult, string documentName) { _inspectionResult = inspectionResult; + _documentName = documentName; } public object[] ToArray() @@ -28,30 +30,10 @@ public object[] ToArray() }; } - /// - /// WARNING: This property can have side effects. It can change the ActiveVBProject if the result has a null Declaration, - /// which causes a flicker in the VBE. This should only be called if it is *absolutely* necessary. - /// public string ToClipboardString() { var module = _inspectionResult.QualifiedSelection.QualifiedName; - var documentName = _inspectionResult.Target != null - ? _inspectionResult.Target.ProjectDisplayName - : string.Empty; - - //todo: Find a sane way to reimplement this. - //if (string.IsNullOrEmpty(documentName)) - //{ - // var component = module.Component; - // documentName = component != null - // ? component.ParentProject.ProjectDisplayName - // : string.Empty; - //} - - if (string.IsNullOrEmpty(documentName)) - { - documentName = Path.GetFileName(module.ProjectPath); - } + var documentName = _documentName; return string.Format( InspectionsUI.QualifiedSelectionInspection, diff --git a/Rubberduck.Parsing/Symbols/ProjectDeclaration.cs b/Rubberduck.Parsing/Symbols/ProjectDeclaration.cs index 13ef5e1795..c401b3a66f 100644 --- a/Rubberduck.Parsing/Symbols/ProjectDeclaration.cs +++ b/Rubberduck.Parsing/Symbols/ProjectDeclaration.cs @@ -3,20 +3,17 @@ using Rubberduck.VBEditor; using System.Collections.Generic; using System.Linq; -using Rubberduck.VBEditor.SafeComWrappers.Abstract; namespace Rubberduck.Parsing.Symbols { public sealed class ProjectDeclaration : Declaration, IDisposable { private readonly List _projectReferences; - private readonly IVBProject _project; public ProjectDeclaration( QualifiedMemberName qualifiedName, string name, - bool isUserDefined, - IVBProject project) + bool isUserDefined) : base( qualifiedName, null, @@ -34,12 +31,11 @@ public ProjectDeclaration( null, isUserDefined) { - _project = project; _projectReferences = new List(); } public ProjectDeclaration(ComProject project, QualifiedModuleName module) - : this(module.QualifyMemberName(project.Name), project.Name, false, null) + : this(module.QualifyMemberName(project.Name), project.Name, false) { Guid = project.Guid; MajorVersion = project.MajorVersion; @@ -72,24 +68,6 @@ public void ClearProjectReferences() _projectReferences.Clear(); } - private string _displayName; - /// - /// WARNING: This property has side effects. It changes the ActiveVBProject, which causes a flicker in the VBE. - /// This should only be called if it is *absolutely* necessary. - /// - public override string ProjectDisplayName - { - get - { - if (_displayName != null) - { - return _displayName; - } - _displayName = !IsDisposed && _project != null ? _project.ProjectDisplayName : string.Empty; - return _displayName; - } - } - public bool IsDisposed { get; private set; } public void Dispose() diff --git a/Rubberduck.Parsing/VBA/DeclarationResolving/DeclarationResolveRunnerBase.cs b/Rubberduck.Parsing/VBA/DeclarationResolving/DeclarationResolveRunnerBase.cs index 9883b5edd7..6920696118 100644 --- a/Rubberduck.Parsing/VBA/DeclarationResolving/DeclarationResolveRunnerBase.cs +++ b/Rubberduck.Parsing/VBA/DeclarationResolving/DeclarationResolveRunnerBase.cs @@ -80,7 +80,7 @@ private Declaration CreateProjectDeclaration(string projectId) var qualifiedModuleName = new QualifiedModuleName(project); var qualifiedName = qualifiedModuleName.QualifyMemberName(project.Name); - var projectDeclaration = new ProjectDeclaration(qualifiedName, qualifiedName.MemberName, true, project); + var projectDeclaration = new ProjectDeclaration(qualifiedName, qualifiedName.MemberName, true); return projectDeclaration; } diff --git a/RubberduckTests/Symbols/AccessibilityCheckTests.cs b/RubberduckTests/Symbols/AccessibilityCheckTests.cs index 729c2e0e51..fdb936fd32 100644 --- a/RubberduckTests/Symbols/AccessibilityCheckTests.cs +++ b/RubberduckTests/Symbols/AccessibilityCheckTests.cs @@ -23,7 +23,7 @@ public void ProjectsAreAlwaysAccessible() private static ProjectDeclaration GetTestProject(string name) { var qualifiedProjectName = new QualifiedMemberName(StubQualifiedModuleName(), name); - return new ProjectDeclaration(qualifiedProjectName, name, true, null); + return new ProjectDeclaration(qualifiedProjectName, name, true); } private static QualifiedModuleName StubQualifiedModuleName() diff --git a/RubberduckTests/Symbols/ClassModuleDeclarationTests.cs b/RubberduckTests/Symbols/ClassModuleDeclarationTests.cs index c528934ace..11ac4bf0da 100644 --- a/RubberduckTests/Symbols/ClassModuleDeclarationTests.cs +++ b/RubberduckTests/Symbols/ClassModuleDeclarationTests.cs @@ -22,7 +22,7 @@ public void ClassModulesHaveDeclarationTypeClassModule() private static ProjectDeclaration GetTestProject(string name) { var qualifiedProjectName = new QualifiedMemberName(StubQualifiedModuleName(), name); - return new ProjectDeclaration(qualifiedProjectName, name, true, null); + return new ProjectDeclaration(qualifiedProjectName, name, true); } private static QualifiedModuleName StubQualifiedModuleName() diff --git a/RubberduckTests/Symbols/DeclarationFinderTests.cs b/RubberduckTests/Symbols/DeclarationFinderTests.cs index e0939cee4d..369724e297 100644 --- a/RubberduckTests/Symbols/DeclarationFinderTests.cs +++ b/RubberduckTests/Symbols/DeclarationFinderTests.cs @@ -1583,7 +1583,7 @@ private static ClassModuleDeclaration GetTestClassModule(Declaration projectDecl private static ProjectDeclaration GetTestProject(string name) { var qualifiedProjectName = new QualifiedMemberName(StubQualifiedModuleName("proj"), name); - return new ProjectDeclaration(qualifiedProjectName, name, true, null); + return new ProjectDeclaration(qualifiedProjectName, name, true); } private static QualifiedModuleName StubQualifiedModuleName(string name) diff --git a/RubberduckTests/Symbols/ProceduralModuleDeclarationTests.cs b/RubberduckTests/Symbols/ProceduralModuleDeclarationTests.cs index c0484ca9d7..e4e13df61a 100644 --- a/RubberduckTests/Symbols/ProceduralModuleDeclarationTests.cs +++ b/RubberduckTests/Symbols/ProceduralModuleDeclarationTests.cs @@ -21,7 +21,7 @@ public void ProceduralModulesHaveDeclarationTypeProceduralModule() private static ProjectDeclaration GetTestProject(string name) { var qualifiedProjectName = new QualifiedMemberName(StubQualifiedModuleName(), name); - return new ProjectDeclaration(qualifiedProjectName, name, true, null); + return new ProjectDeclaration(qualifiedProjectName, name, true); } private static QualifiedModuleName StubQualifiedModuleName() diff --git a/RubberduckTests/Symbols/ProjectDeclarationTests.cs b/RubberduckTests/Symbols/ProjectDeclarationTests.cs index fd35497823..8defd54eca 100644 --- a/RubberduckTests/Symbols/ProjectDeclarationTests.cs +++ b/RubberduckTests/Symbols/ProjectDeclarationTests.cs @@ -20,7 +20,7 @@ public void ProjectsHaveDeclarationTypeProject() private static ProjectDeclaration GetTestProject(string name) { var qualifiedProjectName = new QualifiedMemberName(StubQualifiedModuleName(), name); - return new ProjectDeclaration(qualifiedProjectName, name, true, null); + return new ProjectDeclaration(qualifiedProjectName, name, true); } private static QualifiedModuleName StubQualifiedModuleName() From 302e1df8a9d51b20b0a39e18187b30990b70de48 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Tue, 18 Feb 2020 00:58:32 +0100 Subject: [PATCH 237/461] Fix export (to clipboard) for inspection results and todo items --- .../Formatters/InspectionResultFormatter.cs | 1 - .../Inspections/InspectionResultsViewModel.cs | 29 +++++++++++++++++-- .../UI/ToDoItems/ToDoExplorerViewModel.cs | 10 +++++-- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/Rubberduck.Core/Formatters/InspectionResultFormatter.cs b/Rubberduck.Core/Formatters/InspectionResultFormatter.cs index 2cb217665d..d98a739442 100644 --- a/Rubberduck.Core/Formatters/InspectionResultFormatter.cs +++ b/Rubberduck.Core/Formatters/InspectionResultFormatter.cs @@ -1,6 +1,5 @@ using Rubberduck.Common; using Rubberduck.Parsing.Inspections.Abstract; -using System.IO; using Rubberduck.Resources.Inspections; namespace Rubberduck.Formatters diff --git a/Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs b/Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs index 330170ae58..edfa29fd58 100644 --- a/Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs +++ b/Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs @@ -5,6 +5,7 @@ using System.ComponentModel; using System.Diagnostics; using System.Globalization; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -13,6 +14,7 @@ using System.Windows.Input; using NLog; using Rubberduck.Common; +using Rubberduck.Formatters; using Rubberduck.Inspections.Abstract; using Rubberduck.Interaction.Navigation; using Rubberduck.JunkDrawer.Extensions; @@ -666,7 +668,11 @@ private void ExecuteCopyResultsCommand(object parameter) return; } - var resultArray = Results.OfType().Select(result => result.ToArray()).ToArray(); + var resultArray = Results + .OfType() + .Select(result => new InspectionResultFormatter(result, DocumentName(result))) + .Select(formattedResult => formattedResult.ToArray()) + .ToArray(); var resource = resultArray.Length == 1 ? Resources.RubberduckUI.CodeInspections_NumberOfIssuesFound_Singular @@ -674,7 +680,12 @@ private void ExecuteCopyResultsCommand(object parameter) var title = string.Format(resource, DateTime.Now.ToString(CultureInfo.InvariantCulture), resultArray.Count()); - var textResults = title + Environment.NewLine + string.Join(string.Empty, Results.OfType().Select(result => result.ToClipboardString() + Environment.NewLine).ToArray()); + var resultTexts = Results + .OfType() + .Select(result => new InspectionResultFormatter(result, DocumentName(result))) + .Select(formattedResult => $"{formattedResult.ToClipboardString()}{Environment.NewLine}") + .ToArray(); + var textResults = $"{title}{Environment.NewLine}{string.Join(string.Empty, resultTexts)}"; var csvResults = ExportFormatter.Csv(resultArray, title, ColumnInformation); var htmlResults = ExportFormatter.HtmlClipboardFragment(resultArray, title, ColumnInformation); var rtfResults = ExportFormatter.RTF(resultArray, title); @@ -691,6 +702,20 @@ private void ExecuteCopyResultsCommand(object parameter) _clipboard.Flush(); } + private string DocumentName(IInspectionResult result) + { + var module = result.QualifiedSelection.QualifiedName; + var projectId = module.ProjectId; + var project = _state.ProjectsProvider.Project(projectId); + + if (project == null) + { + return Path.GetFileName(module.ProjectPath); + } + + return project.ProjectDisplayName; + } + private bool CanExecuteCopyResultsCommand(object parameter) { return !IsBusy && _results != null && _results.Any(); diff --git a/Rubberduck.Core/UI/ToDoItems/ToDoExplorerViewModel.cs b/Rubberduck.Core/UI/ToDoItems/ToDoExplorerViewModel.cs index 0b2969b4b8..ac09a160bf 100644 --- a/Rubberduck.Core/UI/ToDoItems/ToDoExplorerViewModel.cs +++ b/Rubberduck.Core/UI/ToDoItems/ToDoExplorerViewModel.cs @@ -249,7 +249,9 @@ public void ExecuteCopyResultsCommand(object obj) ColumnInfo[] columnInfos = { new ColumnInfo("Type"), new ColumnInfo("Description"), new ColumnInfo("Project"), new ColumnInfo("Component"), new ColumnInfo("Line", hAlignment.Right), new ColumnInfo("Column", hAlignment.Right) }; - var resultArray = _items.OfType().Select(result => result.ToArray()).ToArray(); + var resultArray = _items + .Select(item => new ToDoItemFormatter(item)) + .Select(formattedItem => formattedItem.ToArray()).ToArray(); var resource = _items.Count == 1 ? ToDoExplorerUI.ToDoExplorer_NumberOfIssuesFound_Singular @@ -257,7 +259,11 @@ public void ExecuteCopyResultsCommand(object obj) var title = string.Format(resource, DateTime.Now.ToString(CultureInfo.InvariantCulture), _items.Count); - var textResults = title + Environment.NewLine + string.Join(string.Empty, _items.OfType().Select(result => result.ToClipboardString() + Environment.NewLine).ToArray()); + var itemTexts = _items + .Select(item => new ToDoItemFormatter(item)) + .Select(formattedItem => $"{formattedItem.ToClipboardString()}{Environment.NewLine}") + .ToArray(); + var textResults = $"{title}{Environment.NewLine}{string.Join(string.Empty, itemTexts)}"; var csvResults = ExportFormatter.Csv(resultArray, title, columnInfos); var htmlResults = ExportFormatter.HtmlClipboardFragment(resultArray, title, columnInfos); var rtfResults = ExportFormatter.RTF(resultArray, title); From 12a06ee2d40a6b4702794ddaa26f8b14ade9c2a6 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Tue, 18 Feb 2020 19:24:01 +0100 Subject: [PATCH 238/461] Fix MoveToFolderRefactoringAction for folders containing double quotes --- .../MoveToFolderRefactoringAction.cs | 6 +++- ... => MoveToFolderRefactoringActionTests.cs} | 28 ++++++++++++++++++- ...stBase.cs => RefactoringActionTestBase.cs} | 2 +- 3 files changed, 33 insertions(+), 3 deletions(-) rename RubberduckTests/Refactoring/{MoveToFolderTests.cs => MoveToFolderRefactoringActionTests.cs} (70%) rename RubberduckTests/Refactoring/{BaseRefactoringTestBase.cs => RefactoringActionTestBase.cs} (97%) diff --git a/Rubberduck.Refactorings/MoveToFolder/MoveToFolderRefactoringAction.cs b/Rubberduck.Refactorings/MoveToFolder/MoveToFolderRefactoringAction.cs index 5214491832..f3b10b77b5 100644 --- a/Rubberduck.Refactorings/MoveToFolder/MoveToFolderRefactoringAction.cs +++ b/Rubberduck.Refactorings/MoveToFolder/MoveToFolderRefactoringAction.cs @@ -47,8 +47,12 @@ private void UpdateFolderAnnotation(MoveToFolderModel model, IParseTreeAnnotatio private static (IAnnotation annotation, IReadOnlyList annotationArguments) NewAnnotation(string targetFolder) { + var targetFolderLiteral = targetFolder + .Replace("\"", "\"\"") + .EnQuote(); + var annotation = new FolderAnnotation(); - var annotationValues = new List { targetFolder.EnQuote() }; + var annotationValues = new List { targetFolderLiteral }; return (annotation, annotationValues); } diff --git a/RubberduckTests/Refactoring/MoveToFolderTests.cs b/RubberduckTests/Refactoring/MoveToFolderRefactoringActionTests.cs similarity index 70% rename from RubberduckTests/Refactoring/MoveToFolderTests.cs rename to RubberduckTests/Refactoring/MoveToFolderRefactoringActionTests.cs index 7cb8bc0f54..f3dfc998d4 100644 --- a/RubberduckTests/Refactoring/MoveToFolderTests.cs +++ b/RubberduckTests/Refactoring/MoveToFolderRefactoringActionTests.cs @@ -10,7 +10,7 @@ namespace RubberduckTests.Refactoring { [TestFixture] - public class MoveToFolderTests : BaseRefactoringTestBase + public class MoveToFolderRefactoringActionTests : RefactoringActionTestBase { [Test] [Category("Refactorings")] @@ -65,6 +65,32 @@ End Sub Assert.AreEqual(expectedCode, refactoredCode); } + [Test] + [Category("Refactorings")] + public void MoveToFolderBaseRefactoring_NameContainingDoubleQuotes() + { + const string code = @" +Public Sub Foo() +End Sub +"; + const string expectedCode = @"'@Folder ""MyNew""""Folder.My""""""""""""""""SubFolder"" + +Public Sub Foo() +End Sub +"; + Func modelBuilder = (state) => + { + var module = state.DeclarationFinder + .UserDeclarations(DeclarationType.ProceduralModule) + .Single() as ModuleDeclaration; + return new MoveToFolderModel(module, "MyNew\"Folder.My\"\"\"\"SubFolder"); + }; + + var refactoredCode = RefactoredCode(code, modelBuilder); + + Assert.AreEqual(expectedCode, refactoredCode); + } + protected override IRefactoringAction TestBaseRefactoring(RubberduckParserState state, IRewritingManager rewritingManager) { var annotationUpdater = new AnnotationUpdater(); diff --git a/RubberduckTests/Refactoring/BaseRefactoringTestBase.cs b/RubberduckTests/Refactoring/RefactoringActionTestBase.cs similarity index 97% rename from RubberduckTests/Refactoring/BaseRefactoringTestBase.cs rename to RubberduckTests/Refactoring/RefactoringActionTestBase.cs index 20489509e2..4e918f079b 100644 --- a/RubberduckTests/Refactoring/BaseRefactoringTestBase.cs +++ b/RubberduckTests/Refactoring/RefactoringActionTestBase.cs @@ -11,7 +11,7 @@ namespace RubberduckTests.Refactoring { - public abstract class BaseRefactoringTestBase + public abstract class RefactoringActionTestBase where TModel : class, IRefactoringModel { From 433a57b3b683d227ca4ad335a2111e895ec18bc2 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Wed, 19 Feb 2020 01:23:32 +0100 Subject: [PATCH 239/461] Enhance IVbProject.ProjectDisplayName implementations They now first try to use the filename, then try to get it from the caption, but with enhanced handling when running into the VBE aPI bug and finally fall back to the BuildFileName. --- .../SafeComWrappers/VB/VBProject.cs | 121 +++++++++++++++--- .../SafeComWrappers/VB/VBProject.cs | 121 +++++++++++++++--- 2 files changed, 204 insertions(+), 38 deletions(-) diff --git a/Rubberduck.VBEditor.VB6/SafeComWrappers/VB/VBProject.cs b/Rubberduck.VBEditor.VB6/SafeComWrappers/VB/VBProject.cs index f6ce4251b7..dfa93bc986 100644 --- a/Rubberduck.VBEditor.VB6/SafeComWrappers/VB/VBProject.cs +++ b/Rubberduck.VBEditor.VB6/SafeComWrappers/VB/VBProject.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text.RegularExpressions; @@ -165,11 +166,9 @@ public void ExportSourceFiles(string folder) } } - private static readonly Regex CaptionProjectRegex = new Regex(@"^(?:[^-]+)(?:\s-\s)(?.+)(?:\s-\s.*)?$"); - private static readonly Regex OpenModuleRegex = new Regex(@"^(?.+)(?\s-\s\[.*\((Code|UserForm)\)\])$"); private string _displayName; /// - /// WARNING: This property has side effects. It changes the ActiveVBProject, which causes a flicker in the VBE. + /// WARNING: This property might have has side effects. If the filename cannot be accessed, it changes the ActiveVBProject, which causes a flicker in the VBE. /// This should only be called if it is *absolutely* necessary. /// public string ProjectDisplayName @@ -187,32 +186,116 @@ public string ProjectDisplayName return _displayName; } - var vbe = VBE; - var activeProject = vbe.ActiveVBProject; - var mainWindow = vbe.MainWindow; + _displayName = DisplayNameFromFileName(); + + if (string.IsNullOrEmpty(_displayName)) + { + _displayName = DisplayNameFromWindowCaption(); + } + + if (string.IsNullOrEmpty(_displayName) + || _displayName.EndsWith("...")) { - try + var nameFromBuildFileName = DisplayNameFromBuildFileName(); + if (!string.IsNullOrEmpty(nameFromBuildFileName) + && nameFromBuildFileName.Length > _displayName.Length - 3) //Otherwise, we got more of the name from the previous attempt. { - if (Target.HelpFile != activeProject.HelpFile) - { - vbe.ActiveVBProject = this; - } + _displayName = nameFromBuildFileName; + } + } + + return _displayName; + } + } + + private string DisplayNameFromFileName() + { + return Path.GetFileName(FileName); + } + + private string DisplayNameFromBuildFileName() + { + var pseudoDllName = Path.GetFileName(BuildFileName); + return pseudoDllName == null || pseudoDllName.Length <= 4 //Should not happen as the string should always end in .DLL. + ? string.Empty + : pseudoDllName.Substring(0, pseudoDllName.Length - 4); + } + + private static readonly Regex CaptionProjectRegex = new Regex(@"^(?:[^-]+)(?:\s-\s)(?.+)(?:\s-\s.*)?$"); + private static readonly Regex OpenModuleRegex = new Regex(@"^(?.+)(?\s-\s\[.*\((Code|UserForm)\)\])$"); + private static readonly Regex PartialOpenModuleRegex = new Regex(@"^(?.+)(\s-\s\[)"); + private static readonly Regex NearlyOnlyProject = new Regex(@"^(?.+)(\s-?\s?)$"); + + private string DisplayNameFromWindowCaption() + { + using (var vbe = VBE) + using (var activeProject = vbe.ActiveVBProject) + using (var mainWindow = vbe.MainWindow) + { + try + { + if (ProjectId != activeProject.ProjectId) + { + vbe.ActiveVBProject = this; + } + + var caption = mainWindow.Caption; + if (caption.Length > 99) + { + //The value returned will be truncated at character 99 and the rest is garbage due to a bug in the VBE API. + caption = caption.Substring(0, 99); - var caption = mainWindow.Caption; if (CaptionProjectRegex.IsMatch(caption)) { - caption = CaptionProjectRegex.Matches(caption)[0].Groups["project"].Value; - _displayName = OpenModuleRegex.IsMatch(caption) - ? OpenModuleRegex.Matches(caption)[0].Groups["project"].Value - : caption; + var projectRelatedPartOfCaption = CaptionProjectRegex + .Matches(caption)[0] + .Groups["project"] + .Value; + + if (PartialOpenModuleRegex.IsMatch(projectRelatedPartOfCaption)) + { + return PartialOpenModuleRegex + .Matches(projectRelatedPartOfCaption)[0] + .Groups["project"] + .Value; + } + + if (NearlyOnlyProject.IsMatch(projectRelatedPartOfCaption)) + { + return NearlyOnlyProject + .Matches(projectRelatedPartOfCaption)[0] + .Groups["project"] + .Value; + } + + return $"{projectRelatedPartOfCaption}..."; } } - catch + else { - _displayName = string.Empty; + if (CaptionProjectRegex.IsMatch(caption)) + { + var projectRelatedPartOfCaption = CaptionProjectRegex + .Matches(caption)[0] + .Groups["project"] + .Value; + + if (OpenModuleRegex.IsMatch(projectRelatedPartOfCaption)) + { + return OpenModuleRegex + .Matches(projectRelatedPartOfCaption)[0] + .Groups["project"] + .Value; + } + } } - return _displayName; } + catch + { + return string.Empty; + } + + return string.Empty; } } diff --git a/Rubberduck.VBEditor.VBA/SafeComWrappers/VB/VBProject.cs b/Rubberduck.VBEditor.VBA/SafeComWrappers/VB/VBProject.cs index ae83996f3a..4b60f2c594 100644 --- a/Rubberduck.VBEditor.VBA/SafeComWrappers/VB/VBProject.cs +++ b/Rubberduck.VBEditor.VBA/SafeComWrappers/VB/VBProject.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text.RegularExpressions; using Rubberduck.VBEditor.SafeComWrappers.Abstract; @@ -164,11 +165,9 @@ public void ExportSourceFiles(string folder) } } - private static readonly Regex CaptionProjectRegex = new Regex(@"^(?:[^-]+)(?:\s-\s)(?.+)(?:\s-\s.*)?$"); - private static readonly Regex OpenModuleRegex = new Regex(@"^(?.+)(?\s-\s\[.*\((Code|UserForm)\)\])$"); private string _displayName; /// - /// WARNING: This property has side effects. It changes the ActiveVBProject, which causes a flicker in the VBE. + /// WARNING: This property might have has side effects. If the filename cannot be accessed, it changes the ActiveVBProject, which causes a flicker in the VBE. /// This should only be called if it is *absolutely* necessary. /// public string ProjectDisplayName @@ -186,32 +185,116 @@ public string ProjectDisplayName return _displayName; } - using (var vbe = VBE) - using (var activeProject = vbe.ActiveVBProject) - using (var mainWindow = vbe.MainWindow) + _displayName = DisplayNameFromFileName(); + + if (string.IsNullOrEmpty(_displayName)) + { + _displayName = DisplayNameFromWindowCaption(); + } + + if (string.IsNullOrEmpty(_displayName) + || _displayName.EndsWith("...")) { - try + var nameFromBuildFileName = DisplayNameFromBuildFileName(); + if (!string.IsNullOrEmpty(nameFromBuildFileName) + && nameFromBuildFileName.Length > _displayName.Length - 3) //Otherwise, we got more of the name from the previous attempt. { - if (Target.HelpFile != activeProject.HelpFile) - { - vbe.ActiveVBProject = this; - } + _displayName = nameFromBuildFileName; + } + } + + return _displayName; + } + } + + private string DisplayNameFromFileName() + { + return Path.GetFileName(FileName); + } + + private string DisplayNameFromBuildFileName() + { + var pseudoDllName = Path.GetFileName(BuildFileName); + return pseudoDllName == null || pseudoDllName.Length <= 4 //Should not happen as the string should always end in .DLL. + ? string.Empty + : pseudoDllName.Substring(0, pseudoDllName.Length - 4); + } + + private static readonly Regex CaptionProjectRegex = new Regex(@"^(?:[^-]+)(?:\s-\s)(?.+)(?:\s-\s.*)?$"); + private static readonly Regex OpenModuleRegex = new Regex(@"^(?.+)(?\s-\s\[.*\((Code|UserForm)\)\])$"); + private static readonly Regex PartialOpenModuleRegex = new Regex(@"^(?.+)(\s-\s\[)"); + private static readonly Regex NearlyOnlyProject = new Regex(@"^(?.+)(\s-?\s?)$"); + + private string DisplayNameFromWindowCaption() + { + using (var vbe = VBE) + using (var activeProject = vbe.ActiveVBProject) + using (var mainWindow = vbe.MainWindow) + { + try + { + if (ProjectId != activeProject.ProjectId) + { + vbe.ActiveVBProject = this; + } + + var caption = mainWindow.Caption; + if (caption.Length > 99) + { + //The value returned will be truncated at character 99 and the rest is garbage due to a bug in the VBE API. + caption = caption.Substring(0, 99); - var caption = mainWindow.Caption; if (CaptionProjectRegex.IsMatch(caption)) { - caption = CaptionProjectRegex.Matches(caption)[0].Groups["project"].Value; - _displayName = OpenModuleRegex.IsMatch(caption) - ? OpenModuleRegex.Matches(caption)[0].Groups["project"].Value - : caption; + var projectRelatedPartOfCaption = CaptionProjectRegex + .Matches(caption)[0] + .Groups["project"] + .Value; + + if (PartialOpenModuleRegex.IsMatch(projectRelatedPartOfCaption)) + { + return PartialOpenModuleRegex + .Matches(projectRelatedPartOfCaption)[0] + .Groups["project"] + .Value; + } + + if (NearlyOnlyProject.IsMatch(projectRelatedPartOfCaption)) + { + return NearlyOnlyProject + .Matches(projectRelatedPartOfCaption)[0] + .Groups["project"] + .Value; + } + + return $"{projectRelatedPartOfCaption}..."; } } - catch + else { - _displayName = string.Empty; + if (CaptionProjectRegex.IsMatch(caption)) + { + var projectRelatedPartOfCaption = CaptionProjectRegex + .Matches(caption)[0] + .Groups["project"] + .Value; + + if (OpenModuleRegex.IsMatch(projectRelatedPartOfCaption)) + { + return OpenModuleRegex + .Matches(projectRelatedPartOfCaption)[0] + .Groups["project"] + .Value; + } + } } - return _displayName; } + catch + { + return string.Empty; + } + + return string.Empty; } } From be89af3eef891ec9181a0d1e4697ab6330f09afa Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Wed, 19 Feb 2020 20:48:40 +0100 Subject: [PATCH 240/461] Use AddComponentService in ExtractInterfaceRefactoringBase Also adds @Interface annotations to the interfaces. --- .../ExtractInterfaceRefactoringAction.cs | 48 +++++++++---------- .../CodeExplorer/MockedCodeExplorer.cs | 9 +++- .../ExtractInterfaceCommandTests.cs | 11 ++++- .../Refactoring/ExtractInterfaceTests.cs | 32 +++++++++---- 4 files changed, 65 insertions(+), 35 deletions(-) diff --git a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoringAction.cs b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoringAction.cs index c3fa031284..92ff864b51 100644 --- a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoringAction.cs +++ b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoringAction.cs @@ -2,6 +2,7 @@ using System.Linq; using Antlr4.Runtime; using Rubberduck.Parsing; +using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; @@ -11,6 +12,7 @@ using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; +using Rubberduck.VBEditor.Utility; namespace Rubberduck.Refactorings.ExtractInterface { @@ -19,18 +21,21 @@ public class ExtractInterfaceRefactoringAction : RefactoringActionWithSuspension private readonly ICodeOnlyRefactoringAction _addImplementationsRefactoringAction; private readonly IParseTreeProvider _parseTreeProvider; private readonly IProjectsProvider _projectsProvider; + private readonly IAddComponentService _addComponentService; public ExtractInterfaceRefactoringAction( AddInterfaceImplementationsRefactoringAction addImplementationsRefactoringAction, IParseTreeProvider parseTreeProvider, IParseManager parseManager, IRewritingManager rewritingManager, - IProjectsProvider projectsProvider) + IProjectsProvider projectsProvider, + IAddComponentService addComponentService) : base(parseManager, rewritingManager) { _addImplementationsRefactoringAction = addImplementationsRefactoringAction; _parseTreeProvider = parseTreeProvider; _projectsProvider = projectsProvider; + _addComponentService = addComponentService; } protected override bool RequiresSuspension(ExtractInterfaceModel model) @@ -51,30 +56,28 @@ private void AddInterface(ExtractInterfaceModel model, IRewriteSession rewriteSe return; //The target project is not available. } - AddInterfaceClass(targetProject, model.InterfaceName, GetInterfaceModuleBody(model)); + AddInterfaceClass(model); AddImplementsStatement(model, rewriteSession); AddInterfaceMembersToClass(model, rewriteSession); } - private void AddInterfaceClass(IVBProject targetProject, string interfaceName, string interfaceBody) + private void AddInterfaceClass(ExtractInterfaceModel model) { - using (var components = targetProject.VBComponents) - { - using (var interfaceComponent = components.Add(ComponentType.ClassModule)) - { - using (var interfaceModule = interfaceComponent.CodeModule) - { - interfaceComponent.Name = interfaceName; - - var optionPresent = interfaceModule.CountOfLines > 1; - if (!optionPresent) - { - interfaceModule.InsertLines(1, $"{Tokens.Option} {Tokens.Explicit}{Environment.NewLine}"); - } - interfaceModule.InsertLines(3, interfaceBody); - } - } - } + var targetProjectId = model.TargetDeclaration.ProjectId; + var interfaceCode = InterfaceModuleBody(model); + var interfaceName = model.InterfaceName; + + _addComponentService.AddComponent(targetProjectId, ComponentType.ClassModule, interfaceCode, componentName: interfaceName); + } + + private static string InterfaceModuleBody(ExtractInterfaceModel model) + { + var interfaceMembers = string.Join(Environment.NewLine, model.SelectedMembers.Select(m => m.Body)); + var optionExplicit = $"{Tokens.Option} {Tokens.Explicit}{Environment.NewLine}"; + var interfaceAnnotation = new InterfaceAnnotation(); + var interfaceAnnotationText = $"'@{interfaceAnnotation.Name}{Environment.NewLine}"; + + return $"{optionExplicit}{Environment.NewLine}{interfaceAnnotationText}{Environment.NewLine}{interfaceMembers}"; } private void AddImplementsStatement(ExtractInterfaceModel model, IRewriteSession rewriteSession) @@ -134,11 +137,6 @@ private void AddInterfaceMembersToClass(ExtractInterfaceModel model, IRewriteSes _addImplementationsRefactoringAction.Refactor(addMembersModel, rewriteSession); } - private static string GetInterfaceModuleBody(ExtractInterfaceModel model) - { - return string.Join(Environment.NewLine, model.SelectedMembers.Select(m => m.Body)); - } - private static readonly DeclarationType[] ModuleTypes = { DeclarationType.ClassModule, diff --git a/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs b/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs index 6371f8354e..fd7f546039 100644 --- a/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs +++ b/RubberduckTests/CodeExplorer/MockedCodeExplorer.cs @@ -504,13 +504,20 @@ public MockedCodeExplorer ImplementIndenterCommand() public MockedCodeExplorer ImplementExtractInterfaceCommand() { var addImplementationsBaseRefactoring = new AddInterfaceImplementationsRefactoringAction(null); - var extractInterfaceBaseRefactoring = new ExtractInterfaceRefactoringAction(addImplementationsBaseRefactoring, State, State, null, State.ProjectsProvider); + var addComponentService = TestAddComponentService(State.ProjectsProvider); + var extractInterfaceBaseRefactoring = new ExtractInterfaceRefactoringAction(addImplementationsBaseRefactoring, State, State, null, State.ProjectsProvider, addComponentService); ViewModel.CodeExplorerExtractInterfaceCommand = new CodeExplorerExtractInterfaceCommand( new ExtractInterfaceRefactoring(extractInterfaceBaseRefactoring, State, null, null, _uiDispatcher.Object), State, null, VbeEvents.Object); return this; } + private static IAddComponentService TestAddComponentService(IProjectsProvider projectsProvider) + { + var sourceCodeHandler = new CodeModuleComponentSourceCodeHandler(); + return new AddComponentService(projectsProvider, sourceCodeHandler, sourceCodeHandler); + } + public MockedCodeExplorer ConfigureSaveDialog(string path, DialogResult result) { SaveDialog.Setup(o => o.FileName).Returns(path); diff --git a/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs b/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs index e0efee80fe..e81a8ddde8 100644 --- a/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs +++ b/RubberduckTests/Commands/RefactorCommands/ExtractInterfaceCommandTests.cs @@ -12,8 +12,10 @@ using Rubberduck.UI.Command.Refactorings; using Rubberduck.UI.Command.Refactorings.Notifiers; using Rubberduck.VBEditor; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; +using Rubberduck.VBEditor.SourceCodeHandling; using Rubberduck.VBEditor.Utility; using RubberduckTests.Mocks; @@ -172,12 +174,19 @@ protected override CommandBase TestCommand(IVBE vbe, RubberduckParserState state .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); var addImplementationsBaseRefactoring = new AddInterfaceImplementationsRefactoringAction(rewritingManager); - var baseRefactoring = new ExtractInterfaceRefactoringAction(addImplementationsBaseRefactoring, state, state, rewritingManager, state.ProjectsProvider); + var addComponentService = TestAddComponentService(state.ProjectsProvider); + var baseRefactoring = new ExtractInterfaceRefactoringAction(addImplementationsBaseRefactoring, state, state, rewritingManager, state.ProjectsProvider, addComponentService); var refactoring = new ExtractInterfaceRefactoring(baseRefactoring, state, factory, selectionService, uiDispatcherMock.Object); var notifier = new ExtractInterfaceFailedNotifier(msgBox); return new RefactorExtractInterfaceCommand(refactoring, notifier, state, selectionService); } + private static IAddComponentService TestAddComponentService(IProjectsProvider projectsProvider) + { + var sourceCodeHandler = new CodeModuleComponentSourceCodeHandler(); + return new AddComponentService(projectsProvider, sourceCodeHandler, sourceCodeHandler); + } + protected override IVBE SetupAllowingExecution() { const string input = diff --git a/RubberduckTests/Refactoring/ExtractInterfaceTests.cs b/RubberduckTests/Refactoring/ExtractInterfaceTests.cs index 0936181e53..3ba24c0b0e 100644 --- a/RubberduckTests/Refactoring/ExtractInterfaceTests.cs +++ b/RubberduckTests/Refactoring/ExtractInterfaceTests.cs @@ -12,7 +12,9 @@ using Rubberduck.Refactorings.Exceptions; using Rubberduck.Refactorings.ExtractInterface; using Rubberduck.VBEditor; +using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.SafeComWrappers; +using Rubberduck.VBEditor.SourceCodeHandling; using Rubberduck.VBEditor.Utility; using RubberduckTests.Mocks; @@ -47,9 +49,10 @@ End Sub const string expectedInterfaceCode = @"Option Explicit +'@Interface + Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) End Sub - "; Func presenterAction = model => { @@ -194,6 +197,8 @@ End Property const string expectedInterfaceCode = @"Option Explicit +'@Interface + Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) End Sub @@ -208,7 +213,6 @@ End Property Public Property Set Buzz(ByRef value As Variant) End Property - "; Func presenterAction = model => { @@ -281,12 +285,13 @@ End Function const string expectedInterfaceCode = @"Option Explicit +'@Interface + Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) End Sub Public Function Fizz(ByRef b As Variant) As Variant End Function - "; Func presenterAction = model => { @@ -401,9 +406,10 @@ End Sub const string expectedInterfaceCode = @"Option Explicit +'@Interface + Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) End Sub - "; Func presenterAction = model => { @@ -466,9 +472,10 @@ End Sub const string expectedInterfaceCode = @"Option Explicit +'@Interface + Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) End Sub - "; Func presenterAction = model => { @@ -545,9 +552,10 @@ End Sub const string expectedInterfaceCode = @"Option Explicit +'@Interface + Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) End Sub - "; Func presenterAction = model => { @@ -622,9 +630,10 @@ End Sub const string expectedInterfaceCode = @"Option Explicit +'@Interface + Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) End Sub - "; Func presenterAction = model => { @@ -650,8 +659,15 @@ protected override IRefactoring TestRefactoring(IRewritingManager rewritingManag .Setup(m => m.Invoke(It.IsAny())) .Callback((Action action) => action.Invoke()); var addImplementationsBaseRefactoring = new AddInterfaceImplementationsRefactoringAction(rewritingManager); - var baseRefactoring = new ExtractInterfaceRefactoringAction(addImplementationsBaseRefactoring, state, state, rewritingManager, state?.ProjectsProvider); + var addComponentService = TestAddComponentService(state?.ProjectsProvider); + var baseRefactoring = new ExtractInterfaceRefactoringAction(addImplementationsBaseRefactoring, state, state, rewritingManager, state?.ProjectsProvider, addComponentService); return new ExtractInterfaceRefactoring(baseRefactoring, state, factory, selectionService, uiDispatcherMock.Object); } + + private static IAddComponentService TestAddComponentService(IProjectsProvider projectsProvider) + { + var sourceCodeHandler = new CodeModuleComponentSourceCodeHandler(); + return new AddComponentService(projectsProvider, sourceCodeHandler, sourceCodeHandler); + } } } \ No newline at end of file From 9d45411a9d09925732861fc864973aab645f9342 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Wed, 19 Feb 2020 21:07:02 +0100 Subject: [PATCH 241/461] Put extracted interfaces in same folder as the origin --- .../ExtractInterfaceRefactoringAction.cs | 9 +++- .../Refactoring/ExtractInterfaceTests.cs | 52 +++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoringAction.cs b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoringAction.cs index 92ff864b51..288e71f6dd 100644 --- a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoringAction.cs +++ b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoringAction.cs @@ -74,10 +74,17 @@ private static string InterfaceModuleBody(ExtractInterfaceModel model) { var interfaceMembers = string.Join(Environment.NewLine, model.SelectedMembers.Select(m => m.Body)); var optionExplicit = $"{Tokens.Option} {Tokens.Explicit}{Environment.NewLine}"; + + var targetModule = Declaration.GetModuleParent(model.TargetDeclaration); + var folderAnnotation = targetModule?.Annotations.FirstOrDefault(pta => pta.Annotation is FolderAnnotation); + var folderAnnotationText = folderAnnotation != null + ? $"'@{folderAnnotation.Context.GetText()}{Environment.NewLine}" + : string.Empty; + var interfaceAnnotation = new InterfaceAnnotation(); var interfaceAnnotationText = $"'@{interfaceAnnotation.Name}{Environment.NewLine}"; - return $"{optionExplicit}{Environment.NewLine}{interfaceAnnotationText}{Environment.NewLine}{interfaceMembers}"; + return $"{optionExplicit}{Environment.NewLine}{folderAnnotationText}{interfaceAnnotationText}{Environment.NewLine}{interfaceMembers}"; } private void AddImplementsStatement(ExtractInterfaceModel model, IRewriteSession rewriteSession) diff --git a/RubberduckTests/Refactoring/ExtractInterfaceTests.cs b/RubberduckTests/Refactoring/ExtractInterfaceTests.cs index 3ba24c0b0e..e731db027d 100644 --- a/RubberduckTests/Refactoring/ExtractInterfaceTests.cs +++ b/RubberduckTests/Refactoring/ExtractInterfaceTests.cs @@ -652,6 +652,58 @@ End Sub Assert.AreEqual(expectedInterfaceCode, actualInterfaceCode); } + [Test] + [Category("Refactorings")] + [Category("Extract Interface")] + public void ExtractInterfaceRefactoring_PutsInterfaceInFolderOfClassItIsExtractedFrom() + { + //Input + const string inputCode = + @"'@Folder(""MyFolder.MySubFolder"") + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub"; + var selection = new Selection(1, 23, 1, 27); + + //Expectation + const string expectedCode = + @"Implements IClass + +'@Folder(""MyFolder.MySubFolder"") + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub + +Private Sub IClass_Foo(ByVal arg1 As Integer, ByVal arg2 As String) + Err.Raise 5 'TODO implement interface member +End Sub +"; + + const string expectedInterfaceCode = + @"Option Explicit + +'@Folder(""MyFolder.MySubFolder"") +'@Interface + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub +"; + Func presenterAction = model => + { + foreach (var interfaceMember in model.Members) + { + interfaceMember.IsSelected = true; + } + + return model; + }; + + var actualCode = RefactoredCode("Class", selection, presenterAction, null, false, ("Class", inputCode, ComponentType.ClassModule)); + Assert.AreEqual(expectedCode, actualCode["Class"]); + var actualInterfaceCode = actualCode[actualCode.Keys.Single(componentName => !componentName.Equals("Class"))]; + Assert.AreEqual(expectedInterfaceCode, actualInterfaceCode); + } + protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) { var uiDispatcherMock = new Mock(); From 93939e6054a59595273597cbae36d5174a56ae54 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Wed, 19 Feb 2020 23:27:04 +0100 Subject: [PATCH 242/461] Split tests for ImplementInterface and ExtractInterface into refactoring and refactoring action part --- .../ExtractInterfaceRefactoringActionTests.cs | 475 +++++++++ .../ExtractInterface/ExtractInterfaceTests.cs | 267 +++++ .../Refactoring/ExtractInterfaceTests.cs | 725 -------------- ...mplementInterfaceRefactoringActionTests.cs | 585 +++++++++++ .../ImplementInterfaceTests.cs | 226 +++++ .../Refactoring/ImplementInterfaceTests.cs | 920 ------------------ 6 files changed, 1553 insertions(+), 1645 deletions(-) create mode 100644 RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceRefactoringActionTests.cs create mode 100644 RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceTests.cs delete mode 100644 RubberduckTests/Refactoring/ExtractInterfaceTests.cs create mode 100644 RubberduckTests/Refactoring/ImplementInterface/ImplementInterfaceRefactoringActionTests.cs create mode 100644 RubberduckTests/Refactoring/ImplementInterface/ImplementInterfaceTests.cs delete mode 100644 RubberduckTests/Refactoring/ImplementInterfaceTests.cs diff --git a/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceRefactoringActionTests.cs b/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceRefactoringActionTests.cs new file mode 100644 index 0000000000..ebcd6cbb2e --- /dev/null +++ b/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceRefactoringActionTests.cs @@ -0,0 +1,475 @@ +using System; +using System.Linq; +using NUnit.Framework; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.Refactorings; +using Rubberduck.Refactorings.AddInterfaceImplementations; +using Rubberduck.Refactorings.ExtractInterface; +using Rubberduck.VBEditor.ComManagement; +using Rubberduck.VBEditor.SafeComWrappers; +using Rubberduck.VBEditor.SourceCodeHandling; +using Rubberduck.VBEditor.Utility; + +namespace RubberduckTests.Refactoring +{ + [TestFixture] + public class ExtractInterfaceRefactoringActionTests : RefactoringActionTestBase + { + [Test] + [Category("Refactorings")] + [Category("Extract Interface")] + public void ExtractInterfaceRefactoring_ImplementProc() + { + const string inputCode = + @"Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub"; + const string expectedClassCode = + @"Implements IClass + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub + +Private Sub IClass_Foo(ByVal arg1 As Integer, ByVal arg2 As String) + Err.Raise 5 'TODO implement interface member +End Sub +"; + const string expectedInterfaceCode = + @"Option Explicit + +'@Interface + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub +"; + ExecuteTest(inputCode, expectedClassCode, expectedInterfaceCode, SelectAllMembers); + } + + [Test] + [Category("Refactorings")] + [Category("Extract Interface")] + public void ExtractInterfaceRefactoring_ImplementProcAndFuncAndPropGetSetLet() + { + //Input + const string inputCode = @" +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub + +Public Function Fizz(b) As Variant +End Function + +Public Property Get Buzz() +End Property + +Public Property Let Buzz(value) +End Property + +Public Property Set Buzz(value) +End Property"; + + //Expectation + const string expectedClassCode = @"Implements IClass + + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub + +Public Function Fizz(b) As Variant +End Function + +Public Property Get Buzz() +End Property + +Public Property Let Buzz(value) +End Property + +Public Property Set Buzz(value) +End Property + +Private Sub IClass_Foo(ByVal arg1 As Integer, ByVal arg2 As String) + Err.Raise 5 'TODO implement interface member +End Sub + +Private Function IClass_Fizz(ByRef b As Variant) As Variant + Err.Raise 5 'TODO implement interface member +End Function + +Private Property Get IClass_Buzz() As Variant + Err.Raise 5 'TODO implement interface member +End Property + +Private Property Let IClass_Buzz(ByRef value As Variant) + Err.Raise 5 'TODO implement interface member +End Property + +Private Property Set IClass_Buzz(ByRef value As Variant) + Err.Raise 5 'TODO implement interface member +End Property +"; + + const string expectedInterfaceCode = + @"Option Explicit + +'@Interface + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub + +Public Function Fizz(ByRef b As Variant) As Variant +End Function + +Public Property Get Buzz() As Variant +End Property + +Public Property Let Buzz(ByRef value As Variant) +End Property + +Public Property Set Buzz(ByRef value As Variant) +End Property +"; + ExecuteTest(inputCode, expectedClassCode, expectedInterfaceCode, SelectAllMembers); + } + + [Test] + [Category("Refactorings")] + [Category("Extract Interface")] + public void ExtractInterfaceRefactoring_ImplementProcAndFunc_IgnoreProperties() + { + //Input + const string inputCode = + @"Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub + +Public Function Fizz(b) As Variant +End Function + +Public Property Get Buzz() +End Property + +Public Property Let Buzz(value) +End Property + +Public Property Set Buzz(value) +End Property"; + + //Expectation + const string expectedClassCode = + @"Implements IClass + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub + +Public Function Fizz(b) As Variant +End Function + +Public Property Get Buzz() +End Property + +Public Property Let Buzz(value) +End Property + +Public Property Set Buzz(value) +End Property + +Private Sub IClass_Foo(ByVal arg1 As Integer, ByVal arg2 As String) + Err.Raise 5 'TODO implement interface member +End Sub + +Private Function IClass_Fizz(ByRef b As Variant) As Variant + Err.Raise 5 'TODO implement interface member +End Function +"; + + const string expectedInterfaceCode = + @"Option Explicit + +'@Interface + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub + +Public Function Fizz(ByRef b As Variant) As Variant +End Function +"; + var modelAdjustment = SelectFilteredMembers(member => !member.FullMemberSignature.Contains("Property")); + ExecuteTest(inputCode, expectedClassCode, expectedInterfaceCode, modelAdjustment); + } + + [Test] + [Category("Refactorings")] + [Category("Extract Interface")] + public void ExtractInterfaceRefactoring_BelowLastImplementStatement() + { + //Input + const string inputCode = + @" + +Option Explicit + +Implements Interface1 + + +Implements Interface2 + + + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub"; + + //Expectation + const string expectedClassCode = + @" + +Option Explicit + +Implements Interface1 + + +Implements Interface2 +Implements IClass + + + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub + +Private Sub IClass_Foo(ByVal arg1 As Integer, ByVal arg2 As String) + Err.Raise 5 'TODO implement interface member +End Sub +"; + + const string expectedInterfaceCode = + @"Option Explicit + +'@Interface + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub +"; + ExecuteTest(inputCode, expectedClassCode, expectedInterfaceCode, SelectAllMembers); + } + + [Test] + [Category("Refactorings")] + [Category("Extract Interface")] + public void ExtractInterfaceRefactoring_BelowLastOptionStatement() + { + //Input + const string inputCode = + @" + +Option Explicit + + + +Option Base 1 + + + + + +Private bar As Variant + + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub"; + + //Expectation + const string expectedClassCode = + @" + +Option Explicit + + + +Option Base 1 + +Implements IClass + + + + + +Private bar As Variant + + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub + +Private Sub IClass_Foo(ByVal arg1 As Integer, ByVal arg2 As String) + Err.Raise 5 'TODO implement interface member +End Sub +"; + + const string expectedInterfaceCode = + @"Option Explicit + +'@Interface + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub +"; + ExecuteTest(inputCode, expectedClassCode, expectedInterfaceCode, SelectAllMembers); + } + + [Test] + [Category("Refactorings")] + [Category("Extract Interface")] + public void ExtractInterfaceRefactoring_AtTopOfModule() + { + //Input + const string inputCode = + @" + + + + + + + + + + + +Private bar As Variant + + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub"; + + //Expectation + const string expectedClassCode = + @"Implements IClass + + + + + + + + + + + + + +Private bar As Variant + + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub + +Private Sub IClass_Foo(ByVal arg1 As Integer, ByVal arg2 As String) + Err.Raise 5 'TODO implement interface member +End Sub +"; + + const string expectedInterfaceCode = + @"Option Explicit + +'@Interface + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub +"; + ExecuteTest(inputCode, expectedClassCode, expectedInterfaceCode, SelectAllMembers); + } + + [Test] + [Category("Refactorings")] + [Category("Extract Interface")] + public void ExtractInterfaceRefactoring_PutsInterfaceInFolderOfClassItIsExtractedFrom() + { + //Input + const string inputCode = + @"'@Folder(""MyFolder.MySubFolder"") + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub"; + + //Expectation + const string expectedClassCode = + @"Implements IClass + +'@Folder(""MyFolder.MySubFolder"") + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub + +Private Sub IClass_Foo(ByVal arg1 As Integer, ByVal arg2 As String) + Err.Raise 5 'TODO implement interface member +End Sub +"; + + const string expectedInterfaceCode = + @"Option Explicit + +'@Folder(""MyFolder.MySubFolder"") +'@Interface + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub +"; + ExecuteTest(inputCode, expectedClassCode, expectedInterfaceCode, SelectAllMembers); + } + + private void ExecuteTest(string inputCode, string expectedClassCode, string expectedInterfaceCode, Func modelAdjustment) + { + var refactoredCode = RefactoredCode( + state => TestModel(state, modelAdjustment), + ("Class", inputCode, ComponentType.ClassModule)); + + Assert.AreEqual(expectedClassCode, refactoredCode["Class"]); + Assert.AreEqual(expectedInterfaceCode, refactoredCode["IClass"]); + } + + private static ExtractInterfaceModel SelectAllMembers(ExtractInterfaceModel model) + { + foreach (var interfaceMember in model.Members) + { + interfaceMember.IsSelected = true; + } + + return model; + } + + private static Func SelectFilteredMembers(Func filter) + { + return model => SelectFilteredMembers(model, filter); + } + + private static ExtractInterfaceModel SelectFilteredMembers(ExtractInterfaceModel model, Func filter) + { + foreach (var interfaceMember in model.Members.Where(filter)) + { + interfaceMember.IsSelected = true; + } + + return model; + } + + private static ExtractInterfaceModel TestModel(IDeclarationFinderProvider state, Func modelAdjustment) + { + var finder = state.DeclarationFinder; + var targetClass = finder.UserDeclarations(DeclarationType.ClassModule) + .OfType() + .Single(module => module.IdentifierName == "Class"); + var model = new ExtractInterfaceModel(state, targetClass); + return modelAdjustment(model); + } + + protected override IRefactoringAction TestBaseRefactoring(RubberduckParserState state, IRewritingManager rewritingManager) + { + var addInterfaceImplementationsAction = new AddInterfaceImplementationsRefactoringAction(rewritingManager); + var addComponentService = TestAddComponentService(state?.ProjectsProvider); + return new ExtractInterfaceRefactoringAction(addInterfaceImplementationsAction, state, state, rewritingManager, state?.ProjectsProvider, addComponentService); + } + + private static IAddComponentService TestAddComponentService(IProjectsProvider projectsProvider) + { + var sourceCodeHandler = new CodeModuleComponentSourceCodeHandler(); + return new AddComponentService(projectsProvider, sourceCodeHandler, sourceCodeHandler); + } + } +} \ No newline at end of file diff --git a/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceTests.cs b/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceTests.cs new file mode 100644 index 0000000000..1db7eeb3cd --- /dev/null +++ b/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceTests.cs @@ -0,0 +1,267 @@ +using System; +using System.Collections.ObjectModel; +using System.Linq; +using Moq; +using NUnit.Framework; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.UIContext; +using Rubberduck.Parsing.VBA; +using Rubberduck.Refactorings; +using Rubberduck.Refactorings.AddInterfaceImplementations; +using Rubberduck.Refactorings.Exceptions; +using Rubberduck.Refactorings.ExtractInterface; +using Rubberduck.VBEditor; +using Rubberduck.VBEditor.ComManagement; +using Rubberduck.VBEditor.SafeComWrappers; +using Rubberduck.VBEditor.SourceCodeHandling; +using Rubberduck.VBEditor.Utility; +using RubberduckTests.Mocks; + +namespace RubberduckTests.Refactoring +{ + [TestFixture] + public class ExtractInterfaceTests : InteractiveRefactoringTestBase + { + [Test] + [Category("Refactorings")] + [Category("Extract Interface")] + public void ExtractInterfaceRefactoring_ImplementProc() + { + //Input + const string inputCode = + @"Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub"; + var selection = new Selection(1, 23, 1, 27); + + //Expectation + const string expectedCode = + @"Implements IClass + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub + +Private Sub IClass_Foo(ByVal arg1 As Integer, ByVal arg2 As String) + Err.Raise 5 'TODO implement interface member +End Sub +"; + + const string expectedInterfaceCode = + @"Option Explicit + +'@Interface + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub +"; + Func presenterAction = model => + { + foreach (var interfaceMember in model.Members) + { + interfaceMember.IsSelected = true; + } + + return model; + }; + + var actualCode = RefactoredCode("Class", selection, presenterAction, null, false, ("Class", inputCode, ComponentType.ClassModule)); + Assert.AreEqual(expectedCode, actualCode["Class"]); + var actualInterfaceCode = actualCode[actualCode.Keys.Single(componentName => !componentName.Equals("Class"))]; + Assert.AreEqual(expectedInterfaceCode, actualInterfaceCode); + } + + [Test] + [Category("Refactorings")] + [Category("Extract Interface")] + public void ExtractInterfaceRefactoring_InvalidTargetType_Throws() + { + //Input + const string inputCode = + @"Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub"; + + Func presenterAction = model => + { + foreach (var interfaceMember in model.Members) + { + interfaceMember.IsSelected = true; + } + + return model; + }; + + var actualCode = RefactoredCode( + "Module", + DeclarationType.ProceduralModule, + presenterAction, + typeof(InvalidDeclarationTypeException), + ("Module", inputCode, ComponentType.StandardModule)); + Assert.AreEqual(inputCode, actualCode["Module"]); + } + + [Test] + [Category("Refactorings")] + [Category("Extract Interface")] + public void ExtractInterfaceRefactoring_NoValidTargetSelected_Throws() + { + //Input + const string inputCode = + @"Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub"; + var selection = new Selection(1, 23, 1, 27); + + Func presenterAction = model => + { + foreach (var interfaceMember in model.Members) + { + interfaceMember.IsSelected = true; + } + + return model; + }; + + var actualCode = RefactoredCode( + "Module", + selection, + presenterAction, + typeof(NoDeclarationForSelectionException), + false, + ("Module", inputCode, ComponentType.StandardModule)); + Assert.AreEqual(inputCode, actualCode["Module"]); + } + + [Test] + [Category("Refactorings")] + [Category("Extract Interface")] + public void ExtractInterfaceRefactoring_IgnoresField() + { + //Input + const string inputCode = + @"Public Fizz As Boolean"; + + var selection = new Selection(1, 23, 1, 27); + + var vbe = MockVbeBuilder.BuildFromSingleModule(inputCode, ComponentType.ClassModule, out _, selection); + using(var state = MockParser.CreateAndParse(vbe.Object)) + { + var target = state.DeclarationFinder.UserDeclarations(DeclarationType.ClassModule).First(); + + //Specify Params to remove + var model = new ExtractInterfaceModel(state, target); + Assert.AreEqual(0, model.Members.Count); + } + } + + [Test] + [Category("Refactorings")] + [Category("Extract Interface")] + public void ExtractInterfaceRefactoring_NullPresenter_NoChanges() + { + //Input + const string inputCode = + @"Private Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub"; + var selection = new Selection(1, 23, 1, 27); + + var vbe = MockVbeBuilder.BuildFromSingleModule(inputCode, ComponentType.ClassModule, out var component, selection); + var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe.Object); + using(state) + { + var qualifiedSelection = new QualifiedSelection(new QualifiedModuleName(component), selection); + + //SetupFactory + var factory = new Mock(); + factory.Setup(f => f.Create(It.IsAny())).Returns(value: null); + + var selectionService = MockedSelectionService(); + + var refactoring = TestRefactoring(rewritingManager, state, factory.Object, selectionService); + + Assert.Throws(() => refactoring.Refactor(qualifiedSelection)); + + Assert.AreEqual(1, vbe.Object.ActiveVBProject.VBComponents.Count()); + Assert.AreEqual(inputCode, component.CodeModule.Content()); + } + } + + [Test] + [Category("Refactorings")] + [Category("Extract Interface")] + public void ExtractInterfaceRefactoring_NullModel_NoChanges() + { + //Input + const string inputCode = + @"Private Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub"; + var selection = new Selection(1, 23, 1, 27); + + Func presenterAction = model => null; + + var actualCode = RefactoredCode("Class", selection, presenterAction, typeof(InvalidRefactoringModelException), false, ("Class", inputCode, ComponentType.ClassModule)); + Assert.AreEqual(inputCode, actualCode["Class"]); + Assert.AreEqual(1, actualCode.Count); + } + + [Test] + [Category("Refactorings")] + [Category("Extract Interface")] + public void ExtractInterfaceRefactoring_PassTargetIn() + { + //Input + const string inputCode = + @"Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub"; + + //Expectation + const string expectedCode = + @"Implements IClass + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub + +Private Sub IClass_Foo(ByVal arg1 As Integer, ByVal arg2 As String) + Err.Raise 5 'TODO implement interface member +End Sub +"; + + const string expectedInterfaceCode = + @"Option Explicit + +'@Interface + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub +"; + Func presenterAction = model => + { + model.Members.ElementAt(0).IsSelected = true; + model.Members = new ObservableCollection(new[] { model.Members.ElementAt(0) }.ToList()); + + return model; + }; + + var actualCode = RefactoredCode("Class", DeclarationType.ClassModule, presenterAction, null, ("Class", inputCode, ComponentType.ClassModule)); + Assert.AreEqual(expectedCode, actualCode["Class"]); + var actualInterfaceCode = actualCode[actualCode.Keys.Single(componentName => !componentName.Equals("Class"))]; + Assert.AreEqual(expectedInterfaceCode, actualInterfaceCode); + } + + protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) + { + var uiDispatcherMock = new Mock(); + uiDispatcherMock + .Setup(m => m.Invoke(It.IsAny())) + .Callback((Action action) => action.Invoke()); + var addImplementationsBaseRefactoring = new AddInterfaceImplementationsRefactoringAction(rewritingManager); + var addComponentService = TestAddComponentService(state?.ProjectsProvider); + var baseRefactoring = new ExtractInterfaceRefactoringAction(addImplementationsBaseRefactoring, state, state, rewritingManager, state?.ProjectsProvider, addComponentService); + return new ExtractInterfaceRefactoring(baseRefactoring, state, factory, selectionService, uiDispatcherMock.Object); + } + + private static IAddComponentService TestAddComponentService(IProjectsProvider projectsProvider) + { + var sourceCodeHandler = new CodeModuleComponentSourceCodeHandler(); + return new AddComponentService(projectsProvider, sourceCodeHandler, sourceCodeHandler); + } + } +} \ No newline at end of file diff --git a/RubberduckTests/Refactoring/ExtractInterfaceTests.cs b/RubberduckTests/Refactoring/ExtractInterfaceTests.cs deleted file mode 100644 index e731db027d..0000000000 --- a/RubberduckTests/Refactoring/ExtractInterfaceTests.cs +++ /dev/null @@ -1,725 +0,0 @@ -using System; -using System.Collections.ObjectModel; -using System.Linq; -using Moq; -using NUnit.Framework; -using Rubberduck.Parsing.Rewriter; -using Rubberduck.Parsing.Symbols; -using Rubberduck.Parsing.UIContext; -using Rubberduck.Parsing.VBA; -using Rubberduck.Refactorings; -using Rubberduck.Refactorings.AddInterfaceImplementations; -using Rubberduck.Refactorings.Exceptions; -using Rubberduck.Refactorings.ExtractInterface; -using Rubberduck.VBEditor; -using Rubberduck.VBEditor.ComManagement; -using Rubberduck.VBEditor.SafeComWrappers; -using Rubberduck.VBEditor.SourceCodeHandling; -using Rubberduck.VBEditor.Utility; -using RubberduckTests.Mocks; - -namespace RubberduckTests.Refactoring -{ - [TestFixture] - public class ExtractInterfaceTests : InteractiveRefactoringTestBase - { - [Test] - [Category("Refactorings")] - [Category("Extract Interface")] - public void ExtractInterfaceRefactoring_ImplementProc() - { - //Input - const string inputCode = - @"Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub"; - var selection = new Selection(1, 23, 1, 27); - - //Expectation - const string expectedCode = - @"Implements IClass - -Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub - -Private Sub IClass_Foo(ByVal arg1 As Integer, ByVal arg2 As String) - Err.Raise 5 'TODO implement interface member -End Sub -"; - - const string expectedInterfaceCode = - @"Option Explicit - -'@Interface - -Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub -"; - Func presenterAction = model => - { - foreach (var interfaceMember in model.Members) - { - interfaceMember.IsSelected = true; - } - - return model; - }; - - var actualCode = RefactoredCode("Class", selection, presenterAction, null, false, ("Class", inputCode, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class"]); - var actualInterfaceCode = actualCode[actualCode.Keys.Single(componentName => !componentName.Equals("Class"))]; - Assert.AreEqual(expectedInterfaceCode, actualInterfaceCode); - } - - [Test] - [Category("Refactorings")] - [Category("Extract Interface")] - public void ExtractInterfaceRefactoring_InvalidTargetType_Throws() - { - //Input - const string inputCode = - @"Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub"; - - Func presenterAction = model => - { - foreach (var interfaceMember in model.Members) - { - interfaceMember.IsSelected = true; - } - - return model; - }; - - var actualCode = RefactoredCode( - "Module", - DeclarationType.ProceduralModule, - presenterAction, - typeof(InvalidDeclarationTypeException), - ("Module", inputCode, ComponentType.StandardModule)); - Assert.AreEqual(inputCode, actualCode["Module"]); - } - - [Test] - [Category("Refactorings")] - [Category("Extract Interface")] - public void ExtractInterfaceRefactoring_NoValidTargetSelected_Throws() - { - //Input - const string inputCode = - @"Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub"; - var selection = new Selection(1, 23, 1, 27); - - Func presenterAction = model => - { - foreach (var interfaceMember in model.Members) - { - interfaceMember.IsSelected = true; - } - - return model; - }; - - var actualCode = RefactoredCode( - "Module", - selection, - presenterAction, - typeof(NoDeclarationForSelectionException), - false, - ("Module", inputCode, ComponentType.StandardModule)); - Assert.AreEqual(inputCode, actualCode["Module"]); - } - - [Test] - [Category("Refactorings")] - [Category("Extract Interface")] - public void ExtractInterfaceRefactoring_ImplementProcAndFuncAndPropGetSetLet() - { - //Input - const string inputCode = @" -Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub - -Public Function Fizz(b) As Variant -End Function - -Public Property Get Buzz() -End Property - -Public Property Let Buzz(value) -End Property - -Public Property Set Buzz(value) -End Property"; - - var selection = new Selection(1, 23, 1, 27); - - //Expectation - const string expectedCode = @"Implements IClass - - -Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub - -Public Function Fizz(b) As Variant -End Function - -Public Property Get Buzz() -End Property - -Public Property Let Buzz(value) -End Property - -Public Property Set Buzz(value) -End Property - -Private Sub IClass_Foo(ByVal arg1 As Integer, ByVal arg2 As String) - Err.Raise 5 'TODO implement interface member -End Sub - -Private Function IClass_Fizz(ByRef b As Variant) As Variant - Err.Raise 5 'TODO implement interface member -End Function - -Private Property Get IClass_Buzz() As Variant - Err.Raise 5 'TODO implement interface member -End Property - -Private Property Let IClass_Buzz(ByRef value As Variant) - Err.Raise 5 'TODO implement interface member -End Property - -Private Property Set IClass_Buzz(ByRef value As Variant) - Err.Raise 5 'TODO implement interface member -End Property -"; - - const string expectedInterfaceCode = - @"Option Explicit - -'@Interface - -Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub - -Public Function Fizz(ByRef b As Variant) As Variant -End Function - -Public Property Get Buzz() As Variant -End Property - -Public Property Let Buzz(ByRef value As Variant) -End Property - -Public Property Set Buzz(ByRef value As Variant) -End Property -"; - Func presenterAction = model => - { - foreach (var interfaceMember in model.Members) - { - interfaceMember.IsSelected = true; - } - - return model; - }; - - var actualCode = RefactoredCode("Class", selection, presenterAction, null, false, ("Class", inputCode, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class"]); - var actualInterfaceCode = actualCode[actualCode.Keys.Single(componentName => !componentName.Equals("Class"))]; - Assert.AreEqual(expectedInterfaceCode, actualInterfaceCode); - } - - [Test] - [Category("Refactorings")] - [Category("Extract Interface")] - public void ExtractInterfaceRefactoring_ImplementProcAndFunc_IgnoreProperties() - { - //Input - const string inputCode = - @"Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub - -Public Function Fizz(b) As Variant -End Function - -Public Property Get Buzz() -End Property - -Public Property Let Buzz(value) -End Property - -Public Property Set Buzz(value) -End Property"; - - var selection = new Selection(1, 23, 1, 27); - - //Expectation - const string expectedCode = - @"Implements IClass - -Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub - -Public Function Fizz(b) As Variant -End Function - -Public Property Get Buzz() -End Property - -Public Property Let Buzz(value) -End Property - -Public Property Set Buzz(value) -End Property - -Private Sub IClass_Foo(ByVal arg1 As Integer, ByVal arg2 As String) - Err.Raise 5 'TODO implement interface member -End Sub - -Private Function IClass_Fizz(ByRef b As Variant) As Variant - Err.Raise 5 'TODO implement interface member -End Function -"; - - const string expectedInterfaceCode = - @"Option Explicit - -'@Interface - -Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub - -Public Function Fizz(ByRef b As Variant) As Variant -End Function -"; - Func presenterAction = model => - { - foreach (var interfaceMember in model.Members.Where(member => !member.FullMemberSignature.Contains("Property"))) - { - interfaceMember.IsSelected = true; - } - - return model; - }; - - var actualCode = RefactoredCode("Class", selection, presenterAction, null, false, ("Class", inputCode, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class"]); - var actualInterfaceCode = actualCode[actualCode.Keys.Single(componentName => !componentName.Equals("Class"))]; - Assert.AreEqual(expectedInterfaceCode, actualInterfaceCode); - } - - [Test] - [Category("Refactorings")] - [Category("Extract Interface")] - public void ExtractInterfaceRefactoring_IgnoresField() - { - //Input - const string inputCode = - @"Public Fizz As Boolean"; - - var selection = new Selection(1, 23, 1, 27); - - var vbe = MockVbeBuilder.BuildFromSingleModule(inputCode, ComponentType.ClassModule, out _, selection); - using(var state = MockParser.CreateAndParse(vbe.Object)) - { - var target = state.DeclarationFinder.UserDeclarations(DeclarationType.ClassModule).First(); - - //Specify Params to remove - var model = new ExtractInterfaceModel(state, target); - Assert.AreEqual(0, model.Members.Count); - } - } - - [Test] - [Category("Refactorings")] - [Category("Extract Interface")] - public void ExtractInterfaceRefactoring_NullPresenter_NoChanges() - { - //Input - const string inputCode = - @"Private Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub"; - var selection = new Selection(1, 23, 1, 27); - - var vbe = MockVbeBuilder.BuildFromSingleModule(inputCode, ComponentType.ClassModule, out var component, selection); - var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(vbe.Object); - using(state) - { - var qualifiedSelection = new QualifiedSelection(new QualifiedModuleName(component), selection); - - //SetupFactory - var factory = new Mock(); - factory.Setup(f => f.Create(It.IsAny())).Returns(value: null); - - var selectionService = MockedSelectionService(); - - var refactoring = TestRefactoring(rewritingManager, state, factory.Object, selectionService); - - Assert.Throws(() => refactoring.Refactor(qualifiedSelection)); - - Assert.AreEqual(1, vbe.Object.ActiveVBProject.VBComponents.Count()); - Assert.AreEqual(inputCode, component.CodeModule.Content()); - } - } - - [Test] - [Category("Refactorings")] - [Category("Extract Interface")] - public void ExtractInterfaceRefactoring_NullModel_NoChanges() - { - //Input - const string inputCode = - @"Private Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub"; - var selection = new Selection(1, 23, 1, 27); - - Func presenterAction = model => null; - - var actualCode = RefactoredCode("Class", selection, presenterAction, typeof(InvalidRefactoringModelException), false, ("Class", inputCode, ComponentType.ClassModule)); - Assert.AreEqual(inputCode, actualCode["Class"]); - Assert.AreEqual(1, actualCode.Count); - } - - [Test] - [Category("Refactorings")] - [Category("Extract Interface")] - public void ExtractInterfaceRefactoring_PassTargetIn() - { - //Input - const string inputCode = - @"Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub"; - - //Expectation - const string expectedCode = - @"Implements IClass - -Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub - -Private Sub IClass_Foo(ByVal arg1 As Integer, ByVal arg2 As String) - Err.Raise 5 'TODO implement interface member -End Sub -"; - - const string expectedInterfaceCode = - @"Option Explicit - -'@Interface - -Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub -"; - Func presenterAction = model => - { - model.Members.ElementAt(0).IsSelected = true; - model.Members = new ObservableCollection(new[] { model.Members.ElementAt(0) }.ToList()); - - return model; - }; - - var actualCode = RefactoredCode("Class", DeclarationType.ClassModule, presenterAction, null, ("Class", inputCode, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class"]); - var actualInterfaceCode = actualCode[actualCode.Keys.Single(componentName => !componentName.Equals("Class"))]; - Assert.AreEqual(expectedInterfaceCode, actualInterfaceCode); - } - - [Test] - [Category("Refactorings")] - [Category("Extract Interface")] - public void ExtractInterfaceRefactoring_BelowLastImplementStatement() - { - //Input - const string inputCode = - @" - -Option Explicit - -Implements Interface1 - - -Implements Interface2 - - - -Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub"; - var selection = new Selection(1, 23, 1, 27); - - //Expectation - const string expectedCode = - @" - -Option Explicit - -Implements Interface1 - - -Implements Interface2 -Implements IClass - - - -Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub - -Private Sub IClass_Foo(ByVal arg1 As Integer, ByVal arg2 As String) - Err.Raise 5 'TODO implement interface member -End Sub -"; - - const string expectedInterfaceCode = - @"Option Explicit - -'@Interface - -Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub -"; - Func presenterAction = model => - { - foreach (var interfaceMember in model.Members) - { - interfaceMember.IsSelected = true; - } - - return model; - }; - - var actualCode = RefactoredCode("Class", selection, presenterAction, null, false, - ("Class", inputCode, ComponentType.ClassModule), - ("Interface1", string.Empty, ComponentType.ClassModule), - ("Interface2", string.Empty, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class"]); - var actualInterfaceCode = actualCode[actualCode.Keys.Single(componentName => !new[]{"Class", "Interface1", "Interface2"}.Contains(componentName))]; - Assert.AreEqual(expectedInterfaceCode, actualInterfaceCode); - } - - [Test] - [Category("Refactorings")] - [Category("Extract Interface")] - public void ExtractInterfaceRefactoring_BelowLastOptionStatement() - { - //Input - const string inputCode = - @" - -Option Explicit - - - -Option Base 1 - - - - - -Private bar As Variant - - -Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub"; - var selection = new Selection(1, 23, 1, 27); - - //Expectation - const string expectedCode = - @" - -Option Explicit - - - -Option Base 1 - -Implements IClass - - - - - -Private bar As Variant - - -Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub - -Private Sub IClass_Foo(ByVal arg1 As Integer, ByVal arg2 As String) - Err.Raise 5 'TODO implement interface member -End Sub -"; - - const string expectedInterfaceCode = - @"Option Explicit - -'@Interface - -Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub -"; - Func presenterAction = model => - { - foreach (var interfaceMember in model.Members) - { - interfaceMember.IsSelected = true; - } - - return model; - }; - - var actualCode = RefactoredCode("Class", selection, presenterAction, null, false, - ("Class", inputCode, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class"]); - var actualInterfaceCode = actualCode[actualCode.Keys.Single(componentName => !componentName.Equals("Class"))]; - Assert.AreEqual(expectedInterfaceCode, actualInterfaceCode); - } - - [Test] - [Category("Refactorings")] - [Category("Extract Interface")] - public void ExtractInterfaceRefactoring_AtTopOfModule() - { - //Input - const string inputCode = - @" - - - - - - - - - - - -Private bar As Variant - - -Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub"; - var selection = new Selection(1, 23, 1, 27); - - //Expectation - const string expectedCode = - @"Implements IClass - - - - - - - - - - - - - -Private bar As Variant - - -Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub - -Private Sub IClass_Foo(ByVal arg1 As Integer, ByVal arg2 As String) - Err.Raise 5 'TODO implement interface member -End Sub -"; - - const string expectedInterfaceCode = - @"Option Explicit - -'@Interface - -Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub -"; - Func presenterAction = model => - { - foreach (var interfaceMember in model.Members) - { - interfaceMember.IsSelected = true; - } - - return model; - }; - - var actualCode = RefactoredCode("Class", selection, presenterAction, null, false, - ("Class", inputCode, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class"]); - var actualInterfaceCode = actualCode[actualCode.Keys.Single(componentName => !componentName.Equals("Class"))]; - Assert.AreEqual(expectedInterfaceCode, actualInterfaceCode); - } - - [Test] - [Category("Refactorings")] - [Category("Extract Interface")] - public void ExtractInterfaceRefactoring_PutsInterfaceInFolderOfClassItIsExtractedFrom() - { - //Input - const string inputCode = - @"'@Folder(""MyFolder.MySubFolder"") - -Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub"; - var selection = new Selection(1, 23, 1, 27); - - //Expectation - const string expectedCode = - @"Implements IClass - -'@Folder(""MyFolder.MySubFolder"") - -Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub - -Private Sub IClass_Foo(ByVal arg1 As Integer, ByVal arg2 As String) - Err.Raise 5 'TODO implement interface member -End Sub -"; - - const string expectedInterfaceCode = - @"Option Explicit - -'@Folder(""MyFolder.MySubFolder"") -'@Interface - -Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub -"; - Func presenterAction = model => - { - foreach (var interfaceMember in model.Members) - { - interfaceMember.IsSelected = true; - } - - return model; - }; - - var actualCode = RefactoredCode("Class", selection, presenterAction, null, false, ("Class", inputCode, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class"]); - var actualInterfaceCode = actualCode[actualCode.Keys.Single(componentName => !componentName.Equals("Class"))]; - Assert.AreEqual(expectedInterfaceCode, actualInterfaceCode); - } - - protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, IRefactoringPresenterFactory factory, ISelectionService selectionService) - { - var uiDispatcherMock = new Mock(); - uiDispatcherMock - .Setup(m => m.Invoke(It.IsAny())) - .Callback((Action action) => action.Invoke()); - var addImplementationsBaseRefactoring = new AddInterfaceImplementationsRefactoringAction(rewritingManager); - var addComponentService = TestAddComponentService(state?.ProjectsProvider); - var baseRefactoring = new ExtractInterfaceRefactoringAction(addImplementationsBaseRefactoring, state, state, rewritingManager, state?.ProjectsProvider, addComponentService); - return new ExtractInterfaceRefactoring(baseRefactoring, state, factory, selectionService, uiDispatcherMock.Object); - } - - private static IAddComponentService TestAddComponentService(IProjectsProvider projectsProvider) - { - var sourceCodeHandler = new CodeModuleComponentSourceCodeHandler(); - return new AddComponentService(projectsProvider, sourceCodeHandler, sourceCodeHandler); - } - } -} \ No newline at end of file diff --git a/RubberduckTests/Refactoring/ImplementInterface/ImplementInterfaceRefactoringActionTests.cs b/RubberduckTests/Refactoring/ImplementInterface/ImplementInterfaceRefactoringActionTests.cs new file mode 100644 index 0000000000..750a11a3ec --- /dev/null +++ b/RubberduckTests/Refactoring/ImplementInterface/ImplementInterfaceRefactoringActionTests.cs @@ -0,0 +1,585 @@ +using System; +using System.Linq; +using NUnit.Framework; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.Refactorings; +using Rubberduck.Refactorings.AddInterfaceImplementations; +using Rubberduck.Refactorings.ImplementInterface; +using Rubberduck.VBEditor.SafeComWrappers; + +namespace RubberduckTests.Refactoring +{ + [TestFixture] + public class ImplementInterfaceRefactoringActionTests : RefactoringActionTestBase + { + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_Procedure() + { + //Input + const string interfaceCode = + @"Public Sub Foo() +End Sub"; + + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Sub Interface1_Foo() + Err.Raise 5 'TODO implement interface member +End Sub +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_Procedure_ClassHasOtherProcedure() + { + //Input + const string interfaceCode = + @"Public Sub Foo() +End Sub"; + + const string classCode = + @"Implements Interface1 + +Public Sub Bar() +End Sub"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Public Sub Bar() +End Sub + +Private Sub Interface1_Foo() + Err.Raise 5 'TODO implement interface member +End Sub +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_PartiallyImplementedInterface() + { + //Input + const string interfaceCode = + @"Public Property Get a() As String +End Property +Public Property Let a(RHS As String) +End Property +Public Property Get b() As String +End Property +Public Property Let b(RHS As String) +End Property"; + + const string classCode = + @"Implements Interface1 + +Private Property Let Interface1_b(RHS As String) +End Property"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Property Let Interface1_b(RHS As String) +End Property + +Private Property Get Interface1_a() As String + Err.Raise 5 'TODO implement interface member +End Property + +Private Property Let Interface1_a(ByRef RHS As String) + Err.Raise 5 'TODO implement interface member +End Property + +Private Property Get Interface1_b() As String + Err.Raise 5 'TODO implement interface member +End Property +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_Procedure_WithParams() + { + //Input + const string interfaceCode = + @"Public Sub Foo(ByVal a As Integer, ByRef b, c, d As Long) +End Sub"; + + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Sub Interface1_Foo(ByVal a As Integer, ByRef b As Variant, ByRef c As Variant, ByRef d As Long) + Err.Raise 5 'TODO implement interface member +End Sub +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_Function() + { + //Input + const string interfaceCode = + @"Public Function Foo() As Integer +End Function"; + + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Function Interface1_Foo() As Integer + Err.Raise 5 'TODO implement interface member +End Function +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_Function_WithImplicitType() + { + //Input + const string interfaceCode = + @"Public Function Foo() +End Function"; + + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Function Interface1_Foo() As Variant + Err.Raise 5 'TODO implement interface member +End Function +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_Function_WithParam() + { + //Input + const string interfaceCode = + @"Public Function Foo(a) +End Function"; + + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Function Interface1_Foo(ByRef a As Variant) As Variant + Err.Raise 5 'TODO implement interface member +End Function +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_PropertyGet() + { + //Input + const string interfaceCode = + @"Public Property Get Foo() As Integer +End Property"; + + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Property Get Interface1_Foo() As Integer + Err.Raise 5 'TODO implement interface member +End Property +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_PropertyGet_WithImplicitType() + { + //Input + const string interfaceCode = + @"Public Property Get Foo() +End Property"; + + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Property Get Interface1_Foo() As Variant + Err.Raise 5 'TODO implement interface member +End Property +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_PropertyGet_WithParam() + { + //Input + const string interfaceCode = + @"Public Property Get Foo(a) +End Property"; + + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Property Get Interface1_Foo(ByRef a As Variant) As Variant + Err.Raise 5 'TODO implement interface member +End Property +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_PropertyLet() + { + //Input + const string interfaceCode = + @"Public Property Let Foo(ByRef value As Long) +End Property"; + + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Property Let Interface1_Foo(ByRef value As Long) + Err.Raise 5 'TODO implement interface member +End Property +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_PropertyLet_WithParam() + { + //Input + const string interfaceCode = + @"Public Property Let Foo(a) +End Property"; + + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Property Let Interface1_Foo(ByRef a As Variant) + Err.Raise 5 'TODO implement interface member +End Property +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_PropertySet() + { + //Input + const string interfaceCode = + @"Public Property Set Foo(ByRef value As Variant) +End Property"; + + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Property Set Interface1_Foo(ByRef value As Variant) + Err.Raise 5 'TODO implement interface member +End Property +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_PropertySet_WithParam() + { + //Input + const string interfaceCode = + @"Public Property Set Foo(a) +End Property"; + + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Property Set Interface1_Foo(ByRef a As Variant) + Err.Raise 5 'TODO implement interface member +End Property +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_PropertySet_AllTypes() + { + //Input + const string interfaceCode = + @"Public Sub Foo() +End Sub + +Public Function Bar(ByVal a As Integer) As Boolean +End Function + +Public Property Get Buz(ByVal a As Boolean) As Integer +End Property + +Public Property Let Buz(ByVal a As Boolean, ByRef value As Integer) +End Property"; + + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Sub Interface1_Foo() + Err.Raise 5 'TODO implement interface member +End Sub + +Private Function Interface1_Bar(ByVal a As Integer) As Boolean + Err.Raise 5 'TODO implement interface member +End Function + +Private Property Get Interface1_Buz(ByVal a As Boolean) As Integer + Err.Raise 5 'TODO implement interface member +End Property + +Private Property Let Interface1_Buz(ByVal a As Boolean, ByRef value As Integer) + Err.Raise 5 'TODO implement interface member +End Property +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void CreatesMethodStubForAllProcedureKinds() + { + //Input + const string interfaceCode = + @"Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub + +Public Function Fizz(b) +End Function + +Public Property Get Buzz() As Variant +End Property + +Public Property Let Buzz(value) +End Property + +Public Property Set Buzz(value) +End Property"; + + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Sub Interface1_Foo(ByVal arg1 As Integer, ByVal arg2 As String) + Err.Raise 5 'TODO implement interface member +End Sub + +Private Function Interface1_Fizz(ByRef b As Variant) As Variant + Err.Raise 5 'TODO implement interface member +End Function + +Private Property Get Interface1_Buzz() As Variant + Err.Raise 5 'TODO implement interface member +End Property + +Private Property Let Interface1_Buzz(ByRef value As Variant) + Err.Raise 5 'TODO implement interface member +End Property + +Private Property Set Interface1_Buzz(ByRef value As Variant) + Err.Raise 5 'TODO implement interface member +End Property +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [TestCase(@"Public Foo As Long")] + [TestCase(@"Dim Foo As Long")] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_PublicIntrinsic(string interfaceCode) + { + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Property Get Interface1_Foo() As Long + Err.Raise 5 'TODO implement interface member +End Property + +Private Property Let Interface1_Foo(ByVal rhs As Long) + Err.Raise 5 'TODO implement interface member +End Property +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [TestCase(@"Public Foo As Object")] + [TestCase(@"Dim Foo As Object")] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_PublicObject(string interfaceCode) + { + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Property Get Interface1_Foo() As Object + Err.Raise 5 'TODO implement interface member +End Property + +Private Property Set Interface1_Foo(ByVal rhs As Object) + Err.Raise 5 'TODO implement interface member +End Property +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [TestCase(@"Public Foo As Variant")] + [TestCase(@"Public Foo")] + [TestCase(@"Dim Foo As Variant")] + [TestCase(@"Dim Foo")] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_PublicVariant(string interfaceCode) + { + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Property Get Interface1_Foo() As Variant + Err.Raise 5 'TODO implement interface member +End Property + +Private Property Let Interface1_Foo(ByVal rhs As Variant) + Err.Raise 5 'TODO implement interface member +End Property + +Private Property Set Interface1_Foo(ByVal rhs As Variant) + Err.Raise 5 'TODO implement interface member +End Property +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + private void ExecuteTest(string classCode, string interfaceCode, string expectedClassCode) + { + var refactoredCode = RefactoredCode( + TestModel, + ("Class1", classCode,ComponentType.ClassModule), + ("Interface1", interfaceCode, ComponentType.ClassModule)); + + Assert.AreEqual(expectedClassCode, refactoredCode["Class1"]); + } + + private static ImplementInterfaceModel TestModel(RubberduckParserState state) + { + var finder = state.DeclarationFinder; + var targetInterface = finder.UserDeclarations(DeclarationType.ClassModule) + .OfType() + .Single(module => module.IdentifierName == "Interface1"); + var targetClass = finder.UserDeclarations(DeclarationType.ClassModule) + .OfType() + .Single(module => module.IdentifierName == "Class1"); + return new ImplementInterfaceModel(targetInterface, targetClass); + } + + protected override IRefactoringAction TestBaseRefactoring(RubberduckParserState state, IRewritingManager rewritingManager) + { + var addInterfaceImplementationsAction = new AddInterfaceImplementationsRefactoringAction(rewritingManager); + return new ImplementInterfaceRefactoringAction(addInterfaceImplementationsAction, rewritingManager); + } + } +} \ No newline at end of file diff --git a/RubberduckTests/Refactoring/ImplementInterface/ImplementInterfaceTests.cs b/RubberduckTests/Refactoring/ImplementInterface/ImplementInterfaceTests.cs new file mode 100644 index 0000000000..01c271821c --- /dev/null +++ b/RubberduckTests/Refactoring/ImplementInterface/ImplementInterfaceTests.cs @@ -0,0 +1,226 @@ +using System; +using System.Linq; +using NUnit.Framework; +using Rubberduck.Parsing.Rewriter; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.Refactorings; +using Rubberduck.Refactorings.AddInterfaceImplementations; +using Rubberduck.Refactorings.Exceptions.ImplementInterface; +using Rubberduck.Refactorings.ImplementInterface; +using Rubberduck.VBEditor; +using Rubberduck.VBEditor.SafeComWrappers; +using Rubberduck.VBEditor.Utility; +using RubberduckTests.Mocks; + +namespace RubberduckTests.Refactoring +{ + [TestFixture] + public class ImplementInterfaceTests : RefactoringTestBase + { + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public override void TargetNull_Throws() + { + var testVbe = TestVbe(string.Empty, out _); + var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(testVbe); + using (state) + { + var refactoring = TestRefactoring(rewritingManager, state); + Assert.Throws(() => refactoring.Refactor((Declaration)null)); + } + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void DoesNotSupportCallingWithADeclaration() + { + var testVbe = TestVbe(("testClass", string.Empty, ComponentType.ClassModule)); + var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(testVbe); + using (state) + { + var target = state.DeclarationFinder.UserDeclarations(DeclarationType.ClassModule).Single(); + var refactoring = TestRefactoring(rewritingManager, state); + Assert.Throws(() => refactoring.Refactor(target)); + } + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_SelectionOnImplementsStatement() + { + //Input + const string inputCode1 = + @"Public Sub Foo() +End Sub"; + + const string inputCode2 = + @"Implements Class1"; + + var selection = Selection.Home; + + //Expectation + const string expectedCode = + @"Implements Class1 + +Private Sub Class1_Foo() + Err.Raise 5 'TODO implement interface member +End Sub +"; + + var actualCode = RefactoredCode( + "Class2", + selection, + null, + false, + ("Class1", inputCode1, ComponentType.ClassModule), + ("Class2", inputCode2, ComponentType.ClassModule)); + Assert.AreEqual(expectedCode, actualCode["Class2"]); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void DoesNotImplementInterface_SelectionNotOnImplementsStatement() + { + //Input + const string inputCode1 = + @"Public Sub Foo() +End Sub"; + + const string inputCode2 = + @"Implements Class1 + +"; + var selection = new Selection(2, 2); + + //Expectation + const string expectedCode = + @"Implements Class1 + +"; + + var actualCode = RefactoredCode( + "Class2", + selection, + typeof(NoImplementsStatementSelectedException), + false, + ("Class1", inputCode1, ComponentType.ClassModule), + ("Class2", inputCode2, ComponentType.ClassModule)); + Assert.AreEqual(expectedCode, actualCode["Class2"]); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementsInterfaceInDocumentModule() + { + const string interfaceCode = @"Option Explicit +Public Sub DoSomething() +End Sub +"; + const string initialCode = @"Implements IInterface"; + + var selection = Selection.Home; + + const string expectedCode = @"Implements IInterface + +Private Sub IInterface_DoSomething() + Err.Raise 5 'TODO implement interface member +End Sub +"; + + var actualCode = RefactoredCode( + "Sheet1", + selection, + null, + false, + ("IInterface", interfaceCode, ComponentType.ClassModule), + ("Sheet1", initialCode, ComponentType.Document)); + Assert.AreEqual(expectedCode, actualCode["Sheet1"]); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementsInterfaceInUserFormModule() + { + const string interfaceCode = @"Option Explicit +Public Sub DoSomething() +End Sub +"; + const string initialCode = @"Implements IInterface"; + + var selection = Selection.Home; + + const string expectedCode = @"Implements IInterface + +Private Sub IInterface_DoSomething() + Err.Raise 5 'TODO implement interface member +End Sub +"; + + var actualCode = RefactoredCode( + "Form1", + selection, + null, + false, + ("IInterface", interfaceCode, ComponentType.ClassModule), + ("Form1", initialCode, ComponentType.UserForm)); + Assert.AreEqual(expectedCode, actualCode["Form1"]); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementsCorrectInterface_MultipleInterfaces() + { + //Input + const string inputCode1 = + @"Public Sub Foo() +End Sub"; + + const string inputCode2 = + @"Implements Class1 +Implements Class3"; + + var selection = new Selection(1, 1); + + const string inputCode3 = + @"Public Sub Foo() +End Sub"; + + //Expectation + const string expectedCode = + @"Implements Class1 +Implements Class3 + +Private Sub Class1_Foo() + Err.Raise 5 'TODO implement interface member +End Sub +"; + + var actualCode = RefactoredCode( + "Class2", + selection, + null, + false, + ("Class1", inputCode1, ComponentType.ClassModule), + ("Class2", inputCode2, ComponentType.ClassModule), + ("Class3", inputCode3, ComponentType.ClassModule)); + Assert.AreEqual(expectedCode, actualCode["Class2"]); + } + + protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, + ISelectionService selectionService) + { + var addImplementationsBaseRefactoring = new AddInterfaceImplementationsRefactoringAction(rewritingManager); + var baseRefactoring = new ImplementInterfaceRefactoringAction(addImplementationsBaseRefactoring, rewritingManager); + return new ImplementInterfaceRefactoring(baseRefactoring, state, selectionService); + } + } +} + diff --git a/RubberduckTests/Refactoring/ImplementInterfaceTests.cs b/RubberduckTests/Refactoring/ImplementInterfaceTests.cs deleted file mode 100644 index f7ed1f7433..0000000000 --- a/RubberduckTests/Refactoring/ImplementInterfaceTests.cs +++ /dev/null @@ -1,920 +0,0 @@ -using System; -using System.Linq; -using NUnit.Framework; -using Rubberduck.Parsing.Rewriter; -using Rubberduck.Parsing.Symbols; -using Rubberduck.Parsing.VBA; -using Rubberduck.Refactorings; -using Rubberduck.Refactorings.AddInterfaceImplementations; -using Rubberduck.Refactorings.Exceptions; -using Rubberduck.Refactorings.Exceptions.ImplementInterface; -using Rubberduck.Refactorings.ImplementInterface; -using Rubberduck.VBEditor; -using Rubberduck.VBEditor.SafeComWrappers; -using Rubberduck.VBEditor.Utility; -using RubberduckTests.Mocks; - -namespace RubberduckTests.Refactoring -{ - [TestFixture] - public class ImplementInterfaceTests : RefactoringTestBase - { - [Test] - [Category("Refactorings")] - [Category("Implement Interface")] - public override void TargetNull_Throws() - { - var testVbe = TestVbe(string.Empty, out _); - var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(testVbe); - using (state) - { - var refactoring = TestRefactoring(rewritingManager, state); - Assert.Throws(() => refactoring.Refactor((Declaration)null)); - } - } - - [Test] - [Category("Refactorings")] - [Category("Implement Interface")] - public void DoesNotSupportCallingWithADeclaration() - { - var testVbe = TestVbe(("testClass", string.Empty, ComponentType.ClassModule)); - var (state, rewritingManager) = MockParser.CreateAndParseWithRewritingManager(testVbe); - using (state) - { - var target = state.DeclarationFinder.UserDeclarations(DeclarationType.ClassModule).Single(); - var refactoring = TestRefactoring(rewritingManager, state); - Assert.Throws(() => refactoring.Refactor(target)); - } - } - - [Test] - [Category("Refactorings")] - [Category("Implement Interface")] - public void ImplementInterface_Procedure() - { - //Input - const string inputCode1 = - @"Public Sub Foo() -End Sub"; - - const string inputCode2 = - @"Implements Class1"; - - var selection = Selection.Home; - - //Expectation - const string expectedCode = - @"Implements Class1 - -Private Sub Class1_Foo() - Err.Raise 5 'TODO implement interface member -End Sub -"; - - var actualCode = RefactoredCode( - "Class2", - selection, - null, - false, - ("Class1", inputCode1, ComponentType.ClassModule), - ("Class2", inputCode2, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class2"]); - } - - [Test] - [Category("Refactorings")] - [Category("Implement Interface")] - public void DoesNotImplementInterface_SelectionNotOnImplementsStatement() - { - //Input - const string inputCode1 = - @"Public Sub Foo() -End Sub"; - - const string inputCode2 = - @"Implements Class1 - -"; - var selection = new Selection(2, 2); - - //Expectation - const string expectedCode = - @"Implements Class1 - -"; - - var actualCode = RefactoredCode( - "Class2", - selection, - typeof(NoImplementsStatementSelectedException), - false, - ("Class1", inputCode1, ComponentType.ClassModule), - ("Class2", inputCode2, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class2"]); - } - - [Test] - [Category("Refactorings")] - [Category("Implement Interface")] - public void ImplementInterface_Procedure_ClassHasOtherProcedure() - { - //Input - const string inputCode1 = - @"Public Sub Foo() -End Sub"; - - const string inputCode2 = - @"Implements Class1 - -Public Sub Bar() -End Sub"; - var selection = Selection.Home; - - //Expectation - const string expectedCode = - @"Implements Class1 - -Public Sub Bar() -End Sub - -Private Sub Class1_Foo() - Err.Raise 5 'TODO implement interface member -End Sub -"; - - var actualCode = RefactoredCode( - "Class2", - selection, - null, - false, - ("Class1", inputCode1, ComponentType.ClassModule), - ("Class2", inputCode2, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class2"]); - } - - [Test] - [Category("Refactorings")] - [Category("Implement Interface")] - public void ImplementInterface_PartiallyImplementedInterface() - { - //Input - const string inputCode1 = - @"Public Property Get a() As String -End Property -Public Property Let a(RHS As String) -End Property -Public Property Get b() As String -End Property -Public Property Let b(RHS As String) -End Property"; - - const string inputCode2 = - @"Implements Class1 - -Private Property Let Class1_b(RHS As String) -End Property"; - var selection = Selection.Home; - - //Expectation - const string expectedCode = - @"Implements Class1 - -Private Property Let Class1_b(RHS As String) -End Property - -Private Property Get Class1_a() As String - Err.Raise 5 'TODO implement interface member -End Property - -Private Property Let Class1_a(ByRef RHS As String) - Err.Raise 5 'TODO implement interface member -End Property - -Private Property Get Class1_b() As String - Err.Raise 5 'TODO implement interface member -End Property -"; - - var actualCode = RefactoredCode( - "Class2", - selection, - null, - false, - ("Class1", inputCode1, ComponentType.ClassModule), - ("Class2", inputCode2, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class2"]); - } - - [Test] - [Category("Refactorings")] - [Category("Implement Interface")] - public void ImplementInterface_Procedure_WithParams() - { - //Input - const string inputCode1 = - @"Public Sub Foo(ByVal a As Integer, ByRef b, c, d As Long) -End Sub"; - - const string inputCode2 = - @"Implements Class1"; - var selection = Selection.Home; - - //Expectation - const string expectedCode = - @"Implements Class1 - -Private Sub Class1_Foo(ByVal a As Integer, ByRef b As Variant, ByRef c As Variant, ByRef d As Long) - Err.Raise 5 'TODO implement interface member -End Sub -"; - - var actualCode = RefactoredCode( - "Class2", - selection, - null, - false, - ("Class1", inputCode1, ComponentType.ClassModule), - ("Class2", inputCode2, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class2"]); - } - - [Test] - [Category("Refactorings")] - [Category("Implement Interface")] - public void ImplementInterface_Function() - { - //Input - const string inputCode1 = - @"Public Function Foo() As Integer -End Function"; - - const string inputCode2 = - @"Implements Class1"; - - var selection = Selection.Home; - - //Expectation - const string expectedCode = - @"Implements Class1 - -Private Function Class1_Foo() As Integer - Err.Raise 5 'TODO implement interface member -End Function -"; - - var actualCode = RefactoredCode( - "Class2", - selection, - null, - false, - ("Class1", inputCode1, ComponentType.ClassModule), - ("Class2", inputCode2, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class2"]); - } - - [Test] - [Category("Refactorings")] - [Category("Implement Interface")] - public void ImplementInterface_Function_WithImplicitType() - { - //Input - const string inputCode1 = - @"Public Function Foo() -End Function"; - - const string inputCode2 = - @"Implements Class1"; - - var selection = Selection.Home; - - //Expectation - const string expectedCode = - @"Implements Class1 - -Private Function Class1_Foo() As Variant - Err.Raise 5 'TODO implement interface member -End Function -"; - - var actualCode = RefactoredCode( - "Class2", - selection, - null, - false, - ("Class1", inputCode1, ComponentType.ClassModule), - ("Class2", inputCode2, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class2"]); - } - - [Test] - [Category("Refactorings")] - [Category("Implement Interface")] - public void ImplementInterface_Function_WithParam() - { - //Input - const string inputCode1 = - @"Public Function Foo(a) -End Function"; - - const string inputCode2 = - @"Implements Class1"; - - var selection = Selection.Home; - - //Expectation - const string expectedCode = - @"Implements Class1 - -Private Function Class1_Foo(ByRef a As Variant) As Variant - Err.Raise 5 'TODO implement interface member -End Function -"; - - var actualCode = RefactoredCode( - "Class2", - selection, - null, - false, - ("Class1", inputCode1, ComponentType.ClassModule), - ("Class2", inputCode2, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class2"]); - } - - [Test] - [Category("Refactorings")] - [Category("Implement Interface")] - public void ImplementInterface_PropertyGet() - { - //Input - const string inputCode1 = - @"Public Property Get Foo() As Integer -End Property"; - - const string inputCode2 = - @"Implements Class1"; - - var selection = Selection.Home; - - //Expectation - const string expectedCode = - @"Implements Class1 - -Private Property Get Class1_Foo() As Integer - Err.Raise 5 'TODO implement interface member -End Property -"; - - var actualCode = RefactoredCode( - "Class2", - selection, - null, - false, - ("Class1", inputCode1, ComponentType.ClassModule), - ("Class2", inputCode2, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class2"]); - } - - [Test] - [Category("Refactorings")] - [Category("Implement Interface")] - public void ImplementInterface_PropertyGet_WithImplicitType() - { - //Input - const string inputCode1 = - @"Public Property Get Foo() -End Property"; - - const string inputCode2 = - @"Implements Class1"; - - var selection = Selection.Home; - - //Expectation - const string expectedCode = - @"Implements Class1 - -Private Property Get Class1_Foo() As Variant - Err.Raise 5 'TODO implement interface member -End Property -"; - - var actualCode = RefactoredCode( - "Class2", - selection, - null, - false, - ("Class1", inputCode1, ComponentType.ClassModule), - ("Class2", inputCode2, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class2"]); - } - - [Test] - [Category("Refactorings")] - [Category("Implement Interface")] - public void ImplementInterface_PropertyGet_WithParam() - { - //Input - const string inputCode1 = - @"Public Property Get Foo(a) -End Property"; - - const string inputCode2 = - @"Implements Class1"; - - var selection = Selection.Home; - - //Expectation - const string expectedCode = - @"Implements Class1 - -Private Property Get Class1_Foo(ByRef a As Variant) As Variant - Err.Raise 5 'TODO implement interface member -End Property -"; - - var actualCode = RefactoredCode( - "Class2", - selection, - null, - false, - ("Class1", inputCode1, ComponentType.ClassModule), - ("Class2", inputCode2, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class2"]); - } - - [Test] - [Category("Refactorings")] - [Category("Implement Interface")] - public void ImplementInterface_PropertyLet() - { - //Input - const string inputCode1 = - @"Public Property Let Foo(ByRef value As Long) -End Property"; - - const string inputCode2 = - @"Implements Class1"; - - var selection = Selection.Home; - - //Expectation - const string expectedCode = - @"Implements Class1 - -Private Property Let Class1_Foo(ByRef value As Long) - Err.Raise 5 'TODO implement interface member -End Property -"; - - var actualCode = RefactoredCode( - "Class2", - selection, - null, - false, - ("Class1", inputCode1, ComponentType.ClassModule), - ("Class2", inputCode2, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class2"]); - } - - [Test] - [Category("Refactorings")] - [Category("Implement Interface")] - public void ImplementInterface_PropertyLet_WithParam() - { - //Input - const string inputCode1 = - @"Public Property Let Foo(a) -End Property"; - - const string inputCode2 = - @"Implements Class1"; - - var selection = Selection.Home; - - //Expectation - const string expectedCode = - @"Implements Class1 - -Private Property Let Class1_Foo(ByRef a As Variant) - Err.Raise 5 'TODO implement interface member -End Property -"; - - var actualCode = RefactoredCode( - "Class2", - selection, - null, - false, - ("Class1", inputCode1, ComponentType.ClassModule), - ("Class2", inputCode2, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class2"]); - } - - [Test] - [Category("Refactorings")] - [Category("Implement Interface")] - public void ImplementInterface_PropertySet() - { - //Input - const string inputCode1 = - @"Public Property Set Foo(ByRef value As Variant) -End Property"; - - const string inputCode2 = - @"Implements Class1"; - - var selection = Selection.Home; - - //Expectation - const string expectedCode = - @"Implements Class1 - -Private Property Set Class1_Foo(ByRef value As Variant) - Err.Raise 5 'TODO implement interface member -End Property -"; - - var actualCode = RefactoredCode( - "Class2", - selection, - null, - false, - ("Class1", inputCode1, ComponentType.ClassModule), - ("Class2", inputCode2, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class2"]); - } - - [Test] - [Category("Refactorings")] - [Category("Implement Interface")] - public void ImplementInterface_PropertySet_WithParam() - { - //Input - const string inputCode1 = - @"Public Property Set Foo(a) -End Property"; - - const string inputCode2 = - @"Implements Class1"; - - var selection = Selection.Home; - - //Expectation - const string expectedCode = - @"Implements Class1 - -Private Property Set Class1_Foo(ByRef a As Variant) - Err.Raise 5 'TODO implement interface member -End Property -"; - - var actualCode = RefactoredCode( - "Class2", - selection, - null, - false, - ("Class1", inputCode1, ComponentType.ClassModule), - ("Class2", inputCode2, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class2"]); - } - - [Test] - [Category("Refactorings")] - [Category("Implement Interface")] - public void ImplementInterface_PropertySet_AllTypes() - { - //Input - const string inputCode1 = - @"Public Sub Foo() -End Sub - -Public Function Bar(ByVal a As Integer) As Boolean -End Function - -Public Property Get Buz(ByVal a As Boolean) As Integer -End Property - -Public Property Let Buz(ByVal a As Boolean, ByRef value As Integer) -End Property"; - - const string inputCode2 = - @"Implements Class1"; - - var selection = Selection.Home; - - //Expectation - const string expectedCode = - @"Implements Class1 - -Private Sub Class1_Foo() - Err.Raise 5 'TODO implement interface member -End Sub - -Private Function Class1_Bar(ByVal a As Integer) As Boolean - Err.Raise 5 'TODO implement interface member -End Function - -Private Property Get Class1_Buz(ByVal a As Boolean) As Integer - Err.Raise 5 'TODO implement interface member -End Property - -Private Property Let Class1_Buz(ByVal a As Boolean, ByRef value As Integer) - Err.Raise 5 'TODO implement interface member -End Property -"; - - var actualCode = RefactoredCode( - "Class2", - selection, - null, - false, - ("Class1", inputCode1, ComponentType.ClassModule), - ("Class2", inputCode2, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class2"]); - } - - [Test] - [Category("Refactorings")] - [Category("Implement Interface")] - public void CreatesMethodStubForAllProcedureKinds() - { - //Input - const string interfaceCode = - @"Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) -End Sub - -Public Function Fizz(b) -End Function - -Public Property Get Buzz() As Variant -End Property - -Public Property Let Buzz(value) -End Property - -Public Property Set Buzz(value) -End Property"; - - const string inputCode = - @"Implements IClassModule"; - - var selection = Selection.Home; - - //Expectation - const string expectedCode = - @"Implements IClassModule - -Private Sub IClassModule_Foo(ByVal arg1 As Integer, ByVal arg2 As String) - Err.Raise 5 'TODO implement interface member -End Sub - -Private Function IClassModule_Fizz(ByRef b As Variant) As Variant - Err.Raise 5 'TODO implement interface member -End Function - -Private Property Get IClassModule_Buzz() As Variant - Err.Raise 5 'TODO implement interface member -End Property - -Private Property Let IClassModule_Buzz(ByRef value As Variant) - Err.Raise 5 'TODO implement interface member -End Property - -Private Property Set IClassModule_Buzz(ByRef value As Variant) - Err.Raise 5 'TODO implement interface member -End Property -"; - - var actualCode = RefactoredCode( - "Class2", - selection, - null, - false, - ("IClassModule", interfaceCode, ComponentType.ClassModule), - ("Class2", inputCode, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class2"]); - } - - [Test] - [Category("Refactorings")] - [Category("Implement Interface")] - public void ImplementsInterfaceInDocumentModule() - { - const string interfaceCode = @"Option Explicit -Public Sub DoSomething() -End Sub -"; - const string initialCode = @"Implements IInterface"; - - var selection = Selection.Home; - - const string expectedCode = @"Implements IInterface - -Private Sub IInterface_DoSomething() - Err.Raise 5 'TODO implement interface member -End Sub -"; - - var actualCode = RefactoredCode( - "Sheet1", - selection, - null, - false, - ("IInterface", interfaceCode, ComponentType.ClassModule), - ("Sheet1", initialCode, ComponentType.Document)); - Assert.AreEqual(expectedCode, actualCode["Sheet1"]); - } - - [Test] - [Category("Refactorings")] - [Category("Implement Interface")] - public void ImplementsInterfaceInUserFormModule() - { - const string interfaceCode = @"Option Explicit -Public Sub DoSomething() -End Sub -"; - const string initialCode = @"Implements IInterface"; - - var selection = Selection.Home; - - const string expectedCode = @"Implements IInterface - -Private Sub IInterface_DoSomething() - Err.Raise 5 'TODO implement interface member -End Sub -"; - - var actualCode = RefactoredCode( - "Form1", - selection, - null, - false, - ("IInterface", interfaceCode, ComponentType.ClassModule), - ("Form1", initialCode, ComponentType.UserForm)); - Assert.AreEqual(expectedCode, actualCode["Form1"]); - } - - [Test] - [TestCase(@"Public Foo As Long")] - [TestCase(@"Dim Foo As Long")] - [Category("Refactorings")] - [Category("Implement Interface")] - public void ImplementInterface_PublicIntrinsic(string inputCode1) - { - const string inputCode2 = - @"Implements Class1"; - - var selection = Selection.Home; - - //Expectation - const string expectedCode = - @"Implements Class1 - -Private Property Get Class1_Foo() As Long - Err.Raise 5 'TODO implement interface member -End Property - -Private Property Let Class1_Foo(ByVal rhs As Long) - Err.Raise 5 'TODO implement interface member -End Property -"; - - var actualCode = RefactoredCode( - "Class2", - selection, - null, - false, - ("Class1", inputCode1, ComponentType.ClassModule), - ("Class2", inputCode2, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class2"]); - } - - [Test] - [TestCase(@"Public Foo As Object")] - [TestCase(@"Dim Foo As Object")] - [Category("Refactorings")] - [Category("Implement Interface")] - public void ImplementInterface_PublicObject(string inputCode1) - { - const string inputCode2 = - @"Implements Class1"; - - var selection = Selection.Home; - - //Expectation - const string expectedCode = - @"Implements Class1 - -Private Property Get Class1_Foo() As Object - Err.Raise 5 'TODO implement interface member -End Property - -Private Property Set Class1_Foo(ByVal rhs As Object) - Err.Raise 5 'TODO implement interface member -End Property -"; - - var actualCode = RefactoredCode( - "Class2", - selection, - null, - false, - ("Class1", inputCode1, ComponentType.ClassModule), - ("Class2", inputCode2, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class2"]); - } - - [Test] - [TestCase(@"Public Foo As Variant")] - [TestCase(@"Public Foo")] - [TestCase(@"Dim Foo As Variant")] - [TestCase(@"Dim Foo")] - [Category("Refactorings")] - [Category("Implement Interface")] - public void ImplementInterface_PublicVariant(string inputCode1) - { - const string inputCode2 = - @"Implements Class1"; - - var selection = Selection.Home; - - //Expectation - const string expectedCode = - @"Implements Class1 - -Private Property Get Class1_Foo() As Variant - Err.Raise 5 'TODO implement interface member -End Property - -Private Property Let Class1_Foo(ByVal rhs As Variant) - Err.Raise 5 'TODO implement interface member -End Property - -Private Property Set Class1_Foo(ByVal rhs As Variant) - Err.Raise 5 'TODO implement interface member -End Property -"; - - var actualCode = RefactoredCode( - "Class2", - selection, - null, - false, - ("Class1", inputCode1, ComponentType.ClassModule), - ("Class2", inputCode2, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class2"]); - } - - [Test] - [Category("Refactorings")] - [Category("Implement Interface")] - public void ImplementsCorrectInterface_MultipleInterfaces() - { - //Input - const string inputCode1 = - @"Public Sub Foo() -End Sub"; - - const string inputCode2 = - @"Implements Class1 -Implements Class3"; - - var selection = new Selection(1, 1); - - const string inputCode3 = - @"Public Sub Foo() -End Sub"; - - //Expectation - const string expectedCode = - @"Implements Class1 -Implements Class3 - -Private Sub Class1_Foo() - Err.Raise 5 'TODO implement interface member -End Sub -"; - - var actualCode = RefactoredCode( - "Class2", - selection, - null, - false, - ("Class1", inputCode1, ComponentType.ClassModule), - ("Class2", inputCode2, ComponentType.ClassModule), - ("Class3", inputCode3, ComponentType.ClassModule)); - Assert.AreEqual(expectedCode, actualCode["Class2"]); - } - - protected override IRefactoring TestRefactoring(IRewritingManager rewritingManager, RubberduckParserState state, - ISelectionService selectionService) - { - var addImplementationsBaseRefactoring = new AddInterfaceImplementationsRefactoringAction(rewritingManager); - var baseRefactoring = new ImplementInterfaceRefactoringAction(addImplementationsBaseRefactoring, rewritingManager); - return new ImplementInterfaceRefactoring(baseRefactoring, state, selectionService); - } - } -} - From d16d94f23661459d716138a4c088307e22e93592 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Thu, 20 Feb 2020 00:24:25 +0100 Subject: [PATCH 243/461] Fix ImplementInterface regarding optional parameters --- ...terfaceImplementationsRefactoringAction.cs | 13 +- .../ImplementInterface/Parameter.cs | 47 +++- .../ExtractInterfaceRefactoringActionTests.cs | 8 +- ...mplementInterfaceRefactoringActionTests.cs | 210 +++++++++++++++++- 4 files changed, 256 insertions(+), 22 deletions(-) diff --git a/Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterfaceImplementationsRefactoringAction.cs b/Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterfaceImplementationsRefactoringAction.cs index 4277dc0886..70bb5e89db 100644 --- a/Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterfaceImplementationsRefactoringAction.cs +++ b/Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterfaceImplementationsRefactoringAction.cs @@ -85,14 +85,13 @@ private IEnumerable GetParameters(Declaration member) }; } - return ((ModuleBodyElementDeclaration)member).Parameters.Select(p => new Parameter + if (member is ModuleBodyElementDeclaration method) { - Accessibility = ((VBAParser.ArgContext)p.Context).BYVAL() != null - ? Tokens.ByVal - : Tokens.ByRef, - Name = p.IdentifierName, - AsTypeName = p.AsTypeName - }); + return method.Parameters + .Select(parameter => new Parameter(parameter)); + } + + return Enumerable.Empty(); } } } \ No newline at end of file diff --git a/Rubberduck.Refactorings/ImplementInterface/Parameter.cs b/Rubberduck.Refactorings/ImplementInterface/Parameter.cs index a218a4ae4d..c60e5ac492 100644 --- a/Rubberduck.Refactorings/ImplementInterface/Parameter.cs +++ b/Rubberduck.Refactorings/ImplementInterface/Parameter.cs @@ -1,14 +1,57 @@ -namespace Rubberduck.Refactorings.ImplementInterface +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Symbols; + +namespace Rubberduck.Refactorings.ImplementInterface { public class Parameter { public string Accessibility { get; set; } public string Name { get; set; } public string AsTypeName { get; set; } + public string Optional { get; set; } + public string DefaultValue { get; set; } + + public Parameter() + {} + + public Parameter(ParameterDeclaration parameter) + { + Accessibility = parameter.IsImplicitByRef + ? string.Empty + : parameter.IsByRef + ? Tokens.ByRef + : Tokens.ByVal; + + Name = parameter.IsArray + ? $"{parameter.IdentifierName}()" + : parameter.IdentifierName; + + AsTypeName = parameter.AsTypeName; + + Optional = parameter.IsParamArray + ? Tokens.ParamArray + : parameter.IsOptional + ? Tokens.Optional + : string.Empty; + + DefaultValue = parameter.DefaultValue; + } + + private static string FormatStandardElement(string element) => string.IsNullOrEmpty(element) + ? string.Empty + : $"{element} "; + + private string FormattedAsTypeName => string.IsNullOrEmpty(AsTypeName) + ? string.Empty + : $"As {AsTypeName} "; + + private string FormattedDefaultValue => string.IsNullOrEmpty(DefaultValue) + ? string.Empty + : $"= {DefaultValue}"; public override string ToString() { - return $"{Accessibility} {Name} As {AsTypeName}"; + return $"{FormatStandardElement(Optional)}{FormatStandardElement(Accessibility)}{FormatStandardElement(Name)}{FormattedAsTypeName}{FormattedDefaultValue}".Trim(); } } } diff --git a/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceRefactoringActionTests.cs b/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceRefactoringActionTests.cs index ebcd6cbb2e..b3e0c7e02a 100644 --- a/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceRefactoringActionTests.cs +++ b/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceRefactoringActionTests.cs @@ -91,7 +91,7 @@ Private Sub IClass_Foo(ByVal arg1 As Integer, ByVal arg2 As String) Err.Raise 5 'TODO implement interface member End Sub -Private Function IClass_Fizz(ByRef b As Variant) As Variant +Private Function IClass_Fizz(b As Variant) As Variant Err.Raise 5 'TODO implement interface member End Function @@ -99,11 +99,11 @@ Private Property Get IClass_Buzz() As Variant Err.Raise 5 'TODO implement interface member End Property -Private Property Let IClass_Buzz(ByRef value As Variant) +Private Property Let IClass_Buzz(value As Variant) Err.Raise 5 'TODO implement interface member End Property -Private Property Set IClass_Buzz(ByRef value As Variant) +Private Property Set IClass_Buzz(value As Variant) Err.Raise 5 'TODO implement interface member End Property "; @@ -176,7 +176,7 @@ Private Sub IClass_Foo(ByVal arg1 As Integer, ByVal arg2 As String) Err.Raise 5 'TODO implement interface member End Sub -Private Function IClass_Fizz(ByRef b As Variant) As Variant +Private Function IClass_Fizz(b As Variant) As Variant Err.Raise 5 'TODO implement interface member End Function "; diff --git a/RubberduckTests/Refactoring/ImplementInterface/ImplementInterfaceRefactoringActionTests.cs b/RubberduckTests/Refactoring/ImplementInterface/ImplementInterfaceRefactoringActionTests.cs index 750a11a3ec..4ad31ccd6b 100644 --- a/RubberduckTests/Refactoring/ImplementInterface/ImplementInterfaceRefactoringActionTests.cs +++ b/RubberduckTests/Refactoring/ImplementInterface/ImplementInterfaceRefactoringActionTests.cs @@ -101,7 +101,7 @@ Private Property Get Interface1_a() As String Err.Raise 5 'TODO implement interface member End Property -Private Property Let Interface1_a(ByRef RHS As String) +Private Property Let Interface1_a(RHS As String) Err.Raise 5 'TODO implement interface member End Property @@ -129,7 +129,7 @@ public void ImplementInterface_Procedure_WithParams() const string expectedCode = @"Implements Interface1 -Private Sub Interface1_Foo(ByVal a As Integer, ByRef b As Variant, ByRef c As Variant, ByRef d As Long) +Private Sub Interface1_Foo(ByVal a As Integer, ByRef b As Variant, c As Variant, d As Long) Err.Raise 5 'TODO implement interface member End Sub "; @@ -201,7 +201,7 @@ public void ImplementInterface_Function_WithParam() const string expectedCode = @"Implements Interface1 -Private Function Interface1_Foo(ByRef a As Variant) As Variant +Private Function Interface1_Foo(a As Variant) As Variant Err.Raise 5 'TODO implement interface member End Function "; @@ -273,7 +273,7 @@ public void ImplementInterface_PropertyGet_WithParam() const string expectedCode = @"Implements Interface1 -Private Property Get Interface1_Foo(ByRef a As Variant) As Variant +Private Property Get Interface1_Foo(a As Variant) As Variant Err.Raise 5 'TODO implement interface member End Property "; @@ -321,7 +321,7 @@ public void ImplementInterface_PropertyLet_WithParam() const string expectedCode = @"Implements Interface1 -Private Property Let Interface1_Foo(ByRef a As Variant) +Private Property Let Interface1_Foo(a As Variant) Err.Raise 5 'TODO implement interface member End Property "; @@ -369,7 +369,7 @@ public void ImplementInterface_PropertySet_WithParam() const string expectedCode = @"Implements Interface1 -Private Property Set Interface1_Foo(ByRef a As Variant) +Private Property Set Interface1_Foo(a As Variant) Err.Raise 5 'TODO implement interface member End Property "; @@ -454,7 +454,7 @@ Private Sub Interface1_Foo(ByVal arg1 As Integer, ByVal arg2 As String) Err.Raise 5 'TODO implement interface member End Sub -Private Function Interface1_Fizz(ByRef b As Variant) As Variant +Private Function Interface1_Fizz(b As Variant) As Variant Err.Raise 5 'TODO implement interface member End Function @@ -462,11 +462,11 @@ Private Property Get Interface1_Buzz() As Variant Err.Raise 5 'TODO implement interface member End Property -Private Property Let Interface1_Buzz(ByRef value As Variant) +Private Property Let Interface1_Buzz(value As Variant) Err.Raise 5 'TODO implement interface member End Property -Private Property Set Interface1_Buzz(ByRef value As Variant) +Private Property Set Interface1_Buzz(value As Variant) Err.Raise 5 'TODO implement interface member End Property "; @@ -554,6 +554,198 @@ End Property ExecuteTest(classCode, interfaceCode, expectedCode); } + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_ImplicitByRefParameter() + { + //Input + const string interfaceCode = + @"Public Sub Foo(arg As Variant) +End Sub"; + + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Sub Interface1_Foo(arg As Variant) + Err.Raise 5 'TODO implement interface member +End Sub +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_ExplicitByRefParameter() + { + //Input + const string interfaceCode = + @"Public Sub Foo(ByRef arg As Variant) +End Sub"; + + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Sub Interface1_Foo(ByRef arg As Variant) + Err.Raise 5 'TODO implement interface member +End Sub +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_ByValParameter() + { + //Input + const string interfaceCode = + @"Public Sub Foo(ByVal arg As Variant) +End Sub"; + + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Sub Interface1_Foo(ByVal arg As Variant) + Err.Raise 5 'TODO implement interface member +End Sub +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_OptionalParameter_WoDefault() + { + //Input + const string interfaceCode = + @"Public Sub Foo(Optional arg As Variant) +End Sub"; + + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Sub Interface1_Foo(Optional arg As Variant) + Err.Raise 5 'TODO implement interface member +End Sub +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_OptionalParameter_WithDefault() + { + //Input + const string interfaceCode = + @"Public Sub Foo(Optional arg As Variant = 42) +End Sub"; + + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Sub Interface1_Foo(Optional arg As Variant = 42) + Err.Raise 5 'TODO implement interface member +End Sub +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_ParamArray() + { + //Input + const string interfaceCode = + @"Public Sub Foo(arg1 As Long, ParamArray args() As Variant) +End Sub"; + + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Sub Interface1_Foo(arg1 As Long, ParamArray args() As Variant) + Err.Raise 5 'TODO implement interface member +End Sub +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_MakesMissingAsTypesExplicit() + { + //Input + const string interfaceCode = + @"Public Sub Foo(arg1) +End Sub"; + + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Sub Interface1_Foo(arg1 As Variant) + Err.Raise 5 'TODO implement interface member +End Sub +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ImplementInterface_Array() + { + //Input + const string interfaceCode = + @"Public Sub Foo(arg1() As Long) +End Sub"; + + const string classCode = + @"Implements Interface1"; + + //Expectation + const string expectedCode = + @"Implements Interface1 + +Private Sub Interface1_Foo(arg1() As Long) + Err.Raise 5 'TODO implement interface member +End Sub +"; + ExecuteTest(classCode, interfaceCode, expectedCode); + } + private void ExecuteTest(string classCode, string interfaceCode, string expectedClassCode) { var refactoredCode = RefactoredCode( From d5d11decd5011bd9a57ed7d55f8107fbfaab6585 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Thu, 20 Feb 2020 01:09:46 +0100 Subject: [PATCH 244/461] Fix ExtractInterface regarding optional arguments --- .../ExtractInterfaceRefactoringAction.cs | 8 - .../ExtractInterface/InterfaceMember.cs | 24 +- ...terfaceImplementationsRefactoringAction.cs | 1 + .../ExtractInterfaceRefactoringActionTests.cs | 256 +++++++++++++++++- 4 files changed, 256 insertions(+), 33 deletions(-) diff --git a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoringAction.cs b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoringAction.cs index 288e71f6dd..05360f689e 100644 --- a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoringAction.cs +++ b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoringAction.cs @@ -11,7 +11,6 @@ using Rubberduck.Refactorings.AddInterfaceImplementations; using Rubberduck.VBEditor.ComManagement; using Rubberduck.VBEditor.SafeComWrappers; -using Rubberduck.VBEditor.SafeComWrappers.Abstract; using Rubberduck.VBEditor.Utility; namespace Rubberduck.Refactorings.ExtractInterface @@ -143,12 +142,5 @@ private void AddInterfaceMembersToClass(ExtractInterfaceModel model, IRewriteSes var addMembersModel = new AddInterfaceImplementationsModel(targetModule, interfaceName, membersToImplement); _addImplementationsRefactoringAction.Refactor(addMembersModel, rewriteSession); } - - private static readonly DeclarationType[] ModuleTypes = - { - DeclarationType.ClassModule, - DeclarationType.Document, - DeclarationType.UserForm - }; } } \ No newline at end of file diff --git a/Rubberduck.Refactorings/ExtractInterface/InterfaceMember.cs b/Rubberduck.Refactorings/ExtractInterface/InterfaceMember.cs index 3817516ebe..debe4c7b19 100644 --- a/Rubberduck.Refactorings/ExtractInterface/InterfaceMember.cs +++ b/Rubberduck.Refactorings/ExtractInterface/InterfaceMember.cs @@ -5,21 +5,10 @@ using System.Runtime.CompilerServices; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; +using Rubberduck.Refactorings.ImplementInterface; namespace Rubberduck.Refactorings.ExtractInterface { - public class Parameter - { - public string ParamAccessibility { get; set; } - public string ParamName { get; set; } - public string ParamType { get; set; } - - public override string ToString() - { - return $"{ParamAccessibility} {ParamName} As {ParamType}"; - } - } - public class InterfaceMember : INotifyPropertyChanged { public Declaration Member { get; } @@ -61,15 +50,8 @@ public InterfaceMember(Declaration member) if (member is IParameterizedDeclaration memberWithParams) { MemberParams = memberWithParams.Parameters - .OrderBy(o => o.Selection.StartLine) - .ThenBy(t => t.Selection.StartColumn) - .Select(p => new Parameter - { - ParamAccessibility = - ((VBAParser.ArgContext) p.Context).BYVAL() != null ? Tokens.ByVal : Tokens.ByRef, - ParamName = p.IdentifierName, - ParamType = p.AsTypeName - }) + .OrderBy(parameter => parameter.Selection) + .Select(parameter => new Parameter(parameter)) .ToList(); } else diff --git a/Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterfaceImplementationsRefactoringAction.cs b/Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterfaceImplementationsRefactoringAction.cs index 70bb5e89db..f64e92f2de 100644 --- a/Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterfaceImplementationsRefactoringAction.cs +++ b/Rubberduck.Refactorings/ImplementInterface/AddInterfaceImplementations/AddInterfaceImplementationsRefactoringAction.cs @@ -88,6 +88,7 @@ private IEnumerable GetParameters(Declaration member) if (member is ModuleBodyElementDeclaration method) { return method.Parameters + .OrderBy(parameter => parameter.Selection) .Select(parameter => new Parameter(parameter)); } diff --git a/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceRefactoringActionTests.cs b/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceRefactoringActionTests.cs index b3e0c7e02a..dbe9b7ece6 100644 --- a/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceRefactoringActionTests.cs +++ b/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceRefactoringActionTests.cs @@ -116,16 +116,16 @@ End Property Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) End Sub -Public Function Fizz(ByRef b As Variant) As Variant +Public Function Fizz(b As Variant) As Variant End Function Public Property Get Buzz() As Variant End Property -Public Property Let Buzz(ByRef value As Variant) +Public Property Let Buzz(value As Variant) End Property -Public Property Set Buzz(ByRef value As Variant) +Public Property Set Buzz(value As Variant) End Property "; ExecuteTest(inputCode, expectedClassCode, expectedInterfaceCode, SelectAllMembers); @@ -189,7 +189,7 @@ End Function Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) End Sub -Public Function Fizz(ByRef b As Variant) As Variant +Public Function Fizz(b As Variant) As Variant End Function "; var modelAdjustment = SelectFilteredMembers(member => !member.FullMemberSignature.Contains("Property")); @@ -414,6 +414,254 @@ End Sub ExecuteTest(inputCode, expectedClassCode, expectedInterfaceCode, SelectAllMembers); } + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ExtractInterfaceRefactoring_ImplicitByRefParameter() + { + //Input + const string inputCode = + @"Public Sub Foo(arg As Variant) +End Sub"; + //Expectation + const string expectedClassCode = + @"Implements IClass + +Public Sub Foo(arg As Variant) +End Sub + +Private Sub IClass_Foo(arg As Variant) + Err.Raise 5 'TODO implement interface member +End Sub +"; + const string expectedInterfaceCode = + @"Option Explicit + +'@Interface + +Public Sub Foo(arg As Variant) +End Sub +"; + ExecuteTest(inputCode, expectedClassCode, expectedInterfaceCode, SelectAllMembers); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ExtractInterfaceRefactoring_ExplicitByRefParameter() + { + //Input + const string inputCode = + @"Public Sub Foo(ByRef arg As Variant) +End Sub"; + //Expectation + const string expectedClassCode = + @"Implements IClass + +Public Sub Foo(ByRef arg As Variant) +End Sub + +Private Sub IClass_Foo(ByRef arg As Variant) + Err.Raise 5 'TODO implement interface member +End Sub +"; + const string expectedInterfaceCode = + @"Option Explicit + +'@Interface + +Public Sub Foo(ByRef arg As Variant) +End Sub +"; + ExecuteTest(inputCode, expectedClassCode, expectedInterfaceCode, SelectAllMembers); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ExtractInterfaceRefactoring_ByValParameter() + { + //Input + const string inputCode = + @"Public Sub Foo(ByVal arg As Variant) +End Sub"; + //Expectation + const string expectedClassCode = + @"Implements IClass + +Public Sub Foo(ByVal arg As Variant) +End Sub + +Private Sub IClass_Foo(ByVal arg As Variant) + Err.Raise 5 'TODO implement interface member +End Sub +"; + const string expectedInterfaceCode = + @"Option Explicit + +'@Interface + +Public Sub Foo(ByVal arg As Variant) +End Sub +"; + ExecuteTest(inputCode, expectedClassCode, expectedInterfaceCode, SelectAllMembers); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ExtractInterfaceRefactoring_OptionalParameter_WoDefault() + { + //Input + const string inputCode = + @"Public Sub Foo(Optional arg As Variant) +End Sub"; + //Expectation + const string expectedClassCode = + @"Implements IClass + +Public Sub Foo(Optional arg As Variant) +End Sub + +Private Sub IClass_Foo(Optional arg As Variant) + Err.Raise 5 'TODO implement interface member +End Sub +"; + const string expectedInterfaceCode = + @"Option Explicit + +'@Interface + +Public Sub Foo(Optional arg As Variant) +End Sub +"; + ExecuteTest(inputCode, expectedClassCode, expectedInterfaceCode, SelectAllMembers); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ExtractInterfaceRefactoring_OptionalParameter_WithDefault() + { + //Input + const string inputCode = + @"Public Sub Foo(Optional arg As Variant = 42) +End Sub"; + //Expectation + const string expectedClassCode = + @"Implements IClass + +Public Sub Foo(Optional arg As Variant = 42) +End Sub + +Private Sub IClass_Foo(Optional arg As Variant = 42) + Err.Raise 5 'TODO implement interface member +End Sub +"; + const string expectedInterfaceCode = + @"Option Explicit + +'@Interface + +Public Sub Foo(Optional arg As Variant = 42) +End Sub +"; + ExecuteTest(inputCode, expectedClassCode, expectedInterfaceCode, SelectAllMembers); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ExtractInterfaceRefactoring_ParamArray() + { + //Input + const string inputCode = + @"Public Sub Foo(arg1 As Long, ParamArray args() As Variant) +End Sub"; + //Expectation + const string expectedClassCode = + @"Implements IClass + +Public Sub Foo(arg1 As Long, ParamArray args() As Variant) +End Sub + +Private Sub IClass_Foo(arg1 As Long, ParamArray args() As Variant) + Err.Raise 5 'TODO implement interface member +End Sub +"; + const string expectedInterfaceCode = + @"Option Explicit + +'@Interface + +Public Sub Foo(arg1 As Long, ParamArray args() As Variant) +End Sub +"; + ExecuteTest(inputCode, expectedClassCode, expectedInterfaceCode, SelectAllMembers); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ExtractInterfaceRefactoring_MakesMissingAsTypesExplicit() + { + //Input + const string inputCode = + @"Public Sub Foo(arg1) +End Sub"; + //Expectation + const string expectedClassCode = + @"Implements IClass + +Public Sub Foo(arg1) +End Sub + +Private Sub IClass_Foo(arg1 As Variant) + Err.Raise 5 'TODO implement interface member +End Sub +"; + const string expectedInterfaceCode = + @"Option Explicit + +'@Interface + +Public Sub Foo(arg1 As Variant) +End Sub +"; + ExecuteTest(inputCode, expectedClassCode, expectedInterfaceCode, SelectAllMembers); + } + + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ExtractInterfaceRefactoring_Array() + { + //Input + const string inputCode = + @"Public Sub Foo(arg1() As Long) +End Sub"; + //Expectation + const string expectedClassCode = + @"Implements IClass + +Public Sub Foo(arg1() As Long) +End Sub + +Private Sub IClass_Foo(arg1() As Long) + Err.Raise 5 'TODO implement interface member +End Sub +"; + const string expectedInterfaceCode = + @"Option Explicit + +'@Interface + +Public Sub Foo(arg1() As Long) +End Sub +"; + ExecuteTest(inputCode, expectedClassCode, expectedInterfaceCode, SelectAllMembers); + } + private void ExecuteTest(string inputCode, string expectedClassCode, string expectedInterfaceCode, Func modelAdjustment) { var refactoredCode = RefactoredCode( From 1b69ca4f789206b1f5f8c0f900e2946a52ef241b Mon Sep 17 00:00:00 2001 From: IvenBach Date: Thu, 20 Feb 2020 16:05:24 -0800 Subject: [PATCH 245/461] Don't special case document modules --- .../UI/CodeExplorer/Commands/ExportCommand.cs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/Rubberduck.Core/UI/CodeExplorer/Commands/ExportCommand.cs b/Rubberduck.Core/UI/CodeExplorer/Commands/ExportCommand.cs index 0d41a2db60..1755a183f4 100644 --- a/Rubberduck.Core/UI/CodeExplorer/Commands/ExportCommand.cs +++ b/Rubberduck.Core/UI/CodeExplorer/Commands/ExportCommand.cs @@ -100,15 +100,8 @@ public bool PromptFileNameAndExport(QualifiedModuleName qualifiedModule) var component = ProjectsProvider.Component(qualifiedModule); try { - if (component.Type == ComponentType.Document) - { - var path = System.IO.Path.GetDirectoryName(dialog.FileName); - component.ExportAsSourceFile(path); - } - else - { - component.Export(dialog.FileName); - } + var path = System.IO.Path.GetDirectoryName(dialog.FileName); + component.ExportAsSourceFile(path); } catch (Exception ex) { From 6beba450411c90bd976629f7c5fa5c8611bd24d1 Mon Sep 17 00:00:00 2001 From: IvenBach Date: Thu, 20 Feb 2020 16:26:36 -0800 Subject: [PATCH 246/461] Permit single trailing Newline --- Rubberduck.Parsing/Rewriter/ModuleRewriter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Rubberduck.Parsing/Rewriter/ModuleRewriter.cs b/Rubberduck.Parsing/Rewriter/ModuleRewriter.cs index 6863db9c75..80e8e72bb2 100644 --- a/Rubberduck.Parsing/Rewriter/ModuleRewriter.cs +++ b/Rubberduck.Parsing/Rewriter/ModuleRewriter.cs @@ -35,9 +35,9 @@ public void Rewrite() var tentativeCode = _rewriter.GetText(); - while (tentativeCode.EndsWith(Environment.NewLine)) + while (tentativeCode.EndsWith(Environment.NewLine + Environment.NewLine)) { - tentativeCode = tentativeCode.Remove(tentativeCode.Length - 2); + tentativeCode = tentativeCode.Remove(tentativeCode.Length - Environment.NewLine.Length); }; var newCode = tentativeCode; From c4ad4c82cf148c6ffeb168911397f35f5c79d249 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Fri, 21 Feb 2020 13:40:16 +0100 Subject: [PATCH 247/461] Add ability to extract exposed interfaces to ExtractInterfaceRefactoring This takes the idea from PR #5357 and adds the implementation in the ExtractInterfaceRefactoringAction according to the current design. --- .../Symbols/ClassModuleDeclaration.cs | 1 - .../ExtractInterface/ExtractInterfaceModel.cs | 15 ++++- .../ExtractInterfaceRefactoring.cs | 5 +- .../ExtractInterfaceRefactoringAction.cs | 41 ++++++++++++- .../ExtractInterfaceRefactoringActionTests.cs | 52 ++++++++++++++++ .../ExtractInterface/ExtractInterfaceTests.cs | 59 ++++++++++++++++++- 6 files changed, 164 insertions(+), 9 deletions(-) diff --git a/Rubberduck.Parsing/Symbols/ClassModuleDeclaration.cs b/Rubberduck.Parsing/Symbols/ClassModuleDeclaration.cs index 4ac757a5eb..17f4fb09f3 100644 --- a/Rubberduck.Parsing/Symbols/ClassModuleDeclaration.cs +++ b/Rubberduck.Parsing/Symbols/ClassModuleDeclaration.cs @@ -1,6 +1,5 @@ using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.ComReflection; -using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor; using System; using System.Collections.Concurrent; diff --git a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceModel.cs b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceModel.cs index 4ccd4cca88..22af322d07 100644 --- a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceModel.cs +++ b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceModel.cs @@ -6,14 +6,24 @@ namespace Rubberduck.Refactorings.ExtractInterface { + public enum ClassInstancing + { + Private, + Public + } + public class ExtractInterfaceModel : IRefactoringModel { public IDeclarationFinderProvider DeclarationFinderProvider { get; } - public Declaration TargetDeclaration { get; } + public ClassModuleDeclaration TargetDeclaration { get; } public string InterfaceName { get; set; } public ObservableCollection Members { get; set; } = new ObservableCollection(); public IEnumerable SelectedMembers => Members.Where(m => m.IsSelected); + public ClassInstancing InterfaceInstancing { get; set; } + public ClassInstancing ImplementingClassInstancing => TargetDeclaration.IsExposed + ? ClassInstancing.Public + : ClassInstancing.Private; public static readonly DeclarationType[] MemberTypes = { @@ -24,7 +34,7 @@ public class ExtractInterfaceModel : IRefactoringModel DeclarationType.PropertySet, }; - public ExtractInterfaceModel(IDeclarationFinderProvider declarationFinderProvider, Declaration target) + public ExtractInterfaceModel(IDeclarationFinderProvider declarationFinderProvider, ClassModuleDeclaration target) { TargetDeclaration = target; DeclarationFinderProvider = declarationFinderProvider; @@ -35,6 +45,7 @@ public ExtractInterfaceModel(IDeclarationFinderProvider declarationFinderProvide } InterfaceName = $"I{TargetDeclaration.IdentifierName}"; + InterfaceInstancing = ImplementingClassInstancing; LoadMembers(); } diff --git a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs index 6c545f2fb8..baaa7073db 100644 --- a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs +++ b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoring.cs @@ -51,12 +51,13 @@ protected override ExtractInterfaceModel InitializeModel(Declaration target) throw new TargetDeclarationIsNullException(); } - if (!ModuleTypes.Contains(target.DeclarationType)) + if (!ModuleTypes.Contains(target.DeclarationType) + || !(target is ClassModuleDeclaration targetClass)) { throw new InvalidDeclarationTypeException(target); } - return new ExtractInterfaceModel(_declarationFinderProvider, target); + return new ExtractInterfaceModel(_declarationFinderProvider, targetClass); } protected override void RefactorImpl(ExtractInterfaceModel model) diff --git a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoringAction.cs b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoringAction.cs index 05360f689e..4292f05ce6 100644 --- a/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoringAction.cs +++ b/Rubberduck.Refactorings/ExtractInterface/ExtractInterfaceRefactoringAction.cs @@ -63,10 +63,30 @@ private void AddInterface(ExtractInterfaceModel model, IRewriteSession rewriteSe private void AddInterfaceClass(ExtractInterfaceModel model) { var targetProjectId = model.TargetDeclaration.ProjectId; - var interfaceCode = InterfaceModuleBody(model); + var interfaceCode = InterfaceCode(model); var interfaceName = model.InterfaceName; - _addComponentService.AddComponent(targetProjectId, ComponentType.ClassModule, interfaceCode, componentName: interfaceName); + if (model.InterfaceInstancing == ClassInstancing.Public) + { + _addComponentService.AddComponentWithAttributes(targetProjectId, ComponentType.ClassModule, interfaceCode, componentName: interfaceName); + } + else + { + _addComponentService.AddComponent(targetProjectId, ComponentType.ClassModule, interfaceCode, componentName: interfaceName); + } + } + + private static string InterfaceCode(ExtractInterfaceModel model) + { + var interfaceBody = InterfaceModuleBody(model); + + if (model.InterfaceInstancing == ClassInstancing.Public) + { + var moduleHeader = ExposedInterfaceHeader(model.InterfaceName); + return $"{moduleHeader}{Environment.NewLine}{interfaceBody}"; + } + + return interfaceBody; } private static string InterfaceModuleBody(ExtractInterfaceModel model) @@ -80,10 +100,25 @@ private static string InterfaceModuleBody(ExtractInterfaceModel model) ? $"'@{folderAnnotation.Context.GetText()}{Environment.NewLine}" : string.Empty; + var exposedAnnotation = new ExposedModuleAnnotation(); + var exposedAnnotationText = model.InterfaceInstancing == ClassInstancing.Public + ? $"'@{exposedAnnotation.Name}{Environment.NewLine}" + : string.Empty; + var interfaceAnnotation = new InterfaceAnnotation(); var interfaceAnnotationText = $"'@{interfaceAnnotation.Name}{Environment.NewLine}"; - return $"{optionExplicit}{Environment.NewLine}{folderAnnotationText}{interfaceAnnotationText}{Environment.NewLine}{interfaceMembers}"; + return $"{optionExplicit}{Environment.NewLine}{folderAnnotationText}{exposedAnnotationText}{interfaceAnnotationText}{Environment.NewLine}{interfaceMembers}"; + } + + private static string ExposedInterfaceHeader(string interfaceName) + { + return $@"VERSION 1.0 CLASS +BEGIN + MultiUse = -1 'True +END +Attribute VB_Name = ""{interfaceName}"" +Attribute VB_Exposed = True"; } private void AddImplementsStatement(ExtractInterfaceModel model, IRewriteSession rewriteSession) diff --git a/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceRefactoringActionTests.cs b/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceRefactoringActionTests.cs index dbe9b7ece6..b39ea8362d 100644 --- a/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceRefactoringActionTests.cs +++ b/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceRefactoringActionTests.cs @@ -662,6 +662,58 @@ End Sub ExecuteTest(inputCode, expectedClassCode, expectedInterfaceCode, SelectAllMembers); } + [Test] + [Category("Refactorings")] + [Category("Implement Interface")] + public void ExtractInterfaceRefactoring_PublicInterfaceInstancingCreatesExposedInterface() + { + + //Input + const string inputCode = + @"'@Folder(""MyFolder.MySubFolder"") + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub"; + + //Expectation + const string expectedClassCode = + @"Implements IClass + +'@Folder(""MyFolder.MySubFolder"") + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub + +Private Sub IClass_Foo(ByVal arg1 As Integer, ByVal arg2 As String) + Err.Raise 5 'TODO implement interface member +End Sub +"; + + const string expectedInterfaceCode = + @"VERSION 1.0 CLASS +BEGIN + MultiUse = -1 'True +END +Attribute VB_Name = ""IClass"" +Attribute VB_Exposed = True +Option Explicit + +'@Folder(""MyFolder.MySubFolder"") +'@Exposed +'@Interface + +Public Sub Foo(ByVal arg1 As Integer, ByVal arg2 As String) +End Sub +"; + Func modelAdjustment = model => + { + var modifiedModel = SelectAllMembers(model); + modifiedModel.InterfaceInstancing = ClassInstancing.Public; + return modifiedModel; + }; + ExecuteTest(inputCode, expectedClassCode, expectedInterfaceCode, modelAdjustment); + } + private void ExecuteTest(string inputCode, string expectedClassCode, string expectedInterfaceCode, Func modelAdjustment) { var refactoredCode = RefactoredCode( diff --git a/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceTests.cs b/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceTests.cs index 1db7eeb3cd..cf9c7b90d2 100644 --- a/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceTests.cs +++ b/RubberduckTests/Refactoring/ExtractInterface/ExtractInterfaceTests.cs @@ -144,7 +144,10 @@ public void ExtractInterfaceRefactoring_IgnoresField() var vbe = MockVbeBuilder.BuildFromSingleModule(inputCode, ComponentType.ClassModule, out _, selection); using(var state = MockParser.CreateAndParse(vbe.Object)) { - var target = state.DeclarationFinder.UserDeclarations(DeclarationType.ClassModule).First(); + var target = state.DeclarationFinder + .UserDeclarations(DeclarationType.ClassModule) + .OfType() + .First(); //Specify Params to remove var model = new ExtractInterfaceModel(state, target); @@ -152,6 +155,60 @@ public void ExtractInterfaceRefactoring_IgnoresField() } } + [Test] + [Category("Refactorings")] + [Category("Extract Interface")] + public void ExtractInterfaceRefactoring_DefaultsToPublicInterfaceForExposedImplementingClass() + { + //Input + const string inputCode = + @"Attribute VB_Exposed = True + +Public Sub Foo +End Sub"; + + var selection = new Selection(1, 23, 1, 27); + + var vbe = MockVbeBuilder.BuildFromSingleModule(inputCode, ComponentType.ClassModule, out _, selection); + using (var state = MockParser.CreateAndParse(vbe.Object)) + { + var target = state.DeclarationFinder + .UserDeclarations(DeclarationType.ClassModule) + .OfType() + .First(); + + //Specify Params to remove + var model = new ExtractInterfaceModel(state, target); + Assert.AreEqual(ClassInstancing.Public, model.InterfaceInstancing); + } + } + + [Test] + [Category("Refactorings")] + [Category("Extract Interface")] + public void ExtractInterfaceRefactoring_DefaultsToPrivateInterfaceForNonExposedImplementingClass() + { + //Input + const string inputCode = + @"Public Sub Foo +End Sub"; + + var selection = new Selection(1, 23, 1, 27); + + var vbe = MockVbeBuilder.BuildFromSingleModule(inputCode, ComponentType.ClassModule, out _, selection); + using (var state = MockParser.CreateAndParse(vbe.Object)) + { + var target = state.DeclarationFinder + .UserDeclarations(DeclarationType.ClassModule) + .OfType() + .First(); + + //Specify Params to remove + var model = new ExtractInterfaceModel(state, target); + Assert.AreEqual(ClassInstancing.Private, model.InterfaceInstancing); + } + } + [Test] [Category("Refactorings")] [Category("Extract Interface")] From e9937a2a8ce9d6274268edb8644d94c103f82b09 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Fri, 21 Feb 2020 14:17:43 +0100 Subject: [PATCH 248/461] Correct ProjectDisplayName for VB6 --- .../CodeExplorerProjectViewModel.cs | 1 - .../SafeComWrappers/VB/VBProject.cs | 73 +++---------------- 2 files changed, 10 insertions(+), 64 deletions(-) diff --git a/Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerProjectViewModel.cs b/Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerProjectViewModel.cs index f88c3cd967..b4de112842 100644 --- a/Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerProjectViewModel.cs +++ b/Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerProjectViewModel.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.ComponentModel; using System.Linq; using System.Windows; using Rubberduck.AddRemoveReferences; diff --git a/Rubberduck.VBEditor.VB6/SafeComWrappers/VB/VBProject.cs b/Rubberduck.VBEditor.VB6/SafeComWrappers/VB/VBProject.cs index dfa93bc986..99cbc0e50a 100644 --- a/Rubberduck.VBEditor.VB6/SafeComWrappers/VB/VBProject.cs +++ b/Rubberduck.VBEditor.VB6/SafeComWrappers/VB/VBProject.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.Linq; using System.Runtime.InteropServices; using System.Text.RegularExpressions; using Rubberduck.VBEditor.SafeComWrappers.Abstract; @@ -193,15 +192,9 @@ public string ProjectDisplayName _displayName = DisplayNameFromWindowCaption(); } - if (string.IsNullOrEmpty(_displayName) - || _displayName.EndsWith("...")) + if (string.IsNullOrEmpty(_displayName)) { - var nameFromBuildFileName = DisplayNameFromBuildFileName(); - if (!string.IsNullOrEmpty(nameFromBuildFileName) - && nameFromBuildFileName.Length > _displayName.Length - 3) //Otherwise, we got more of the name from the previous attempt. - { - _displayName = nameFromBuildFileName; - } + _displayName = DisplayNameFromBuildFileName(); } return _displayName; @@ -221,11 +214,7 @@ private string DisplayNameFromBuildFileName() : pseudoDllName.Substring(0, pseudoDllName.Length - 4); } - private static readonly Regex CaptionProjectRegex = new Regex(@"^(?:[^-]+)(?:\s-\s)(?.+)(?:\s-\s.*)?$"); - private static readonly Regex OpenModuleRegex = new Regex(@"^(?.+)(?\s-\s\[.*\((Code|UserForm)\)\])$"); - private static readonly Regex PartialOpenModuleRegex = new Regex(@"^(?.+)(\s-\s\[)"); - private static readonly Regex NearlyOnlyProject = new Regex(@"^(?.+)(\s-?\s?)$"); - + private static readonly Regex CaptionProjectRegex = new Regex(@"^(?.+)(?:\s-\s)Microsoft Visual"); private string DisplayNameFromWindowCaption() { using (var vbe = VBE) @@ -240,62 +229,20 @@ private string DisplayNameFromWindowCaption() } var caption = mainWindow.Caption; - if (caption.Length > 99) + if (CaptionProjectRegex.IsMatch(caption)) { - //The value returned will be truncated at character 99 and the rest is garbage due to a bug in the VBE API. - caption = caption.Substring(0, 99); - - if (CaptionProjectRegex.IsMatch(caption)) - { - var projectRelatedPartOfCaption = CaptionProjectRegex - .Matches(caption)[0] - .Groups["project"] - .Value; - - if (PartialOpenModuleRegex.IsMatch(projectRelatedPartOfCaption)) - { - return PartialOpenModuleRegex - .Matches(projectRelatedPartOfCaption)[0] - .Groups["project"] - .Value; - } - - if (NearlyOnlyProject.IsMatch(projectRelatedPartOfCaption)) - { - return NearlyOnlyProject - .Matches(projectRelatedPartOfCaption)[0] - .Groups["project"] - .Value; - } - - return $"{projectRelatedPartOfCaption}..."; - } - } - else - { - if (CaptionProjectRegex.IsMatch(caption)) - { - var projectRelatedPartOfCaption = CaptionProjectRegex - .Matches(caption)[0] - .Groups["project"] - .Value; - - if (OpenModuleRegex.IsMatch(projectRelatedPartOfCaption)) - { - return OpenModuleRegex - .Matches(projectRelatedPartOfCaption)[0] - .Groups["project"] - .Value; - } - } + return CaptionProjectRegex + .Matches(caption)[0] + .Groups["project"] + .Value; } + + return string.Empty; } catch { return string.Empty; } - - return string.Empty; } } From d76917c082ea269f8bceb9ecc46c61cc613c39d5 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Fri, 21 Feb 2020 18:31:29 +0100 Subject: [PATCH 249/461] Refactor inspection base classes Loosely based on review comments to PR #5384 --- .../Abstract/DeclarationInspectionBase.cs | 14 ++++++-- .../Abstract/DeclarationInspectionBaseBase.cs | 29 +++-------------- ...ionInspectionUsingGlobalInformationBase.cs | 14 ++++++-- ...nspectionUsingGlobalInformationBaseBase.cs | 32 +++++-------------- .../IdentifierReferenceInspectionBase.cs | 31 +++++++++--------- ...ReferenceInspectionFromDeclarationsBase.cs | 14 ++++++-- 6 files changed, 61 insertions(+), 73 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs index ea3b5cc195..6821e3ae7f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs @@ -62,15 +62,23 @@ protected DeclarationInspectionBase(RubberduckParserState state, DeclarationType protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { var objectionableDeclarationsWithAdditionalProperties = RelevantDeclarationsInModule(module, finder) - .Select(declaration => (declaration, IsResultDeclarationWithAdditionalProperties(declaration, finder))) - .Where(tpl => tpl.Item2.isResult) - .Select(tpl => (tpl.declaration, tpl.Item2.properties)); + .Select(declaration => DeclarationWithResultProperties(declaration, finder)) + .Where(result => result.HasValue) + .Select(result => result.Value); return objectionableDeclarationsWithAdditionalProperties .Select(tpl => InspectionResult(tpl.declaration, tpl.properties)) .ToList(); } + private (Declaration declaration, T properties)? DeclarationWithResultProperties(Declaration declaration, DeclarationFinder finder) + { + var (isResult, properties) = IsResultDeclarationWithAdditionalProperties(declaration, finder); + return isResult + ? (declaration, properties) + : ((Declaration declaration, T properties)?) null; + } + protected virtual IInspectionResult InspectionResult(Declaration declaration, T properties) { return new DeclarationInspectionResult( diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs index 3f46d4f1ef..74339e77a8 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs @@ -33,30 +33,11 @@ protected override IEnumerable DoGetInspectionResults() { var finder = DeclarationFinderProvider.DeclarationFinder; - var results = new List(); - foreach (var moduleDeclaration in finder.UserDeclarations(DeclarationType.Module)) - { - if (moduleDeclaration == null) - { - continue; - } - - var module = moduleDeclaration.QualifiedModuleName; - results.AddRange(DoGetInspectionResults(module, finder)); - } - - foreach (var projectDeclaration in finder.UserDeclarations(DeclarationType.Project)) - { - if (projectDeclaration == null) - { - continue; - } - - var module = projectDeclaration.QualifiedModuleName; - results.AddRange(DoGetInspectionResults(module, finder)); - } - - return results; + return finder.UserDeclarations(DeclarationType.Module) + .Concat(finder.UserDeclarations(DeclarationType.Project)) + .Where(declaration => declaration != null) + .SelectMany(declaration => DoGetInspectionResults(declaration.QualifiedModuleName, finder)) + .ToList(); } protected virtual IEnumerable DoGetInspectionResults(QualifiedModuleName module) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBase.cs index 1a75d36861..0c39aebce5 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBase.cs @@ -62,15 +62,23 @@ protected DeclarationInspectionUsingGlobalInformationBase(RubberduckParserState protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder, TGlobalInfo globalInformation) { var objectionableDeclarationsWithAdditionalProperties = RelevantDeclarationsInModule(module, finder) - .Select(declaration => (declaration, IsResultDeclarationWithAdditionalProperties(declaration, finder, globalInformation))) - .Where(tpl => tpl.Item2.isResult) - .Select(tpl => (tpl.declaration, tpl.Item2.properties)); + .Select(declaration => DeclarationWithResultProperties(declaration, finder, globalInformation)) + .Where(result => result.HasValue) + .Select(result => result.Value); return objectionableDeclarationsWithAdditionalProperties .Select(tpl => InspectionResult(tpl.declaration, tpl.properties)) .ToList(); } + private (Declaration declaration, TProperties properties)? DeclarationWithResultProperties(Declaration declaration, DeclarationFinder finder, TGlobalInfo globalInformation) + { + var (isResult, properties) = IsResultDeclarationWithAdditionalProperties(declaration, finder, globalInformation); + return isResult + ? (declaration, properties) + : ((Declaration declaration, TProperties properties)?)null; + } + protected virtual IInspectionResult InspectionResult(Declaration declaration, TProperties properties) { return new DeclarationInspectionResult( diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs index 3d302a05bf..f4486a341b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs @@ -30,6 +30,9 @@ protected DeclarationInspectionUsingGlobalInformationBaseBase(RubberduckParserSt protected abstract IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder, T globalInformation); protected abstract T GlobalInformation(DeclarationFinder finder); + /// + /// Can be overwritten to enhance performance if providing the global information for one module module only is cheaper than getting it for all modules. + /// protected virtual T GlobalInformation(QualifiedModuleName module, DeclarationFinder finder) { return GlobalInformation(finder); @@ -40,30 +43,11 @@ protected override IEnumerable DoGetInspectionResults() var finder = DeclarationFinderProvider.DeclarationFinder; var globalInformation = GlobalInformation(finder); - var results = new List(); - foreach (var moduleDeclaration in finder.UserDeclarations(DeclarationType.Module)) - { - if (moduleDeclaration == null) - { - continue; - } - - var module = moduleDeclaration.QualifiedModuleName; - results.AddRange(DoGetInspectionResults(module, finder, globalInformation)); - } - - foreach (var projectDeclaration in finder.UserDeclarations(DeclarationType.Project)) - { - if (projectDeclaration == null) - { - continue; - } - - var module = projectDeclaration.QualifiedModuleName; - results.AddRange(DoGetInspectionResults(module, finder, globalInformation)); - } - - return results; + return finder.UserDeclarations(DeclarationType.Module) + .Concat(finder.UserDeclarations(DeclarationType.Project)) + .Where(declaration => declaration != null) + .SelectMany(declaration => DoGetInspectionResults(declaration.QualifiedModuleName, finder, globalInformation)) + .ToList(); } protected virtual IEnumerable DoGetInspectionResults(QualifiedModuleName module) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs index 6a5b1b4fee..ff48afa1ca 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs @@ -24,19 +24,10 @@ protected override IEnumerable DoGetInspectionResults() { var finder = DeclarationFinderProvider.DeclarationFinder; - var results = new List(); - foreach (var moduleDeclaration in State.DeclarationFinder.UserDeclarations(DeclarationType.Module)) - { - if (moduleDeclaration == null) - { - continue; - } - - var module = moduleDeclaration.QualifiedModuleName; - results.AddRange(DoGetInspectionResults(module, finder)); - } - - return results; + return finder.UserDeclarations(DeclarationType.Module) + .Where(declaration => declaration != null) + .SelectMany(declaration => DoGetInspectionResults(declaration.QualifiedModuleName, finder)) + .ToList(); } protected IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) @@ -104,15 +95,23 @@ protected override IEnumerable DoGetInspectionResults() protected IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { var objectionableReferencesWithProperties = ReferencesInModule(module, finder) - .Select(reference => (reference, IsResultReferenceWithAdditionalProperties(reference, finder))) - .Where(tpl => tpl.Item2.isResult) - .Select(tpl => (tpl.reference, tpl.Item2.properties)); + .Select(reference => ReferenceWithResultProperties(reference, finder)) + .Where(result => result.HasValue) + .Select(result => result.Value); return objectionableReferencesWithProperties .Select(tpl => InspectionResult(tpl.reference, DeclarationFinderProvider, tpl.properties)) .ToList(); } + private (IdentifierReference reference, T properties)? ReferenceWithResultProperties(IdentifierReference reference, DeclarationFinder finder) + { + var (isResult, properties) = IsResultReferenceWithAdditionalProperties(reference, finder); + return isResult + ? (reference, properties) + : ((IdentifierReference reference, T properties)?)null; + } + protected IEnumerable DoGetInspectionResults(QualifiedModuleName module) { var finder = DeclarationFinderProvider.DeclarationFinder; diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs index 0a3baba8a4..6db547f2bb 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs @@ -92,9 +92,17 @@ protected override IEnumerable DoGetInspectionResults() private IEnumerable<(IdentifierReference reference, T properties)> ResultReferences(IEnumerable potentialResultReferences, DeclarationFinder finder) { return potentialResultReferences - .Select(reference => (reference, IsResultReferenceWithAdditionalProperties(reference, finder))) - .Where(tpl => tpl.Item2.isResult) - .Select(tpl => (tpl.reference, tpl.Item2.properties)); + .Select(reference => ReferenceWithResultProperties(reference, finder)) + .Where(result => result.HasValue) + .Select(result => result.Value); ; + } + + private (IdentifierReference reference, T properties)? ReferenceWithResultProperties(IdentifierReference reference, DeclarationFinder finder) + { + var (isResult, properties) = IsResultReferenceWithAdditionalProperties(reference, finder); + return isResult + ? (reference, properties) + : ((IdentifierReference reference, T properties)?)null; } protected virtual IEnumerable ObjectionableReferences(DeclarationFinder finder) From 137e3dc1e049b8372c7bfec8689a7d03ccd60c11 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Tue, 25 Feb 2020 21:20:51 +0100 Subject: [PATCH 250/461] Redesign ParseTreeInspection base class Also adds a base for inspection listeners. --- .../Abstract/ParseTreeInspectionBase.cs | 140 ++++++++++++++++++ .../BooleanAssignedInIfElseInspection.cs | 37 ++--- .../Concrete/DefTypeStatementInspection.cs | 45 ++---- .../EmptyBlockInspectionListenerBase.cs | 25 +--- .../Concrete/EmptyCaseBlockInspection.cs | 16 +- .../Concrete/EmptyDoWhileBlockInspection.cs | 15 +- .../Concrete/EmptyElseBlockInspection.cs | 16 +- .../Concrete/EmptyForEachBlockInspection.cs | 16 +- .../Concrete/EmptyForLoopBlockInspection.cs | 17 +-- .../Concrete/EmptyIfBlockInspection.cs | 15 +- .../Concrete/EmptyStringLiteralInspection.cs | 31 +--- .../Concrete/EmptyWhileWendBlockInspection.cs | 16 +- .../Concrete/IllegalAnnotationInspection.cs | 1 - .../ImplicitByRefModifierInspection.cs | 58 +++----- .../MissingAnnotationArgumentInspection.cs | 42 ++---- .../ModuleScopeDimKeywordInspection.cs | 31 ++-- .../Concrete/MultilineParameterInspection.cs | 35 +---- .../MultipleDeclarationsInspection.cs | 28 +--- .../ObsoleteCallStatementInspection.cs | 67 +++------ .../ObsoleteCallingConventionInspection.cs | 36 ++--- .../ObsoleteCommentSyntaxInspection.cs | 27 +--- .../Concrete/ObsoleteErrorSyntaxInspection.cs | 27 +--- .../ObsoleteLetStatementInspection.cs | 24 +-- .../ObsoleteWhileWendStatementInspection.cs | 27 +--- .../Concrete/OnLocalErrorInspection.cs | 28 +--- .../Concrete/OptionBaseInspection.cs | 30 +--- .../Concrete/OptionExplicitInspection.cs | 53 +++---- ...ocedureCanBeWrittenAsFunctionInspection.cs | 29 ++-- .../RedundantByRefModifierInspection.cs | 57 +++---- .../Concrete/RedundantOptionInspection.cs | 31 +--- .../Concrete/StepIsNotSpecifiedInspection.cs | 40 ++--- .../Concrete/StepOneIsRedundantInspection.cs | 43 ++---- .../Concrete/StopKeywordInspection.cs | 31 +--- ...neContinuationBetweenKeywordsInspection.cs | 27 +--- .../NegativeLineNumberInspection.cs | 26 +--- .../OnErrorGoToMinusOneInspection.cs | 26 +--- .../UnhandledOnErrorResumeNextInspection.cs | 46 +++--- .../ParseTreeValueVisitor.cs | 4 +- .../UnreachableCaseInspection.cs | 68 ++++++--- .../AttributeAnnotationListener.cs | 116 --------------- .../RestoreErrorHandlingQuickFix.cs | 2 +- .../Abstract/IInpsectionListener.cs | 3 +- .../ObsoleteCallStatementInspectionTests.cs | 4 +- .../RedundantOptionInspectionTests.cs | 2 +- .../UnreachableCaseInspectionTests.cs | 6 +- .../QuickFixes/IgnoreOnceQuickFixTests.cs | 2 +- ...emoveExplicitCallStatementQuickFixTests.cs | 2 +- 47 files changed, 536 insertions(+), 932 deletions(-) delete mode 100644 Rubberduck.CodeAnalysis/Inspections/ParseTreeListeners/AttributeAnnotationListener.cs diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs index 37a0511d32..21183b4b13 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs @@ -1,6 +1,14 @@ +using System.Collections.Generic; +using System.Linq; +using Antlr4.Runtime; +using Rubberduck.Inspections.Results; +using Rubberduck.Parsing; +using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.Parsing; +using Rubberduck.VBEditor; +using Rubberduck.VBEditor.Extensions; namespace Rubberduck.Inspections.Abstract { @@ -10,6 +18,138 @@ protected ParseTreeInspectionBase(RubberduckParserState state) : base(state) { } public abstract IInspectionListener Listener { get; } + protected abstract string ResultDescription(QualifiedContext context); + + protected virtual bool IsResultContext(QualifiedContext context) => true; + + protected override IEnumerable DoGetInspectionResults() + { + return DoGetInspectionResults(Listener.Contexts()); + } + + private IEnumerable DoGetInspectionResults(QualifiedModuleName module) + { + return DoGetInspectionResults(Listener.Contexts(module)); + } + + private IEnumerable DoGetInspectionResults(IEnumerable> contexts) + { + var objectionableContexts = contexts + .Where(IsResultContext); + + return objectionableContexts + .Select(InspectionResult) + .ToList(); + } + + protected virtual IInspectionResult InspectionResult(QualifiedContext context) + { + return new QualifiedContextInspectionResult( + this, + ResultDescription(context), + context, + DisabledQuickFixes(context)); + } + + protected virtual ICollection DisabledQuickFixes(QualifiedContext context) => new List(); + public virtual CodeKind TargetKindOfCode => CodeKind.CodePaneCode; + } + + + public abstract class ParseTreeInspectionBase : InspectionBase, IParseTreeInspection + { + protected ParseTreeInspectionBase(RubberduckParserState state) + : base(state) + {} + + public abstract IInspectionListener Listener { get; } + protected abstract string ResultDescription(QualifiedContext context, T properties); + protected abstract (bool isResult, T properties) IsResultContextWithAdditionalProperties(QualifiedContext context); + + protected override IEnumerable DoGetInspectionResults() + { + return DoGetInspectionResults(Listener.Contexts()); + } + + private IEnumerable DoGetInspectionResults(QualifiedModuleName module) + { + return DoGetInspectionResults(Listener.Contexts(module)); + } + + private IEnumerable DoGetInspectionResults(IEnumerable> contexts) + { + var objectionableContexts = contexts + .Select(ContextsWithResultProperties) + .Where(result => result.HasValue) + .Select(result => result.Value); + + return objectionableContexts + .Select(tpl => InspectionResult(tpl.context, tpl.properties)) + .ToList(); + } + + private (QualifiedContext context, T properties)? ContextsWithResultProperties(QualifiedContext context) + { + var (isResult, properties) = IsResultContextWithAdditionalProperties(context); + return isResult + ? (context, properties) + : ((QualifiedContext context, T properties)?) null; + } + + protected virtual IInspectionResult InspectionResult(QualifiedContext context, T properties) + { + return new QualifiedContextInspectionResult( + this, + ResultDescription(context, properties), + context, + properties, + DisabledQuickFixes(context, properties)); + } + + protected virtual ICollection DisabledQuickFixes(QualifiedContext context, T properties) => new List(); public virtual CodeKind TargetKindOfCode => CodeKind.CodePaneCode; } + + public class InspectionListenerBase : VBAParserBaseListener, IInspectionListener + { + private readonly IDictionary>> _contexts; + + public InspectionListenerBase() + { + _contexts = new Dictionary>>(); + } + + public QualifiedModuleName CurrentModuleName { get; set; } + + public IReadOnlyList> Contexts() + { + return _contexts.AllValues().ToList(); + } + + public IReadOnlyList> Contexts(QualifiedModuleName module) + { + return _contexts.TryGetValue(module, out var contexts) + ? contexts + : new List>(); + } + + public virtual void ClearContexts() + { + _contexts.Clear(); + } + + protected void SaveContext(ParserRuleContext context) + { + var module = CurrentModuleName; + var qualifiedContext = new QualifiedContext(module, context); + if (_contexts.TryGetValue(module, out var contexts)) + { + contexts.Add(qualifiedContext); + } + else + { + _contexts.Add(module, new List>{qualifiedContext}); + } + } + } } \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs index 7f6b2c93c7..993aa29f9a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs @@ -1,14 +1,11 @@ -using System.Collections.Generic; -using System.Linq; +using System.Linq; using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete { @@ -48,27 +45,21 @@ public BooleanAssignedInIfElseInspection(RubberduckParserState state) public override IInspectionListener Listener { get; } = new BooleanAssignedInIfElseListener(); - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts - .Select(result => new QualifiedContextInspectionResult(this, - string.Format(InspectionResults.BooleanAssignedInIfElseInspection, - (((VBAParser.IfStmtContext)result.Context).block().GetDescendent()).lExpression().GetText().Trim()), - result)); + var literalText = ((VBAParser.IfStmtContext) context.Context) + .block() + .GetDescendent() + .lExpression() + .GetText() + .Trim(); + return string.Format( + InspectionResults.BooleanAssignedInIfElseInspection, + literalText); } - public class BooleanAssignedInIfElseListener : VBAParserBaseListener, IInspectionListener + public class BooleanAssignedInIfElseListener : InspectionListenerBase { - private readonly List> _contexts = new List>(); - public IReadOnlyList> Contexts => _contexts; - - public QualifiedModuleName CurrentModuleName { get; set; } - - public void ClearContexts() - { - _contexts.Clear(); - } - public override void ExitIfStmt(VBAParser.IfStmtContext context) { if (context.elseIfBlock() != null && context.elseIfBlock().Any()) @@ -101,10 +92,10 @@ public override void ExitIfStmt(VBAParser.IfStmtContext context) return; } - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } - private bool IsSingleBooleanAssignment(VBAParser.BlockContext block) + private static bool IsSingleBooleanAssignment(VBAParser.BlockContext block) { if (block.ChildCount != 2) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs index b960134ec1..833f02c88b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Inspections; @@ -7,10 +6,7 @@ using Rubberduck.Parsing.Grammar; using Antlr4.Runtime; using Rubberduck.Parsing; -using Rubberduck.VBEditor; using Antlr4.Runtime.Misc; -using Rubberduck.Inspections.Results; -using Rubberduck.Inspections.Inspections.Extensions; namespace Rubberduck.Inspections.Concrete { @@ -40,34 +36,15 @@ public DefTypeStatementInspection(RubberduckParserState state) } public override IInspectionListener Listener { get; } - - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - var results = Listener.Contexts - .Select(context => new QualifiedContextInspectionResult(this, - string.Format(InspectionResults.DefTypeStatementInspection, - GetTypeOfDefType(context.Context.start.Text), - context.Context.start.Text), - context)); - return results; - } - - public class DefTypeStatementInspectionListener : VBAParserBaseListener, IInspectionListener - { - private readonly List> _contexts = new List>(); - public IReadOnlyList> Contexts => _contexts; - - public QualifiedModuleName CurrentModuleName { get; set; } + var typeName = GetTypeOfDefType(context.Context.start.Text); + var defStmtText = context.Context.start.Text; - public void ClearContexts() - { - _contexts.Clear(); - } - - public override void ExitDefType([NotNull] VBAParser.DefTypeContext context) - { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); - } + return string.Format( + InspectionResults.DefTypeStatementInspection, + typeName, + defStmtText); } private string GetTypeOfDefType(string defType) @@ -90,5 +67,13 @@ private string GetTypeOfDefType(string defType) { "DefObj", "Object" }, { "DefVar", "Variant" } }; + + public class DefTypeStatementInspectionListener : InspectionListenerBase + { + public override void ExitDefType([NotNull] VBAParser.DefTypeContext context) + { + SaveContext(context); + } + } } } \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlockInspectionListenerBase.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlockInspectionListenerBase.cs index 9cf11b3ef8..bcd20c524c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlockInspectionListenerBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlockInspectionListenerBase.cs @@ -1,39 +1,22 @@ using Antlr4.Runtime; -using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; -using Rubberduck.VBEditor; using System.Collections.Generic; using System.Diagnostics; using Antlr4.Runtime.Tree; +using Rubberduck.Inspections.Abstract; namespace Rubberduck.Inspections.Concrete { - public class EmptyBlockInspectionListenerBase : VBAParserBaseListener, IInspectionListener + public class EmptyBlockInspectionListenerBase : InspectionListenerBase { - private readonly List> _contexts = new List>(); - public IReadOnlyList> Contexts => _contexts; - - public QualifiedModuleName CurrentModuleName { get; set; } - - public void ClearContexts() - { - _contexts.Clear(); - } - public void InspectBlockForExecutableStatements(VBAParser.BlockContext block, T context) where T : ParserRuleContext { if (!BlockContainsExecutableStatements(block)) { - AddResult(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } } - public void AddResult(QualifiedContext qualifiedContext) - { - _contexts.Add(qualifiedContext); - } - private bool BlockContainsExecutableStatements(VBAParser.BlockContext block) { return block?.children != null && ContainsExecutableStatements(block.children); @@ -82,7 +65,7 @@ public void InspectBlockForExecutableStatements(VBAParser.UnterminatedBlockCo { if (!BlockContainsExecutableStatements(block)) { - AddResult(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyCaseBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyCaseBlockInspection.cs index 06530cc92b..a26b244dbe 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyCaseBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyCaseBlockInspection.cs @@ -1,15 +1,13 @@ using Antlr4.Runtime.Misc; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Common; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using System.Collections.Generic; -using System.Linq; +using Antlr4.Runtime; using Rubberduck.Resources.Experimentals; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing; namespace Rubberduck.Inspections.Concrete { @@ -46,17 +44,15 @@ namespace Rubberduck.Inspections.Concrete internal class EmptyCaseBlockInspection : ParseTreeInspectionBase { public EmptyCaseBlockInspection(RubberduckParserState state) - : base(state) { } + : base(state) + {} public override IInspectionListener Listener { get; } = new EmptyCaseBlockListener(); - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts - .Select(result => new QualifiedContextInspectionResult(this, - InspectionResults.EmptyCaseBlockInspection, - result)); + return InspectionResults.EmptyCaseBlockInspection; } public class EmptyCaseBlockListener : EmptyBlockInspectionListenerBase diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyDoWhileBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyDoWhileBlockInspection.cs index a1f47e54b2..9c9fb755a2 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyDoWhileBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyDoWhileBlockInspection.cs @@ -1,15 +1,13 @@ using Antlr4.Runtime.Misc; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Common; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using System.Collections.Generic; -using System.Linq; +using Antlr4.Runtime; using Rubberduck.Resources.Experimentals; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing; namespace Rubberduck.Inspections.Concrete { @@ -41,13 +39,12 @@ namespace Rubberduck.Inspections.Concrete internal class EmptyDoWhileBlockInspection : ParseTreeInspectionBase { public EmptyDoWhileBlockInspection(RubberduckParserState state) - : base(state) { } + : base(state) + {} - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts - .Select(result => - new QualifiedContextInspectionResult(this, InspectionResults.EmptyDoWhileBlockInspection, result)); + return InspectionResults.EmptyDoWhileBlockInspection; } public override IInspectionListener Listener { get; } = new EmptyDoWhileBlockListener(); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyElseBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyElseBlockInspection.cs index e7417e100c..a01d71e03d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyElseBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyElseBlockInspection.cs @@ -1,15 +1,13 @@ using Antlr4.Runtime.Misc; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Common; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using System.Collections.Generic; -using System.Linq; +using Antlr4.Runtime; using Rubberduck.Resources.Experimentals; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing; namespace Rubberduck.Inspections.Concrete { @@ -43,14 +41,12 @@ namespace Rubberduck.Inspections.Concrete internal class EmptyElseBlockInspection : ParseTreeInspectionBase { public EmptyElseBlockInspection(RubberduckParserState state) - : base(state) { } + : base(state) + {} - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts - .Select(result => new QualifiedContextInspectionResult(this, - InspectionResults.EmptyElseBlockInspection, - result)); + return InspectionResults.EmptyElseBlockInspection; } public override IInspectionListener Listener { get; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForEachBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForEachBlockInspection.cs index 8078779758..ee39380e81 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForEachBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForEachBlockInspection.cs @@ -1,15 +1,13 @@ using Antlr4.Runtime.Misc; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Common; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using System.Collections.Generic; -using System.Linq; +using Antlr4.Runtime; using Rubberduck.Resources.Experimentals; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing; namespace Rubberduck.Inspections.Concrete { @@ -43,14 +41,12 @@ namespace Rubberduck.Inspections.Concrete internal class EmptyForEachBlockInspection : ParseTreeInspectionBase { public EmptyForEachBlockInspection(RubberduckParserState state) - : base(state) { } + : base(state) + {} - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts - .Select(result => new QualifiedContextInspectionResult(this, - InspectionResults.EmptyForEachBlockInspection, - result)); + return InspectionResults.EmptyForEachBlockInspection; } public override IInspectionListener Listener { get; } = diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForLoopBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForLoopBlockInspection.cs index e96baf4aba..cb39392bff 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForLoopBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForLoopBlockInspection.cs @@ -1,15 +1,13 @@ using Antlr4.Runtime.Misc; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Common; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using System.Collections.Generic; -using System.Linq; +using Antlr4.Runtime; using Rubberduck.Resources.Experimentals; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing; namespace Rubberduck.Inspections.Concrete { @@ -45,18 +43,15 @@ internal class EmptyForLoopBlockInspection : ParseTreeInspectionBase public EmptyForLoopBlockInspection(RubberduckParserState state) : base(state) { } - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts - .Select(result => new QualifiedContextInspectionResult(this, - InspectionResults.EmptyForLoopBlockInspection, - result)); + return InspectionResults.EmptyForLoopBlockInspection; } public override IInspectionListener Listener { get; } = - new EmptyForloopBlockListener(); + new EmptyForLoopBlockListener(); - public class EmptyForloopBlockListener : EmptyBlockInspectionListenerBase + public class EmptyForLoopBlockListener : EmptyBlockInspectionListenerBase { public override void EnterForNextStmt([NotNull] VBAParser.ForNextStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyIfBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyIfBlockInspection.cs index d124bba6dc..6d552909cd 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyIfBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyIfBlockInspection.cs @@ -1,14 +1,11 @@ using Antlr4.Runtime; using Antlr4.Runtime.Misc; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using System.Collections.Generic; -using System.Linq; namespace Rubberduck.Inspections.Concrete { @@ -40,14 +37,12 @@ namespace Rubberduck.Inspections.Concrete internal class EmptyIfBlockInspection : ParseTreeInspectionBase { public EmptyIfBlockInspection(RubberduckParserState state) - : base(state) { } + : base(state) + {} - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts - .Select(result => new QualifiedContextInspectionResult(this, - InspectionResults.EmptyIfBlockInspection, - result)); + return InspectionResults.EmptyIfBlockInspection; } public override IInspectionListener Listener { get; } = @@ -69,7 +64,7 @@ public override void EnterSingleLineIfStmt([NotNull] VBAParser.SingleLineIfStmtC { if (context.ifWithEmptyThen() != null) { - AddResult(new QualifiedContext(CurrentModuleName, context.ifWithEmptyThen())); + SaveContext(context.ifWithEmptyThen()); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs index 4324dac774..cab31f2acf 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs @@ -1,15 +1,10 @@ -using System.Collections.Generic; -using System.Linq; -using Antlr4.Runtime; +using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Rubberduck.VBEditor; -using Rubberduck.Inspections.Inspections.Extensions; namespace Rubberduck.Inspections.Concrete { @@ -42,37 +37,25 @@ namespace Rubberduck.Inspections.Concrete public sealed class EmptyStringLiteralInspection : ParseTreeInspectionBase { public EmptyStringLiteralInspection(RubberduckParserState state) - : base(state) { } + : base(state) + {} public override IInspectionListener Listener { get; } = new EmptyStringLiteralListener(); - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts - .Select(result => new QualifiedContextInspectionResult(this, - InspectionResults.EmptyStringLiteralInspection, - result)); + return InspectionResults.EmptyStringLiteralInspection; } - public class EmptyStringLiteralListener : VBAParserBaseListener, IInspectionListener + public class EmptyStringLiteralListener : InspectionListenerBase { - private readonly List> _contexts = new List>(); - public IReadOnlyList> Contexts => _contexts; - - public QualifiedModuleName CurrentModuleName { get; set; } - - public void ClearContexts() - { - _contexts.Clear(); - } - public override void ExitLiteralExpression(VBAParser.LiteralExpressionContext context) { var literal = context.STRINGLITERAL(); if (literal != null && literal.GetText() == "\"\"") { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyWhileWendBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyWhileWendBlockInspection.cs index 156704ac4a..aebf257729 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyWhileWendBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyWhileWendBlockInspection.cs @@ -1,15 +1,13 @@ using Antlr4.Runtime.Misc; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Common; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using System.Collections.Generic; -using System.Linq; +using Antlr4.Runtime; using Rubberduck.Resources.Experimentals; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing; namespace Rubberduck.Inspections.Concrete { @@ -41,14 +39,12 @@ namespace Rubberduck.Inspections.Concrete internal class EmptyWhileWendBlockInspection : ParseTreeInspectionBase { public EmptyWhileWendBlockInspection(RubberduckParserState state) - : base(state) { } + : base(state) + {} - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts - .Select(result => new QualifiedContextInspectionResult(this, - InspectionResults.EmptyWhileWendBlockInspection, - result)); + return InspectionResults.EmptyWhileWendBlockInspection; } public override IInspectionListener Listener { get; } = diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs index 6b0ba7da00..cd34338487 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs @@ -9,7 +9,6 @@ using Rubberduck.Parsing.Symbols; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.VBA.Extensions; using Rubberduck.VBEditor.SafeComWrappers; namespace Rubberduck.Inspections.Concrete diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitByRefModifierInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitByRefModifierInspection.cs index 4bde338b26..29f8733587 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitByRefModifierInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitByRefModifierInspection.cs @@ -1,16 +1,11 @@ -using System.Collections.Generic; using System.Linq; using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.VBA.Extensions; -using Rubberduck.VBEditor; -using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.JunkDrawer.Extensions; namespace Rubberduck.Inspections.Concrete @@ -40,52 +35,41 @@ public sealed class ImplicitByRefModifierInspection : ParseTreeInspectionBase { public ImplicitByRefModifierInspection(RubberduckParserState state) : base(state) - { - } + {} public override IInspectionListener Listener { get; } = new ImplicitByRefModifierListener(); - - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - var builtInEventHandlerContexts = State.DeclarationFinder.FindEventHandlers().Select(handler => handler.Context).ToHashSet(); - var interfaceImplementationMemberContexts = State.DeclarationFinder.FindAllInterfaceImplementingMembers().Select(member => member.Context).ToHashSet(); - - var issues = Listener.Contexts.Where(context => - !builtInEventHandlerContexts.Contains(context.Context.Parent.Parent) && - !interfaceImplementationMemberContexts.Contains(context.Context.Parent.Parent)); + var identifier = ((VBAParser.ArgContext)context.Context) + .unrestrictedIdentifier() + .identifier(); - return issues.Select(issue => - { - var identifier = ((VBAParser.ArgContext)issue.Context) - .unrestrictedIdentifier() - .identifier(); + var identifierText = identifier.untypedIdentifier() != null + ? identifier.untypedIdentifier().identifierValue().GetText() + : identifier.typedIdentifier().untypedIdentifier().identifierValue().GetText(); - return new QualifiedContextInspectionResult(this, - string.Format(InspectionResults.ImplicitByRefModifierInspection, - identifier.untypedIdentifier() != null - ? identifier.untypedIdentifier().identifierValue().GetText() - : identifier.typedIdentifier().untypedIdentifier().identifierValue().GetText()), issue); - }); + return string.Format( + InspectionResults.ImplicitByRefModifierInspection, + identifierText); } - public class ImplicitByRefModifierListener : VBAParserBaseListener, IInspectionListener + protected override bool IsResultContext(QualifiedContext context) { - private readonly List> _contexts = new List>(); - - public IReadOnlyList> Contexts => _contexts; - - public QualifiedModuleName CurrentModuleName { get; set; } + //FIXME : This should really be a declaration inspection on the parameter. + var builtInEventHandlerContexts = State.DeclarationFinder.FindEventHandlers().Select(handler => handler.Context).ToHashSet(); + var interfaceImplementationMemberContexts = State.DeclarationFinder.FindAllInterfaceImplementingMembers().Select(member => member.Context).ToHashSet(); - public void ClearContexts() - { - _contexts.Clear(); - } + return !builtInEventHandlerContexts.Contains(context.Context.Parent.Parent) + && !interfaceImplementationMemberContexts.Contains(context.Context.Parent.Parent); + } + public class ImplicitByRefModifierListener : InspectionListenerBase + { public override void ExitArg(VBAParser.ArgContext context) { if (context.PARAMARRAY() == null && context.BYVAL() == null && context.BYREF() == null) { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs index b79b9b0111..ba74bcb8b2 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs @@ -1,16 +1,11 @@ -using System.Collections.Generic; -using System.Linq; using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; -using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.Parsing; -using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete { @@ -46,38 +41,31 @@ public MissingAnnotationArgumentInspection(RubberduckParserState state) public override IInspectionListener Listener { get; } = new InvalidAnnotationStatementListener(); - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) + { + var expressionText = ((VBAParser.AnnotationContext) context.Context).annotationName().GetText(); + return string.Format( + InspectionResults.MissingAnnotationArgumentInspection, + expressionText); + } + + protected override bool IsResultContext(QualifiedContext context) { // FIXME don't actually use listeners here, iterate the Annotations instead // FIXME don't maintain a separate list for annotations that require arguments, instead use AnnotationAttribute to store that information - return (from result in Listener.Contexts - let context = (VBAParser.AnnotationContext)result.Context - where context.annotationName().GetText() == "Ignore" - || context.annotationName().GetText() == "Folder" - where context.annotationArgList() == null - select new QualifiedContextInspectionResult(this, - string.Format(InspectionResults.MissingAnnotationArgumentInspection, - ((VBAParser.AnnotationContext)result.Context).annotationName().GetText()), - result)); + var annotationContext = (VBAParser.AnnotationContext) context.Context; + return (annotationContext.annotationName().GetText() == "Ignore" + || annotationContext.annotationName().GetText() == "Folder") + && annotationContext.annotationArgList() == null; } - public class InvalidAnnotationStatementListener : VBAParserBaseListener, IInspectionListener + public class InvalidAnnotationStatementListener : InspectionListenerBase { - private readonly List> _contexts = new List>(); - public IReadOnlyList> Contexts => _contexts; - - public QualifiedModuleName CurrentModuleName { get; set; } - - public void ClearContexts() - { - _contexts.Clear(); - } - public override void ExitAnnotation(VBAParser.AnnotationContext context) { if (context.annotationName() != null) { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs index 5e6b2c4875..9294ce1207 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs @@ -41,34 +41,25 @@ public ModuleScopeDimKeywordInspection(RubberduckParserState state) : base(state) { } public override IInspectionListener Listener { get; } = new ModuleScopedDimListener(); - - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts - .SelectMany(result => result.Context.GetDescendents() - .Select(r => new QualifiedContext(result.ModuleName, r))) - .Select(result => new QualifiedContextInspectionResult(this, - string.Format(InspectionResults.ModuleScopeDimKeywordInspection, ((VBAParser.VariableSubStmtContext)result.Context).identifier().GetText()), - result)); + var identifierName = ((VBAParser.VariableSubStmtContext) context.Context).identifier().GetText(); + return string.Format( + InspectionResults.ModuleScopeDimKeywordInspection, + identifierName); } - public class ModuleScopedDimListener : VBAParserBaseListener, IInspectionListener + public class ModuleScopedDimListener : InspectionListenerBase { - private readonly List> _contexts = new List>(); - public IReadOnlyList> Contexts => _contexts; - - public QualifiedModuleName CurrentModuleName { get; set; } - - public void ClearContexts() - { - _contexts.Clear(); - } - public override void ExitVariableStmt([NotNull] VBAParser.VariableStmtContext context) { if (context.DIM() != null && context.TryGetAncestor(out _)) { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + var resultContexts = context.GetDescendents(); + foreach (var resultContext in resultContexts) + { + SaveContext(resultContext); + } } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs index cef6749190..5b758ed1a9 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs @@ -1,16 +1,11 @@ -using System.Collections.Generic; -using System.Linq; using Antlr4.Runtime; using Antlr4.Runtime.Misc; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Resources; -using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete { @@ -45,36 +40,22 @@ public MultilineParameterInspection(RubberduckParserState state) } public override IInspectionListener Listener { get; } - - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts - .Select(context => new QualifiedContextInspectionResult(this, - string.Format(context.Context.GetSelection().LineCount > 3 - ? RubberduckUI.EasterEgg_Continuator - : Resources.Inspections.InspectionResults.MultilineParameterInspection, ((VBAParser.ArgContext)context.Context).unrestrictedIdentifier().GetText()), - context)); + var parameterText = ((VBAParser.ArgContext) context.Context).unrestrictedIdentifier().GetText(); + return string.Format(context.Context.GetSelection().LineCount > 3 + ? RubberduckUI.EasterEgg_Continuator + : Resources.Inspections.InspectionResults.MultilineParameterInspection, + parameterText); } - public class ParameterListener : VBAParserBaseListener, IInspectionListener + public class ParameterListener : InspectionListenerBase { - private readonly List> _contexts - = new List>(); - - public IReadOnlyList> Contexts => _contexts; - - public QualifiedModuleName CurrentModuleName { get; set; } - - public void ClearContexts() - { - _contexts.Clear(); - } - public override void ExitArg([NotNull] VBAParser.ArgContext context) { if (context.Start.Line != context.Stop.Line) { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs index 2a133d3f55..3e383a3e84 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs @@ -1,16 +1,11 @@ -using System.Collections.Generic; -using System.Linq; using Antlr4.Runtime; using Antlr4.Runtime.Misc; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Rubberduck.VBEditor; -using Rubberduck.Inspections.Inspections.Extensions; namespace Rubberduck.Inspections.Concrete { @@ -36,33 +31,20 @@ public sealed class MultipleDeclarationsInspection : ParseTreeInspectionBase public MultipleDeclarationsInspection(RubberduckParserState state) : base(state) { } - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts - .Select(context => new QualifiedContextInspectionResult(this, - InspectionResults.MultipleDeclarationsInspection, - context)); + return InspectionResults.MultipleDeclarationsInspection; } public override IInspectionListener Listener { get; } = new ParameterListListener(); - public class ParameterListListener : VBAParserBaseListener, IInspectionListener + public class ParameterListListener : InspectionListenerBase { - private readonly List> _contexts = new List>(); - public IReadOnlyList> Contexts => _contexts; - - public QualifiedModuleName CurrentModuleName { get; set; } - - public void ClearContexts() - { - _contexts.Clear(); - } - public override void ExitVariableListStmt([NotNull] VBAParser.VariableListStmtContext context) { if (context.variableSubStmt().Length > 1) { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } } @@ -70,7 +52,7 @@ public override void ExitConstStmt([NotNull] VBAParser.ConstStmtContext context) { if (context.constSubStmt().Length > 1) { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs index 466b4143ec..413be7114d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs @@ -1,16 +1,12 @@ -using System.Collections.Generic; -using System.Linq; using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.Extensions; -using Rubberduck.VBEditor; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.VBEditor.ComManagement; namespace Rubberduck.Inspections.Concrete { @@ -44,64 +40,49 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ObsoleteCallStatementInspection : ParseTreeInspectionBase { - public ObsoleteCallStatementInspection(RubberduckParserState state) + private readonly IProjectsProvider _projectsProvider; + + public ObsoleteCallStatementInspection(RubberduckParserState state, IProjectsProvider projectsProvider) : base(state) { Listener = new ObsoleteCallStatementListener(); + _projectsProvider = projectsProvider; } public override IInspectionListener Listener { get; } + protected override string ResultDescription(QualifiedContext context) + { + return InspectionResults.ObsoleteCallStatementInspection; + } - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultContext(QualifiedContext context) { - var results = new List(); - // do prefiltering to reduce searchspace - var prefilteredContexts = Listener.Contexts.Where(context => !context.IsIgnoringInspectionResultFor(State.DeclarationFinder, AnnotationName)); - foreach (var context in prefilteredContexts) + //FIXME At least use a parse tree here instead of the COM API. + string lines; + var component = _projectsProvider.Component(context.ModuleName); + using (var module = component.CodeModule) { - string lines; - var component = State.ProjectsProvider.Component(context.ModuleName); - using (var module = component.CodeModule) - { - lines = module.GetLines(context.Context.Start.Line, - context.Context.Stop.Line - context.Context.Start.Line + 1); - } - - var stringStrippedLines = string.Join(string.Empty, lines).StripStringLiterals(); + lines = module.GetLines(context.Context.Start.Line, + context.Context.Stop.Line - context.Context.Start.Line + 1); + } - if (stringStrippedLines.HasComment(out var commentIndex)) - { - stringStrippedLines = stringStrippedLines.Remove(commentIndex); - } + var stringStrippedLines = string.Join(string.Empty, lines).StripStringLiterals(); - if (!stringStrippedLines.Contains(":")) - { - results.Add(new QualifiedContextInspectionResult(this, - InspectionResults.ObsoleteCallStatementInspection, - context)); - } + if (stringStrippedLines.HasComment(out var commentIndex)) + { + stringStrippedLines = stringStrippedLines.Remove(commentIndex); } - return results; + return !stringStrippedLines.Contains(":"); } - public class ObsoleteCallStatementListener : VBAParserBaseListener, IInspectionListener + public class ObsoleteCallStatementListener : InspectionListenerBase { - private readonly List> _contexts = new List>(); - public IReadOnlyList> Contexts => _contexts; - - public QualifiedModuleName CurrentModuleName { get; set; } - - public void ClearContexts() - { - _contexts.Clear(); - } - public override void ExitCallStmt(VBAParser.CallStmtContext context) { if (context.CALL() != null) { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs index 09f027081b..3e639ab5bb 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs @@ -1,15 +1,10 @@ -using System.Collections.Generic; -using System.Linq; -using Antlr4.Runtime; +using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Inspections; -using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Inspections.Concrete { @@ -40,31 +35,24 @@ public ObsoleteCallingConventionInspection(RubberduckParserState state) public override IInspectionListener Listener { get; } - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts - .Where(context => ((VBAParser.DeclareStmtContext) context.Context).CDECL() != null) - .Select(context => new QualifiedContextInspectionResult(this, - string.Format(InspectionResults.ObsoleteCallingConventionInspection, - ((VBAParser.DeclareStmtContext) context.Context).identifier().GetText()), context)); + var identifierName = ((VBAParser.DeclareStmtContext) context.Context).identifier().GetText(); + return string.Format( + InspectionResults.ObsoleteCallingConventionInspection, + identifierName); } - public class ObsoleteCallingConventionListener : VBAParserBaseListener, IInspectionListener + protected override bool IsResultContext(QualifiedContext context) { - private readonly List> _contexts = new List>(); - public IReadOnlyList> Contexts => _contexts; - - public QualifiedModuleName CurrentModuleName { get; set; } - - public void ClearContexts() - { - _contexts.Clear(); - } + return ((VBAParser.DeclareStmtContext)context.Context).CDECL() != null; + } + public class ObsoleteCallingConventionListener : InspectionListenerBase + { public override void ExitDeclareStmt(VBAParser.DeclareStmtContext context) { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); - base.ExitDeclareStmt(context); + SaveContext(context); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs index a33233e272..6eeddd3044 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs @@ -1,15 +1,10 @@ -using System.Collections.Generic; -using System.Linq; -using Antlr4.Runtime; +using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Rubberduck.VBEditor; -using Rubberduck.Inspections.Inspections.Extensions; namespace Rubberduck.Inspections.Concrete { @@ -42,28 +37,16 @@ public ObsoleteCommentSyntaxInspection(RubberduckParserState state) } public override IInspectionListener Listener { get; } - - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts - .Select(context => new QualifiedContextInspectionResult(this, InspectionResults.ObsoleteCommentSyntaxInspection, context)); + return InspectionResults.ObsoleteCommentSyntaxInspection; } - public class ObsoleteCommentSyntaxListener : VBAParserBaseListener, IInspectionListener + public class ObsoleteCommentSyntaxListener : InspectionListenerBase { - private readonly List> _contexts = new List>(); - public IReadOnlyList> Contexts => _contexts; - - public QualifiedModuleName CurrentModuleName { get; set; } - - public void ClearContexts() - { - _contexts.Clear(); - } - public override void ExitRemComment(VBAParser.RemCommentContext context) { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs index 6c26eb4245..460cbcb2f8 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs @@ -1,15 +1,10 @@ -using System.Collections.Generic; -using System.Linq; -using Antlr4.Runtime; +using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Rubberduck.VBEditor; -using Rubberduck.Inspections.Inspections.Extensions; namespace Rubberduck.Inspections.Concrete { @@ -42,28 +37,16 @@ public ObsoleteErrorSyntaxInspection(RubberduckParserState state) } public override IInspectionListener Listener { get; } - - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts - .Select(context => new QualifiedContextInspectionResult(this, InspectionResults.ObsoleteErrorSyntaxInspection, context)); + return InspectionResults.ObsoleteErrorSyntaxInspection; } - public class ObsoleteErrorSyntaxListener : VBAParserBaseListener, IInspectionListener + public class ObsoleteErrorSyntaxListener : InspectionListenerBase { - private readonly List> _contexts = new List>(); - public IReadOnlyList> Contexts => _contexts; - - public QualifiedModuleName CurrentModuleName { get; set; } - - public void ClearContexts() - { - _contexts.Clear(); - } - public override void ExitErrorStmt(VBAParser.ErrorStmtContext context) { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs index df472e53ae..382609b6fa 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs @@ -1,15 +1,10 @@ -using System.Collections.Generic; -using System.Linq; using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Rubberduck.VBEditor; -using Rubberduck.Inspections.Inspections.Extensions; namespace Rubberduck.Inspections.Concrete { @@ -45,29 +40,18 @@ public ObsoleteLetStatementInspection(RubberduckParserState state) public override IInspectionListener Listener { get; } - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts - .Select(context => new QualifiedContextInspectionResult(this, InspectionResults.ObsoleteLetStatementInspection, context)); + return InspectionResults.ObsoleteLetStatementInspection; } - public class ObsoleteLetStatementListener : VBAParserBaseListener, IInspectionListener + public class ObsoleteLetStatementListener : InspectionListenerBase { - private readonly List> _contexts = new List>(); - public IReadOnlyList> Contexts => _contexts; - - public QualifiedModuleName CurrentModuleName { get; set; } - - public void ClearContexts() - { - _contexts.Clear(); - } - public override void ExitLetStmt(VBAParser.LetStmtContext context) { if (context.LET() != null) { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs index a4c2cae5bb..c509f41dcd 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs @@ -1,15 +1,10 @@ using Rubberduck.Inspections.Abstract; -using System.Collections.Generic; -using System.Linq; using Antlr4.Runtime; -using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Inspections; -using Rubberduck.VBEditor; namespace Rubberduck.CodeAnalysis.Inspections.Concrete { @@ -47,30 +42,16 @@ public ObsoleteWhileWendStatementInspection(RubberduckParserState state) } public override IInspectionListener Listener { get; } - - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts - .Select(context => new QualifiedContextInspectionResult(this, InspectionResults.ObsoleteWhileWendStatementInspection, context)); + return InspectionResults.ObsoleteWhileWendStatementInspection; } - public class ObsoleteWhileWendStatementListener : VBAParserBaseListener, IInspectionListener + public class ObsoleteWhileWendStatementListener : InspectionListenerBase { - private readonly List> _contexts = - new List>(); - - public IReadOnlyList> Contexts => _contexts; - - public QualifiedModuleName CurrentModuleName { get; set; } - - public void ClearContexts() - { - _contexts.Clear(); - } - public override void ExitWhileWendStmt(VBAParser.WhileWendStmtContext context) { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs index ead1d51d81..bb0195fffa 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs @@ -1,16 +1,11 @@ -using System.Collections.Generic; -using System.Linq; -using Antlr4.Runtime; +using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Rubberduck.VBEditor; using Antlr4.Runtime.Misc; -using Rubberduck.Inspections.Inspections.Extensions; namespace Rubberduck.Inspections.Concrete { @@ -50,31 +45,18 @@ public OnLocalErrorInspection(RubberduckParserState state) public override IInspectionListener Listener { get; } = new OnLocalErrorListener(); - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts - .Select(result => new QualifiedContextInspectionResult(this, - InspectionResults.OnLocalErrorInspection, - result)); + return InspectionResults.OnLocalErrorInspection; } - public class OnLocalErrorListener : VBAParserBaseListener, IInspectionListener + public class OnLocalErrorListener : InspectionListenerBase { - private readonly List> _contexts = new List>(); - public IReadOnlyList> Contexts => _contexts; - - public QualifiedModuleName CurrentModuleName { get; set; } - - public void ClearContexts() - { - _contexts.Clear(); - } - public override void ExitOnErrorStmt([NotNull] VBAParser.OnErrorStmtContext context) { if (context.ON_LOCAL_ERROR() != null) { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs index 8503186ddf..704ffd878d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs @@ -1,15 +1,10 @@ -using System.Collections.Generic; -using System.Linq; using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Rubberduck.VBEditor; -using Rubberduck.Inspections.Inspections.Extensions; namespace Rubberduck.Inspections.Concrete { @@ -51,32 +46,21 @@ public OptionBaseInspection(RubberduckParserState state) } public override IInspectionListener Listener { get; } - - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts - .Select(context => new QualifiedContextInspectionResult(this, - string.Format(InspectionResults.OptionBaseInspection, context.ModuleName.ComponentName), - context)); + var moduleName = context.ModuleName.ComponentName; + return string.Format( + InspectionResults.OptionBaseInspection, + moduleName); } - public class OptionBaseStatementListener : VBAParserBaseListener, IInspectionListener + public class OptionBaseStatementListener : InspectionListenerBase { - private readonly List> _contexts = new List>(); - public IReadOnlyList> Contexts => _contexts; - - public QualifiedModuleName CurrentModuleName { get; set; } - - public void ClearContexts() - { - _contexts.Clear(); - } - public override void ExitOptionBaseStmt(VBAParser.OptionBaseStmtContext context) { if (context.numberLiteral()?.INTEGERLITERAL().Symbol.Text == "1") { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs index a163c2763f..53fb79f67f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs @@ -1,16 +1,13 @@ using System.Collections.Generic; -using System.Linq; using Antlr4.Runtime; using Antlr4.Runtime.Misc; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor; -using Rubberduck.Inspections.Inspections.Extensions; namespace Rubberduck.Inspections.Concrete { @@ -48,49 +45,45 @@ public OptionExplicitInspection(RubberduckParserState state) } public override IInspectionListener Listener { get; } + protected override string ResultDescription(QualifiedContext context) + { + var moduleName = context.ModuleName.ComponentName; + return string.Format( + InspectionResults.OptionExplicitInspection, + moduleName); + } - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultContext(QualifiedContext context) { - return Listener.Contexts - .Select(context => new QualifiedContextInspectionResult(this, - string.Format(InspectionResults.OptionExplicitInspection, context.ModuleName.ComponentName), - context)); + var moduleBody = (context.Context as VBAParser.ModuleContext)?.moduleBody(); + return moduleBody != null && moduleBody.ChildCount != 0; } - public class MissingOptionExplicitListener : VBAParserBaseListener, IInspectionListener + public class MissingOptionExplicitListener : InspectionListenerBase { - private readonly IDictionary> _contexts = new Dictionary>(); - public IReadOnlyList> Contexts => _contexts.Values.ToList(); + private readonly IDictionary _hasOptionExplicit = new Dictionary(); - public QualifiedModuleName CurrentModuleName { get; set; } + public override void ClearContexts() + { + _hasOptionExplicit.Clear(); + base.ClearContexts(); + } - public void ClearContexts() + public override void EnterModuleDeclarations(VBAParser.ModuleDeclarationsContext context) { - _contexts.Clear(); + _hasOptionExplicit[CurrentModuleName] = false; } - public override void ExitModuleBody(VBAParser.ModuleBodyContext context) + public override void ExitOptionExplicitStmt(VBAParser.OptionExplicitStmtContext context) { - if (context.ChildCount == 0 && _contexts.ContainsKey(CurrentModuleName.Name)) - { - _contexts.Remove(CurrentModuleName.Name); - } + _hasOptionExplicit[CurrentModuleName] = true; } public override void ExitModuleDeclarations([NotNull] VBAParser.ModuleDeclarationsContext context) { - var hasOptionExplicit = false; - foreach (var element in context.moduleDeclarationsElement()) - { - if (element.moduleOption() is VBAParser.OptionExplicitStmtContext) - { - hasOptionExplicit = true; - } - } - - if (!hasOptionExplicit) + if (!_hasOptionExplicit.TryGetValue(CurrentModuleName, out var hasOptionExplicit) || !hasOptionExplicit) { - _contexts.Add(CurrentModuleName.Name, new QualifiedContext(CurrentModuleName, (ParserRuleContext)context.Parent)); + SaveContext((ParserRuleContext)context.Parent); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureCanBeWrittenAsFunctionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureCanBeWrittenAsFunctionInspection.cs index 95cb5ae5a8..122cebb901 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureCanBeWrittenAsFunctionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureCanBeWrittenAsFunctionInspection.cs @@ -9,7 +9,7 @@ using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.VBEditor; +using Rubberduck.Parsing.VBA.Parsing; namespace Rubberduck.Inspections.Concrete { @@ -39,7 +39,7 @@ namespace Rubberduck.Inspections.Concrete /// End Function /// ]]> /// - public sealed class ProcedureCanBeWrittenAsFunctionInspection : ParseTreeInspectionBase + public sealed class ProcedureCanBeWrittenAsFunctionInspection : InspectionBase, IParseTreeInspection { public ProcedureCanBeWrittenAsFunctionInspection(RubberduckParserState state) : base(state) @@ -47,16 +47,19 @@ public ProcedureCanBeWrittenAsFunctionInspection(RubberduckParserState state) Listener = new SingleByRefParamArgListListener(); } - public override IInspectionListener Listener { get; } + public CodeKind TargetKindOfCode => CodeKind.CodePaneCode; + public IInspectionListener Listener { get; } + + //FIXME This should really be a declaration inspection. protected override IEnumerable DoGetInspectionResults() { - if (!Listener.Contexts.Any()) + if (!Listener.Contexts().Any()) { return Enumerable.Empty(); } - var userDeclarations = UserDeclarations.ToList(); + var userDeclarations = State.AllUserDeclarations.ToList(); var builtinHandlers = State.DeclarationFinder.FindEventHandlers().ToList(); var contextLookup = userDeclarations.Where(decl => decl.Context != null).ToDictionary(decl => decl.Context); @@ -66,7 +69,7 @@ protected override IEnumerable DoGetInspectionResults() .Concat(builtinHandlers) .Concat(userDeclarations.Where(item => item.IsWithEvents))); - return Listener.Contexts + return Listener.Contexts() .Where(context => context.Context.Parent is VBAParser.SubStmtContext && HasArgumentReferencesWithIsAssignmentFlagged(context)) .Select(GetSubStmtParentDeclaration) @@ -93,24 +96,14 @@ Declaration GetSubStmtParentDeclaration(QualifiedContext cont } } - public class SingleByRefParamArgListListener : VBAParserBaseListener, IInspectionListener + public class SingleByRefParamArgListListener : InspectionListenerBase { - private readonly List> _contexts = new List>(); - public IReadOnlyList> Contexts => _contexts; - - public QualifiedModuleName CurrentModuleName { get; set; } - - public void ClearContexts() - { - _contexts.Clear(); - } - public override void ExitArgList(VBAParser.ArgListContext context) { var args = context.arg(); if (args != null && args.All(a => a.PARAMARRAY() == null && a.LPAREN() == null) && args.Count(a => a.BYREF() != null || (a.BYREF() == null && a.BYVAL() == null)) == 1) { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantByRefModifierInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantByRefModifierInspection.cs index a384bd6005..8902269bc1 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantByRefModifierInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantByRefModifierInspection.cs @@ -1,16 +1,11 @@ -using System.Collections.Generic; -using System.Linq; +using System.Linq; using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.VBA.Extensions; -using Rubberduck.VBEditor; -using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.JunkDrawer.Extensions; namespace Rubberduck.Inspections.Concrete @@ -49,48 +44,38 @@ public RedundantByRefModifierInspection(RubberduckParserState state) } public override IInspectionListener Listener { get; } = new RedundantByRefModifierListener(); - - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - var builtInEventHandlerContexts = State.DeclarationFinder.FindEventHandlers().Select(handler => handler.Context).ToHashSet(); - var interfaceImplementationMemberContexts = State.DeclarationFinder.FindAllInterfaceImplementingMembers().Select(member => member.Context).ToHashSet(); + var identifier = ((VBAParser.ArgContext)context.Context) + .unrestrictedIdentifier() + .identifier(); - var issues = Listener.Contexts.Where(context => - !builtInEventHandlerContexts.Contains(context.Context.Parent.Parent) && - !interfaceImplementationMemberContexts.Contains(context.Context.Parent.Parent)); + var identifierText = identifier.untypedIdentifier() != null + ? identifier.untypedIdentifier().identifierValue().GetText() + : identifier.typedIdentifier().untypedIdentifier().identifierValue().GetText(); - return issues.Select(issue => - { - var identifier = ((VBAParser.ArgContext) issue.Context) - .unrestrictedIdentifier() - .identifier(); - - return new QualifiedContextInspectionResult(this, - string.Format(InspectionResults.RedundantByRefModifierInspection, - identifier.untypedIdentifier() != null - ? identifier.untypedIdentifier().identifierValue().GetText() - : identifier.typedIdentifier().untypedIdentifier().identifierValue().GetText()), issue); - }); + return string.Format( + InspectionResults.RedundantByRefModifierInspection, + identifierText); } - public class RedundantByRefModifierListener : VBAParserBaseListener, IInspectionListener + protected override bool IsResultContext(QualifiedContext context) { - private readonly List> _contexts = new List>(); - - public IReadOnlyList> Contexts => _contexts; - - public QualifiedModuleName CurrentModuleName { get; set; } + //FIXME This should be an inspection on parameter declarations. + var builtInEventHandlerContexts = State.DeclarationFinder.FindEventHandlers().Select(handler => handler.Context).ToHashSet(); + var interfaceImplementationMemberContexts = State.DeclarationFinder.FindAllInterfaceImplementingMembers().Select(member => member.Context).ToHashSet(); - public void ClearContexts() - { - _contexts.Clear(); - } + return !builtInEventHandlerContexts.Contains(context.Context.Parent.Parent) + && !interfaceImplementationMemberContexts.Contains(context.Context.Parent.Parent); + } + public class RedundantByRefModifierListener : InspectionListenerBase + { public override void ExitArg(VBAParser.ArgContext context) { if (context.BYREF() != null) { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs index 5cfe51569b..8016b011b8 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs @@ -1,15 +1,10 @@ -using System.Collections.Generic; -using System.Linq; using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Rubberduck.VBEditor; -using Rubberduck.Inspections.Inspections.Extensions; namespace Rubberduck.Inspections.Concrete { @@ -47,32 +42,20 @@ public RedundantOptionInspection(RubberduckParserState state) } public override IInspectionListener Listener { get; } - - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts - .Select(context => new QualifiedContextInspectionResult(this, - string.Format(InspectionResults.RedundantOptionInspection, context.Context.GetText()), - context)); + return string.Format( + InspectionResults.RedundantOptionInspection, + context.Context.GetText()); } - public class RedundantModuleOptionListener : VBAParserBaseListener, IInspectionListener + public class RedundantModuleOptionListener : InspectionListenerBase { - private readonly List> _contexts = new List>(); - public IReadOnlyList> Contexts => _contexts; - - public QualifiedModuleName CurrentModuleName { get; set; } - - public void ClearContexts() - { - _contexts.Clear(); - } - public override void ExitOptionBaseStmt(VBAParser.OptionBaseStmtContext context) { if (context.numberLiteral()?.INTEGERLITERAL().Symbol.Text == "0") { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } } @@ -81,7 +64,7 @@ public override void ExitOptionCompareStmt(VBAParser.OptionCompareStmtContext co // BINARY is the default, and DATABASE is specified by default + only valid in Access. if (context.TEXT() == null && context.DATABASE() == null) { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs index 65b4229b77..dea08b6ee6 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs @@ -1,17 +1,11 @@ using Rubberduck.Inspections.Abstract; -using System.Collections.Generic; -using System.Linq; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.Grammar; using Antlr4.Runtime.Misc; using Antlr4.Runtime; using Rubberduck.Parsing; -using Rubberduck.VBEditor; -using Rubberduck.Inspections.Results; -using static Rubberduck.Parsing.Grammar.VBAParser; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing.Grammar; namespace Rubberduck.Inspections.Concrete { @@ -44,43 +38,27 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class StepIsNotSpecifiedInspection : ParseTreeInspectionBase { - public StepIsNotSpecifiedInspection(RubberduckParserState state) : base(state) { } + public StepIsNotSpecifiedInspection(RubberduckParserState state) + : base(state) { } - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts - .Select(result => new QualifiedContextInspectionResult(this, - InspectionResults.StepIsNotSpecifiedInspection, - result)); + return InspectionResults.StepIsNotSpecifiedInspection; } public override IInspectionListener Listener { get; } = new StepIsNotSpecifiedListener(); } - public class StepIsNotSpecifiedListener : VBAParserBaseListener, IInspectionListener + public class StepIsNotSpecifiedListener : InspectionListenerBase { - private readonly List> _contexts = new List>(); - public IReadOnlyList> Contexts => _contexts; - - public QualifiedModuleName CurrentModuleName - { - get; - set; - } - - public void ClearContexts() - { - _contexts.Clear(); - } - - public override void EnterForNextStmt([NotNull] ForNextStmtContext context) + public override void EnterForNextStmt([NotNull] VBAParser.ForNextStmtContext context) { - StepStmtContext stepStatement = context.stepStmt(); + var stepStatement = context.stepStmt(); if (stepStatement == null) { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs index b5ca7bf931..a16fb4d7c0 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs @@ -1,17 +1,11 @@ using Rubberduck.Inspections.Abstract; -using System.Collections.Generic; -using System.Linq; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.Grammar; using Antlr4.Runtime.Misc; using Antlr4.Runtime; using Rubberduck.Parsing; -using Rubberduck.VBEditor; -using Rubberduck.Inspections.Results; -using static Rubberduck.Parsing.Grammar.VBAParser; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing.Grammar; namespace Rubberduck.Inspections.Concrete { @@ -44,50 +38,35 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class StepOneIsRedundantInspection : ParseTreeInspectionBase { - public StepOneIsRedundantInspection(RubberduckParserState state) : base(state) { } + public StepOneIsRedundantInspection(RubberduckParserState state) + : base(state) + {} - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts - .Select(result => new QualifiedContextInspectionResult(this, - InspectionResults.StepOneIsRedundantInspection, - result)); + return InspectionResults.StepOneIsRedundantInspection; } public override IInspectionListener Listener { get; } = new StepOneIsRedundantListener(); } - public class StepOneIsRedundantListener : VBAParserBaseListener, IInspectionListener + public class StepOneIsRedundantListener : InspectionListenerBase { - private readonly List> _contexts = new List>(); - public IReadOnlyList> Contexts => _contexts; - - public QualifiedModuleName CurrentModuleName - { - get; - set; - } - - public void ClearContexts() - { - _contexts.Clear(); - } - - public override void EnterForNextStmt([NotNull] ForNextStmtContext context) + public override void EnterForNextStmt([NotNull] VBAParser.ForNextStmtContext context) { - StepStmtContext stepStatement = context.stepStmt(); + var stepStatement = context.stepStmt(); if (stepStatement == null) { return; } - string stepText = stepStatement.expression().GetText(); + var stepText = stepStatement.expression().GetText(); if(stepText == "1") { - _contexts.Add(new QualifiedContext(CurrentModuleName, stepStatement)); + SaveContext(stepStatement); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs index 86a48acc62..3607228c80 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs @@ -1,16 +1,11 @@ -using System.Collections.Generic; -using System.Linq; -using Antlr4.Runtime; +using Antlr4.Runtime; using Antlr4.Runtime.Misc; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Rubberduck.VBEditor; -using Rubberduck.Inspections.Inspections.Extensions; namespace Rubberduck.Inspections.Concrete { @@ -41,34 +36,22 @@ namespace Rubberduck.Inspections.Concrete public sealed class StopKeywordInspection : ParseTreeInspectionBase { public StopKeywordInspection(RubberduckParserState state) - : base(state) { } + : base(state) + {} public override IInspectionListener Listener { get; } = new StopKeywordListener(); - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts - .Select(result => new QualifiedContextInspectionResult(this, - InspectionResults.StopKeywordInspection, - result)); + return InspectionResults.StopKeywordInspection; } - public class StopKeywordListener : VBAParserBaseListener, IInspectionListener + public class StopKeywordListener : InspectionListenerBase { - private readonly List> _contexts = new List>(); - public IReadOnlyList> Contexts => _contexts; - - public QualifiedModuleName CurrentModuleName { get; set; } - - public void ClearContexts() - { - _contexts.Clear(); - } - public override void ExitStopStmt([NotNull] VBAParser.StopStmtContext context) { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/LineContinuationBetweenKeywordsInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/LineContinuationBetweenKeywordsInspection.cs index cffc6f3f8a..1ab25c714c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/LineContinuationBetweenKeywordsInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/LineContinuationBetweenKeywordsInspection.cs @@ -1,15 +1,11 @@ -using System.Collections.Generic; -using System.Linq; -using Antlr4.Runtime; +using Antlr4.Runtime; using Antlr4.Runtime.Tree; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Inspections; -using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Inspections.Concrete.ThunderCode { @@ -27,29 +23,21 @@ namespace Rubberduck.Inspections.Inspections.Concrete.ThunderCode /// public class LineContinuationBetweenKeywordsInspection : ParseTreeInspectionBase { - public LineContinuationBetweenKeywordsInspection(RubberduckParserState state) : base(state) + public LineContinuationBetweenKeywordsInspection(RubberduckParserState state) + : base(state) { Listener = new LineContinuationBetweenKeywordsListener(); } - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts.Select(c => new QualifiedContextInspectionResult( - this, InspectionResults.LineContinuationBetweenKeywordsInspection.ThunderCodeFormat(), c)); + return InspectionResults.LineContinuationBetweenKeywordsInspection.ThunderCodeFormat(); } public override IInspectionListener Listener { get; } - public class LineContinuationBetweenKeywordsListener : VBAParserBaseListener, IInspectionListener + public class LineContinuationBetweenKeywordsListener : InspectionListenerBase { - private readonly List> _contexts = new List>(); - - public IReadOnlyList> Contexts => _contexts; - - public void ClearContexts() => _contexts.Clear(); - - public QualifiedModuleName CurrentModuleName { get; set; } - public override void EnterSubStmt(VBAParser.SubStmtContext context) { CheckContext(context, context.END_SUB()); @@ -149,12 +137,11 @@ public override void EnterUdtDeclaration(VBAParser.UdtDeclarationContext context } - private void CheckContext(ParserRuleContext context, IParseTree subTreeToExamine) { if (subTreeToExamine?.GetText().Contains("_") ?? false) { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NegativeLineNumberInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NegativeLineNumberInspection.cs index 749a9639a9..7c27ed6e58 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NegativeLineNumberInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NegativeLineNumberInspection.cs @@ -1,15 +1,11 @@ -using System.Collections.Generic; -using System.Linq; -using Antlr4.Runtime; +using Antlr4.Runtime; using Antlr4.Runtime.Tree; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Inspections; -using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Inspections.Concrete.ThunderCode { @@ -23,29 +19,21 @@ namespace Rubberduck.Inspections.Inspections.Concrete.ThunderCode /// public class NegativeLineNumberInspection : ParseTreeInspectionBase { - public NegativeLineNumberInspection(RubberduckParserState state) : base(state) + public NegativeLineNumberInspection(RubberduckParserState state) + : base(state) { Listener = new NegativeLineNumberKeywordsListener(); } - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts.Select(c => new QualifiedContextInspectionResult( - this, InspectionResults.NegativeLineNumberInspection.ThunderCodeFormat(), c)); + return InspectionResults.NegativeLineNumberInspection.ThunderCodeFormat(); } public override IInspectionListener Listener { get; } - public class NegativeLineNumberKeywordsListener : VBAParserBaseListener, IInspectionListener + public class NegativeLineNumberKeywordsListener : InspectionListenerBase { - private readonly List> _contexts = new List>(); - - public IReadOnlyList> Contexts => _contexts; - - public void ClearContexts() => _contexts.Clear(); - - public QualifiedModuleName CurrentModuleName { get; set; } - public override void EnterOnErrorStmt(VBAParser.OnErrorStmtContext context) { CheckContext(context, context.expression()); @@ -69,7 +57,7 @@ private void CheckContext(ParserRuleContext context, IParseTree expression) var target = expression?.GetText().Trim() ?? string.Empty; if (target.StartsWith("-") && int.TryParse(target.Substring(1), out _)) { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs index 3e913def92..149fc41ea7 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs @@ -1,15 +1,11 @@ -using System.Collections.Generic; -using System.Linq; -using Antlr4.Runtime; +using Antlr4.Runtime; using Antlr4.Runtime.Tree; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Inspections; -using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Inspections.Concrete.ThunderCode { @@ -23,29 +19,21 @@ namespace Rubberduck.Inspections.Inspections.Concrete.ThunderCode /// public class OnErrorGoToMinusOneInspection : ParseTreeInspectionBase { - public OnErrorGoToMinusOneInspection(RubberduckParserState state) : base(state) + public OnErrorGoToMinusOneInspection(RubberduckParserState state) + : base(state) { Listener = new OnErrorGoToMinusOneListener(); } - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context) { - return Listener.Contexts.Select(c => new QualifiedContextInspectionResult( - this, InspectionResults.OnErrorGoToMinusOneInspection.ThunderCodeFormat(), c)); + return InspectionResults.OnErrorGoToMinusOneInspection.ThunderCodeFormat(); } public override IInspectionListener Listener { get; } - public class OnErrorGoToMinusOneListener : VBAParserBaseListener, IInspectionListener + public class OnErrorGoToMinusOneListener : InspectionListenerBase { - private readonly List> _contexts = new List>(); - - public IReadOnlyList> Contexts => _contexts; - - public void ClearContexts() => _contexts.Clear(); - - public QualifiedModuleName CurrentModuleName { get; set; } - public override void EnterOnErrorStmt(VBAParser.OnErrorStmtContext context) { CheckContext(context, context.expression()); @@ -57,7 +45,7 @@ private void CheckContext(ParserRuleContext context, IParseTree expression) var target = expression?.GetText().Trim() ?? string.Empty; if (target.StartsWith("-") && int.TryParse(target.Substring(1), out var result) && result == 1) { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs index b9168b5374..2c296b90aa 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs @@ -2,15 +2,11 @@ using System.Linq; using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Rubberduck.VBEditor; -using Rubberduck.Inspections.Inspections.Extensions; namespace Rubberduck.Inspections.Concrete { @@ -39,33 +35,31 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public class UnhandledOnErrorResumeNextInspection : ParseTreeInspectionBase + public class UnhandledOnErrorResumeNextInspection : ParseTreeInspectionBase> { private readonly Dictionary, List> _unhandledContextsMap = new Dictionary, List>(); - public UnhandledOnErrorResumeNextInspection(RubberduckParserState state) : base(state) + public UnhandledOnErrorResumeNextInspection(RubberduckParserState state) + : base(state) { Listener = new OnErrorStatementListener(_unhandledContextsMap); } public override IInspectionListener Listener { get; } - - protected override IEnumerable DoGetInspectionResults() + protected override string ResultDescription(QualifiedContext context, IList properties) { - return Listener.Contexts - .Select(result => - { - var unhandledContexts = _unhandledContextsMap[result]; + return InspectionResults.UnhandledOnErrorResumeNextInspection; + } - return new QualifiedContextInspectionResult>(this, InspectionResults.UnhandledOnErrorResumeNextInspection, result, unhandledContexts); - }); + protected override (bool isResult, IList properties) IsResultContextWithAdditionalProperties(QualifiedContext context) + { + return (true, _unhandledContextsMap[context]); } } - public class OnErrorStatementListener : VBAParserBaseListener, IInspectionListener + public class OnErrorStatementListener : InspectionListenerBase { - private readonly List> _contexts = new List>(); private readonly List> _unhandledContexts = new List>(); private readonly Dictionary, List> _unhandledContextsMap; @@ -74,16 +68,12 @@ public OnErrorStatementListener(Dictionary, _unhandledContextsMap = unhandledContextsMap; } - public IReadOnlyList> Contexts => _contexts; - - public void ClearContexts() + public override void ClearContexts() { - _contexts.Clear(); _unhandledContextsMap.Clear(); + base.ClearContexts(); } - public QualifiedModuleName CurrentModuleName { get; set; } - public override void ExitModuleBodyElement(VBAParser.ModuleBodyElementContext context) { if (_unhandledContexts.Any()) @@ -91,10 +81,9 @@ public override void ExitModuleBodyElement(VBAParser.ModuleBodyElementContext co foreach (var errorContext in _unhandledContexts) { _unhandledContextsMap.Add(errorContext, new List(_unhandledContexts.Select(ctx => ctx.Context))); + SaveContext(errorContext.Context); } - _contexts.AddRange(_unhandledContexts); - _unhandledContexts.Clear(); } } @@ -103,12 +92,19 @@ public override void ExitOnErrorStmt(VBAParser.OnErrorStmtContext context) { if (context.RESUME() != null) { - _unhandledContexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveUnhandledContext(context); } else if (context.GOTO() != null) { _unhandledContexts.Clear(); } } + + private void SaveUnhandledContext(ParserRuleContext context) + { + var module = CurrentModuleName; + var qualifiedContext = new QualifiedContext(module, context); + _unhandledContexts.Add(qualifiedContext); + } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs index 2893c07851..eaae74b389 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs @@ -36,10 +36,10 @@ public EnumMember(VBAParser.EnumerationStmt_ConstantContext constContext, long i private IParseTreeVisitorResults _contextValues; private IParseTreeValueFactory _inspValueFactory; - private List _enumStmtContexts; + private IReadOnlyList _enumStmtContexts; private List _enumMembers; - public ParseTreeValueVisitor(IParseTreeValueFactory valueFactory, List allEnums, Func idRefRetriever) + public ParseTreeValueVisitor(IParseTreeValueFactory valueFactory, IReadOnlyList allEnums, Func idRefRetriever) { _inspValueFactory = valueFactory; IdRefRetriever = idRefRetriever; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs index db8d1b5978..fcc4336f21 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs @@ -13,6 +13,8 @@ using Rubberduck.Parsing.Symbols; using System; using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing.VBA.Parsing; +using Rubberduck.VBEditor.Extensions; namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { @@ -111,10 +113,11 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection /// End Sub /// ]]> /// - public sealed class UnreachableCaseInspection : ParseTreeInspectionBase + public sealed class UnreachableCaseInspection : InspectionBase, IParseTreeInspection { private readonly IUnreachableCaseInspectorFactory _unreachableCaseInspectorFactory; private readonly IParseTreeValueFactory _valueFactory; + private readonly IDeclarationFinderProvider _declarationFinderProvider; private enum CaseInspectionResult { Unreachable, InherentlyUnreachable, MismatchType, Overflow, CaseElse }; @@ -127,15 +130,19 @@ private enum CaseInspectionResult { Unreachable, InherentlyUnreachable, Mismatch [CaseInspectionResult.CaseElse] = InspectionResults.UnreachableCaseInspection_CaseElse }; - public UnreachableCaseInspection(RubberduckParserState state) : base(state) + public UnreachableCaseInspection(RubberduckParserState state, IDeclarationFinderProvider declarationFinderProvider) + : base(state) { var factoryProvider = new UnreachableCaseInspectionFactoryProvider(); _unreachableCaseInspectorFactory = factoryProvider.CreateIUnreachableInspectorFactory(); _valueFactory = factoryProvider.CreateIParseTreeValueFactory(); + _declarationFinderProvider = declarationFinderProvider; } - public override IInspectionListener Listener { get; } = + public CodeKind TargetKindOfCode => CodeKind.CodePaneCode; + + public IInspectionListener Listener { get; } = new UnreachableCaseInspectionListener(); private List _inspectionResults = new List(); @@ -143,10 +150,11 @@ public UnreachableCaseInspection(RubberduckParserState state) : base(state) protected override IEnumerable DoGetInspectionResults() { + //FIXME Get the declaration finder only once inside the inspection to avoid possible inconsistent state due to a reparse while inspections run. _inspectionResults = new List(); - var qualifiedSelectCaseStmts = Listener.Contexts + var qualifiedSelectCaseStmts = Listener.Contexts() // ignore filtering here to make the search space smaller - .Where(result => !result.IsIgnoringInspectionResultFor(State.DeclarationFinder, AnnotationName)); + .Where(result => !result.IsIgnoringInspectionResultFor(_declarationFinderProvider.DeclarationFinder, AnnotationName)); ParseTreeValueVisitor.OnValueResultCreated += ValueResults.OnNewValueResult; @@ -174,7 +182,7 @@ public IParseTreeValueVisitor ParseTreeValueVisitor if (_parseTreeValueVisitor is null) { var listener = (UnreachableCaseInspectionListener)Listener; - _parseTreeValueVisitor = CreateParseTreeValueVisitor(_valueFactory, listener.EnumerationStmtContexts.ToList(), GetIdentifierReferenceForContext); + _parseTreeValueVisitor = CreateParseTreeValueVisitor(_valueFactory, listener.EnumerationStmtContexts(), GetIdentifierReferenceForContext); } return _parseTreeValueVisitor; } @@ -188,16 +196,17 @@ private void CreateInspectionResult(QualifiedContext selectSt _inspectionResults.Add(result); } - public static IParseTreeValueVisitor CreateParseTreeValueVisitor(IParseTreeValueFactory valueFactory, List allEnums, Func func) + public static IParseTreeValueVisitor CreateParseTreeValueVisitor(IParseTreeValueFactory valueFactory, IReadOnlyList allEnums, Func func) => new ParseTreeValueVisitor(valueFactory, allEnums, func); - //Method is used as a delegate to avoid propogating RubberduckParserState beyond this class + //Method is used as a delegate to avoid propagating RubberduckParserState beyond this class private (bool success, IdentifierReference idRef) GetIdentifierReferenceForContext(ParserRuleContext context) { - return GetIdentifierReferenceForContext(context, State); + return GetIdentifierReferenceForContext(context, _declarationFinderProvider); } //public static to support tests + //FIXME There should not be additional public methods just for tests. This class seems to want to be split or at least reorganized. public static (bool success, IdentifierReference idRef) GetIdentifierReferenceForContext(ParserRuleContext context, IDeclarationFinderProvider declarationFinderProvider) { if (context == null) @@ -219,10 +228,10 @@ public static (bool success, IdentifierReference idRef) GetIdentifierReferenceFo //Method is used as a delegate to avoid propogating RubberduckParserState beyond this class private string GetVariableTypeName(string variableName, ParserRuleContext ancestor) { - var descendents = ancestor.GetDescendents().Where(desc => desc.GetText().Equals(variableName)); + var descendents = ancestor.GetDescendents().Where(desc => desc.GetText().Equals(variableName)).ToList(); if (descendents.Any()) { - (bool success, IdentifierReference idRef) = GetIdentifierReferenceForContext(descendents.First(), State); + (bool success, IdentifierReference idRef) = GetIdentifierReferenceForContext(descendents.First(), _declarationFinderProvider); if (success) { return GetBaseTypeForDeclaration(idRef.Declaration); @@ -245,29 +254,42 @@ private string GetBaseTypeForDeclaration(Declaration declaration) } #region UnreachableCaseInspectionListeners - public class UnreachableCaseInspectionListener : VBAParserBaseListener, IInspectionListener + public class UnreachableCaseInspectionListener : InspectionListenerBase { - private readonly List> _contexts = new List>(); - public IReadOnlyList> Contexts => _contexts; - - private readonly List _enumStmts = new List(); - public IReadOnlyList EnumerationStmtContexts => _enumStmts; + private readonly IDictionary> _enumStmts = new Dictionary>(); + public IReadOnlyList EnumerationStmtContexts() => _enumStmts.AllValues().ToList(); + public IReadOnlyList EnumerationStmtContexts(QualifiedModuleName module) => + _enumStmts.TryGetValue(module, out var stmts) + ? stmts + : new List(); - public QualifiedModuleName CurrentModuleName { get; set; } - - public void ClearContexts() + public override void ClearContexts() { - _contexts.Clear(); + _enumStmts.Clear(); + base.ClearContexts(); } public override void EnterSelectCaseStmt([NotNull] VBAParser.SelectCaseStmtContext context) { - _contexts.Add(new QualifiedContext(CurrentModuleName, context)); + SaveContext(context); } public override void EnterEnumerationStmt([NotNull] VBAParser.EnumerationStmtContext context) { - _enumStmts.Add(context); + SaveEnumStmt(context); + } + + private void SaveEnumStmt(VBAParser.EnumerationStmtContext context) + { + var module = CurrentModuleName; + if (_enumStmts.TryGetValue(module, out var stmts)) + { + stmts.Add(context); + } + else + { + _enumStmts.Add(module, new List { context }); + } } } #endregion diff --git a/Rubberduck.CodeAnalysis/Inspections/ParseTreeListeners/AttributeAnnotationListener.cs b/Rubberduck.CodeAnalysis/Inspections/ParseTreeListeners/AttributeAnnotationListener.cs deleted file mode 100644 index 0beaefcddc..0000000000 --- a/Rubberduck.CodeAnalysis/Inspections/ParseTreeListeners/AttributeAnnotationListener.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using Antlr4.Runtime; -using Rubberduck.Parsing; -using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; -using Rubberduck.Parsing.Symbols; -using Rubberduck.Parsing.VBA; -using Rubberduck.VBEditor; - -namespace Rubberduck.Inspections.ParseTreeListeners -{ - public abstract class AttributeAnnotationListener : VBAParserBaseListener, IInspectionListener - { - protected AttributeAnnotationListener(RubberduckParserState state) - { - State = state; - } - - public IReadOnlyList> Contexts => _contexts; - public QualifiedModuleName CurrentModuleName { get; set; } - public void ClearContexts() => _contexts.Clear(); - - protected RubberduckParserState State { get; } - protected Lazy Module { get; private set; } - protected Lazy> Members { get; private set; } - - protected Declaration FirstMember - { - get - { - return CurrentScopeDeclaration = State.DeclarationFinder - .UserDeclarations(DeclarationType.Procedure) - .Where(declaration => declaration.QualifiedName.QualifiedModuleName.Equals(CurrentModuleName)) - .OrderBy(declaration => declaration.Selection) - .FirstOrDefault(); - } - } - - protected bool HasMembers { get; private set; } - protected Declaration CurrentScopeDeclaration { get; set; } - - private readonly List> _contexts = new List>(); - - protected void AddContext(QualifiedContext context) - { - _contexts.Add(context); - } - - private void SetCurrentScope(string memberName = null) - { - HasMembers = !string.IsNullOrEmpty(memberName); - CurrentScopeDeclaration = HasMembers ? Members.Value[memberName] : Module.Value; - } - - public override void EnterModule(VBAParser.ModuleContext context) - { - Module = new Lazy(() => State.DeclarationFinder - .UserDeclarations(DeclarationType.Module) - .SingleOrDefault(m => m.QualifiedName.QualifiedModuleName.Equals(CurrentModuleName))); - - Members = new Lazy>(() => State.DeclarationFinder - .Members(CurrentModuleName) - .Where(m => !m.DeclarationType.HasFlag(DeclarationType.Module)) - .GroupBy(m => m.IdentifierName) - .ToDictionary(m => m.Key, m => m.FirstOrDefault())); - - SetCurrentScope(); - } - - public override void ExitModule(VBAParser.ModuleContext context) - { - CurrentScopeDeclaration = null; - } - - public override void ExitModuleDeclarations(VBAParser.ModuleDeclarationsContext context) - { - var firstMember = Members.Value.Values.OrderBy(d => d.Selection).FirstOrDefault(); - if (firstMember != null) - { - CurrentScopeDeclaration = firstMember; - } - else - { - CurrentScopeDeclaration = State.DeclarationFinder.UserDeclarations(DeclarationType.Module) - .SingleOrDefault(d => d.QualifiedName.QualifiedModuleName.Equals(CurrentModuleName)); - } - } - - public override void EnterSubStmt(VBAParser.SubStmtContext context) - { - SetCurrentScope(Identifier.GetName(context.subroutineName())); - } - - public override void EnterFunctionStmt(VBAParser.FunctionStmtContext context) - { - SetCurrentScope(Identifier.GetName(context.functionName())); - } - - public override void EnterPropertyGetStmt(VBAParser.PropertyGetStmtContext context) - { - SetCurrentScope(Identifier.GetName(context.functionName())); - } - - public override void EnterPropertyLetStmt(VBAParser.PropertyLetStmtContext context) - { - SetCurrentScope(Identifier.GetName(context.subroutineName())); - } - - public override void EnterPropertySetStmt(VBAParser.PropertySetStmtContext context) - { - SetCurrentScope(Identifier.GetName(context.subroutineName())); - } - } -} \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs index 0332205111..8579a66dd0 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs @@ -55,7 +55,7 @@ public RestoreErrorHandlingQuickFix() public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) { - if (!(result is IWithInspectionResultProperties> resultProperties)) + if (!(result is IWithInspectionResultProperties> resultProperties)) { return; } diff --git a/Rubberduck.Parsing/Inspections/Abstract/IInpsectionListener.cs b/Rubberduck.Parsing/Inspections/Abstract/IInpsectionListener.cs index daf2eea0ba..bd0484aadf 100644 --- a/Rubberduck.Parsing/Inspections/Abstract/IInpsectionListener.cs +++ b/Rubberduck.Parsing/Inspections/Abstract/IInpsectionListener.cs @@ -7,7 +7,8 @@ namespace Rubberduck.Parsing.Inspections.Abstract { public interface IInspectionListener: IParseTreeListener { - IReadOnlyList> Contexts { get; } + IReadOnlyList> Contexts(); + IReadOnlyList> Contexts(QualifiedModuleName module); void ClearContexts(); QualifiedModuleName CurrentModuleName { get; set; } } diff --git a/RubberduckTests/Inspections/ObsoleteCallStatementInspectionTests.cs b/RubberduckTests/Inspections/ObsoleteCallStatementInspectionTests.cs index 47e9e1b25a..a947d20b71 100644 --- a/RubberduckTests/Inspections/ObsoleteCallStatementInspectionTests.cs +++ b/RubberduckTests/Inspections/ObsoleteCallStatementInspectionTests.cs @@ -111,14 +111,14 @@ Call Foo [Category("Inspections")] public void InspectionName() { - var inspection = new ObsoleteCallStatementInspection(null); + var inspection = new ObsoleteCallStatementInspection(null, null); Assert.AreEqual(nameof(ObsoleteCallStatementInspection), inspection.Name); } protected override IInspection InspectionUnderTest(RubberduckParserState state) { - return new ObsoleteCallStatementInspection(state); + return new ObsoleteCallStatementInspection(state, state.ProjectsProvider); } } } diff --git a/RubberduckTests/Inspections/RedundantOptionInspectionTests.cs b/RubberduckTests/Inspections/RedundantOptionInspectionTests.cs index 946eb48495..e4473f10cc 100644 --- a/RubberduckTests/Inspections/RedundantOptionInspectionTests.cs +++ b/RubberduckTests/Inspections/RedundantOptionInspectionTests.cs @@ -32,7 +32,7 @@ public void RedundantOptionInspection_Ignored_DoesNotReturnResult() using (var state = MockParser.CreateAndParse(vbe.Object)) { - var inspection = new ObsoleteCallStatementInspection(state); + var inspection = new ObsoleteCallStatementInspection(state, state.ProjectsProvider); var inspector = InspectionsHelper.GetInspector(inspection); var inspectionResults = inspector.FindIssuesAsync(state, CancellationToken.None).Result; diff --git a/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs b/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs index 2819a0da79..fbd41b47ab 100644 --- a/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs +++ b/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs @@ -2473,7 +2473,7 @@ End Sub var actualResults = Enumerable.Empty(); using (var state = MockParser.CreateAndParse(vbe.Object)) { - var inspection = new UnreachableCaseInspection(state); + var inspection = new UnreachableCaseInspection(state, state); var parseTreeValueVisitor = inspection.ParseTreeValueVisitor as ITestParseTreeVisitor; parseTreeValueVisitor.InjectValuedDeclarationEvaluator(TestGetValuedDeclaration); @@ -2527,7 +2527,7 @@ End Sub var actualResults = Enumerable.Empty(); using (var state = MockParser.CreateAndParse(vbe.Object)) { - var inspection = new UnreachableCaseInspection(state); + var inspection = new UnreachableCaseInspection(state, state); var parseTreeValueVisitor = inspection.ParseTreeValueVisitor as ITestParseTreeVisitor; parseTreeValueVisitor.InjectValuedDeclarationEvaluator(TestGetValuedDeclaration); @@ -2636,7 +2636,7 @@ private IParseTreeVisitorResults GetParseTreeValueResults(string inputCode, out protected override IInspection InspectionUnderTest(RubberduckParserState state) { - return new UnreachableCaseInspection(state); + return new UnreachableCaseInspection(state, state); } } } diff --git a/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs b/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs index 13a1fdf2b3..86809350f0 100644 --- a/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs @@ -465,7 +465,7 @@ Sub Goo(arg1 As Integer, arg1 As String) Call Foo End Sub"; - var actualCode = ApplyIgnoreOnceToAllResults(inputCode, state => new ObsoleteCallStatementInspection(state), TestStandardModuleVbeSetup); + var actualCode = ApplyIgnoreOnceToAllResults(inputCode, state => new ObsoleteCallStatementInspection(state, state.ProjectsProvider), TestStandardModuleVbeSetup); Assert.AreEqual(expectedCode, actualCode); } diff --git a/RubberduckTests/QuickFixes/RemoveExplicitCallStatementQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveExplicitCallStatementQuickFixTests.cs index b50d2ba040..c17ff58470 100644 --- a/RubberduckTests/QuickFixes/RemoveExplicitCallStatementQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveExplicitCallStatementQuickFixTests.cs @@ -32,7 +32,7 @@ Sub Goo(arg1 As Integer, arg1 As String) Foo End Sub"; - var actualCode = ApplyQuickFixToAllInspectionResults(inputCode, state => new ObsoleteCallStatementInspection(state)); + var actualCode = ApplyQuickFixToAllInspectionResults(inputCode, state => new ObsoleteCallStatementInspection(state, state.ProjectsProvider)); Assert.AreEqual(expectedCode, actualCode); } From 7d620a87ef85405a549518341576b914c9684c46 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Wed, 26 Feb 2020 13:45:40 +0100 Subject: [PATCH 251/461] Remove declaration members and state from the InspectionBase The DeclarationFinderProvider remains protected for now. --- .../IdentifierReferenceInspectionBase.cs | 16 +++-------- .../Inspections/Abstract/InspectionBase.cs | 27 ++----------------- .../ApplicationWorksheetFunctionInspection.cs | 6 ++--- ...elUdfNameIsValidCellReferenceInspection.cs | 14 +++++++--- .../Concrete/IllegalAnnotationInspection.cs | 14 +++++++--- .../ImplicitByRefModifierInspection.cs | 5 ++-- ...bjectWhereProcedureIsRequiredInspection.cs | 21 +++++++-------- ...ocedureCanBeWrittenAsFunctionInspection.cs | 12 +++++---- .../RedundantByRefModifierInspection.cs | 5 ++-- .../SuspiciousLetAssignmentInspection.cs | 21 +++++++-------- 10 files changed, 59 insertions(+), 82 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs index ff48afa1ca..e21ca82a16 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs @@ -77,19 +77,9 @@ protected override IEnumerable DoGetInspectionResults() { var finder = DeclarationFinderProvider.DeclarationFinder; - var results = new List(); - foreach (var moduleDeclaration in State.DeclarationFinder.UserDeclarations(DeclarationType.Module)) - { - if (moduleDeclaration == null) - { - continue; - } - - var module = moduleDeclaration.QualifiedModuleName; - results.AddRange(DoGetInspectionResults(module, finder)); - } - - return results; + return finder.UserDeclarations(DeclarationType.Module) + .Where(module => module != null) + .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder)); } protected IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs index ab846af7ec..857bd2373e 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs @@ -3,7 +3,6 @@ using System.Globalization; using System.Linq; using Rubberduck.Parsing.Inspections.Abstract; -using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor; using System.Diagnostics; @@ -16,17 +15,15 @@ namespace Rubberduck.Inspections.Abstract { public abstract class InspectionBase : IInspection { - protected readonly RubberduckParserState State; protected readonly IDeclarationFinderProvider DeclarationFinderProvider; protected readonly ILogger Logger; - protected InspectionBase(RubberduckParserState state) + protected InspectionBase(IDeclarationFinderProvider declarationFinderProvider) { Logger = LogManager.GetLogger(GetType().FullName); - State = state; - DeclarationFinderProvider = state; + DeclarationFinderProvider = declarationFinderProvider; Name = GetType().Name; } @@ -67,26 +64,6 @@ protected InspectionBase(RubberduckParserState state) /// public virtual string AnnotationName => Name.Replace("Inspection", string.Empty); - /// - /// Gets all declarations in the parser state without an @Ignore annotation for this inspection. - /// - protected virtual IEnumerable Declarations => DeclarationFinderProvider - .DeclarationFinder - .AllDeclarations - .Where(declaration => !declaration.IsIgnoringInspectionResultFor(AnnotationName)); - - /// - /// Gets all user declarations in the parser state without an @Ignore annotation for this inspection. - /// - protected virtual IEnumerable UserDeclarations => DeclarationFinderProvider - .DeclarationFinder - .AllUserDeclarations - .Where(declaration => !declaration.IsIgnoringInspectionResultFor(AnnotationName)); - - protected virtual IEnumerable BuiltInDeclarations => DeclarationFinderProvider - .DeclarationFinder - .AllBuiltInDeclarations; - public int CompareTo(IInspection other) => string.Compare(InspectionType + Name, other.InspectionType + other.Name, StringComparison.Ordinal); public int CompareTo(object obj) => CompareTo(obj as IInspection); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs index b8bea5cb81..0f0fa9c6f4 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs @@ -63,18 +63,18 @@ public ApplicationWorksheetFunctionInspection(RubberduckParserState state) protected override IEnumerable ObjectionableDeclarations(DeclarationFinder finder) { - var excel = State.DeclarationFinder.Projects.SingleOrDefault(item => !item.IsUserDefined && item.IdentifierName == "Excel"); + var excel = finder.Projects.SingleOrDefault(item => !item.IsUserDefined && item.IdentifierName == "Excel"); if (excel == null) { return Enumerable.Empty(); } - if (!(State.DeclarationFinder.FindClassModule("WorksheetFunction", excel, true) is ModuleDeclaration worksheetFunctionsModule)) + if (!(finder.FindClassModule("WorksheetFunction", excel, true) is ModuleDeclaration worksheetFunctionsModule)) { return Enumerable.Empty(); } - if (!(State.DeclarationFinder.FindClassModule("Application", excel, true) is ModuleDeclaration excelApplicationClass)) + if (!(finder.FindClassModule("Application", excel, true) is ModuleDeclaration excelApplicationClass)) { return Enumerable.Empty(); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs index 80c80cf479..6151a646ef 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs @@ -43,8 +43,11 @@ public ExcelUdfNameIsValidCellReferenceInspection(RubberduckParserState state) protected override IEnumerable DoGetInspectionResults() { - if (!State.DeclarationFinder.Projects.Any(project => !project.IsUserDefined - && project.IdentifierName == "Excel")) + //FIXME As-is, both this method and the base method get a declaration finder. + var finder = DeclarationFinderProvider.DeclarationFinder; + + if (!finder.Projects.Any(project => !project.IsUserDefined + && project.IdentifierName == "Excel")) { return Enumerable.Empty(); } @@ -54,8 +57,11 @@ protected override IEnumerable DoGetInspectionResults() protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) { - if (!State.DeclarationFinder.Projects.Any(project => !project.IsUserDefined - && project.IdentifierName == "Excel")) + //FIXME As-is, both this method and the base method get a declaration finder. + var finder = DeclarationFinderProvider.DeclarationFinder; + + if (!finder.Projects.Any(project => !project.IsUserDefined + && project.IdentifierName == "Excel")) { return Enumerable.Empty(); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs index cd34338487..5686f615ff 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs @@ -41,15 +41,21 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class IllegalAnnotationInspection : InspectionBase { + private readonly RubberduckParserState _state; + public IllegalAnnotationInspection(RubberduckParserState state) : base(state) - {} + { + _state = state; + } protected override IEnumerable DoGetInspectionResults() { - var userDeclarations = State.DeclarationFinder.AllUserDeclarations.ToList(); - var identifierReferences = State.DeclarationFinder.AllIdentifierReferences().ToList(); - var annotations = State.AllAnnotations; + var finder = DeclarationFinderProvider.DeclarationFinder; + + var userDeclarations = finder.AllUserDeclarations.ToList(); + var identifierReferences = finder.AllIdentifierReferences().ToList(); + var annotations = _state.AllAnnotations; var unboundAnnotations = UnboundAnnotations(annotations, userDeclarations, identifierReferences) .Where(annotation => !annotation.Annotation.Target.HasFlag(AnnotationTarget.General) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitByRefModifierInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitByRefModifierInspection.cs index 29f8733587..29ca375d88 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitByRefModifierInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitByRefModifierInspection.cs @@ -56,8 +56,9 @@ protected override string ResultDescription(QualifiedContext protected override bool IsResultContext(QualifiedContext context) { //FIXME : This should really be a declaration inspection on the parameter. - var builtInEventHandlerContexts = State.DeclarationFinder.FindEventHandlers().Select(handler => handler.Context).ToHashSet(); - var interfaceImplementationMemberContexts = State.DeclarationFinder.FindAllInterfaceImplementingMembers().Select(member => member.Context).ToHashSet(); + var finder = DeclarationFinderProvider.DeclarationFinder; + var builtInEventHandlerContexts = finder.FindEventHandlers().Select(handler => handler.Context).ToHashSet(); + var interfaceImplementationMemberContexts = finder.FindAllInterfaceImplementingMembers().Select(member => member.Context).ToHashSet(); return !builtInEventHandlerContexts.Contains(context.Context.Parent.Parent) && !interfaceImplementationMemberContexts.Contains(context.Context.Parent.Parent); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs index f0e4050264..66942b2dda 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs @@ -63,24 +63,21 @@ public ObjectWhereProcedureIsRequiredInspection(RubberduckParserState state) protected override IEnumerable DoGetInspectionResults() { - var results = new List(); - foreach (var moduleDeclaration in State.DeclarationFinder.UserDeclarations(DeclarationType.Module)) - { - if (moduleDeclaration == null) - { - continue; - } - - var module = moduleDeclaration.QualifiedModuleName; - results.AddRange(DoGetInspectionResults(module)); - } + var finder = DeclarationFinderProvider.DeclarationFinder; - return results; + return finder.UserDeclarations(DeclarationType.Module) + .Where(module => module != null) + .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName)); } private IEnumerable DoGetInspectionResults(QualifiedModuleName module) { var finder = DeclarationFinderProvider.DeclarationFinder; + return DoGetInspectionResults(module, finder); + } + + private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + { return BoundInspectionResults(module, finder) .Concat(UnboundInspectionResults(module, finder)); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureCanBeWrittenAsFunctionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureCanBeWrittenAsFunctionInspection.cs index 122cebb901..71d4071a4f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureCanBeWrittenAsFunctionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureCanBeWrittenAsFunctionInspection.cs @@ -59,13 +59,15 @@ protected override IEnumerable DoGetInspectionResults() return Enumerable.Empty(); } - var userDeclarations = State.AllUserDeclarations.ToList(); - var builtinHandlers = State.DeclarationFinder.FindEventHandlers().ToList(); + var finder = DeclarationFinderProvider.DeclarationFinder; + + var userDeclarations = finder.AllUserDeclarations.ToList(); + var builtinHandlers = finder.FindEventHandlers().ToList(); var contextLookup = userDeclarations.Where(decl => decl.Context != null).ToDictionary(decl => decl.Context); - var ignored = new HashSet( State.DeclarationFinder.FindAllInterfaceMembers() - .Concat(State.DeclarationFinder.FindAllInterfaceImplementingMembers()) + var ignored = new HashSet(finder.FindAllInterfaceMembers() + .Concat(finder.FindAllInterfaceImplementingMembers()) .Concat(builtinHandlers) .Concat(userDeclarations.Where(item => item.IsWithEvents))); @@ -76,7 +78,7 @@ protected override IEnumerable DoGetInspectionResults() .Where(decl => decl != null && !ignored.Contains(decl) && userDeclarations.Where(item => item.IsWithEvents) - .All(withEvents => !State.DeclarationFinder.FindHandlersForWithEventsField(withEvents).Any()) && + .All(withEvents => !finder.FindHandlersForWithEventsField(withEvents).Any()) && !builtinHandlers.Contains(decl)) .Select(result => new DeclarationInspectionResult(this, string.Format(InspectionResults.ProcedureCanBeWrittenAsFunctionInspection, result.IdentifierName), diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantByRefModifierInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantByRefModifierInspection.cs index 8902269bc1..6243dc5837 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantByRefModifierInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantByRefModifierInspection.cs @@ -62,8 +62,9 @@ protected override string ResultDescription(QualifiedContext protected override bool IsResultContext(QualifiedContext context) { //FIXME This should be an inspection on parameter declarations. - var builtInEventHandlerContexts = State.DeclarationFinder.FindEventHandlers().Select(handler => handler.Context).ToHashSet(); - var interfaceImplementationMemberContexts = State.DeclarationFinder.FindAllInterfaceImplementingMembers().Select(member => member.Context).ToHashSet(); + var finder = DeclarationFinderProvider.DeclarationFinder; + var builtInEventHandlerContexts = finder.FindEventHandlers().Select(handler => handler.Context).ToHashSet(); + var interfaceImplementationMemberContexts = finder.FindAllInterfaceImplementingMembers().Select(member => member.Context).ToHashSet(); return !builtInEventHandlerContexts.Contains(context.Context.Parent.Parent) && !interfaceImplementationMemberContexts.Contains(context.Context.Parent.Parent); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs index e61503077b..99c487d8a9 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs @@ -53,24 +53,21 @@ public SuspiciousLetAssignmentInspection(RubberduckParserState state) protected override IEnumerable DoGetInspectionResults() { - var results = new List(); - foreach (var moduleDeclaration in State.DeclarationFinder.UserDeclarations(DeclarationType.Module)) - { - if (moduleDeclaration == null || moduleDeclaration.IsIgnoringInspectionResultFor(AnnotationName)) - { - continue; - } - - var module = moduleDeclaration.QualifiedModuleName; - results.AddRange(DoGetInspectionResults(module)); - } + var finder = DeclarationFinderProvider.DeclarationFinder; - return results; + return finder.UserDeclarations(DeclarationType.Module) + .Where(module => module != null) + .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder)); } private IEnumerable DoGetInspectionResults(QualifiedModuleName module) { var finder = DeclarationFinderProvider.DeclarationFinder; + return DoGetInspectionResults(module, finder); + } + + private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + { return BoundLhsInspectionResults(module, finder) .Concat(UnboundLhsInspectionResults(module, finder)); } From f1b6bb0d7549cb271d1e576bbd75171ab3d735ef Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Wed, 26 Feb 2020 17:03:40 +0100 Subject: [PATCH 252/461] Make ImplicitByRef- and RedundantByRefInspection declaration inspections --- .../ImplicitByRefModifierInspection.cs | 60 +++++-------- .../RedundantByRefModifierInspection.cs | 66 ++++++-------- .../UnhandledOnErrorResumeNextInspection.cs | 6 +- .../RemoveExplicitByRefModifierQuickFix.cs | 86 ++++++++++++------- .../RestoreErrorHandlingQuickFix.cs | 3 +- .../SpecifyExplicitByRefModifierQuickFix.cs | 76 +++++++++------- .../Extensions/ReadOnlyListExtensions.cs | 26 ++++++ .../Rubberduck.JunkDrawer.csproj | 3 + .../Symbols/EventDeclaration.cs | 2 +- .../Symbols/ExternalProcedureDeclaration.cs | 2 +- .../Symbols/IParameterizedDeclaration.cs | 2 +- .../Symbols/ModuleBodyElementDeclaration.cs | 2 +- 12 files changed, 188 insertions(+), 146 deletions(-) create mode 100644 Rubberduck.JunkDrawer/Extensions/ReadOnlyListExtensions.cs diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitByRefModifierInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitByRefModifierInspection.cs index 29ca375d88..21c05bce64 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitByRefModifierInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitByRefModifierInspection.cs @@ -1,12 +1,8 @@ -using System.Linq; -using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; -using Rubberduck.Parsing; -using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Rubberduck.JunkDrawer.Extensions; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -31,48 +27,38 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ImplicitByRefModifierInspection : ParseTreeInspectionBase + public sealed class ImplicitByRefModifierInspection : DeclarationInspectionBase { public ImplicitByRefModifierInspection(RubberduckParserState state) - : base(state) + : base(state, DeclarationType.Parameter) {} - public override IInspectionListener Listener { get; } = new ImplicitByRefModifierListener(); - protected override string ResultDescription(QualifiedContext context) + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { - var identifier = ((VBAParser.ArgContext)context.Context) - .unrestrictedIdentifier() - .identifier(); + if (!(declaration is ParameterDeclaration parameter) + || !parameter.IsImplicitByRef + || parameter.IsParamArray) + { + return false; + } - var identifierText = identifier.untypedIdentifier() != null - ? identifier.untypedIdentifier().identifierValue().GetText() - : identifier.typedIdentifier().untypedIdentifier().identifierValue().GetText(); + var parentDeclaration = parameter.ParentDeclaration; - return string.Format( - InspectionResults.ImplicitByRefModifierInspection, - identifierText); - } - - protected override bool IsResultContext(QualifiedContext context) - { - //FIXME : This should really be a declaration inspection on the parameter. - var finder = DeclarationFinderProvider.DeclarationFinder; - var builtInEventHandlerContexts = finder.FindEventHandlers().Select(handler => handler.Context).ToHashSet(); - var interfaceImplementationMemberContexts = finder.FindAllInterfaceImplementingMembers().Select(member => member.Context).ToHashSet(); + if (parentDeclaration is ModuleBodyElementDeclaration enclosingMethod) + { + return !enclosingMethod.IsInterfaceImplementation + && !finder.FindEventHandlers().Contains(enclosingMethod); + } - return !builtInEventHandlerContexts.Contains(context.Context.Parent.Parent) - && !interfaceImplementationMemberContexts.Contains(context.Context.Parent.Parent); + return parentDeclaration.DeclarationType != DeclarationType.LibraryFunction + && parentDeclaration.DeclarationType != DeclarationType.LibraryProcedure; } - public class ImplicitByRefModifierListener : InspectionListenerBase + protected override string ResultDescription(Declaration declaration) { - public override void ExitArg(VBAParser.ArgContext context) - { - if (context.PARAMARRAY() == null && context.BYVAL() == null && context.BYREF() == null) - { - SaveContext(context); - } - } + return string.Format( + InspectionResults.ImplicitByRefModifierInspection, + declaration.IdentifierName); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantByRefModifierInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantByRefModifierInspection.cs index 6243dc5837..0d9f8bd03f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantByRefModifierInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantByRefModifierInspection.cs @@ -1,12 +1,8 @@ -using System.Linq; -using Antlr4.Runtime; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Parsing; -using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Rubberduck.JunkDrawer.Extensions; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -36,49 +32,39 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class RedundantByRefModifierInspection : ParseTreeInspectionBase + public sealed class RedundantByRefModifierInspection : DeclarationInspectionBase { public RedundantByRefModifierInspection(RubberduckParserState state) - : base(state) - { - } + : base(state, DeclarationType.Parameter) + { } - public override IInspectionListener Listener { get; } = new RedundantByRefModifierListener(); - protected override string ResultDescription(QualifiedContext context) + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { - var identifier = ((VBAParser.ArgContext)context.Context) - .unrestrictedIdentifier() - .identifier(); - - var identifierText = identifier.untypedIdentifier() != null - ? identifier.untypedIdentifier().identifierValue().GetText() - : identifier.typedIdentifier().untypedIdentifier().identifierValue().GetText(); + if (!(declaration is ParameterDeclaration parameter) + || parameter.IsImplicitByRef + || !parameter.IsByRef + || parameter.IsParamArray) + { + return false; + } - return string.Format( - InspectionResults.RedundantByRefModifierInspection, - identifierText); - } + var parentDeclaration = parameter.ParentDeclaration; - protected override bool IsResultContext(QualifiedContext context) - { - //FIXME This should be an inspection on parameter declarations. - var finder = DeclarationFinderProvider.DeclarationFinder; - var builtInEventHandlerContexts = finder.FindEventHandlers().Select(handler => handler.Context).ToHashSet(); - var interfaceImplementationMemberContexts = finder.FindAllInterfaceImplementingMembers().Select(member => member.Context).ToHashSet(); + if (parentDeclaration is ModuleBodyElementDeclaration enclosingMethod) + { + return !enclosingMethod.IsInterfaceImplementation + && !finder.FindEventHandlers().Contains(enclosingMethod); + } - return !builtInEventHandlerContexts.Contains(context.Context.Parent.Parent) - && !interfaceImplementationMemberContexts.Contains(context.Context.Parent.Parent); + return parentDeclaration.DeclarationType != DeclarationType.LibraryFunction + && parentDeclaration.DeclarationType != DeclarationType.LibraryProcedure; } - public class RedundantByRefModifierListener : InspectionListenerBase + protected override string ResultDescription(Declaration declaration) { - public override void ExitArg(VBAParser.ArgContext context) - { - if (context.BYREF() != null) - { - SaveContext(context); - } - } + return string.Format( + InspectionResults.RedundantByRefModifierInspection, + declaration.IdentifierName); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs index 2c296b90aa..395ae4fb5a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs @@ -35,7 +35,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public class UnhandledOnErrorResumeNextInspection : ParseTreeInspectionBase> + public class UnhandledOnErrorResumeNextInspection : ParseTreeInspectionBase> { private readonly Dictionary, List> _unhandledContextsMap = new Dictionary, List>(); @@ -47,12 +47,12 @@ public UnhandledOnErrorResumeNextInspection(RubberduckParserState state) } public override IInspectionListener Listener { get; } - protected override string ResultDescription(QualifiedContext context, IList properties) + protected override string ResultDescription(QualifiedContext context, IReadOnlyList properties) { return InspectionResults.UnhandledOnErrorResumeNextInspection; } - protected override (bool isResult, IList properties) IsResultContextWithAdditionalProperties(QualifiedContext context) + protected override (bool isResult, IReadOnlyList properties) IsResultContextWithAdditionalProperties(QualifiedContext context) { return (true, _unhandledContextsMap[context]); } diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitByRefModifierQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitByRefModifierQuickFix.cs index 8e64fd7a87..43e9737d10 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitByRefModifierQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitByRefModifierQuickFix.cs @@ -1,5 +1,4 @@ -using System; -using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Grammar; using System.Linq; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Concrete; @@ -8,6 +7,7 @@ using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.QuickFixes { @@ -50,38 +50,57 @@ public RemoveExplicitByRefModifierQuickFix(IDeclarationFinderProvider declaratio public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) { - var context = (VBAParser.ArgContext) result.Context; + if (!(result.Target is ParameterDeclaration parameter)) + { + return; + } - RemoveByRefIdentifier(rewriteSession.CheckOutModuleRewriter(result.QualifiedSelection.QualifiedName), context); + RemoveByRefIdentifier(rewriteSession, parameter); - var interfaceMembers = _declarationFinderProvider.DeclarationFinder.FindAllInterfaceMembers().ToArray(); + var finder = _declarationFinderProvider.DeclarationFinder; + var parentDeclaration = parameter.ParentDeclaration; - var matchingInterfaceMemberContext = interfaceMembers.Select(member => member.Context).FirstOrDefault(c => c == context.Parent.Parent); + if (parentDeclaration is ModuleBodyElementDeclaration enclosingMember + && enclosingMember.IsInterfaceMember) + { + var parameterIndex = ParameterIndex(parameter, enclosingMember); + RemoveByRefIdentifierFromImplementations(enclosingMember, parameterIndex, finder, rewriteSession); + } - if (matchingInterfaceMemberContext != null) + if (parentDeclaration is EventDeclaration enclosingEvent) { - var interfaceParameterIndex = GetParameterIndex(context); - - var implementationMembers = - _declarationFinderProvider.DeclarationFinder.FindInterfaceImplementationMembers(interfaceMembers.First( - member => member.Context == matchingInterfaceMemberContext)).ToHashSet(); - - var parameters = - _declarationFinderProvider.DeclarationFinder.UserDeclarations(DeclarationType.Parameter) - .Where(p => implementationMembers.Contains(p.ParentDeclaration)) - .Cast() - .ToArray(); - - foreach (var parameter in parameters) - { - var parameterContext = (VBAParser.ArgContext) parameter.Context; - var parameterIndex = GetParameterIndex(parameterContext); - - if (parameterIndex == interfaceParameterIndex) - { - RemoveByRefIdentifier(rewriteSession.CheckOutModuleRewriter(parameter.QualifiedModuleName), parameterContext); - } - } + var parameterIndex = ParameterIndex(parameter, enclosingEvent); + RemoveByRefIdentifierFromHandlers(enclosingEvent, parameterIndex, finder, rewriteSession); + } + } + + private static void RemoveByRefIdentifierFromImplementations( + ModuleBodyElementDeclaration interfaceMember, + int parameterIndex, + DeclarationFinder finder, + IRewriteSession rewriteSession) + { + var implementationParameters = finder.FindInterfaceImplementationMembers(interfaceMember) + .Select(implementation => implementation.Parameters[parameterIndex]); + + foreach (var parameter in implementationParameters) + { + RemoveByRefIdentifier(rewriteSession, parameter); + } + } + + private static void RemoveByRefIdentifierFromHandlers( + EventDeclaration eventDeclaration, + int parameterIndex, + DeclarationFinder finder, + IRewriteSession rewriteSession) + { + var handlers = finder.FindEventHandlers(eventDeclaration) + .Select(implementation => implementation.Parameters[parameterIndex]); + + foreach (var parameter in handlers) + { + RemoveByRefIdentifier(rewriteSession, parameter); } } @@ -91,13 +110,16 @@ public override void Fix(IInspectionResult result, IRewriteSession rewriteSessio public override bool CanFixInModule => true; public override bool CanFixInProject => true; - private static int GetParameterIndex(VBAParser.ArgContext context) + private static int ParameterIndex(ParameterDeclaration parameter, IParameterizedDeclaration enclosingMember) { - return Array.IndexOf(((VBAParser.ArgListContext)context.Parent).arg().ToArray(), context); + return enclosingMember.Parameters.IndexOf(parameter); } - private static void RemoveByRefIdentifier(IModuleRewriter rewriter, VBAParser.ArgContext context) + private static void RemoveByRefIdentifier(IRewriteSession rewriteSession, ParameterDeclaration parameter) { + var rewriter = rewriteSession.CheckOutModuleRewriter(parameter.QualifiedModuleName); + var context = (VBAParser.ArgContext)parameter.Context; + if (context.BYREF() != null) { rewriter.Remove(context.BYREF()); diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs index 8579a66dd0..4706372e81 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs @@ -3,6 +3,7 @@ using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Concrete; +using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -55,7 +56,7 @@ public RestoreErrorHandlingQuickFix() public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) { - if (!(result is IWithInspectionResultProperties> resultProperties)) + if (!(result is IWithInspectionResultProperties> resultProperties)) { return; } diff --git a/Rubberduck.CodeAnalysis/QuickFixes/SpecifyExplicitByRefModifierQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/SpecifyExplicitByRefModifierQuickFix.cs index 3c9d6a8887..b562dccaa6 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/SpecifyExplicitByRefModifierQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/SpecifyExplicitByRefModifierQuickFix.cs @@ -1,4 +1,3 @@ -using System; using Rubberduck.Parsing.Grammar; using System.Linq; using Rubberduck.Inspections.Abstract; @@ -8,6 +7,7 @@ using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.QuickFixes { @@ -50,42 +50,58 @@ public SpecifyExplicitByRefModifierQuickFix(IDeclarationFinderProvider declarati public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) { - var context = (VBAParser.ArgContext)result.Context; - - AddByRefIdentifier(rewriteSession.CheckOutModuleRewriter(result.QualifiedSelection.QualifiedName), context); + if (!(result.Target is ParameterDeclaration parameter)) + { + return; + } - var interfaceMembers = _declarationFinderProvider.DeclarationFinder.FindAllInterfaceMembers().ToArray(); + AddByRefIdentifier(rewriteSession, parameter); - var matchingInterfaceMemberContext = interfaceMembers.Select(member => member.Context).FirstOrDefault(c => c == context.Parent.Parent); + var finder = _declarationFinderProvider.DeclarationFinder; + var parentDeclaration = parameter.ParentDeclaration; - if (matchingInterfaceMemberContext == null) + if (parentDeclaration is ModuleBodyElementDeclaration enclosingMember + && enclosingMember.IsInterfaceMember) { - return; + var parameterIndex = ParameterIndex(parameter, enclosingMember); + AddByRefIdentifierToImplementations(enclosingMember, parameterIndex, finder, rewriteSession); } - - var interfaceParameterIndex = GetParameterIndex(context); - var implementationMembers = - _declarationFinderProvider.DeclarationFinder.FindInterfaceImplementationMembers(interfaceMembers.First( - member => member.Context == matchingInterfaceMemberContext)).ToHashSet(); + if (parentDeclaration is EventDeclaration enclosingEvent) + { + var parameterIndex = ParameterIndex(parameter, enclosingEvent); + AddByRefIdentifierToHandlers(enclosingEvent, parameterIndex, finder, rewriteSession); + } + } - var parameters = - _declarationFinderProvider.DeclarationFinder.UserDeclarations(DeclarationType.Parameter) - .Where(p => implementationMembers.Contains(p.ParentDeclaration)) - .Cast() - .ToArray(); + private static void AddByRefIdentifierToImplementations( + ModuleBodyElementDeclaration interfaceMember, + int parameterIndex, + DeclarationFinder finder, + IRewriteSession rewriteSession) + { + var implementationParameters = finder.FindInterfaceImplementationMembers(interfaceMember) + .Select(implementation => implementation.Parameters[parameterIndex]); - foreach (var parameter in parameters) + foreach (var parameter in implementationParameters) { - var parameterContext = (VBAParser.ArgContext)parameter.Context; - var parameterIndex = GetParameterIndex(parameterContext); + AddByRefIdentifier(rewriteSession, parameter); + } + } - if (parameterIndex == interfaceParameterIndex) - { - AddByRefIdentifier(rewriteSession.CheckOutModuleRewriter(parameter.QualifiedModuleName), parameterContext); - } + private static void AddByRefIdentifierToHandlers( + EventDeclaration eventDeclaration, + int parameterIndex, + DeclarationFinder finder, + IRewriteSession rewriteSession) + { + var handlers = finder.FindEventHandlers(eventDeclaration) + .Select(implementation => implementation.Parameters[parameterIndex]); + + foreach (var parameter in handlers) + { + AddByRefIdentifier(rewriteSession, parameter); } - } public override string Description(IInspectionResult result) => Resources.Inspections.QuickFixes.ImplicitByRefModifierQuickFix; @@ -94,13 +110,15 @@ public override void Fix(IInspectionResult result, IRewriteSession rewriteSessio public override bool CanFixInModule => true; public override bool CanFixInProject => true; - private static int GetParameterIndex(VBAParser.ArgContext context) + private static int ParameterIndex(ParameterDeclaration parameter, IParameterizedDeclaration enclosingMember) { - return Array.IndexOf(((VBAParser.ArgListContext)context.Parent).arg().ToArray(), context); + return enclosingMember.Parameters.IndexOf(parameter); } - private static void AddByRefIdentifier(IModuleRewriter rewriter, VBAParser.ArgContext context) + private static void AddByRefIdentifier(IRewriteSession rewriteSession, ParameterDeclaration parameter) { + var rewriter = rewriteSession.CheckOutModuleRewriter(parameter.QualifiedModuleName); + var context = (VBAParser.ArgContext) parameter.Context; if (context.BYREF() == null) { rewriter.InsertBefore(context.unrestrictedIdentifier().Start.TokenIndex, "ByRef "); diff --git a/Rubberduck.JunkDrawer/Extensions/ReadOnlyListExtensions.cs b/Rubberduck.JunkDrawer/Extensions/ReadOnlyListExtensions.cs new file mode 100644 index 0000000000..fd331e01db --- /dev/null +++ b/Rubberduck.JunkDrawer/Extensions/ReadOnlyListExtensions.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Rubberduck.JunkDrawer.Extensions +{ + public static class ReadOnlyListExtensions + { + public static int FindIndex(this IReadOnlyList source, Predicate predicate) + { + var (elem, index) = source.Select((item, i) => (item, i)).FirstOrDefault(tpl => predicate(tpl.item)); + + if (index > 0 || index == 0 && predicate(source[0])) + { + return index; + } + + return -1; + } + + public static int IndexOf(this IReadOnlyList source, T elem) + { + return source.FindIndex(item => elem.Equals(item)); + } + } +} \ No newline at end of file diff --git a/Rubberduck.JunkDrawer/Rubberduck.JunkDrawer.csproj b/Rubberduck.JunkDrawer/Rubberduck.JunkDrawer.csproj index 395718f6fd..c6fed6f74f 100644 --- a/Rubberduck.JunkDrawer/Rubberduck.JunkDrawer.csproj +++ b/Rubberduck.JunkDrawer/Rubberduck.JunkDrawer.csproj @@ -12,4 +12,7 @@ 1701;1702;;4011;1001;7035;1053;1591 + + + \ No newline at end of file diff --git a/Rubberduck.Parsing/Symbols/EventDeclaration.cs b/Rubberduck.Parsing/Symbols/EventDeclaration.cs index 0494223ed9..44af5e6300 100644 --- a/Rubberduck.Parsing/Symbols/EventDeclaration.cs +++ b/Rubberduck.Parsing/Symbols/EventDeclaration.cs @@ -69,7 +69,7 @@ public EventDeclaration(ComMember member, Declaration parent, QualifiedModuleNam .ToList(); } - public IEnumerable Parameters => _parameters.ToList(); + public IReadOnlyList Parameters => _parameters.ToList(); public void AddParameter(ParameterDeclaration parameter) { diff --git a/Rubberduck.Parsing/Symbols/ExternalProcedureDeclaration.cs b/Rubberduck.Parsing/Symbols/ExternalProcedureDeclaration.cs index abd9b24715..1e22a2d177 100644 --- a/Rubberduck.Parsing/Symbols/ExternalProcedureDeclaration.cs +++ b/Rubberduck.Parsing/Symbols/ExternalProcedureDeclaration.cs @@ -47,7 +47,7 @@ public ExternalProcedureDeclaration( _parameters = new List(); } - public IEnumerable Parameters => _parameters.ToList(); + public IReadOnlyList Parameters => _parameters.ToList(); public void AddParameter(ParameterDeclaration parameter) { diff --git a/Rubberduck.Parsing/Symbols/IParameterizedDeclaration.cs b/Rubberduck.Parsing/Symbols/IParameterizedDeclaration.cs index 3cfd93a116..0f37f1b135 100644 --- a/Rubberduck.Parsing/Symbols/IParameterizedDeclaration.cs +++ b/Rubberduck.Parsing/Symbols/IParameterizedDeclaration.cs @@ -4,7 +4,7 @@ namespace Rubberduck.Parsing.Symbols { public interface IParameterizedDeclaration { - IEnumerable Parameters { get; } + IReadOnlyList Parameters { get; } void AddParameter(ParameterDeclaration parameter); } } diff --git a/Rubberduck.Parsing/Symbols/ModuleBodyElementDeclaration.cs b/Rubberduck.Parsing/Symbols/ModuleBodyElementDeclaration.cs index 9229db8b7e..84f9234bac 100644 --- a/Rubberduck.Parsing/Symbols/ModuleBodyElementDeclaration.cs +++ b/Rubberduck.Parsing/Symbols/ModuleBodyElementDeclaration.cs @@ -60,7 +60,7 @@ protected ModuleBodyElementDeclaration( public bool IsDefaultMember => this.IsDefaultMember(); private readonly List _parameters = new List(); - public IEnumerable Parameters => _parameters.ToList(); + public IReadOnlyList Parameters => _parameters.ToList(); public void AddParameter(ParameterDeclaration parameter) { From 46d370700916d051007fd07ec017bb9f78188ec1 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Wed, 26 Feb 2020 17:08:12 +0100 Subject: [PATCH 253/461] Move DeclarationExtensions to JunkDrawer --- .../Inspections/Abstract/ParseTreeInspectionBase.cs | 2 +- .../UnreachableCaseInspection/UnreachableCaseInspection.cs | 2 +- .../Extensions/DictionaryExtensions.cs | 2 +- Rubberduck.Parsing/Preprocessing/CompilationArgumentsCache.cs | 2 +- Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs | 1 - .../VBA/DeclarationResolving/DeclarationResolveRunnerBase.cs | 2 +- 6 files changed, 5 insertions(+), 6 deletions(-) rename {Rubberduck.VBEEditor => Rubberduck.JunkDrawer}/Extensions/DictionaryExtensions.cs (98%) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs index 21183b4b13..8ccff6b2d4 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs @@ -2,13 +2,13 @@ using System.Linq; using Antlr4.Runtime; using Rubberduck.Inspections.Results; +using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.Parsing; using Rubberduck.VBEditor; -using Rubberduck.VBEditor.Extensions; namespace Rubberduck.Inspections.Abstract { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs index fcc4336f21..8c9d8cd81f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs @@ -13,8 +13,8 @@ using Rubberduck.Parsing.Symbols; using System; using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing.VBA.Parsing; -using Rubberduck.VBEditor.Extensions; namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { diff --git a/Rubberduck.VBEEditor/Extensions/DictionaryExtensions.cs b/Rubberduck.JunkDrawer/Extensions/DictionaryExtensions.cs similarity index 98% rename from Rubberduck.VBEEditor/Extensions/DictionaryExtensions.cs rename to Rubberduck.JunkDrawer/Extensions/DictionaryExtensions.cs index c23d8a7e91..979afb8de6 100644 --- a/Rubberduck.VBEEditor/Extensions/DictionaryExtensions.cs +++ b/Rubberduck.JunkDrawer/Extensions/DictionaryExtensions.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; -namespace Rubberduck.VBEditor.Extensions +namespace Rubberduck.JunkDrawer.Extensions { public static class DictionaryExtensions { diff --git a/Rubberduck.Parsing/Preprocessing/CompilationArgumentsCache.cs b/Rubberduck.Parsing/Preprocessing/CompilationArgumentsCache.cs index 3d9fd58a38..33f9788a46 100644 --- a/Rubberduck.Parsing/Preprocessing/CompilationArgumentsCache.cs +++ b/Rubberduck.Parsing/Preprocessing/CompilationArgumentsCache.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using Rubberduck.VBEditor.Extensions; +using Rubberduck.JunkDrawer.Extensions; namespace Rubberduck.Parsing.PreProcessing { diff --git a/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs b/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs index 96b4a1ec19..f745f96be1 100644 --- a/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs +++ b/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs @@ -13,7 +13,6 @@ using Rubberduck.Parsing.VBA.Extensions; using Rubberduck.Parsing.VBA.ReferenceManagement; using Rubberduck.VBEditor; -using Rubberduck.VBEditor.Extensions; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; diff --git a/Rubberduck.Parsing/VBA/DeclarationResolving/DeclarationResolveRunnerBase.cs b/Rubberduck.Parsing/VBA/DeclarationResolving/DeclarationResolveRunnerBase.cs index 6920696118..08aa1ba088 100644 --- a/Rubberduck.Parsing/VBA/DeclarationResolving/DeclarationResolveRunnerBase.cs +++ b/Rubberduck.Parsing/VBA/DeclarationResolving/DeclarationResolveRunnerBase.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -7,6 +6,7 @@ using Antlr4.Runtime; using Antlr4.Runtime.Tree; using NLog; +using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; From 0c7da5a01573d91b3bf9005bf807dbcd15b6a231 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Wed, 26 Feb 2020 17:49:36 +0100 Subject: [PATCH 254/461] Make IllegalAnnotationInspection work for individual modules --- .../Concrete/IllegalAnnotationInspection.cs | 65 +++++++++++++++---- .../MissingAnnotationArgumentInspection.cs | 7 +- .../Annotations/AnnotationBase.cs | 7 +- Rubberduck.Parsing/Annotations/IAnnotation.cs | 4 +- .../DeclarationResolveRunnerBase.cs | 2 +- .../VBA/RubberduckParserState.cs | 2 +- 6 files changed, 64 insertions(+), 23 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs index 5686f615ff..b4c1f34024 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs @@ -9,6 +9,8 @@ using Rubberduck.Parsing.Symbols; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.VBEditor; using Rubberduck.VBEditor.SafeComWrappers; namespace Rubberduck.Inspections.Concrete @@ -53,27 +55,65 @@ protected override IEnumerable DoGetInspectionResults() { var finder = DeclarationFinderProvider.DeclarationFinder; - var userDeclarations = finder.AllUserDeclarations.ToList(); - var identifierReferences = finder.AllIdentifierReferences().ToList(); - var annotations = _state.AllAnnotations; + return finder.UserDeclarations(DeclarationType.Module) + .Where(module => module != null) + .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder)); + } + + private IEnumerable DoGetInspectionResults(QualifiedModuleName module) + { + var finder = DeclarationFinderProvider.DeclarationFinder; + return DoGetInspectionResults(module, finder); + } + + private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + { + var userDeclarations = finder.Members(module).ToList(); + var identifierReferences = finder.IdentifierReferences(module).ToList(); + var annotations = _state.GetAnnotations(module); var unboundAnnotations = UnboundAnnotations(annotations, userDeclarations, identifierReferences) .Where(annotation => !annotation.Annotation.Target.HasFlag(AnnotationTarget.General) || annotation.AnnotatedLine == null); - var attributeAnnotationsInDocuments = AttributeAnnotationsInDocuments(userDeclarations); var attributeAnnotationsOnDeclarationsNotAllowingAttributes = AttributeAnnotationsOnDeclarationsNotAllowingAttributes(userDeclarations); var illegalAnnotations = unboundAnnotations - .Concat(attributeAnnotationsInDocuments) .Concat(attributeAnnotationsOnDeclarationsNotAllowingAttributes) - .ToHashSet(); + .Distinct(); + + if (module.ComponentType == ComponentType.Document) + { + var attributeAnnotationsInDocuments = AttributeAnnotationsInDocuments(userDeclarations); + illegalAnnotations = illegalAnnotations + .Concat(attributeAnnotationsInDocuments) + .Distinct(); + } - return illegalAnnotations.Select(annotation => - new QualifiedContextInspectionResult( - this, - string.Format(InspectionResults.IllegalAnnotationInspection, annotation.Context.annotationName().GetText()), - new QualifiedContext(annotation.QualifiedSelection.QualifiedName, annotation.Context))); + return illegalAnnotations + .Select(InspectionResult) + .ToList(); + } + + private IInspectionResult InspectionResult(IParseTreeAnnotation pta) + { + return new QualifiedContextInspectionResult( + this, + ResultDescription(pta), + Context(pta)); + } + + private static string ResultDescription(IParseTreeAnnotation pta) + { + var annotationText = pta.Context.annotationName().GetText(); + return string.Format( + InspectionResults.IllegalAnnotationInspection, + annotationText); + } + + private static QualifiedContext Context(IParseTreeAnnotation pta) + { + return new QualifiedContext(pta.QualifiedSelection.QualifiedName, pta.Context); } private static IEnumerable UnboundAnnotations(IEnumerable annotations, IEnumerable userDeclarations, IEnumerable identifierReferences) @@ -91,7 +131,8 @@ private static IEnumerable AttributeAnnotationsInDocuments { var declarationsInDocuments = userDeclarations .Where(declaration => declaration.QualifiedModuleName.ComponentType == ComponentType.Document); - return declarationsInDocuments.SelectMany(doc => doc.Annotations).Where(pta => pta.Annotation is IAttributeAnnotation); + return declarationsInDocuments.SelectMany(doc => doc.Annotations) + .Where(pta => pta.Annotation is IAttributeAnnotation); } private static IEnumerable AttributeAnnotationsOnDeclarationsNotAllowingAttributes(IEnumerable userDeclarations) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs index ba74bcb8b2..d4e76e81b7 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs @@ -33,8 +33,13 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class MissingAnnotationArgumentInspection : ParseTreeInspectionBase { + private readonly RubberduckParserState _state; + public MissingAnnotationArgumentInspection(RubberduckParserState state) - : base(state) { } + : base(state) + { + _state = state; + } public override CodeKind TargetKindOfCode => CodeKind.AttributesCode; diff --git a/Rubberduck.Parsing/Annotations/AnnotationBase.cs b/Rubberduck.Parsing/Annotations/AnnotationBase.cs index e1eaaca38a..076e7c5a02 100644 --- a/Rubberduck.Parsing/Annotations/AnnotationBase.cs +++ b/Rubberduck.Parsing/Annotations/AnnotationBase.cs @@ -1,8 +1,5 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; -using Rubberduck.Parsing.Grammar; -using Rubberduck.VBEditor; namespace Rubberduck.Parsing.Annotations { @@ -12,7 +9,7 @@ public abstract class AnnotationBase : IAnnotation public string Name { get; } public AnnotationTarget Target { get; } - public AnnotationBase(string name, AnnotationTarget target, bool allowMultiple = false) + protected AnnotationBase(string name, AnnotationTarget target, bool allowMultiple = false) { Name = name; Target = target; diff --git a/Rubberduck.Parsing/Annotations/IAnnotation.cs b/Rubberduck.Parsing/Annotations/IAnnotation.cs index 0245ad7c75..84139d0bfb 100644 --- a/Rubberduck.Parsing/Annotations/IAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/IAnnotation.cs @@ -1,6 +1,4 @@ -using Rubberduck.Parsing.Grammar; -using Rubberduck.VBEditor; -using System; +using System; using System.Collections.Generic; namespace Rubberduck.Parsing.Annotations diff --git a/Rubberduck.Parsing/VBA/DeclarationResolving/DeclarationResolveRunnerBase.cs b/Rubberduck.Parsing/VBA/DeclarationResolving/DeclarationResolveRunnerBase.cs index 08aa1ba088..79f8c35265 100644 --- a/Rubberduck.Parsing/VBA/DeclarationResolving/DeclarationResolveRunnerBase.cs +++ b/Rubberduck.Parsing/VBA/DeclarationResolving/DeclarationResolveRunnerBase.cs @@ -139,7 +139,7 @@ protected void ResolveDeclarations(QualifiedModuleName module, IParseTree tree, } Logger.Debug($"Creating declarations for module {module.Name}."); - var annotationsOnWhiteSpaceLines = _state.GetModuleAnnotations(module) + var annotationsOnWhiteSpaceLines = _state.GetAnnotations(module) .Where(a => a.AnnotatedLine.HasValue) .GroupBy(a => a.AnnotatedLine.Value) .ToDictionary(); diff --git a/Rubberduck.Parsing/VBA/RubberduckParserState.cs b/Rubberduck.Parsing/VBA/RubberduckParserState.cs index 038b71c630..3980afd817 100644 --- a/Rubberduck.Parsing/VBA/RubberduckParserState.cs +++ b/Rubberduck.Parsing/VBA/RubberduckParserState.cs @@ -687,7 +687,7 @@ public List AllAnnotations } } - public IEnumerable GetModuleAnnotations(QualifiedModuleName module) + public IEnumerable GetAnnotations(QualifiedModuleName module) { if (_moduleStates.TryGetValue(module, out var result)) { From 2fc42173a1aa3c16d9ac3bbafdd75d8fef11b473 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Wed, 26 Feb 2020 18:44:03 +0100 Subject: [PATCH 255/461] Reduce constructor requirements on inspections Require an IDeclarationFinderProvider instead of a RubberduckParserState. --- ...ReferenceInspectionFromDeclarationsBase.cs | 5 +-- .../Abstract/DeclarationInspectionBase.cs | 16 +++++----- .../Abstract/DeclarationInspectionBaseBase.cs | 8 ++--- .../DeclarationInspectionMultiResultBase.cs | 8 ++--- ...ionInspectionUsingGlobalInformationBase.cs | 16 +++++----- ...nspectionUsingGlobalInformationBaseBase.cs | 8 ++--- .../IdentifierReferenceInspectionBase.cs | 10 +++--- ...ReferenceInspectionFromDeclarationsBase.cs | 10 +++--- .../Abstract/ImplicitTypeInspectionBase.cs | 8 ++--- .../Abstract/IsMissingInspectionBase.cs | 5 +-- ...berAccessMayReturnNothingInspectionBase.cs | 4 ++- .../Abstract/ParseTreeInspectionBase.cs | 9 +++--- ...entWithIncompatibleObjectTypeInspection.cs | 8 ++--- .../AssignedByValParameterInspection.cs | 4 +-- .../Concrete/AssignmentNotUsedInspection.cs | 5 +-- .../AttributeValueOutOfSyncInspection.cs | 7 ++-- .../BooleanAssignedInIfElseInspection.cs | 5 +-- .../Concrete/ConstantNotUsedInspection.cs | 5 +-- .../Concrete/DefTypeStatementInspection.cs | 4 +-- .../DefaultMemberRequiredInspection.cs | 5 ++- .../Concrete/DefaultProjectNameInspection.cs | 8 ++--- .../DuplicatedAnnotationInspection.cs | 6 ++-- .../Concrete/EmptyCaseBlockInspection.cs | 4 +-- .../Concrete/EmptyDoWhileBlockInspection.cs | 4 +-- .../Concrete/EmptyElseBlockInspection.cs | 4 +-- .../Concrete/EmptyForEachBlockInspection.cs | 4 +-- .../Concrete/EmptyForLoopBlockInspection.cs | 5 +-- .../Concrete/EmptyIfBlockInspection.cs | 4 +-- .../Concrete/EmptyMethodInspection.cs | 4 +-- .../Concrete/EmptyModuleInspection.cs | 6 ++-- .../Concrete/EmptyStringLiteralInspection.cs | 4 +-- .../Concrete/EmptyWhileWendBlockInspection.cs | 4 +-- .../EncapsulatePublicFieldInspection.cs | 4 +-- .../ApplicationWorksheetFunctionInspection.cs | 9 ++---- .../ExcelMemberMayReturnNothingInspection.cs | 7 ++-- ...elUdfNameIsValidCellReferenceInspection.cs | 6 ++-- .../ImplicitActiveSheetReferenceInspection.cs | 4 +-- ...plicitActiveWorkbookReferenceInspection.cs | 5 +-- .../SheetAccessedUsingStringInspection.cs | 4 +-- ...ionReturnValueAlwaysDiscardedInspection.cs | 4 +-- .../FunctionReturnValueDiscardedInspection.cs | 4 +-- .../HostSpecificExpressionInspection.cs | 7 ++-- .../Concrete/HungarianNotationInspection.cs | 4 +-- .../ImplementedInterfaceMemberInspection.cs | 5 +-- .../ImplicitByRefModifierInspection.cs | 4 +-- .../ImplicitDefaultMemberAccessInspection.cs | 4 +-- .../ImplicitPublicMemberInspection.cs | 4 +-- ...tRecursiveDefaultMemberAccessInspection.cs | 4 +-- ...citUnboundDefaultMemberAccessInspection.cs | 4 +-- .../ImplicitVariantReturnTypeInspection.cs | 4 +-- .../ImplicitlyTypedConstInspection.cs | 4 +-- .../IndexedDefaultMemberAccessInspection.cs | 4 +-- ...dRecursiveDefaultMemberAccessInspection.cs | 4 +-- ...xedUnboundDefaultMemberAccessInspection.cs | 4 +-- .../Concrete/IntegerDataTypeInspection.cs | 6 ++-- ...issingOnInappropriateArgumentInspection.cs | 12 +++---- ...ssingWithNonArgumentParameterInspection.cs | 5 +-- .../Concrete/LineLabelNotUsedInspection.cs | 8 ++--- .../MemberNotOnInterfaceInspection.cs | 9 ++---- .../Concrete/MissingAttributeInspection.cs | 8 ++--- .../MissingMemberAnnotationInspection.cs | 4 +-- .../MissingModuleAnnotationInspection.cs | 5 ++- .../ModuleScopeDimKeywordInspection.cs | 10 ++---- .../Concrete/ModuleWithoutFolderInspection.cs | 4 +-- .../MoveFieldCloserToUsageInspection.cs | 4 +-- .../Concrete/MultilineParameterInspection.cs | 4 +-- .../MultipleDeclarationsInspection.cs | 5 +-- .../NonReturningFunctionInspection.cs | 10 ++---- .../ObjectVariableNotSetInspection.cs | 4 +-- ...bjectWhereProcedureIsRequiredInspection.cs | 4 +-- .../ObsoleteCallStatementInspection.cs | 4 +-- .../ObsoleteCallingConventionInspection.cs | 4 +-- .../ObsoleteCommentSyntaxInspection.cs | 4 +-- .../Concrete/ObsoleteErrorSyntaxInspection.cs | 4 +-- .../Concrete/ObsoleteGlobalInspection.cs | 5 +-- .../ObsoleteLetStatementInspection.cs | 4 +-- .../Concrete/ObsoleteMemberUsageInspection.cs | 11 +++---- .../Concrete/ObsoleteTypeHintInspection.cs | 32 ++++++------------- .../ObsoleteWhileWendStatementInspection.cs | 4 +-- .../Concrete/OnLocalErrorInspection.cs | 5 +-- .../Concrete/OptionBaseInspection.cs | 4 +-- .../Concrete/OptionExplicitInspection.cs | 4 +-- .../Concrete/ParameterCanBeByValInspection.cs | 4 +-- .../Concrete/ParameterNotUsedInspection.cs | 4 +-- ...ocedureCanBeWrittenAsFunctionInspection.cs | 4 +-- .../Concrete/ProcedureNotUsedInspection.cs | 4 +-- .../Concrete/ProcedureRequiredInspection.cs | 5 ++- .../RedundantByRefModifierInspection.cs | 6 ++-- .../Concrete/RedundantOptionInspection.cs | 4 +-- .../SelfAssignedDeclarationInspection.cs | 4 +-- ...entWithIncompatibleObjectTypeInspection.cs | 4 +-- .../Concrete/ShadowedDeclarationInspection.cs | 8 ++--- .../Concrete/StepIsNotSpecifiedInspection.cs | 5 +-- .../Concrete/StepOneIsRedundantInspection.cs | 4 +-- .../Concrete/StopKeywordInspection.cs | 4 +-- .../SuspiciousLetAssignmentInspection.cs | 4 +-- .../KeywordsUsedAsMemberInspection.cs | 6 ++-- ...neContinuationBetweenKeywordsInspection.cs | 4 +-- .../NegativeLineNumberInspection.cs | 4 +-- .../NonBreakingSpaceIdentifierInspection.cs | 4 +-- .../OnErrorGoToMinusOneInspection.cs | 4 +-- .../UnassignedVariableUsageInspection.cs | 5 +-- .../Concrete/UndeclaredVariableInspection.cs | 4 +-- ...coreInPublicClassModuleMemberInspection.cs | 4 +-- .../UnhandledOnErrorResumeNextInspection.cs | 4 +-- .../UnreachableCaseInspection.cs | 12 +++---- .../UntypedFunctionUsageInspection.cs | 5 +-- .../Concrete/UseMeaningfulNameInspection.cs | 8 ++--- .../Concrete/UseOfBangNotationInspection.cs | 5 ++- .../UseOfRecursiveBangNotationInspection.cs | 5 ++- .../UseOfUnboundBangNotationInspection.cs | 5 ++- .../Concrete/ValueRequiredInspection.cs | 5 ++- .../Concrete/VariableNotAssignedInspection.cs | 5 +-- .../Concrete/VariableNotUsedInspection.cs | 4 +-- .../VariableTypeNotDeclaredInspection.cs | 4 +-- .../Concrete/WriteOnlyPropertyInspection.cs | 4 +-- .../Inspections/EmptyModuleInspectionTests.cs | 4 +-- .../UnreachableCaseInspectionTests.cs | 6 ++-- .../QuickFixes/IgnoreOnceQuickFixTests.cs | 2 +- 119 files changed, 315 insertions(+), 359 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/ArgumentReferenceInspectionFromDeclarationsBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/ArgumentReferenceInspectionFromDeclarationsBase.cs index 08bd0da63b..269e324470 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/ArgumentReferenceInspectionFromDeclarationsBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/ArgumentReferenceInspectionFromDeclarationsBase.cs @@ -34,8 +34,9 @@ protected override bool IsResultReference(IdentifierReference reference, Declara public abstract class ArgumentReferenceInspectionFromDeclarationsBase : IdentifierReferenceInspectionFromDeclarationsBase { - protected ArgumentReferenceInspectionFromDeclarationsBase(RubberduckParserState state) - : base(state) { } + protected ArgumentReferenceInspectionFromDeclarationsBase(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} protected abstract (bool isResult, T properties) IsUnsuitableArgumentWithAdditionalProperties(ArgumentReference reference, DeclarationFinder finder); diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs index 6821e3ae7f..99876d0438 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs @@ -11,12 +11,12 @@ namespace Rubberduck.Inspections.Abstract { public abstract class DeclarationInspectionBase : DeclarationInspectionBaseBase { - protected DeclarationInspectionBase(RubberduckParserState state, params DeclarationType[] relevantDeclarationTypes) - : base(state, relevantDeclarationTypes) + protected DeclarationInspectionBase(IDeclarationFinderProvider declarationFinderProvider, params DeclarationType[] relevantDeclarationTypes) + : base(declarationFinderProvider, relevantDeclarationTypes) {} - protected DeclarationInspectionBase(RubberduckParserState state, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) - : base(state, relevantDeclarationTypes, excludeDeclarationTypes) + protected DeclarationInspectionBase(IDeclarationFinderProvider declarationFinderProvider, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) + : base(declarationFinderProvider, relevantDeclarationTypes, excludeDeclarationTypes) {} protected abstract bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder); @@ -46,12 +46,12 @@ protected virtual IInspectionResult InspectionResult(Declaration declaration) public abstract class DeclarationInspectionBase : DeclarationInspectionBaseBase { - protected DeclarationInspectionBase(RubberduckParserState state, params DeclarationType[] relevantDeclarationTypes) - : base(state, relevantDeclarationTypes) + protected DeclarationInspectionBase(IDeclarationFinderProvider declarationFinderProvider, params DeclarationType[] relevantDeclarationTypes) + : base(declarationFinderProvider, relevantDeclarationTypes) {} - protected DeclarationInspectionBase(RubberduckParserState state, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) - : base(state, relevantDeclarationTypes, excludeDeclarationTypes) + protected DeclarationInspectionBase(IDeclarationFinderProvider declarationFinderProvider , DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) + : base(declarationFinderProvider, relevantDeclarationTypes, excludeDeclarationTypes) {} protected abstract (bool isResult, T properties) IsResultDeclarationWithAdditionalProperties(Declaration declaration, DeclarationFinder finder); diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs index 74339e77a8..6df76ebfa6 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs @@ -13,15 +13,15 @@ public abstract class DeclarationInspectionBaseBase : InspectionBase protected readonly DeclarationType[] RelevantDeclarationTypes; protected readonly DeclarationType[] ExcludeDeclarationTypes; - protected DeclarationInspectionBaseBase(RubberduckParserState state, params DeclarationType[] relevantDeclarationTypes) - : base(state) + protected DeclarationInspectionBaseBase(IDeclarationFinderProvider declarationFinderProvider, params DeclarationType[] relevantDeclarationTypes) + : base(declarationFinderProvider) { RelevantDeclarationTypes = relevantDeclarationTypes; ExcludeDeclarationTypes = new DeclarationType[0]; } - protected DeclarationInspectionBaseBase(RubberduckParserState state, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) - : base(state) + protected DeclarationInspectionBaseBase(IDeclarationFinderProvider declarationFinderProvider, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) + : base(declarationFinderProvider) { RelevantDeclarationTypes = relevantDeclarationTypes; ExcludeDeclarationTypes = excludeDeclarationTypes; diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionMultiResultBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionMultiResultBase.cs index 491e2f0d42..c5863dcb83 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionMultiResultBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionMultiResultBase.cs @@ -11,12 +11,12 @@ namespace Rubberduck.Inspections.Abstract { public abstract class DeclarationInspectionMultiResultBase : DeclarationInspectionBaseBase { - protected DeclarationInspectionMultiResultBase(RubberduckParserState state, params DeclarationType[] relevantDeclarationTypes) - : base(state, relevantDeclarationTypes) + protected DeclarationInspectionMultiResultBase(IDeclarationFinderProvider declarationFinderProvider, params DeclarationType[] relevantDeclarationTypes) + : base(declarationFinderProvider, relevantDeclarationTypes) {} - protected DeclarationInspectionMultiResultBase(RubberduckParserState state, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) - : base(state, relevantDeclarationTypes, excludeDeclarationTypes) + protected DeclarationInspectionMultiResultBase(IDeclarationFinderProvider declarationFinderProvider, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) + : base(declarationFinderProvider, relevantDeclarationTypes, excludeDeclarationTypes) {} protected abstract IEnumerable ResultProperties(Declaration declaration, DeclarationFinder finder); diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBase.cs index 0c39aebce5..698f37bf47 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBase.cs @@ -11,12 +11,12 @@ namespace Rubberduck.Inspections.Abstract { public abstract class DeclarationInspectionUsingGlobalInformationBase : DeclarationInspectionUsingGlobalInformationBaseBase { - protected DeclarationInspectionUsingGlobalInformationBase(RubberduckParserState state, params DeclarationType[] relevantDeclarationTypes) - : base(state, relevantDeclarationTypes) + protected DeclarationInspectionUsingGlobalInformationBase(IDeclarationFinderProvider declarationFinderProvider, params DeclarationType[] relevantDeclarationTypes) + : base(declarationFinderProvider, relevantDeclarationTypes) {} - protected DeclarationInspectionUsingGlobalInformationBase(RubberduckParserState state, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) - : base(state, relevantDeclarationTypes, excludeDeclarationTypes) + protected DeclarationInspectionUsingGlobalInformationBase(IDeclarationFinderProvider declarationFinderProvider, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) + : base(declarationFinderProvider, relevantDeclarationTypes, excludeDeclarationTypes) {} protected abstract bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder, TGlobalInfo globalInfo); @@ -46,12 +46,12 @@ protected virtual IInspectionResult InspectionResult(Declaration declaration) public abstract class DeclarationInspectionUsingGlobalInformationBase : DeclarationInspectionUsingGlobalInformationBaseBase { - protected DeclarationInspectionUsingGlobalInformationBase(RubberduckParserState state, params DeclarationType[] relevantDeclarationTypes) - : base(state, relevantDeclarationTypes) + protected DeclarationInspectionUsingGlobalInformationBase(IDeclarationFinderProvider declarationFinderProvider, params DeclarationType[] relevantDeclarationTypes) + : base(declarationFinderProvider, relevantDeclarationTypes) {} - protected DeclarationInspectionUsingGlobalInformationBase(RubberduckParserState state, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) - : base(state, relevantDeclarationTypes, excludeDeclarationTypes) + protected DeclarationInspectionUsingGlobalInformationBase(IDeclarationFinderProvider declarationFinderProvider, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) + : base(declarationFinderProvider, relevantDeclarationTypes, excludeDeclarationTypes) {} protected abstract (bool isResult, TProperties properties) IsResultDeclarationWithAdditionalProperties(Declaration declaration, DeclarationFinder finder, TGlobalInfo globalInformation); diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs index f4486a341b..cccc94d6a4 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs @@ -13,15 +13,15 @@ public abstract class DeclarationInspectionUsingGlobalInformationBaseBase : I protected readonly DeclarationType[] RelevantDeclarationTypes; protected readonly DeclarationType[] ExcludeDeclarationTypes; - protected DeclarationInspectionUsingGlobalInformationBaseBase(RubberduckParserState state, params DeclarationType[] relevantDeclarationTypes) - : base(state) + protected DeclarationInspectionUsingGlobalInformationBaseBase(IDeclarationFinderProvider declarationFinderProvider, params DeclarationType[] relevantDeclarationTypes) + : base(declarationFinderProvider) { RelevantDeclarationTypes = relevantDeclarationTypes; ExcludeDeclarationTypes = new DeclarationType[0]; } - protected DeclarationInspectionUsingGlobalInformationBaseBase(RubberduckParserState state, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) - : base(state) + protected DeclarationInspectionUsingGlobalInformationBaseBase(IDeclarationFinderProvider declarationFinderProvider, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) + : base(declarationFinderProvider) { RelevantDeclarationTypes = relevantDeclarationTypes; ExcludeDeclarationTypes = excludeDeclarationTypes; diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs index e21ca82a16..54818d9f6e 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs @@ -11,8 +11,8 @@ namespace Rubberduck.Inspections.Abstract { public abstract class IdentifierReferenceInspectionBase : InspectionBase { - protected IdentifierReferenceInspectionBase(RubberduckParserState state) - : base(state) + protected IdentifierReferenceInspectionBase(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) {} protected abstract bool IsResultReference(IdentifierReference reference, DeclarationFinder finder); @@ -64,9 +64,9 @@ protected virtual IInspectionResult InspectionResult(IdentifierReference referen public abstract class IdentifierReferenceInspectionBase : InspectionBase { - protected IdentifierReferenceInspectionBase(RubberduckParserState state) - : base(state) - { } + protected IdentifierReferenceInspectionBase(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} protected abstract (bool isResult, T properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder); protected abstract string ResultDescription(IdentifierReference reference, T properties); diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs index 6db547f2bb..b16b67e87d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs @@ -11,8 +11,8 @@ namespace Rubberduck.Inspections.Abstract { public abstract class IdentifierReferenceInspectionFromDeclarationsBase : InspectionBase { - protected IdentifierReferenceInspectionFromDeclarationsBase(RubberduckParserState state) - : base(state) + protected IdentifierReferenceInspectionFromDeclarationsBase(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) {} protected abstract IEnumerable ObjectionableDeclarations(DeclarationFinder finder); @@ -69,9 +69,9 @@ protected virtual IInspectionResult InspectionResult(IdentifierReference referen public abstract class IdentifierReferenceInspectionFromDeclarationsBase : InspectionBase { - protected IdentifierReferenceInspectionFromDeclarationsBase(RubberduckParserState state) - : base(state) - { } + protected IdentifierReferenceInspectionFromDeclarationsBase(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} protected abstract IEnumerable ObjectionableDeclarations(DeclarationFinder finder); protected abstract (bool isResult, T properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder); diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/ImplicitTypeInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/ImplicitTypeInspectionBase.cs index 003d995637..ab19772900 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/ImplicitTypeInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/ImplicitTypeInspectionBase.cs @@ -6,12 +6,12 @@ namespace Rubberduck.Inspections.Abstract { public abstract class ImplicitTypeInspectionBase : DeclarationInspectionBase { - protected ImplicitTypeInspectionBase(RubberduckParserState state, params DeclarationType[] relevantDeclarationTypes) - : base(state, relevantDeclarationTypes) + protected ImplicitTypeInspectionBase(IDeclarationFinderProvider declarationFinderProvider, params DeclarationType[] relevantDeclarationTypes) + : base(declarationFinderProvider, relevantDeclarationTypes) {} - protected ImplicitTypeInspectionBase(RubberduckParserState state, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) - : base(state, relevantDeclarationTypes, excludeDeclarationTypes) + protected ImplicitTypeInspectionBase(IDeclarationFinderProvider declarationFinderProvider, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) + : base(declarationFinderProvider, relevantDeclarationTypes, excludeDeclarationTypes) {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs index 5f5c86b5b5..d1358ca671 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs @@ -10,8 +10,9 @@ namespace Rubberduck.Inspections.Inspections.Abstract { public abstract class IsMissingInspectionBase : ArgumentReferenceInspectionFromDeclarationsBase { - protected IsMissingInspectionBase(RubberduckParserState state) - : base(state) { } + protected IsMissingInspectionBase(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} private static readonly List IsMissingQualifiedNames = new List { diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/MemberAccessMayReturnNothingInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/MemberAccessMayReturnNothingInspectionBase.cs index 0a197ad7ed..866ff85360 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/MemberAccessMayReturnNothingInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/MemberAccessMayReturnNothingInspectionBase.cs @@ -15,7 +15,9 @@ namespace Rubberduck.Inspections.Abstract { public abstract class MemberAccessMayReturnNothingInspectionBase : IdentifierReferenceInspectionFromDeclarationsBase { - protected MemberAccessMayReturnNothingInspectionBase(RubberduckParserState state) : base(state) { } + protected MemberAccessMayReturnNothingInspectionBase(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} public abstract IEnumerable MembersUnderTest(DeclarationFinder finder); public abstract string ResultTemplate { get; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs index 8ccff6b2d4..304570c781 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs @@ -14,8 +14,9 @@ namespace Rubberduck.Inspections.Abstract { public abstract class ParseTreeInspectionBase : InspectionBase, IParseTreeInspection { - protected ParseTreeInspectionBase(RubberduckParserState state) - : base(state) { } + protected ParseTreeInspectionBase(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} public abstract IInspectionListener Listener { get; } protected abstract string ResultDescription(QualifiedContext context); @@ -58,8 +59,8 @@ protected virtual IInspectionResult InspectionResult(QualifiedContext : InspectionBase, IParseTreeInspection { - protected ParseTreeInspectionBase(RubberduckParserState state) - : base(state) + protected ParseTreeInspectionBase(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) {} public abstract IInspectionListener Listener { get; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs index 70dcfe4502..81959d71e3 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs @@ -1,12 +1,8 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Inspections.Abstract; -using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.TypeResolvers; using Rubberduck.Parsing.VBA; @@ -82,8 +78,8 @@ public class ArgumentWithIncompatibleObjectTypeInspection : ArgumentReferenceIns { private readonly ISetTypeResolver _setTypeResolver; - public ArgumentWithIncompatibleObjectTypeInspection(RubberduckParserState state, ISetTypeResolver setTypeResolver) - : base(state) + public ArgumentWithIncompatibleObjectTypeInspection(IDeclarationFinderProvider declarationFinderProvider, ISetTypeResolver setTypeResolver) + : base(declarationFinderProvider) { _setTypeResolver = setTypeResolver; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignedByValParameterInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignedByValParameterInspection.cs index 215acb756f..5b382e1df6 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignedByValParameterInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignedByValParameterInspection.cs @@ -35,8 +35,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class AssignedByValParameterInspection : DeclarationInspectionBase { - public AssignedByValParameterInspection(RubberduckParserState state) - : base(state, DeclarationType.Parameter) + public AssignedByValParameterInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.Parameter) {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs index 70c9cdbe2d..53f0882fd4 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs @@ -41,8 +41,9 @@ public sealed class AssignmentNotUsedInspection : IdentifierReferenceInspectionB { private readonly Walker _walker; - public AssignmentNotUsedInspection(RubberduckParserState state, Walker walker) - : base(state) { + public AssignmentNotUsedInspection(IDeclarationFinderProvider declarationFinderProvider, Walker walker) + : base(declarationFinderProvider) + { _walker = walker; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/AttributeValueOutOfSyncInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/AttributeValueOutOfSyncInspection.cs index 399aee62df..c917924c00 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/AttributeValueOutOfSyncInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/AttributeValueOutOfSyncInspection.cs @@ -39,10 +39,9 @@ namespace Rubberduck.Inspections.Concrete [CannotAnnotate] public sealed class AttributeValueOutOfSyncInspection : DeclarationInspectionMultiResultBase<(IParseTreeAnnotation Annotation, string AttributeName, IReadOnlyList AttributeValues)> { - public AttributeValueOutOfSyncInspection(RubberduckParserState state) - :base(state) - { - } + public AttributeValueOutOfSyncInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} protected override IEnumerable<(IParseTreeAnnotation Annotation, string AttributeName, IReadOnlyList AttributeValues)> ResultProperties(Declaration declaration, DeclarationFinder finder) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs index 993aa29f9a..15843f7214 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs @@ -39,8 +39,9 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class BooleanAssignedInIfElseInspection : ParseTreeInspectionBase { - public BooleanAssignedInIfElseInspection(RubberduckParserState state) - : base(state) { } + public BooleanAssignedInIfElseInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} public override IInspectionListener Listener { get; } = new BooleanAssignedInIfElseListener(); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ConstantNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ConstantNotUsedInspection.cs index 6ad6aa5d0e..109b22b4d8 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ConstantNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ConstantNotUsedInspection.cs @@ -34,8 +34,9 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ConstantNotUsedInspection : DeclarationInspectionBase { - public ConstantNotUsedInspection(RubberduckParserState state) - : base(state, DeclarationType.Constant) { } + public ConstantNotUsedInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.Constant) + {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs index 833f02c88b..9fe14fcaf0 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs @@ -29,8 +29,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class DefTypeStatementInspection : ParseTreeInspectionBase { - public DefTypeStatementInspection(RubberduckParserState state) - : base(state) + public DefTypeStatementInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Listener = new DefTypeStatementInspectionListener(); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs index 64bfe5c634..ff84978636 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; @@ -56,8 +55,8 @@ namespace Rubberduck.CodeAnalysis.Inspections.Concrete /// public class DefaultMemberRequiredInspection : IdentifierReferenceInspectionBase { - public DefaultMemberRequiredInspection(RubberduckParserState state) - : base(state) + public DefaultMemberRequiredInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { //This will most likely cause a runtime error. The exceptions are rare and should be refactored or made explicit with an @Ignore annotation. Severity = CodeInspectionSeverity.Error; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultProjectNameInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultProjectNameInspection.cs index edd4315579..6985072407 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultProjectNameInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultProjectNameInspection.cs @@ -1,7 +1,5 @@ -using System.Collections.Generic; -using Rubberduck.Inspections.Abstract; +using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.Inspections; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; @@ -17,8 +15,8 @@ namespace Rubberduck.Inspections.Concrete [CannotAnnotate] public sealed class DefaultProjectNameInspection : DeclarationInspectionBase { - public DefaultProjectNameInspection(RubberduckParserState state) - : base(state, DeclarationType.Project) + public DefaultProjectNameInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.Project) {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DuplicatedAnnotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DuplicatedAnnotationInspection.cs index 1b79395881..5788ed56ac 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DuplicatedAnnotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DuplicatedAnnotationInspection.cs @@ -36,9 +36,9 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class DuplicatedAnnotationInspection : DeclarationInspectionMultiResultBase { - public DuplicatedAnnotationInspection(RubberduckParserState state) - : base(state) - { } + public DuplicatedAnnotationInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} protected override IEnumerable ResultProperties(Declaration declaration, DeclarationFinder finder) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyCaseBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyCaseBlockInspection.cs index a26b244dbe..bbf47d810b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyCaseBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyCaseBlockInspection.cs @@ -43,8 +43,8 @@ namespace Rubberduck.Inspections.Concrete [Experimental(nameof(ExperimentalNames.EmptyBlockInspections))] internal class EmptyCaseBlockInspection : ParseTreeInspectionBase { - public EmptyCaseBlockInspection(RubberduckParserState state) - : base(state) + public EmptyCaseBlockInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) {} public override IInspectionListener Listener { get; } = diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyDoWhileBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyDoWhileBlockInspection.cs index 9c9fb755a2..06394f1ea2 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyDoWhileBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyDoWhileBlockInspection.cs @@ -38,8 +38,8 @@ namespace Rubberduck.Inspections.Concrete [Experimental(nameof(ExperimentalNames.EmptyBlockInspections))] internal class EmptyDoWhileBlockInspection : ParseTreeInspectionBase { - public EmptyDoWhileBlockInspection(RubberduckParserState state) - : base(state) + public EmptyDoWhileBlockInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) {} protected override string ResultDescription(QualifiedContext context) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyElseBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyElseBlockInspection.cs index a01d71e03d..9eae15eba9 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyElseBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyElseBlockInspection.cs @@ -40,8 +40,8 @@ namespace Rubberduck.Inspections.Concrete [Experimental(nameof(ExperimentalNames.EmptyBlockInspections))] internal class EmptyElseBlockInspection : ParseTreeInspectionBase { - public EmptyElseBlockInspection(RubberduckParserState state) - : base(state) + public EmptyElseBlockInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) {} protected override string ResultDescription(QualifiedContext context) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForEachBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForEachBlockInspection.cs index ee39380e81..e087cfe34f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForEachBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForEachBlockInspection.cs @@ -40,8 +40,8 @@ namespace Rubberduck.Inspections.Concrete [Experimental(nameof(ExperimentalNames.EmptyBlockInspections))] internal class EmptyForEachBlockInspection : ParseTreeInspectionBase { - public EmptyForEachBlockInspection(RubberduckParserState state) - : base(state) + public EmptyForEachBlockInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) {} protected override string ResultDescription(QualifiedContext context) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForLoopBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForLoopBlockInspection.cs index cb39392bff..3de874561c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForLoopBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForLoopBlockInspection.cs @@ -40,8 +40,9 @@ namespace Rubberduck.Inspections.Concrete [Experimental(nameof(ExperimentalNames.EmptyBlockInspections))] internal class EmptyForLoopBlockInspection : ParseTreeInspectionBase { - public EmptyForLoopBlockInspection(RubberduckParserState state) - : base(state) { } + public EmptyForLoopBlockInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} protected override string ResultDescription(QualifiedContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyIfBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyIfBlockInspection.cs index 6d552909cd..4c6f61a13a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyIfBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyIfBlockInspection.cs @@ -36,8 +36,8 @@ namespace Rubberduck.Inspections.Concrete /// internal class EmptyIfBlockInspection : ParseTreeInspectionBase { - public EmptyIfBlockInspection(RubberduckParserState state) - : base(state) + public EmptyIfBlockInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) {} protected override string ResultDescription(QualifiedContext context) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyMethodInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyMethodInspection.cs index 5d63f14dd3..2ae5634261 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyMethodInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyMethodInspection.cs @@ -30,8 +30,8 @@ namespace Rubberduck.Inspections.Concrete /// internal class EmptyMethodInspection : DeclarationInspectionBase { - public EmptyMethodInspection(RubberduckParserState state) - : base(state, DeclarationType.Member) + public EmptyMethodInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.Member) {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyModuleInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyModuleInspection.cs index 9016086a7b..ea55537720 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyModuleInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyModuleInspection.cs @@ -20,11 +20,11 @@ public sealed class EmptyModuleInspection : DeclarationInspectionBase private readonly EmptyModuleVisitor _emptyModuleVisitor; private readonly IParseTreeProvider _parseTreeProvider; - public EmptyModuleInspection(RubberduckParserState state) - : base(state, new []{DeclarationType.Module}, new []{DeclarationType.Document}) + public EmptyModuleInspection(IDeclarationFinderProvider declarationFinderProvider, IParseTreeProvider parseTreeProvider) + : base(declarationFinderProvider, new []{DeclarationType.Module}, new []{DeclarationType.Document}) { _emptyModuleVisitor = new EmptyModuleVisitor(); - _parseTreeProvider = state; + _parseTreeProvider = parseTreeProvider; } protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs index cab31f2acf..dd0600413f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs @@ -36,8 +36,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class EmptyStringLiteralInspection : ParseTreeInspectionBase { - public EmptyStringLiteralInspection(RubberduckParserState state) - : base(state) + public EmptyStringLiteralInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) {} public override IInspectionListener Listener { get; } = diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyWhileWendBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyWhileWendBlockInspection.cs index aebf257729..cefa70155b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyWhileWendBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyWhileWendBlockInspection.cs @@ -38,8 +38,8 @@ namespace Rubberduck.Inspections.Concrete [Experimental(nameof(ExperimentalNames.EmptyBlockInspections))] internal class EmptyWhileWendBlockInspection : ParseTreeInspectionBase { - public EmptyWhileWendBlockInspection(RubberduckParserState state) - : base(state) + public EmptyWhileWendBlockInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) {} protected override string ResultDescription(QualifiedContext context) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EncapsulatePublicFieldInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EncapsulatePublicFieldInspection.cs index 8f3360e12d..ced2df11d2 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EncapsulatePublicFieldInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EncapsulatePublicFieldInspection.cs @@ -29,8 +29,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class EncapsulatePublicFieldInspection : DeclarationInspectionBase { - public EncapsulatePublicFieldInspection(RubberduckParserState state) - : base(state, DeclarationType.Variable) + public EncapsulatePublicFieldInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.Variable) {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs index 0f0fa9c6f4..27eec2d91c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs @@ -1,14 +1,10 @@ using System.Collections.Generic; using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Inspections; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.VBEditor; -using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing.VBA.DeclarationCaching; @@ -58,8 +54,9 @@ namespace Rubberduck.Inspections.Concrete [RequiredLibrary("Excel")] public class ApplicationWorksheetFunctionInspection : IdentifierReferenceInspectionFromDeclarationsBase { - public ApplicationWorksheetFunctionInspection(RubberduckParserState state) - : base(state) { } + public ApplicationWorksheetFunctionInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} protected override IEnumerable ObjectionableDeclarations(DeclarationFinder finder) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelMemberMayReturnNothingInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelMemberMayReturnNothingInspection.cs index 243152c163..6b6febced8 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelMemberMayReturnNothingInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelMemberMayReturnNothingInspection.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.Inspections; @@ -42,7 +41,9 @@ namespace Rubberduck.Inspections.Concrete [RequiredLibrary("Excel")] public class ExcelMemberMayReturnNothingInspection : MemberAccessMayReturnNothingInspectionBase { - public ExcelMemberMayReturnNothingInspection(RubberduckParserState state) : base(state) { } + public ExcelMemberMayReturnNothingInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} private static readonly List<(string className, string memberName)> ExcelMembers = new List<(string className, string memberName)> { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs index 6151a646ef..daa54ceb8c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs @@ -37,9 +37,9 @@ namespace Rubberduck.Inspections.Inspections.Concrete [RequiredLibrary("Excel")] public class ExcelUdfNameIsValidCellReferenceInspection : DeclarationInspectionBase { - public ExcelUdfNameIsValidCellReferenceInspection(RubberduckParserState state) - : base(state, new []{DeclarationType.Function}, new []{DeclarationType.PropertyGet, DeclarationType.LibraryFunction}) - { } + public ExcelUdfNameIsValidCellReferenceInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, new []{DeclarationType.Function}, new []{DeclarationType.PropertyGet, DeclarationType.LibraryFunction}) + {} protected override IEnumerable DoGetInspectionResults() { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs index 7018921528..62fdcb30ff 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs @@ -40,8 +40,8 @@ namespace Rubberduck.Inspections.Concrete [RequiredLibrary("Excel")] public sealed class ImplicitActiveSheetReferenceInspection : IdentifierReferenceInspectionFromDeclarationsBase { - public ImplicitActiveSheetReferenceInspection(RubberduckParserState state) - : base(state) + public ImplicitActiveSheetReferenceInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) {} protected override IEnumerable ObjectionableDeclarations(DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveWorkbookReferenceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveWorkbookReferenceInspection.cs index e8f8b120ed..be4b6db073 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveWorkbookReferenceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveWorkbookReferenceInspection.cs @@ -38,8 +38,9 @@ namespace Rubberduck.Inspections.Concrete [RequiredLibrary("Excel")] public sealed class ImplicitActiveWorkbookReferenceInspection : IdentifierReferenceInspectionFromDeclarationsBase { - public ImplicitActiveWorkbookReferenceInspection(RubberduckParserState state) - : base(state) { } + public ImplicitActiveWorkbookReferenceInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} private static readonly string[] InterestingMembers = { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs index 21ea528c33..c8b8340064 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs @@ -49,8 +49,8 @@ public class SheetAccessedUsingStringInspection : IdentifierReferenceInspectionF { private readonly IProjectsProvider _projectsProvider; - public SheetAccessedUsingStringInspection(RubberduckParserState state, IProjectsProvider projectsProvider) - : base(state) + public SheetAccessedUsingStringInspection(IDeclarationFinderProvider declarationFinderProvider, IProjectsProvider projectsProvider) + : base(declarationFinderProvider) { _projectsProvider = projectsProvider; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueAlwaysDiscardedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueAlwaysDiscardedInspection.cs index 323b7a278c..f0464e1b96 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueAlwaysDiscardedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueAlwaysDiscardedInspection.cs @@ -49,8 +49,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class FunctionReturnValueAlwaysDiscardedInspection : DeclarationInspectionBase { - public FunctionReturnValueAlwaysDiscardedInspection(RubberduckParserState state) - :base(state, DeclarationType.Function) + public FunctionReturnValueAlwaysDiscardedInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.Function) {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueDiscardedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueDiscardedInspection.cs index e626a3425e..7f0ea6e2f0 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueDiscardedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueDiscardedInspection.cs @@ -41,8 +41,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class FunctionReturnValueDiscardedInspection : IdentifierReferenceInspectionBase { - public FunctionReturnValueDiscardedInspection(RubberduckParserState state) - : base(state) + public FunctionReturnValueDiscardedInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Severity = CodeInspectionSeverity.Suggestion; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/HostSpecificExpressionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/HostSpecificExpressionInspection.cs index 75ae75777d..7b4c30247c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/HostSpecificExpressionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/HostSpecificExpressionInspection.cs @@ -1,7 +1,4 @@ -using System.Collections.Generic; -using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; @@ -32,8 +29,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class HostSpecificExpressionInspection : DeclarationInspectionBase { - public HostSpecificExpressionInspection(RubberduckParserState state) - : base(state, DeclarationType.BracketedExpression) + public HostSpecificExpressionInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.BracketedExpression) {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/HungarianNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/HungarianNotationInspection.cs index c111529440..521bd9f0d2 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/HungarianNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/HungarianNotationInspection.cs @@ -69,8 +69,8 @@ public sealed class HungarianNotationInspection : DeclarationInspectionUsingGlob private readonly IConfigurationService _settings; - public HungarianNotationInspection(RubberduckParserState state, IConfigurationService settings) - : base(state, TargetDeclarationTypes, IgnoredProcedureTypes) + public HungarianNotationInspection(IDeclarationFinderProvider declarationFinderProvider, IConfigurationService settings) + : base(declarationFinderProvider, TargetDeclarationTypes, IgnoredProcedureTypes) { _settings = settings; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplementedInterfaceMemberInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplementedInterfaceMemberInspection.cs index 598d83930f..82a9590012 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplementedInterfaceMemberInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplementedInterfaceMemberInspection.cs @@ -5,6 +5,7 @@ using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Common; using Rubberduck.Parsing.Annotations; +using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete @@ -37,8 +38,8 @@ namespace Rubberduck.Inspections.Concrete /// internal class ImplementedInterfaceMemberInspection : DeclarationInspectionBase { - public ImplementedInterfaceMemberInspection(Parsing.VBA.RubberduckParserState state) - : base(state, DeclarationType.ClassModule) + public ImplementedInterfaceMemberInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.ClassModule) {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitByRefModifierInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitByRefModifierInspection.cs index 21c05bce64..25e4fd46a8 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitByRefModifierInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitByRefModifierInspection.cs @@ -29,8 +29,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ImplicitByRefModifierInspection : DeclarationInspectionBase { - public ImplicitByRefModifierInspection(RubberduckParserState state) - : base(state, DeclarationType.Parameter) + public ImplicitByRefModifierInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.Parameter) {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs index 4eb9538eb4..8a5029ebb6 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs @@ -49,8 +49,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ImplicitDefaultMemberAccessInspection : IdentifierReferenceInspectionBase { - public ImplicitDefaultMemberAccessInspection(RubberduckParserState state) - : base(state) + public ImplicitDefaultMemberAccessInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Severity = CodeInspectionSeverity.Suggestion; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitPublicMemberInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitPublicMemberInspection.cs index 7b8e2c1be8..8d513ca519 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitPublicMemberInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitPublicMemberInspection.cs @@ -29,8 +29,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ImplicitPublicMemberInspection : DeclarationInspectionBase { - public ImplicitPublicMemberInspection(RubberduckParserState state) - : base(state, ProcedureTypes) { } + public ImplicitPublicMemberInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, ProcedureTypes) { } private static readonly DeclarationType[] ProcedureTypes = { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs index f2dae91a23..4cd940d458 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs @@ -69,8 +69,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ImplicitRecursiveDefaultMemberAccessInspection : IdentifierReferenceInspectionBase { - public ImplicitRecursiveDefaultMemberAccessInspection(RubberduckParserState state) - : base(state) + public ImplicitRecursiveDefaultMemberAccessInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Severity = CodeInspectionSeverity.Suggestion; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs index 230f79ae34..df8f98abe1 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs @@ -52,8 +52,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ImplicitUnboundDefaultMemberAccessInspection : IdentifierReferenceInspectionBase { - public ImplicitUnboundDefaultMemberAccessInspection(RubberduckParserState state) - : base(state) + public ImplicitUnboundDefaultMemberAccessInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Severity = CodeInspectionSeverity.Warning; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitVariantReturnTypeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitVariantReturnTypeInspection.cs index bd29777c43..d2892ebec7 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitVariantReturnTypeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitVariantReturnTypeInspection.cs @@ -27,8 +27,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ImplicitVariantReturnTypeInspection : ImplicitTypeInspectionBase { - public ImplicitVariantReturnTypeInspection(RubberduckParserState state) - : base(state, DeclarationType.Function) + public ImplicitVariantReturnTypeInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.Function) {} protected override string ResultDescription(Declaration declaration) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs index dafd800c8b..a54da4f18b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs @@ -28,8 +28,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ImplicitlyTypedConstInspection : ImplicitTypeInspectionBase { - public ImplicitlyTypedConstInspection(RubberduckParserState state) - : base(state, DeclarationType.Constant) + public ImplicitlyTypedConstInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.Constant) {} protected override string ResultDescription(Declaration declaration) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs index 66adec3eb6..32331e845f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs @@ -33,8 +33,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class IndexedDefaultMemberAccessInspection : IdentifierReferenceInspectionBase { - public IndexedDefaultMemberAccessInspection(RubberduckParserState state) - : base(state) + public IndexedDefaultMemberAccessInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Severity = CodeInspectionSeverity.Hint; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs index f37bb2305e..15e9d41f97 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs @@ -33,8 +33,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class IndexedRecursiveDefaultMemberAccessInspection : IdentifierReferenceInspectionBase { - public IndexedRecursiveDefaultMemberAccessInspection(RubberduckParserState state) - : base(state) + public IndexedRecursiveDefaultMemberAccessInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Severity = CodeInspectionSeverity.Suggestion; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs index 5fabddaf34..4acdd7553e 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs @@ -36,8 +36,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class IndexedUnboundDefaultMemberAccessInspection : IdentifierReferenceInspectionBase { - public IndexedUnboundDefaultMemberAccessInspection(RubberduckParserState state) - : base(state) + public IndexedUnboundDefaultMemberAccessInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Severity = CodeInspectionSeverity.Warning; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IntegerDataTypeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IntegerDataTypeInspection.cs index 290467caa2..2b09a43ea9 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IntegerDataTypeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IntegerDataTypeInspection.cs @@ -32,9 +32,9 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class IntegerDataTypeInspection : DeclarationInspectionBase { - public IntegerDataTypeInspection(RubberduckParserState state) - : base(state) - { } + public IntegerDataTypeInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs index a168786ce1..b53201a9dc 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs @@ -1,10 +1,5 @@ -using System.Collections.Generic; -using System.Linq; -using Rubberduck.Inspections.Inspections.Abstract; -using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Inspections.Results; +using Rubberduck.Inspections.Inspections.Abstract; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; @@ -37,8 +32,9 @@ namespace Rubberduck.Inspections.Concrete /// public class IsMissingOnInappropriateArgumentInspection : IsMissingInspectionBase { - public IsMissingOnInappropriateArgumentInspection(RubberduckParserState state) - : base(state) { } + public IsMissingOnInappropriateArgumentInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} protected override (bool isResult, ParameterDeclaration properties) IsUnsuitableArgumentWithAdditionalProperties(ArgumentReference reference, DeclarationFinder finder) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs index dd8ed58d57..0847e0762f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs @@ -32,8 +32,9 @@ namespace Rubberduck.Inspections.Concrete /// public class IsMissingWithNonArgumentParameterInspection : IsMissingInspectionBase { - public IsMissingWithNonArgumentParameterInspection(RubberduckParserState state) - : base(state) { } + public IsMissingWithNonArgumentParameterInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} protected override (bool isResult, ParameterDeclaration properties) IsUnsuitableArgumentWithAdditionalProperties(ArgumentReference reference, DeclarationFinder finder) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/LineLabelNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/LineLabelNotUsedInspection.cs index 195169ec1e..c7553c2d71 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/LineLabelNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/LineLabelNotUsedInspection.cs @@ -3,8 +3,8 @@ using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using static Rubberduck.Parsing.Grammar.VBAParser; using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete @@ -40,15 +40,15 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class LineLabelNotUsedInspection : DeclarationInspectionBase { - public LineLabelNotUsedInspection(RubberduckParserState state) - : base(state, DeclarationType.LineLabel) + public LineLabelNotUsedInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.LineLabel) {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { return declaration != null && !declaration.IsWithEvents - && declaration.Context is IdentifierStatementLabelContext + && declaration.Context is VBAParser.IdentifierStatementLabelContext && declaration.References.All(reference => reference.IsAssignment); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MemberNotOnInterfaceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MemberNotOnInterfaceInspection.cs index 26b8eb0abf..5804105ae6 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MemberNotOnInterfaceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MemberNotOnInterfaceInspection.cs @@ -1,13 +1,10 @@ using System.Collections.Generic; using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.VBEditor; @@ -42,9 +39,9 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class MemberNotOnInterfaceInspection : DeclarationInspectionBase { - public MemberNotOnInterfaceInspection(RubberduckParserState state) - : base(state) - { } + public MemberNotOnInterfaceInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} protected override IEnumerable RelevantDeclarationsInModule(QualifiedModuleName module, DeclarationFinder finder) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAttributeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAttributeInspection.cs index 76aa4bc62a..054b31cb19 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAttributeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAttributeInspection.cs @@ -1,12 +1,8 @@ using System.Collections.Generic; using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Inspections.Results; -using Rubberduck.Parsing; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Inspections; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; @@ -42,8 +38,8 @@ namespace Rubberduck.Inspections.Concrete [CannotAnnotate] public sealed class MissingAttributeInspection : DeclarationInspectionMultiResultBase { - public MissingAttributeInspection(RubberduckParserState state) - : base(state) + public MissingAttributeInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) {} protected override IEnumerable ResultProperties(Declaration declaration, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingMemberAnnotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingMemberAnnotationInspection.cs index 44a2036365..677020302c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingMemberAnnotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingMemberAnnotationInspection.cs @@ -36,8 +36,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class MissingMemberAnnotationInspection : DeclarationInspectionMultiResultBase<(string AttributeName, IReadOnlyList AttriguteValues)> { - public MissingMemberAnnotationInspection(RubberduckParserState state) - :base(state, new DeclarationType[0], new []{DeclarationType.Module }) + public MissingMemberAnnotationInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, new DeclarationType[0], new []{DeclarationType.Module }) {} protected override IEnumerable<(string AttributeName, IReadOnlyList AttriguteValues)> ResultProperties(Declaration declaration, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingModuleAnnotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingModuleAnnotationInspection.cs index 953347879d..263f984c90 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingModuleAnnotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingModuleAnnotationInspection.cs @@ -2,7 +2,6 @@ using System.Linq; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.Annotations; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; @@ -34,8 +33,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class MissingModuleAnnotationInspection : DeclarationInspectionMultiResultBase<(string AttributeName, IReadOnlyList AttributeValues)> { - public MissingModuleAnnotationInspection(RubberduckParserState state) - :base(state, new []{DeclarationType.Module}, new []{DeclarationType.Document}) + public MissingModuleAnnotationInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, new []{DeclarationType.Module}, new []{DeclarationType.Document}) {} protected override IEnumerable<(string AttributeName, IReadOnlyList AttributeValues)> ResultProperties(Declaration declaration, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs index 9294ce1207..ace257f777 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs @@ -1,16 +1,11 @@ -using System.Collections.Generic; -using System.Linq; using Antlr4.Runtime; using Antlr4.Runtime.Misc; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Rubberduck.VBEditor; -using Rubberduck.Inspections.Inspections.Extensions; namespace Rubberduck.Inspections.Concrete { @@ -37,8 +32,9 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ModuleScopeDimKeywordInspection : ParseTreeInspectionBase { - public ModuleScopeDimKeywordInspection(RubberduckParserState state) - : base(state) { } + public ModuleScopeDimKeywordInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} public override IInspectionListener Listener { get; } = new ModuleScopedDimListener(); protected override string ResultDescription(QualifiedContext context) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleWithoutFolderInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleWithoutFolderInspection.cs index a500171a3d..d7adcf6aed 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleWithoutFolderInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleWithoutFolderInspection.cs @@ -30,8 +30,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ModuleWithoutFolderInspection : DeclarationInspectionBase { - public ModuleWithoutFolderInspection(RubberduckParserState state) - : base(state, DeclarationType.Module) + public ModuleWithoutFolderInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.Module) {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MoveFieldCloserToUsageInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MoveFieldCloserToUsageInspection.cs index 620c7caa95..d238424760 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MoveFieldCloserToUsageInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MoveFieldCloserToUsageInspection.cs @@ -38,8 +38,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class MoveFieldCloserToUsageInspection : DeclarationInspectionBase { - public MoveFieldCloserToUsageInspection(RubberduckParserState state) - : base(state, DeclarationType.Variable) + public MoveFieldCloserToUsageInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.Variable) {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs index 5b758ed1a9..e617dc11b8 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs @@ -33,8 +33,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class MultilineParameterInspection : ParseTreeInspectionBase { - public MultilineParameterInspection(RubberduckParserState state) - : base(state) + public MultilineParameterInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Listener = new ParameterListener(); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs index 3e383a3e84..7e729d6f5a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs @@ -28,8 +28,9 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class MultipleDeclarationsInspection : ParseTreeInspectionBase { - public MultipleDeclarationsInspection(RubberduckParserState state) - : base(state) { } + public MultipleDeclarationsInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} protected override string ResultDescription(QualifiedContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/NonReturningFunctionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/NonReturningFunctionInspection.cs index 4c2ea5f3dc..61806cdfef 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/NonReturningFunctionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/NonReturningFunctionInspection.cs @@ -1,11 +1,7 @@ -using System.Collections.Generic; using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; -using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; @@ -39,9 +35,9 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class NonReturningFunctionInspection : DeclarationInspectionBase { - public NonReturningFunctionInspection(RubberduckParserState state) - : base(state, DeclarationType.Function) - { } + public NonReturningFunctionInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.Function) + {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs index d8d811ea60..54ca0f318b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs @@ -40,8 +40,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ObjectVariableNotSetInspection : IdentifierReferenceInspectionBase { - public ObjectVariableNotSetInspection(RubberduckParserState state) - : base(state) + public ObjectVariableNotSetInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) {} protected override IEnumerable ReferencesInModule(QualifiedModuleName module, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs index 66942b2dda..9789682069 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs @@ -55,8 +55,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ObjectWhereProcedureIsRequiredInspection : InspectionBase { - public ObjectWhereProcedureIsRequiredInspection(RubberduckParserState state) - : base(state) + public ObjectWhereProcedureIsRequiredInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Severity = CodeInspectionSeverity.Warning; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs index 413be7114d..d98a757523 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs @@ -42,8 +42,8 @@ public sealed class ObsoleteCallStatementInspection : ParseTreeInspectionBase { private readonly IProjectsProvider _projectsProvider; - public ObsoleteCallStatementInspection(RubberduckParserState state, IProjectsProvider projectsProvider) - : base(state) + public ObsoleteCallStatementInspection(IDeclarationFinderProvider declarationFinderProvider, IProjectsProvider projectsProvider) + : base(declarationFinderProvider) { Listener = new ObsoleteCallStatementListener(); _projectsProvider = projectsProvider; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs index 3e639ab5bb..864f5b41d5 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs @@ -27,8 +27,8 @@ namespace Rubberduck.Inspections.Inspections.Concrete /// public sealed class ObsoleteCallingConventionInspection : ParseTreeInspectionBase { - public ObsoleteCallingConventionInspection(RubberduckParserState state) - : base(state) + public ObsoleteCallingConventionInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Listener = new ObsoleteCallingConventionListener(); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs index 6eeddd3044..2d9c39833d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs @@ -30,8 +30,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ObsoleteCommentSyntaxInspection : ParseTreeInspectionBase { - public ObsoleteCommentSyntaxInspection(RubberduckParserState state) - : base(state) + public ObsoleteCommentSyntaxInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Listener = new ObsoleteCommentSyntaxListener(); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs index 460cbcb2f8..824e308a20 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs @@ -30,8 +30,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ObsoleteErrorSyntaxInspection : ParseTreeInspectionBase { - public ObsoleteErrorSyntaxInspection(RubberduckParserState state) - : base(state) + public ObsoleteErrorSyntaxInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Listener = new ObsoleteErrorSyntaxListener(); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteGlobalInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteGlobalInspection.cs index 179e93fc7f..65149ac67e 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteGlobalInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteGlobalInspection.cs @@ -27,8 +27,9 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ObsoleteGlobalInspection : DeclarationInspectionBase { - public ObsoleteGlobalInspection(RubberduckParserState state) - : base(state) { } + public ObsoleteGlobalInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs index 382609b6fa..3865e230ce 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs @@ -32,8 +32,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ObsoleteLetStatementInspection : ParseTreeInspectionBase { - public ObsoleteLetStatementInspection(RubberduckParserState state) - : base(state) + public ObsoleteLetStatementInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Listener = new ObsoleteLetStatementListener(); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs index 15881ffd29..4929affd1a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs @@ -1,9 +1,6 @@ -using System.Collections.Generic; -using System.Linq; +using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Annotations; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; @@ -51,9 +48,9 @@ namespace Rubberduck.Inspections.Inspections.Concrete /// public sealed class ObsoleteMemberUsageInspection : IdentifierReferenceInspectionBase { - public ObsoleteMemberUsageInspection(RubberduckParserState state) : base(state) - { - } + public ObsoleteMemberUsageInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs index d2c3526d7b..2758a142ad 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs @@ -35,36 +35,22 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ObsoleteTypeHintInspection : InspectionBase { - private readonly IDeclarationFinderProvider _declarationFinderProvider; - - public ObsoleteTypeHintInspection(RubberduckParserState state) - : base(state) - { - _declarationFinderProvider = state; - } + public ObsoleteTypeHintInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} protected override IEnumerable DoGetInspectionResults() { - var finder = _declarationFinderProvider.DeclarationFinder; - - var results = new List(); - foreach (var moduleDeclaration in finder.UserDeclarations(DeclarationType.Module)) - { - if (moduleDeclaration == null) - { - continue; - } - - var module = moduleDeclaration.QualifiedModuleName; - results.AddRange(DoGetInspectionResults(module, finder)); - } + var finder = DeclarationFinderProvider.DeclarationFinder; - return results; + return finder.UserDeclarations(DeclarationType.Module) + .Where(module => module != null) + .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder)); } private IEnumerable DoGetInspectionResults(QualifiedModuleName module) { - var finder = _declarationFinderProvider.DeclarationFinder; + var finder = DeclarationFinderProvider.DeclarationFinder; return DoGetInspectionResults(module, finder); } @@ -109,7 +95,7 @@ private IEnumerable ReferenceResults(QualifiedModuleName modu && reference.Declaration.IsUserDefined && reference.HasTypeHint()); return objectionableReferences - .Select(reference => InspectionResult(reference, _declarationFinderProvider)); + .Select(reference => InspectionResult(reference, DeclarationFinderProvider)); } private IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs index c509f41dcd..89a8c1064a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs @@ -35,8 +35,8 @@ namespace Rubberduck.CodeAnalysis.Inspections.Concrete /// public sealed class ObsoleteWhileWendStatementInspection : ParseTreeInspectionBase { - public ObsoleteWhileWendStatementInspection(RubberduckParserState state) - : base(state) + public ObsoleteWhileWendStatementInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Listener = new ObsoleteWhileWendStatementListener(); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs index bb0195fffa..684944fa72 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs @@ -39,8 +39,9 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class OnLocalErrorInspection : ParseTreeInspectionBase { - public OnLocalErrorInspection(RubberduckParserState state) - : base(state) { } + public OnLocalErrorInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} public override IInspectionListener Listener { get; } = new OnLocalErrorListener(); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs index 704ffd878d..48af628c74 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs @@ -39,8 +39,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class OptionBaseInspection : ParseTreeInspectionBase { - public OptionBaseInspection(RubberduckParserState state) - : base(state) + public OptionBaseInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Listener = new OptionBaseStatementListener(); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs index 53fb79f67f..2db49524e8 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs @@ -38,8 +38,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class OptionExplicitInspection : ParseTreeInspectionBase { - public OptionExplicitInspection(RubberduckParserState state) - : base(state) + public OptionExplicitInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Listener = new MissingOptionExplicitListener(); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterCanBeByValInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterCanBeByValInspection.cs index c0f3b2358b..f70dbe005f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterCanBeByValInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterCanBeByValInspection.cs @@ -37,8 +37,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ParameterCanBeByValInspection : DeclarationInspectionBase { - public ParameterCanBeByValInspection(RubberduckParserState state) - : base(state, DeclarationType.Parameter) + public ParameterCanBeByValInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.Parameter) {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterNotUsedInspection.cs index d7d50896ae..fa1f9df638 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterNotUsedInspection.cs @@ -38,8 +38,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ParameterNotUsedInspection : DeclarationInspectionBase { - public ParameterNotUsedInspection(RubberduckParserState state) - : base(state, DeclarationType.Parameter) + public ParameterNotUsedInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.Parameter) {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureCanBeWrittenAsFunctionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureCanBeWrittenAsFunctionInspection.cs index 71d4071a4f..ed78b5d081 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureCanBeWrittenAsFunctionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureCanBeWrittenAsFunctionInspection.cs @@ -41,8 +41,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ProcedureCanBeWrittenAsFunctionInspection : InspectionBase, IParseTreeInspection { - public ProcedureCanBeWrittenAsFunctionInspection(RubberduckParserState state) - : base(state) + public ProcedureCanBeWrittenAsFunctionInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Listener = new SingleByRefParamArgListListener(); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs index 4db0b65c3f..d1a291ea6f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs @@ -42,8 +42,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ProcedureNotUsedInspection : DeclarationInspectionBase { - public ProcedureNotUsedInspection(RubberduckParserState state) - : base(state, ProcedureTypes) + public ProcedureNotUsedInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, ProcedureTypes) {} private static readonly DeclarationType[] ProcedureTypes = diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs index a1d0f811b3..6c8599be27 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; @@ -54,8 +53,8 @@ namespace Rubberduck.CodeAnalysis.Inspections.Concrete /// public class ProcedureRequiredInspection : IdentifierReferenceInspectionBase { - public ProcedureRequiredInspection(RubberduckParserState state) - : base(state) + public ProcedureRequiredInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { //This will most likely cause a runtime error. The exceptions are rare and should be refactored or made explicit with an @Ignore annotation. Severity = CodeInspectionSeverity.Error; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantByRefModifierInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantByRefModifierInspection.cs index 0d9f8bd03f..fca99f3439 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantByRefModifierInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantByRefModifierInspection.cs @@ -34,9 +34,9 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class RedundantByRefModifierInspection : DeclarationInspectionBase { - public RedundantByRefModifierInspection(RubberduckParserState state) - : base(state, DeclarationType.Parameter) - { } + public RedundantByRefModifierInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.Parameter) + {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs index 8016b011b8..8ad9c10f8a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs @@ -35,8 +35,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class RedundantOptionInspection : ParseTreeInspectionBase { - public RedundantOptionInspection(RubberduckParserState state) - : base(state) + public RedundantOptionInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Listener = new RedundantModuleOptionListener(); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SelfAssignedDeclarationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SelfAssignedDeclarationInspection.cs index 1f49fcd9d4..a5175d1de7 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SelfAssignedDeclarationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SelfAssignedDeclarationInspection.cs @@ -42,8 +42,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class SelfAssignedDeclarationInspection : DeclarationInspectionBase { - public SelfAssignedDeclarationInspection(RubberduckParserState state) - : base(state, DeclarationType.Variable) + public SelfAssignedDeclarationInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.Variable) {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs index dd7b8f7cac..38e890437b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs @@ -76,8 +76,8 @@ public class SetAssignmentWithIncompatibleObjectTypeInspection : IdentifierRefer { private readonly ISetTypeResolver _setTypeResolver; - public SetAssignmentWithIncompatibleObjectTypeInspection(RubberduckParserState state, ISetTypeResolver setTypeResolver) - : base(state) + public SetAssignmentWithIncompatibleObjectTypeInspection(IDeclarationFinderProvider declarationFinderProvider, ISetTypeResolver setTypeResolver) + : base(declarationFinderProvider) { _setTypeResolver = setTypeResolver; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ShadowedDeclarationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ShadowedDeclarationInspection.cs index 7f5fdf94e2..d6551e659d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ShadowedDeclarationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ShadowedDeclarationInspection.cs @@ -1,16 +1,12 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Inspections.Results; using Rubberduck.JunkDrawer.Extensions; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; -using Rubberduck.Resources; using Rubberduck.VBEditor; using Rubberduck.VBEditor.SafeComWrappers; @@ -53,8 +49,8 @@ private enum DeclarationSite SameComponent = 3 } - public ShadowedDeclarationInspection(RubberduckParserState state) - : base(state) + public ShadowedDeclarationInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) {} protected override IDictionary> GlobalInformation(DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs index dea08b6ee6..1cab0da37d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs @@ -38,8 +38,9 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class StepIsNotSpecifiedInspection : ParseTreeInspectionBase { - public StepIsNotSpecifiedInspection(RubberduckParserState state) - : base(state) { } + public StepIsNotSpecifiedInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} protected override string ResultDescription(QualifiedContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs index a16fb4d7c0..c323a94159 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs @@ -38,8 +38,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class StepOneIsRedundantInspection : ParseTreeInspectionBase { - public StepOneIsRedundantInspection(RubberduckParserState state) - : base(state) + public StepOneIsRedundantInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) {} protected override string ResultDescription(QualifiedContext context) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs index 3607228c80..0e87196b0f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs @@ -35,8 +35,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class StopKeywordInspection : ParseTreeInspectionBase { - public StopKeywordInspection(RubberduckParserState state) - : base(state) + public StopKeywordInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) {} public override IInspectionListener Listener { get; } = diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs index 99c487d8a9..087f0d7b59 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs @@ -45,8 +45,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class SuspiciousLetAssignmentInspection : InspectionBase { - public SuspiciousLetAssignmentInspection(RubberduckParserState state) - : base(state) + public SuspiciousLetAssignmentInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Severity = CodeInspectionSeverity.Warning; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/KeywordsUsedAsMemberInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/KeywordsUsedAsMemberInspection.cs index d54eef5057..5ff7a5e7c0 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/KeywordsUsedAsMemberInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/KeywordsUsedAsMemberInspection.cs @@ -1,10 +1,8 @@ using System.Collections.Generic; using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; @@ -23,8 +21,8 @@ namespace Rubberduck.Inspections.Inspections.Concrete.ThunderCode /// public class KeywordsUsedAsMemberInspection : DeclarationInspectionBase { - public KeywordsUsedAsMemberInspection(RubberduckParserState state) - : base(state, DeclarationType.EnumerationMember, DeclarationType.UserDefinedTypeMember) + public KeywordsUsedAsMemberInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.EnumerationMember, DeclarationType.UserDefinedTypeMember) {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/LineContinuationBetweenKeywordsInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/LineContinuationBetweenKeywordsInspection.cs index 1ab25c714c..713461beba 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/LineContinuationBetweenKeywordsInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/LineContinuationBetweenKeywordsInspection.cs @@ -23,8 +23,8 @@ namespace Rubberduck.Inspections.Inspections.Concrete.ThunderCode /// public class LineContinuationBetweenKeywordsInspection : ParseTreeInspectionBase { - public LineContinuationBetweenKeywordsInspection(RubberduckParserState state) - : base(state) + public LineContinuationBetweenKeywordsInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Listener = new LineContinuationBetweenKeywordsListener(); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NegativeLineNumberInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NegativeLineNumberInspection.cs index 7c27ed6e58..302540f9c7 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NegativeLineNumberInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NegativeLineNumberInspection.cs @@ -19,8 +19,8 @@ namespace Rubberduck.Inspections.Inspections.Concrete.ThunderCode /// public class NegativeLineNumberInspection : ParseTreeInspectionBase { - public NegativeLineNumberInspection(RubberduckParserState state) - : base(state) + public NegativeLineNumberInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Listener = new NegativeLineNumberKeywordsListener(); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NonBreakingSpaceIdentifierInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NonBreakingSpaceIdentifierInspection.cs index 4850c622af..c6056217b0 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NonBreakingSpaceIdentifierInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NonBreakingSpaceIdentifierInspection.cs @@ -18,8 +18,8 @@ public class NonBreakingSpaceIdentifierInspection : DeclarationInspectionBase { private const string Nbsp = "\u00A0"; - public NonBreakingSpaceIdentifierInspection(RubberduckParserState state) - : base(state) + public NonBreakingSpaceIdentifierInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs index 149fc41ea7..42447c9183 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs @@ -19,8 +19,8 @@ namespace Rubberduck.Inspections.Inspections.Concrete.ThunderCode /// public class OnErrorGoToMinusOneInspection : ParseTreeInspectionBase { - public OnErrorGoToMinusOneInspection(RubberduckParserState state) - : base(state) + public OnErrorGoToMinusOneInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Listener = new OnErrorGoToMinusOneListener(); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs index 76017188fd..9e0e1964ee 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs @@ -43,8 +43,9 @@ namespace Rubberduck.Inspections.Concrete [SuppressMessage("ReSharper", "LoopCanBeConvertedToQuery")] public sealed class UnassignedVariableUsageInspection : IdentifierReferenceInspectionFromDeclarationsBase { - public UnassignedVariableUsageInspection(RubberduckParserState state) - : base(state) { } + public UnassignedVariableUsageInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} //See https://github.com/rubberduck-vba/Rubberduck/issues/2010 for why these are being excluded. private static readonly List IgnoredFunctions = new List diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UndeclaredVariableInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UndeclaredVariableInspection.cs index 08e88954e9..d6103d4bf6 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UndeclaredVariableInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UndeclaredVariableInspection.cs @@ -31,8 +31,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class UndeclaredVariableInspection : DeclarationInspectionBase { - public UndeclaredVariableInspection(RubberduckParserState state) - : base(state, DeclarationType.Variable) + public UndeclaredVariableInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.Variable) {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnderscoreInPublicClassModuleMemberInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnderscoreInPublicClassModuleMemberInspection.cs index 93b22538b8..7d7fb88106 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnderscoreInPublicClassModuleMemberInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnderscoreInPublicClassModuleMemberInspection.cs @@ -31,8 +31,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class UnderscoreInPublicClassModuleMemberInspection : DeclarationInspectionBase { - public UnderscoreInPublicClassModuleMemberInspection(RubberduckParserState state) - : base(state, DeclarationType.Member) + public UnderscoreInPublicClassModuleMemberInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.Member) {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs index 395ae4fb5a..1c2db0e70d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs @@ -40,8 +40,8 @@ public class UnhandledOnErrorResumeNextInspection : ParseTreeInspectionBase, List> _unhandledContextsMap = new Dictionary, List>(); - public UnhandledOnErrorResumeNextInspection(RubberduckParserState state) - : base(state) + public UnhandledOnErrorResumeNextInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Listener = new OnErrorStatementListener(_unhandledContextsMap); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs index 8c9d8cd81f..9079a682af 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs @@ -117,7 +117,6 @@ public sealed class UnreachableCaseInspection : InspectionBase, IParseTreeInspec { private readonly IUnreachableCaseInspectorFactory _unreachableCaseInspectorFactory; private readonly IParseTreeValueFactory _valueFactory; - private readonly IDeclarationFinderProvider _declarationFinderProvider; private enum CaseInspectionResult { Unreachable, InherentlyUnreachable, MismatchType, Overflow, CaseElse }; @@ -130,14 +129,13 @@ private enum CaseInspectionResult { Unreachable, InherentlyUnreachable, Mismatch [CaseInspectionResult.CaseElse] = InspectionResults.UnreachableCaseInspection_CaseElse }; - public UnreachableCaseInspection(RubberduckParserState state, IDeclarationFinderProvider declarationFinderProvider) - : base(state) + public UnreachableCaseInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { var factoryProvider = new UnreachableCaseInspectionFactoryProvider(); _unreachableCaseInspectorFactory = factoryProvider.CreateIUnreachableInspectorFactory(); _valueFactory = factoryProvider.CreateIParseTreeValueFactory(); - _declarationFinderProvider = declarationFinderProvider; } public CodeKind TargetKindOfCode => CodeKind.CodePaneCode; @@ -154,7 +152,7 @@ protected override IEnumerable DoGetInspectionResults() _inspectionResults = new List(); var qualifiedSelectCaseStmts = Listener.Contexts() // ignore filtering here to make the search space smaller - .Where(result => !result.IsIgnoringInspectionResultFor(_declarationFinderProvider.DeclarationFinder, AnnotationName)); + .Where(result => !result.IsIgnoringInspectionResultFor(DeclarationFinderProvider.DeclarationFinder, AnnotationName)); ParseTreeValueVisitor.OnValueResultCreated += ValueResults.OnNewValueResult; @@ -202,7 +200,7 @@ public static IParseTreeValueVisitor CreateParseTreeValueVisitor(IParseTreeValue //Method is used as a delegate to avoid propagating RubberduckParserState beyond this class private (bool success, IdentifierReference idRef) GetIdentifierReferenceForContext(ParserRuleContext context) { - return GetIdentifierReferenceForContext(context, _declarationFinderProvider); + return GetIdentifierReferenceForContext(context, DeclarationFinderProvider); } //public static to support tests @@ -231,7 +229,7 @@ private string GetVariableTypeName(string variableName, ParserRuleContext ancest var descendents = ancestor.GetDescendents().Where(desc => desc.GetText().Equals(variableName)).ToList(); if (descendents.Any()) { - (bool success, IdentifierReference idRef) = GetIdentifierReferenceForContext(descendents.First(), _declarationFinderProvider); + (bool success, IdentifierReference idRef) = GetIdentifierReferenceForContext(descendents.First(), DeclarationFinderProvider); if (success) { return GetBaseTypeForDeclaration(idRef.Declaration); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UntypedFunctionUsageInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UntypedFunctionUsageInspection.cs index 2e8af74cc4..242b09ea57 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UntypedFunctionUsageInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UntypedFunctionUsageInspection.cs @@ -32,8 +32,9 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class UntypedFunctionUsageInspection : IdentifierReferenceInspectionFromDeclarationsBase { - public UntypedFunctionUsageInspection(RubberduckParserState state) - : base(state) { } + public UntypedFunctionUsageInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} private readonly HashSet _tokens = new HashSet{ Tokens.Error, diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseMeaningfulNameInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseMeaningfulNameInspection.cs index 784ef82cf1..f3bdd2916a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseMeaningfulNameInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseMeaningfulNameInspection.cs @@ -3,12 +3,12 @@ using Rubberduck.CodeAnalysis.Settings; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Refactorings.Common; using Rubberduck.SettingsProvider; -using static Rubberduck.Parsing.Grammar.VBAParser; namespace Rubberduck.Inspections.Concrete { @@ -37,8 +37,8 @@ public sealed class UseMeaningfulNameInspection : DeclarationInspectionUsingGlob { private readonly IConfigurationService _settings; - public UseMeaningfulNameInspection(RubberduckParserState state, IConfigurationService settings) - : base(state) + public UseMeaningfulNameInspection(IDeclarationFinderProvider declarationFinderProvider, IConfigurationService settings) + : base(declarationFinderProvider) { _settings = settings; } @@ -62,7 +62,7 @@ protected override bool IsResultDeclaration(Declaration declaration, Declaration { return !string.IsNullOrEmpty(declaration.IdentifierName) && !IgnoreDeclarationTypes.Contains(declaration.DeclarationType) - && !(declaration.Context is LineNumberLabelContext) + && !(declaration.Context is VBAParser.LineNumberLabelContext) && (declaration.ParentDeclaration == null || !IgnoreDeclarationTypes.Contains(declaration.ParentDeclaration.DeclarationType) && !finder.FindEventHandlers().Contains(declaration.ParentDeclaration)) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfBangNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfBangNotationInspection.cs index 998e3a5ca4..aa027a9063 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfBangNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfBangNotationInspection.cs @@ -2,7 +2,6 @@ using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.VBA.DeclarationCaching; @@ -56,8 +55,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class UseOfBangNotationInspection : IdentifierReferenceInspectionBase { - public UseOfBangNotationInspection(RubberduckParserState state) - : base(state) + public UseOfBangNotationInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Severity = CodeInspectionSeverity.Suggestion; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs index a33860da11..dbd47fe466 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs @@ -2,7 +2,6 @@ using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.VBA.DeclarationCaching; @@ -64,8 +63,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class UseOfRecursiveBangNotationInspection : IdentifierReferenceInspectionBase { - public UseOfRecursiveBangNotationInspection(RubberduckParserState state) - : base(state) + public UseOfRecursiveBangNotationInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Severity = CodeInspectionSeverity.Suggestion; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs index a568cdfd40..6b0fa27db2 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs @@ -3,7 +3,6 @@ using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.VBA.DeclarationCaching; @@ -59,8 +58,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class UseOfUnboundBangNotationInspection : IdentifierReferenceInspectionBase { - public UseOfUnboundBangNotationInspection(RubberduckParserState state) - : base(state) + public UseOfUnboundBangNotationInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { Severity = CodeInspectionSeverity.Warning; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs index 7334e1cebf..28b5742400 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; @@ -58,8 +57,8 @@ namespace Rubberduck.CodeAnalysis.Inspections.Concrete /// public class ValueRequiredInspection : IdentifierReferenceInspectionBase { - public ValueRequiredInspection(RubberduckParserState state) - : base(state) + public ValueRequiredInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) { //This will most likely cause a runtime error. The exceptions are rare and should be refactored or made explicit with an @Ignore annotation. Severity = CodeInspectionSeverity.Error; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotAssignedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotAssignedInspection.cs index 365701b7b8..961b4ecbaf 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotAssignedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotAssignedInspection.cs @@ -36,8 +36,9 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class VariableNotAssignedInspection : DeclarationInspectionBase { - public VariableNotAssignedInspection(RubberduckParserState state) - : base(state, DeclarationType.Variable) { } + public VariableNotAssignedInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.Variable) + {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotUsedInspection.cs index 541ca5666e..59e5e41a6a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotUsedInspection.cs @@ -43,8 +43,8 @@ public sealed class VariableNotUsedInspection : DeclarationInspectionBase /// Inspection results for variables that are never referenced. /// /// - public VariableNotUsedInspection(RubberduckParserState state) - : base(state, DeclarationType.Variable) + public VariableNotUsedInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.Variable) {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableTypeNotDeclaredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableTypeNotDeclaredInspection.cs index 1c50e53775..3f9786aad4 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableTypeNotDeclaredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableTypeNotDeclaredInspection.cs @@ -33,8 +33,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class VariableTypeNotDeclaredInspection : ImplicitTypeInspectionBase { - public VariableTypeNotDeclaredInspection(RubberduckParserState state) - : base(state, new []{DeclarationType.Parameter, DeclarationType.Variable}, new[]{DeclarationType.Control}) + public VariableTypeNotDeclaredInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, new []{DeclarationType.Parameter, DeclarationType.Variable}, new[]{DeclarationType.Control}) {} protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/WriteOnlyPropertyInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/WriteOnlyPropertyInspection.cs index af279b3a33..d40134e3ac 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/WriteOnlyPropertyInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/WriteOnlyPropertyInspection.cs @@ -41,8 +41,8 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class WriteOnlyPropertyInspection : DeclarationInspectionBase { - public WriteOnlyPropertyInspection(RubberduckParserState state) - : base(state, DeclarationType.PropertyLet, DeclarationType.PropertySet) { } + public WriteOnlyPropertyInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider, DeclarationType.PropertyLet, DeclarationType.PropertySet) { } protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { diff --git a/RubberduckTests/Inspections/EmptyModuleInspectionTests.cs b/RubberduckTests/Inspections/EmptyModuleInspectionTests.cs index 822397cc7a..308a10b150 100644 --- a/RubberduckTests/Inspections/EmptyModuleInspectionTests.cs +++ b/RubberduckTests/Inspections/EmptyModuleInspectionTests.cs @@ -77,14 +77,14 @@ public void EmptyDocumentModules_NoResults(string inputCode) [Category("Inspections")] public void InspectionName() { - var inspection = new EmptyModuleInspection(null); + var inspection = new EmptyModuleInspection(null, null); Assert.AreEqual(nameof(EmptyModuleInspection), inspection.Name); } protected override IInspection InspectionUnderTest(RubberduckParserState state) { - return new EmptyModuleInspection(state); + return new EmptyModuleInspection(state, state); } } } diff --git a/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs b/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs index fbd41b47ab..2819a0da79 100644 --- a/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs +++ b/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs @@ -2473,7 +2473,7 @@ End Sub var actualResults = Enumerable.Empty(); using (var state = MockParser.CreateAndParse(vbe.Object)) { - var inspection = new UnreachableCaseInspection(state, state); + var inspection = new UnreachableCaseInspection(state); var parseTreeValueVisitor = inspection.ParseTreeValueVisitor as ITestParseTreeVisitor; parseTreeValueVisitor.InjectValuedDeclarationEvaluator(TestGetValuedDeclaration); @@ -2527,7 +2527,7 @@ End Sub var actualResults = Enumerable.Empty(); using (var state = MockParser.CreateAndParse(vbe.Object)) { - var inspection = new UnreachableCaseInspection(state, state); + var inspection = new UnreachableCaseInspection(state); var parseTreeValueVisitor = inspection.ParseTreeValueVisitor as ITestParseTreeVisitor; parseTreeValueVisitor.InjectValuedDeclarationEvaluator(TestGetValuedDeclaration); @@ -2636,7 +2636,7 @@ private IParseTreeVisitorResults GetParseTreeValueResults(string inputCode, out protected override IInspection InspectionUnderTest(RubberduckParserState state) { - return new UnreachableCaseInspection(state, state); + return new UnreachableCaseInspection(state); } } } diff --git a/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs b/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs index 86809350f0..87158f3ffa 100644 --- a/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs @@ -870,7 +870,7 @@ public void EmptyModule_IgnoreQuickFixWorks() @"'@IgnoreModule EmptyModule Option Explicit"; - var actualCode = ApplyIgnoreOnceToFirstResult(inputCode, state => new EmptyModuleInspection(state), TestStandardModuleVbeSetup); + var actualCode = ApplyIgnoreOnceToFirstResult(inputCode, state => new EmptyModuleInspection(state, state), TestStandardModuleVbeSetup); Assert.AreEqual(expectedCode, actualCode); } From 117f00fd501c1d6746cd4274834df79246919f39 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Wed, 26 Feb 2020 21:59:04 +0100 Subject: [PATCH 256/461] Treat IUnknown like Object in incompatible Set type inspections Also adds the missing configurationd for the references libraries in tests. --- ...entWithIncompatibleObjectTypeInspection.cs | 4 +- ...entWithIncompatibleObjectTypeInspection.cs | 4 +- ...thIncompatibleObjectTypeInspectionTests.cs | 21 +- ...thIncompatibleObjectTypeInspectionTests.cs | 230 +++++++++++++++++- RubberduckTests/Mocks/MockVbeBuilder.cs | 10 +- 5 files changed, 247 insertions(+), 22 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs index 81959d71e3..bda9fe6f21 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs @@ -128,7 +128,9 @@ private bool ArgumentPossiblyLegal(Declaration parameterDeclaration , string ass || assignedTypeName == Tokens.Variant || assignedTypeName == Tokens.Object || HasBaseType(parameterDeclaration, assignedTypeName) - || HasSubType(parameterDeclaration, assignedTypeName); + || HasSubType(parameterDeclaration, assignedTypeName) + || assignedTypeName.EndsWith("stdole.IUnknown") + || parameterDeclaration.FullAsTypeName.EndsWith("stdole.IUnknown"); } private static bool HasBaseType(Declaration declaration, string typeName) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs index 38e890437b..46ccbdaa5c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs @@ -135,7 +135,9 @@ private bool SetAssignmentPossiblyLegal(Declaration declaration, string assigned || assignedTypeName == Tokens.Variant || assignedTypeName == Tokens.Object || HasBaseType(declaration, assignedTypeName) - || HasSubType(declaration, assignedTypeName); + || HasSubType(declaration, assignedTypeName) + || assignedTypeName.EndsWith("stdole.IUnknown") + || declaration.FullAsTypeName.EndsWith("stdole.IUnknown"); } private bool HasBaseType(Declaration declaration, string typeName) diff --git a/RubberduckTests/Inspections/ArgumentWithIncompatibleObjectTypeInspectionTests.cs b/RubberduckTests/Inspections/ArgumentWithIncompatibleObjectTypeInspectionTests.cs index ef5f178be1..60b3b103c4 100644 --- a/RubberduckTests/Inspections/ArgumentWithIncompatibleObjectTypeInspectionTests.cs +++ b/RubberduckTests/Inspections/ArgumentWithIncompatibleObjectTypeInspectionTests.cs @@ -23,10 +23,12 @@ public class ArgumentWithIncompatibleObjectTypeInspectionTests : InspectionTests [TestCase("Class1", "TestProject.Class1", 0)] [TestCase("Interface1", "TestProject.Class1", 0)] [TestCase("Class1", "TestProject.Interface1", 0)] - [TestCase("Variant", "Whatever", 0)] //Tokens.Variant cannot be used here because it is not a constant expression. - [TestCase("Object", "Whatever", 0)] - [TestCase("Whatever", "Variant", 0)] - [TestCase("Whatever", "Object", 0)] + [TestCase("Variant", "Class1", 0)] //Tokens.Variant cannot be used here because it is not a constant expression. + [TestCase("Object", "Class1", 0)] + [TestCase("IUnknown", "Class1", 0)] + [TestCase("Class1", "Variant", 0)] + [TestCase("Class1", "Object", 0)] + [TestCase("Class1", ":stdole.IUnknown", 0)] [TestCase("Class1", "TestProject.SomethingIncompatible", 1)] [TestCase("Class1", "SomethingDifferent", 1)] [TestCase("TestProject.Class1", "OtherProject.Class1", 1)] @@ -133,11 +135,18 @@ End Sub private static IVBE BuildTestVBE(string class1, string interface1, string module1) { - return new MockVbeBuilder() + var projectBuilder = new MockVbeBuilder() .ProjectBuilder("TestProject", ProjectProtection.Unprotected) .AddComponent("Class1", ComponentType.ClassModule, class1) .AddComponent("Interface1", ComponentType.ClassModule, interface1) - .AddComponent("Module1", ComponentType.StandardModule, module1) + .AddComponent("Module1", ComponentType.StandardModule, module1); + + if (module1.Contains("IUnknown")) + { + projectBuilder.AddReference(ReferenceLibrary.StdOle); + } + + return projectBuilder .AddProjectToVbeBuilder() .Build() .Object; diff --git a/RubberduckTests/Inspections/SetAssignmentWithIncompatibleObjectTypeInspectionTests.cs b/RubberduckTests/Inspections/SetAssignmentWithIncompatibleObjectTypeInspectionTests.cs index d5f0fbf087..1d2b5a65c1 100644 --- a/RubberduckTests/Inspections/SetAssignmentWithIncompatibleObjectTypeInspectionTests.cs +++ b/RubberduckTests/Inspections/SetAssignmentWithIncompatibleObjectTypeInspectionTests.cs @@ -351,6 +351,40 @@ End Sub Assert.IsFalse(inspectionResults.Any()); } + [Test] + [Category("Inspections")] + public void AssignmentToIUnknown_NoResult() + { + const string class1 = + @" +Private Sub Interface1_DoIt() +End Sub +"; + + const string consumerModule = + @" +Private Sub TestIt() + Dim cls As IUnknown + Dim otherCls As Class1 + + Set otherCls = new Class1 + Set cls = otherCls +End Sub +"; + var testVbe = new MockVbeBuilder() + .ProjectBuilder("TestProject", ProjectProtection.Unprotected) + .AddComponent("Class1", ComponentType.ClassModule, class1) + .AddComponent("Module1", ComponentType.StandardModule, consumerModule) + .AddReference(ReferenceLibrary.StdOle) + .AddProjectToVbeBuilder() + .Build() + .Object; + + var inspectionResults = InspectionResults(testVbe); + + Assert.IsFalse(inspectionResults.Any()); + } + [Test] [Category("Inspections")] public void AssignmentOfObject_NoResult() @@ -409,6 +443,41 @@ End Sub Assert.IsFalse(inspectionResults.Any()); } + [Test] + [Category("Inspections")] + public void AssignmentOfIUnknown_NoResult() + { + const string class1 = + @" +Private Sub Interface1_DoIt() +End Sub +"; + + const string consumerModule = + @" +Private Sub TestIt() + Dim cls As Class1 + Dim otherCls As IUnknown + + Set otherCls = new Class2 + Set cls = otherCls +End Sub +"; + var testVbe = new MockVbeBuilder() + .ProjectBuilder("TestProject", ProjectProtection.Unprotected) + .AddComponent("Class1", ComponentType.ClassModule, class1) + .AddComponent("Class2", ComponentType.ClassModule, class1) + .AddComponent("Module1", ComponentType.StandardModule, consumerModule) + .AddReference(ReferenceLibrary.StdOle) + .AddProjectToVbeBuilder() + .Build() + .Object; + + var inspectionResults = InspectionResults(testVbe); + + Assert.IsFalse(inspectionResults.Any()); + } + [Test] [Category("Inspections")] public void AssignmentOfMeToProperlyTypesVariable_NoResult() @@ -468,10 +537,10 @@ End Sub [TestCase("Class1", "TestProject1.Class1", 0)] [TestCase("Interface1", "TestProject1.Class1", 0)] [TestCase("Class1", "TestProject1.Interface1", 0)] - [TestCase("Variant", "Whatever", 0)] //Tokens.Variant cannot be used here because it is not a constant expression. - [TestCase("Object", "Whatever", 0)] - [TestCase("Whatever", "Variant", 0)] - [TestCase("Whatever", "Object", 0)] + [TestCase("Variant", "Class1", 0)] //Tokens.Variant cannot be used here because it is not a constant expression. + [TestCase("Object", "Class1", 0)] + [TestCase("Class1", "Variant", 0)] + [TestCase("Class1", "Object", 0)] [TestCase("Class1", "TestProject1.SomethingIncompatible", 1)] [TestCase("Class1", "SomethingDifferent", 1)] [TestCase("TestProject1.Class1", "OtherProject.Class1", 1)] @@ -521,15 +590,60 @@ End Function Assert.AreEqual(expectedResultsCount, inspectionResults.Count); } + [Test] + [Category("Inspections")] + [TestCase("IUnknown", "Class1", 0)] + [TestCase("Class1", ":stdole.IUnknown", 0)] + public void MockedSetTypeEvaluatorTest_Function_IUnknown(string lhsTypeName, string expressionFullTypeName, int expectedResultsCount) + { + const string interface1 = + @" +Private Sub Foo() +End Sub +"; + const string class1 = + @"Implements Interface1 + +Private Sub Interface1_Foo() +End Sub +"; + + var module1 = + $@" +Private Function Cls() As {lhsTypeName} + Set Cls = expression +End Function +"; + + var vbe = new MockVbeBuilder() + .ProjectBuilder("TestProject", ProjectProtection.Unprotected) + .AddComponent("Class1", ComponentType.ClassModule, class1) + .AddComponent("Interface1", ComponentType.ClassModule, interface1) + .AddComponent("Module1", ComponentType.StandardModule, module1) + .AddReference(ReferenceLibrary.StdOle) + .AddProjectToVbeBuilder() + .Build() + .Object; + + var setTypeResolverMock = new Mock(); + setTypeResolverMock.Setup(m => + m.SetTypeName(It.IsAny(), It.IsAny())) + .Returns((VBAParser.ExpressionContext context, QualifiedModuleName qmn) => expressionFullTypeName); + + var inspectionResults = InspectionResults(vbe, setTypeResolverMock.Object).ToList(); + + Assert.AreEqual(expectedResultsCount, inspectionResults.Count); + } + [Test] [Category("Inspections")] [TestCase("Class1", "TestProject1.Class1", 0)] [TestCase("Interface1", "TestProject1.Class1", 0)] [TestCase("Class1", "TestProject1.Interface1", 0)] - [TestCase("Variant", "Whatever", 0)] //Tokens.Variant cannot be used here because it is not a constant expression. - [TestCase("Object", "Whatever", 0)] - [TestCase("Whatever", "Variant", 0)] - [TestCase("Whatever", "Object", 0)] + [TestCase("Variant", "Class1", 0)] //Tokens.Variant cannot be used here because it is not a constant expression. + [TestCase("Object", "Class1", 0)] + [TestCase("Class1", "Variant", 0)] + [TestCase("Class1", "Object", 0)] [TestCase("Class1", "TestProject1.SomethingIncompatible", 1)] [TestCase("Class1", "SomethingDifferent", 1)] [TestCase("TestProject1.Class1", "OtherProject.Class1", 1)] @@ -580,15 +694,60 @@ End Property Assert.AreEqual(expectedResultsCount, inspectionResults.Count); } + [Test] + [Category("Inspections")] + [TestCase("IUnknown", "Class1", 0)] + [TestCase("Class1", ":stdole.IUnknown", 0)] + public void MockedSetTypeEvaluatorTest_PropertyGet_IUnknown(string lhsTypeName, string expressionFullTypeName, int expectedResultsCount) + { + const string interface1 = + @" +Private Sub Foo() +End Sub +"; + const string class1 = + @"Implements Interface1 + +Private Sub Interface1_Foo() +End Sub +"; + + var module1 = + $@" +Private Property Get Cls() As {lhsTypeName} + Set Cls = expression +End Property +"; + + var vbe = new MockVbeBuilder() + .ProjectBuilder("TestProject", ProjectProtection.Unprotected) + .AddComponent("Class1", ComponentType.ClassModule, class1) + .AddComponent("Interface1", ComponentType.ClassModule, interface1) + .AddComponent("Module1", ComponentType.StandardModule, module1) + .AddReference(ReferenceLibrary.StdOle) + .AddProjectToVbeBuilder() + .Build() + .Object; + + var setTypeResolverMock = new Mock(); + setTypeResolverMock.Setup(m => + m.SetTypeName(It.IsAny(), It.IsAny())) + .Returns((VBAParser.ExpressionContext context, QualifiedModuleName qmn) => expressionFullTypeName); + + var inspectionResults = InspectionResults(vbe, setTypeResolverMock.Object).ToList(); + + Assert.AreEqual(expectedResultsCount, inspectionResults.Count); + } + [Test] [Category("Inspections")] [TestCase("Class1", "TestProject1.Class1", 0)] [TestCase("Interface1", "TestProject1.Class1", 0)] [TestCase("Class1", "TestProject1.Interface1", 0)] - [TestCase("Variant", "Whatever", 0)] //Tokens.Variant cannot be used here because it is not a constant expression. - [TestCase("Object", "Whatever", 0)] - [TestCase("Whatever", "Variant", 0)] - [TestCase("Whatever", "Object", 0)] + [TestCase("Variant", "Class1", 0)] //Tokens.Variant cannot be used here because it is not a constant expression. + [TestCase("Object", "Class1", 0)] + [TestCase("Class1", "Variant", 0)] + [TestCase("Class1", "Object", 0)] [TestCase("Class1", "TestProject1.SomethingIncompatible", 1)] [TestCase("Class1", "SomethingDifferent", 1)] [TestCase("TestProject1.Class1", "OtherProject.Class1", 1)] @@ -641,6 +800,53 @@ End Sub Assert.AreEqual(expectedResultsCount, inspectionResults.Count); } + [Test] + [Category("Inspections")] + [TestCase("IUnknown", "Class1", 0)] + [TestCase("Class1", ":stdole.IUnknown", 0)] + public void MockedSetTypeEvaluatorTest_Variable_IUnknown(string lhsTypeName, string expressionFullTypeName, int expectedResultsCount) + { + const string interface1 = + @" +Private Sub Foo() +End Sub +"; + const string class1 = + @"Implements Interface1 + +Private Sub Interface1_Foo() +End Sub +"; + + var module1 = + $@" +Private Sub TestIt() + Dim cls As {lhsTypeName} + + Set cls = expression +End Sub +"; + + var vbe = new MockVbeBuilder() + .ProjectBuilder("TestProject", ProjectProtection.Unprotected) + .AddComponent("Class1", ComponentType.ClassModule, class1) + .AddComponent("Interface1", ComponentType.ClassModule, interface1) + .AddComponent("Module1", ComponentType.StandardModule, module1) + .AddReference(ReferenceLibrary.StdOle) + .AddProjectToVbeBuilder() + .Build() + .Object; + + var setTypeResolverMock = new Mock(); + setTypeResolverMock.Setup(m => + m.SetTypeName(It.IsAny(), It.IsAny())) + .Returns((VBAParser.ExpressionContext context, QualifiedModuleName qmn) => expressionFullTypeName); + + var inspectionResults = InspectionResults(vbe, setTypeResolverMock.Object).ToList(); + + Assert.AreEqual(expectedResultsCount, inspectionResults.Count); + } + private static IEnumerable InspectionResults(IVBE vbe, ISetTypeResolver setTypeResolver) { using (var state = MockParser.CreateAndParse(vbe)) diff --git a/RubberduckTests/Mocks/MockVbeBuilder.cs b/RubberduckTests/Mocks/MockVbeBuilder.cs index a29ec5f9a3..0ac5e3a961 100644 --- a/RubberduckTests/Mocks/MockVbeBuilder.cs +++ b/RubberduckTests/Mocks/MockVbeBuilder.cs @@ -4,7 +4,6 @@ using System.Linq; using Moq; using Rubberduck.VBEditor; -using Rubberduck.VBEditor.Events; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; @@ -64,9 +63,16 @@ public class MockVbeBuilder { [ReferenceLibrary.VBA] = (ReferenceLibrary.VBA.Name(), ReferenceLibrary.VBA.Path(), 4, 2, true), [ReferenceLibrary.Excel] = (ReferenceLibrary.Excel.Name(), ReferenceLibrary.Excel.Path(), 1, 8, true), + [ReferenceLibrary.MsOffice] = (ReferenceLibrary.MsOffice.Name(), ReferenceLibrary.MsOffice.Path(), 2, 7, true), + [ReferenceLibrary.StdOle] = (ReferenceLibrary.StdOle.Name(), ReferenceLibrary.StdOle.Path(), 2, 0, true), + [ReferenceLibrary.MsForms] = (ReferenceLibrary.MsForms.Name(), ReferenceLibrary.MsForms.Path(), 2, 0, true), + [ReferenceLibrary.VBIDE] = (ReferenceLibrary.VBIDE.Name(), ReferenceLibrary.VBIDE.Path(), 5, 3, true), [ReferenceLibrary.Scripting] = (ReferenceLibrary.Scripting.Name(), ReferenceLibrary.Scripting.Path(), 1, 0, true), + [ReferenceLibrary.Regex] = (ReferenceLibrary.Regex.Name(), ReferenceLibrary.Regex.Path(), 5, 5, true), + [ReferenceLibrary.MsXml] = (ReferenceLibrary.MsXml.Name(), ReferenceLibrary.MsXml.Path(), 6, 0, true), + [ReferenceLibrary.ShDoc] = (ReferenceLibrary.ShDoc.Name(), ReferenceLibrary.ShDoc.Path(), 1, 1, true), [ReferenceLibrary.AdoDb] = (ReferenceLibrary.AdoDb.Name(), ReferenceLibrary.AdoDb.Path(), 6, 1, false), - [ReferenceLibrary.MsForms] = (ReferenceLibrary.MsForms.Name(), ReferenceLibrary.MsForms.Path(), 2, 0, true), + [ReferenceLibrary.AdoRecordset] = (ReferenceLibrary.AdoRecordset.Name(), ReferenceLibrary.AdoRecordset.Path(), 6, 0, false), }; private readonly Windows _windows = new Windows(); From 15d6320f1fcaf034b9488c44afca13a8353940e4 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Wed, 26 Feb 2020 22:49:16 +0100 Subject: [PATCH 257/461] Make ObsoleteCallStatementInspection more precise Also removes the use of a CodeModule. --- .../ObsoleteCallStatementInspection.cs | 23 ++++++---------- .../ObsoleteCallStatementInspectionTests.cs | 26 +++++++++++++++++-- .../RedundantOptionInspectionTests.cs | 2 +- .../QuickFixes/IgnoreOnceQuickFixTests.cs | 2 +- ...emoveExplicitCallStatementQuickFixTests.cs | 2 +- 5 files changed, 35 insertions(+), 20 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs index d98a757523..6d708289fc 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs @@ -40,13 +40,10 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class ObsoleteCallStatementInspection : ParseTreeInspectionBase { - private readonly IProjectsProvider _projectsProvider; - - public ObsoleteCallStatementInspection(IDeclarationFinderProvider declarationFinderProvider, IProjectsProvider projectsProvider) + public ObsoleteCallStatementInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) { Listener = new ObsoleteCallStatementListener(); - _projectsProvider = projectsProvider; } public override IInspectionListener Listener { get; } @@ -57,23 +54,19 @@ protected override string ResultDescription(QualifiedContext protected override bool IsResultContext(QualifiedContext context) { - //FIXME At least use a parse tree here instead of the COM API. - string lines; - var component = _projectsProvider.Component(context.ModuleName); - using (var module = component.CodeModule) + if (!context.Context.TryGetFollowingContext(out VBAParser.IndividualNonEOFEndOfStatementContext followingEndOfStatement) + || followingEndOfStatement.COLON() == null) { - lines = module.GetLines(context.Context.Start.Line, - context.Context.Stop.Line - context.Context.Start.Line + 1); + return true; } - var stringStrippedLines = string.Join(string.Empty, lines).StripStringLiterals(); - - if (stringStrippedLines.HasComment(out var commentIndex)) + if (!context.Context.TryGetPrecedingContext(out VBAParser.IndividualNonEOFEndOfStatementContext precedingEndOfStatement) + || precedingEndOfStatement.endOfLine() == null) { - stringStrippedLines = stringStrippedLines.Remove(commentIndex); + return true; } - return !stringStrippedLines.Contains(":"); + return false; } public class ObsoleteCallStatementListener : InspectionListenerBase diff --git a/RubberduckTests/Inspections/ObsoleteCallStatementInspectionTests.cs b/RubberduckTests/Inspections/ObsoleteCallStatementInspectionTests.cs index a947d20b71..79949ab47d 100644 --- a/RubberduckTests/Inspections/ObsoleteCallStatementInspectionTests.cs +++ b/RubberduckTests/Inspections/ObsoleteCallStatementInspectionTests.cs @@ -43,6 +43,28 @@ public void ObsoleteCallStatement_DoesNotReturnResult_InstructionSeparator() Assert.AreEqual(0, InspectionResultsForStandardModule(inputCode).Count()); } + [Test] + [Category("Inspections")] + public void ObsoleteCallStatement_ReturnsResult_LabelInFront() + { + const string inputCode = + @"Sub Foo() + Foo: Call Foo +End Sub"; + Assert.AreEqual(1, InspectionResultsForStandardModule(inputCode).Count()); + } + + [Test] + [Category("Inspections")] + public void ObsoleteCallStatement_ReturnsResult_LabelInFrontWithSeparator() + { + const string inputCode = + @"Sub Foo() + Foo: Call Foo : Foo +End Sub"; + Assert.AreEqual(1, InspectionResultsForStandardModule(inputCode).Count()); + } + [Test] [Category("Inspections")] public void ObsoleteCallStatement_ReturnsResult_ColonInComment() @@ -111,14 +133,14 @@ Call Foo [Category("Inspections")] public void InspectionName() { - var inspection = new ObsoleteCallStatementInspection(null, null); + var inspection = new ObsoleteCallStatementInspection(null); Assert.AreEqual(nameof(ObsoleteCallStatementInspection), inspection.Name); } protected override IInspection InspectionUnderTest(RubberduckParserState state) { - return new ObsoleteCallStatementInspection(state, state.ProjectsProvider); + return new ObsoleteCallStatementInspection(state); } } } diff --git a/RubberduckTests/Inspections/RedundantOptionInspectionTests.cs b/RubberduckTests/Inspections/RedundantOptionInspectionTests.cs index e4473f10cc..946eb48495 100644 --- a/RubberduckTests/Inspections/RedundantOptionInspectionTests.cs +++ b/RubberduckTests/Inspections/RedundantOptionInspectionTests.cs @@ -32,7 +32,7 @@ public void RedundantOptionInspection_Ignored_DoesNotReturnResult() using (var state = MockParser.CreateAndParse(vbe.Object)) { - var inspection = new ObsoleteCallStatementInspection(state, state.ProjectsProvider); + var inspection = new ObsoleteCallStatementInspection(state); var inspector = InspectionsHelper.GetInspector(inspection); var inspectionResults = inspector.FindIssuesAsync(state, CancellationToken.None).Result; diff --git a/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs b/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs index 87158f3ffa..e488536a04 100644 --- a/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs @@ -465,7 +465,7 @@ Sub Goo(arg1 As Integer, arg1 As String) Call Foo End Sub"; - var actualCode = ApplyIgnoreOnceToAllResults(inputCode, state => new ObsoleteCallStatementInspection(state, state.ProjectsProvider), TestStandardModuleVbeSetup); + var actualCode = ApplyIgnoreOnceToAllResults(inputCode, state => new ObsoleteCallStatementInspection(state), TestStandardModuleVbeSetup); Assert.AreEqual(expectedCode, actualCode); } diff --git a/RubberduckTests/QuickFixes/RemoveExplicitCallStatementQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveExplicitCallStatementQuickFixTests.cs index c17ff58470..b50d2ba040 100644 --- a/RubberduckTests/QuickFixes/RemoveExplicitCallStatementQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveExplicitCallStatementQuickFixTests.cs @@ -32,7 +32,7 @@ Sub Goo(arg1 As Integer, arg1 As String) Foo End Sub"; - var actualCode = ApplyQuickFixToAllInspectionResults(inputCode, state => new ObsoleteCallStatementInspection(state, state.ProjectsProvider)); + var actualCode = ApplyQuickFixToAllInspectionResults(inputCode, state => new ObsoleteCallStatementInspection(state)); Assert.AreEqual(expectedCode, actualCode); } From c4e0fd84bb3b439fd0e0585d6742073a3d61cd26 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Thu, 27 Feb 2020 00:58:05 +0100 Subject: [PATCH 258/461] Turn ProcedureCanBeWrittenAsFunctionInspection into a declaration inspection --- ...ocedureCanBeWrittenAsFunctionInspection.cs | 118 ++++++++------- .../ChangeProcedureToFunctionQuickFix.cs | 3 +- ...rocedureShouldBeFunctionInspectionTests.cs | 137 ++++++++++++++++++ .../ChangeProcedureToFunctionQuickFixTests.cs | 28 +++- 4 files changed, 228 insertions(+), 58 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureCanBeWrittenAsFunctionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureCanBeWrittenAsFunctionInspection.cs index ed78b5d081..f4bb134eeb 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureCanBeWrittenAsFunctionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureCanBeWrittenAsFunctionInspection.cs @@ -1,15 +1,11 @@ -using System.Collections.Generic; -using System.Linq; -using Antlr4.Runtime; +using System.Linq; using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.VBA.Parsing; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -39,75 +35,85 @@ namespace Rubberduck.Inspections.Concrete /// End Function /// ]]> /// - public sealed class ProcedureCanBeWrittenAsFunctionInspection : InspectionBase, IParseTreeInspection + /// + /// + /// + public sealed class ProcedureCanBeWrittenAsFunctionInspection : DeclarationInspectionBase { public ProcedureCanBeWrittenAsFunctionInspection(IDeclarationFinderProvider declarationFinderProvider) - : base(declarationFinderProvider) - { - Listener = new SingleByRefParamArgListListener(); - } + : base(declarationFinderProvider, new []{DeclarationType.Procedure}, new []{DeclarationType.LibraryProcedure, DeclarationType.PropertyLet, DeclarationType.PropertySet}) + {} - public CodeKind TargetKindOfCode => CodeKind.CodePaneCode; - public IInspectionListener Listener { get; } - - //FIXME This should really be a declaration inspection. - - protected override IEnumerable DoGetInspectionResults() + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) { - if (!Listener.Contexts().Any()) + if (!(declaration is ModuleBodyElementDeclaration member) + || member.IsInterfaceImplementation + || member.IsInterfaceMember + || finder.FindEventHandlers().Contains(member) + || member.Parameters.Count(param => param.IsByRef && !param.IsParamArray) != 1) { - return Enumerable.Empty(); + return false; } - var finder = DeclarationFinderProvider.DeclarationFinder; - - var userDeclarations = finder.AllUserDeclarations.ToList(); - var builtinHandlers = finder.FindEventHandlers().ToList(); + var parameter = member.Parameters.First(param => param.IsByRef && !param.IsParamArray); + var parameterReferences = parameter.References.ToList(); - var contextLookup = userDeclarations.Where(decl => decl.Context != null).ToDictionary(decl => decl.Context); + return parameterReferences.Any(reference => IsAssignment(reference, finder)); + } - var ignored = new HashSet(finder.FindAllInterfaceMembers() - .Concat(finder.FindAllInterfaceImplementingMembers()) - .Concat(builtinHandlers) - .Concat(userDeclarations.Where(item => item.IsWithEvents))); + private static bool IsAssignment(IdentifierReference reference, DeclarationFinder finder) + { + return reference.IsAssignment + || IsUsageAsAssignedToByRefArgument(reference, finder); + } - return Listener.Contexts() - .Where(context => context.Context.Parent is VBAParser.SubStmtContext - && HasArgumentReferencesWithIsAssignmentFlagged(context)) - .Select(GetSubStmtParentDeclaration) - .Where(decl => decl != null && - !ignored.Contains(decl) && - userDeclarations.Where(item => item.IsWithEvents) - .All(withEvents => !finder.FindHandlersForWithEventsField(withEvents).Any()) && - !builtinHandlers.Contains(decl)) - .Select(result => new DeclarationInspectionResult(this, - string.Format(InspectionResults.ProcedureCanBeWrittenAsFunctionInspection, result.IdentifierName), - result)); + private static bool IsUsageAsAssignedToByRefArgument(IdentifierReference reference, DeclarationFinder finder) + { + var argExpression = ImmediateArgumentExpressionContext(reference); - bool HasArgumentReferencesWithIsAssignmentFlagged(QualifiedContext context) + if (argExpression == null) { - return contextLookup.TryGetValue(context.Context.GetChild(), out Declaration decl) - && decl.References.Any(rf => rf.IsAssignment); + return false; } - Declaration GetSubStmtParentDeclaration(QualifiedContext context) + var parameter = finder.FindParameterOfNonDefaultMemberFromSimpleArgumentNotPassedByValExplicitly(argExpression, reference.QualifiedModuleName); + + if (parameter == null) { - return contextLookup.TryGetValue(context.Context.Parent as VBAParser.SubStmtContext, out Declaration decl) - ? decl - : null; + //We have no idea what parameter it is passed to as argument. So, we have to err on the safe side and assume it is not passed by reference. + return false; } + + //We go only one level deep and make a conservative check to avoid a potentially costly recursion. + return parameter.IsByRef + && parameter.References.Any(paramReference => paramReference.IsAssignment); } - public class SingleByRefParamArgListListener : InspectionListenerBase + private static VBAParser.ArgumentExpressionContext ImmediateArgumentExpressionContext(IdentifierReference reference) { - public override void ExitArgList(VBAParser.ArgListContext context) - { - var args = context.arg(); - if (args != null && args.All(a => a.PARAMARRAY() == null && a.LPAREN() == null) && args.Count(a => a.BYREF() != null || (a.BYREF() == null && a.BYVAL() == null)) == 1) - { - SaveContext(context); - } - } + var context = reference.Context; + //The context is either already a simpleNameExprContext or an IdentifierValueContext used in a sub-rule of some other lExpression alternative. + var lExpressionNameContext = context is VBAParser.SimpleNameExprContext simpleName + ? simpleName + : context.GetAncestor(); + + //To be an immediate argument and, thus, assignable by ref, the structure must be argumentExpression -> expression -> lExpression. + return lExpressionNameContext? + .Parent? + .Parent as VBAParser.ArgumentExpressionContext; + } + + protected override string ResultDescription(Declaration declaration) + { + return string.Format( + InspectionResults.ProcedureCanBeWrittenAsFunctionInspection, + declaration.IdentifierName); } } } diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ChangeProcedureToFunctionQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/ChangeProcedureToFunctionQuickFix.cs index 0fb26b261c..bc929993e7 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ChangeProcedureToFunctionQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/ChangeProcedureToFunctionQuickFix.cs @@ -2,6 +2,7 @@ using System.Linq; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Concrete; +using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -56,7 +57,7 @@ public override void Fix(IInspectionResult result, IRewriteSession rewriteSessio { var parameterizedDeclaration = (IParameterizedDeclaration) result.Target; var arg = parameterizedDeclaration.Parameters.First(p => p.IsByRef || p.IsImplicitByRef); - var argIndex = parameterizedDeclaration.Parameters.ToList().IndexOf(arg); + var argIndex = parameterizedDeclaration.Parameters.IndexOf(arg); UpdateSignature(result.Target, arg, rewriteSession); foreach (var reference in result.Target.References.Where(reference => !reference.IsDefaultMemberAccess)) diff --git a/RubberduckTests/Inspections/ProcedureShouldBeFunctionInspectionTests.cs b/RubberduckTests/Inspections/ProcedureShouldBeFunctionInspectionTests.cs index 7f7d45e183..70ad2e8c27 100644 --- a/RubberduckTests/Inspections/ProcedureShouldBeFunctionInspectionTests.cs +++ b/RubberduckTests/Inspections/ProcedureShouldBeFunctionInspectionTests.cs @@ -22,6 +22,90 @@ public void ProcedureShouldBeFunction_ReturnsResult() Assert.AreEqual(1, InspectionResultsForStandardModule(inputCode).Count()); } + [Test] + [Category("Inspections")] + public void ProcedureShouldBeFunction_ReturnsResult_UsedByValAfterConditionalAssignment() + { + const string inputCode = + @"Private Sub Foo(ByRef bar As Boolean, ByVal baz As Boolean) + If baz Then + bar = 42 + End If + Goo bar +End Sub + +Private Sub Goo(ByVal arg As Boolean) +End Sub"; + + Assert.AreEqual(1, InspectionResultsForStandardModule(inputCode).Count()); + } + + [Test] + [Category("Inspections")] + public void ProcedureShouldBeFunction_ReturnsResult_UsedByValBeforeAssignment() + { + const string inputCode = + @"Private Sub Foo(ByRef bar As Boolean) + Goo bar + bar = 42 +End Sub + +Private Sub Goo(ByVal arg As Boolean) +End Sub"; + + Assert.AreEqual(1, InspectionResultsForStandardModule(inputCode).Count()); + } + + [Test] + [Category("Inspections")] + public void ProcedureShouldBeFunction_ReturnsResult_UsedByRef() + { + const string inputCode = + @"Private Sub Foo(ByRef bar As Boolean) + Goo bar, True +End Sub + +Private Sub Goo(ByRef arg1 As Boolean, ByRef arg2 As Boolean) + arg1 = arg2 +End Sub"; + + Assert.AreEqual(1, InspectionResultsForStandardModule(inputCode).Count()); + } + + [Test] + [Category("Inspections")] + public void ProcedureShouldBeFunction_DoesNotReturnResult_UsedInExpression() + { + const string inputCode = + @"Private Sub Foo(ByRef bar As Boolean) + Goo Not bar, True +End Sub + +Private Sub Goo(ByRef arg1 As Boolean, ByRef arg2 As Boolean) + arg1 = arg2 +End Sub"; + + Assert.AreEqual(0, InspectionResultsForStandardModule(inputCode).Count()); + } + + [Test] + [Category("Inspections")] + public void ProcedureShouldBeFunction_ReturnsResult_UsedByRefWithArgumentUsage() + { + const string inputCode = + @"Private Sub Foo(ByRef bar As Boolean) + Goo bar, True +End Sub + +Private Sub Goo(ByRef arg1 As Boolean, ByRef arg2 As Boolean) + Dim baz As Variant + baz = arg1 + arg1 = arg2 +End Sub"; + + Assert.AreEqual(1, InspectionResultsForStandardModule(inputCode).Count()); + } + [Test] [Category("Inspections")] public void ProcedureShouldBeFunction_ReturnsResult_MultipleSubs() @@ -85,6 +169,19 @@ public void ProcedureShouldBeFunction_DoesNotReturnsResult_MultipleByRefParams() Assert.AreEqual(0, InspectionResultsForStandardModule(inputCode).Count()); } + [Test] + [Category("Inspections")] + public void ProcedureShouldBeFunction_ReturnsResult_MultipleParamsOneByRef() + { + const string inputCode = + @"Private Sub Foo(ByVal foo As Integer, ByRef goo As Integer, ByVal hoo As Variant) + foo = 42 + goo = 42 +End Sub"; + + Assert.AreEqual(1, InspectionResultsForStandardModule(inputCode).Count()); + } + [Test] [Category("Inspections")] public void ProcedureShouldBeFunction_DoesNotReturnResult_InterfaceImplementation() @@ -107,6 +204,44 @@ Private Sub IClass1_DoSomething(ByRef a As Integer) Assert.AreEqual(0, InspectionResultsForModules(modules).Count()); } + [Test] + [Category("Inspections")] + public void ProcedureShouldBeFunction_ReturnsResult_Object() + { + const string inputCode1 = + @"Public bar As Variant"; + const string inputCode2 = + @"Private Sub DoSomething(ByRef a As Class1) + Set a = New Class1 +End Sub"; + var modules = new (string, string, ComponentType)[] + { + ("Class1", inputCode1, ComponentType.ClassModule), + ("Class2", inputCode2, ComponentType.ClassModule) + }; + + Assert.AreEqual(1, InspectionResultsForModules(modules).Count()); + } + + [Test] + [Category("Inspections")] + public void ProcedureShouldBeFunction_DoesNotReturnResult_ObjectMember() + { + const string inputCode1 = + @"Public bar As Variant"; + const string inputCode2 = + @"Private Sub DoSomething(ByRef a As Class1) + Set a.bar = New Class1 +End Sub"; + var modules = new (string, string, ComponentType)[] + { + ("Class1", inputCode1, ComponentType.ClassModule), + ("Class2", inputCode2, ComponentType.ClassModule) + }; + + Assert.AreEqual(0, InspectionResultsForModules(modules).Count()); + } + [Test] [Category("Inspections")] public void ProcedureShouldBeFunction_DoesNotReturnResult_EventImplementation() @@ -146,6 +281,8 @@ Private Sub Foo(ByRef foo As Boolean) public void InspectionName() { var inspection = new ProcedureCanBeWrittenAsFunctionInspection(null); + + Assert.AreEqual(nameof(ProcedureCanBeWrittenAsFunctionInspection), inspection.Name); } protected override IInspection InspectionUnderTest(RubberduckParserState state) diff --git a/RubberduckTests/QuickFixes/ChangeProcedureToFunctionQuickFixTests.cs b/RubberduckTests/QuickFixes/ChangeProcedureToFunctionQuickFixTests.cs index 7c5419071d..a34f1cf6f2 100644 --- a/RubberduckTests/QuickFixes/ChangeProcedureToFunctionQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ChangeProcedureToFunctionQuickFixTests.cs @@ -9,7 +9,6 @@ namespace RubberduckTests.QuickFixes [TestFixture] public class ChangeProcedureToFunctionQuickFixTests : QuickFixTestBase { - [Test] [Category("QuickFixes")] public void ProcedureShouldBeFunction_QuickFixWorks() @@ -29,6 +28,33 @@ public void ProcedureShouldBeFunction_QuickFixWorks() Assert.AreEqual(expectedCode, actualCode); } + [Test] + [Category("QuickFixes")] + public void ProcedureShouldBeFunction_QuickFixWorks_AssignedByRef() + { + const string inputCode = + @"Private Sub Foo(ByRef bar As Boolean) + Goo bar, True +End Sub + +Private Sub Goo(ByRef arg1 As Boolean, ByRef arg2 As Boolean) + arg1 = arg2 +End Sub"; + + const string expectedCode = + @"Private Function Foo(ByVal bar As Boolean) As Boolean + Goo bar, True + Foo = bar +End Function + +Private Sub Goo(ByRef arg1 As Boolean, ByRef arg2 As Boolean) + arg1 = arg2 +End Sub"; + + var actualCode = ApplyQuickFixToFirstInspectionResult(inputCode, state => new ProcedureCanBeWrittenAsFunctionInspection(state)); + Assert.AreEqual(expectedCode, actualCode); + } + [Test] [Category("QuickFixes")] public void ProcedureShouldBeFunction_QuickFixWorks_NoAsTypeClauseInParam() From a7ccb69e89bea4da37361e72f5d71db88d947432 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Thu, 27 Feb 2020 01:40:31 +0100 Subject: [PATCH 259/461] Make UnreachableCaseInspection able to run by module --- .../UnreachableCaseInspection.cs | 70 +++++++++++++------ 1 file changed, 49 insertions(+), 21 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs index 9079a682af..07e22a7571 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs @@ -14,6 +14,7 @@ using System; using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.JunkDrawer.Extensions; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Parsing.VBA.Parsing; namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection @@ -143,33 +144,60 @@ public UnreachableCaseInspection(IDeclarationFinderProvider declarationFinderPro public IInspectionListener Listener { get; } = new UnreachableCaseInspectionListener(); - private List _inspectionResults = new List(); - private ParseTreeVisitorResults ValueResults { get; } = new ParseTreeVisitorResults(); + private ParseTreeVisitorResults ValueResults { get; } = new ParseTreeVisitorResults(); protected override IEnumerable DoGetInspectionResults() { - //FIXME Get the declaration finder only once inside the inspection to avoid possible inconsistent state due to a reparse while inspections run. - _inspectionResults = new List(); - var qualifiedSelectCaseStmts = Listener.Contexts() + var finder = DeclarationFinderProvider.DeclarationFinder; + + return finder.UserDeclarations(DeclarationType.Module) + .Where(module => module != null) + .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder)) + .ToList(); + } + + private IEnumerable DoGetInspectionResults(QualifiedModuleName module) + { + var finder = DeclarationFinderProvider.DeclarationFinder; + return DoGetInspectionResults(module, finder); + } + + private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + { + var qualifiedSelectCaseStmts = Listener.Contexts(module) // ignore filtering here to make the search space smaller - .Where(result => !result.IsIgnoringInspectionResultFor(DeclarationFinderProvider.DeclarationFinder, AnnotationName)); + .Where(result => !result.IsIgnoringInspectionResultFor(finder, AnnotationName)); ParseTreeValueVisitor.OnValueResultCreated += ValueResults.OnNewValueResult; - foreach (var qualifiedSelectCaseStmt in qualifiedSelectCaseStmts) - { - qualifiedSelectCaseStmt.Context.Accept(ParseTreeValueVisitor); - var selectCaseInspector = _unreachableCaseInspectorFactory.Create((VBAParser.SelectCaseStmtContext)qualifiedSelectCaseStmt.Context, ValueResults, _valueFactory, GetVariableTypeName); + return qualifiedSelectCaseStmts + .SelectMany(ResultsForContext) + .ToList(); + } - selectCaseInspector.InspectForUnreachableCases(); + private IEnumerable ResultsForContext(QualifiedContext qualifiedSelectCaseStmt) + { + qualifiedSelectCaseStmt.Context.Accept(ParseTreeValueVisitor); + var selectCaseInspector = _unreachableCaseInspectorFactory.Create((VBAParser.SelectCaseStmtContext)qualifiedSelectCaseStmt.Context, ValueResults, _valueFactory, GetVariableTypeName); - selectCaseInspector.UnreachableCases.ForEach(uc => CreateInspectionResult(qualifiedSelectCaseStmt, uc, ResultMessages[CaseInspectionResult.Unreachable])); - selectCaseInspector.MismatchTypeCases.ForEach(mm => CreateInspectionResult(qualifiedSelectCaseStmt, mm, ResultMessages[CaseInspectionResult.MismatchType])); - selectCaseInspector.OverflowCases.ForEach(mm => CreateInspectionResult(qualifiedSelectCaseStmt, mm, ResultMessages[CaseInspectionResult.Overflow])); - selectCaseInspector.InherentlyUnreachableCases.ForEach(mm => CreateInspectionResult(qualifiedSelectCaseStmt, mm, ResultMessages[CaseInspectionResult.InherentlyUnreachable])); - selectCaseInspector.UnreachableCaseElseCases.ForEach(ce => CreateInspectionResult(qualifiedSelectCaseStmt, ce, ResultMessages[CaseInspectionResult.CaseElse])); - } - return _inspectionResults; + selectCaseInspector.InspectForUnreachableCases(); + + return selectCaseInspector + .UnreachableCases + .Select(uc => CreateInspectionResult(qualifiedSelectCaseStmt, uc, ResultMessages[CaseInspectionResult.Unreachable])) + .Concat(selectCaseInspector + .MismatchTypeCases + .Select(mm => CreateInspectionResult(qualifiedSelectCaseStmt, mm, ResultMessages[CaseInspectionResult.MismatchType]))) + .Concat(selectCaseInspector + .OverflowCases + .Select(mm => CreateInspectionResult(qualifiedSelectCaseStmt, mm, ResultMessages[CaseInspectionResult.Overflow]))) + .Concat(selectCaseInspector + .InherentlyUnreachableCases + .Select(mm => CreateInspectionResult(qualifiedSelectCaseStmt, mm, ResultMessages[CaseInspectionResult.InherentlyUnreachable]))) + .Concat(selectCaseInspector + .UnreachableCaseElseCases + .Select(ce => CreateInspectionResult(qualifiedSelectCaseStmt, ce, ResultMessages[CaseInspectionResult.CaseElse]))) + .ToList(); } private IParseTreeValueVisitor _parseTreeValueVisitor; @@ -186,12 +214,11 @@ public IParseTreeValueVisitor ParseTreeValueVisitor } } - private void CreateInspectionResult(QualifiedContext selectStmt, ParserRuleContext unreachableBlock, string message) + private IInspectionResult CreateInspectionResult(QualifiedContext selectStmt, ParserRuleContext unreachableBlock, string message) { - var result = new QualifiedContextInspectionResult(this, + return new QualifiedContextInspectionResult(this, message, new QualifiedContext(selectStmt.ModuleName, unreachableBlock)); - _inspectionResults.Add(result); } public static IParseTreeValueVisitor CreateParseTreeValueVisitor(IParseTreeValueFactory valueFactory, IReadOnlyList allEnums, Func func) @@ -212,6 +239,7 @@ public static (bool success, IdentifierReference idRef) GetIdentifierReferenceFo return (false, null); } + //FIXME Get the declaration finder only once inside the inspection to avoid the possibility of inconsistent state due to a reparse while inspections run. var finder = declarationFinderProvider.DeclarationFinder; var identifierReferences = finder.MatchName(context.GetText()) .SelectMany(declaration => declaration.References) From b24cfcb3edee48089e4639bbeda23a022216248c Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Thu, 27 Feb 2020 20:09:40 +0100 Subject: [PATCH 260/461] Make it possible to run inspections for single modules --- .../Abstract/DeclarationInspectionBaseBase.cs | 2 +- ...nspectionUsingGlobalInformationBaseBase.cs | 2 +- .../IdentifierReferenceInspectionBase.cs | 4 ++-- ...ReferenceInspectionFromDeclarationsBase.cs | 4 ++-- .../Inspections/Abstract/InspectionBase.cs | 21 +++++++++++++++++++ .../Abstract/ParseTreeInspectionBase.cs | 4 ++-- .../Concrete/IllegalAnnotationInspection.cs | 2 +- ...bjectWhereProcedureIsRequiredInspection.cs | 2 +- .../Concrete/ObsoleteTypeHintInspection.cs | 2 +- .../SuspiciousLetAssignmentInspection.cs | 2 +- .../UnreachableCaseInspection.cs | 2 +- .../Inspections/Abstract/IInspection.cs | 8 +++++++ 12 files changed, 42 insertions(+), 13 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs index 6df76ebfa6..6a8346b006 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs @@ -40,7 +40,7 @@ protected override IEnumerable DoGetInspectionResults() .ToList(); } - protected virtual IEnumerable DoGetInspectionResults(QualifiedModuleName module) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) { var finder = DeclarationFinderProvider.DeclarationFinder; return DoGetInspectionResults(module, finder); diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs index cccc94d6a4..c86f2f2b5f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs @@ -50,7 +50,7 @@ protected override IEnumerable DoGetInspectionResults() .ToList(); } - protected virtual IEnumerable DoGetInspectionResults(QualifiedModuleName module) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) { var finder = DeclarationFinderProvider.DeclarationFinder; var globalInformation = GlobalInformation(module, finder); diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs index 54818d9f6e..27eebf3f5a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs @@ -40,7 +40,7 @@ protected IEnumerable DoGetInspectionResults(QualifiedModuleN .ToList(); } - protected IEnumerable DoGetInspectionResults(QualifiedModuleName module) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) { var finder = DeclarationFinderProvider.DeclarationFinder; return DoGetInspectionResults(module, finder); @@ -102,7 +102,7 @@ protected IEnumerable DoGetInspectionResults(QualifiedModuleN : ((IdentifierReference reference, T properties)?)null; } - protected IEnumerable DoGetInspectionResults(QualifiedModuleName module) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) { var finder = DeclarationFinderProvider.DeclarationFinder; return DoGetInspectionResults(module, finder); diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs index b16b67e87d..c2440cde62 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs @@ -45,7 +45,7 @@ protected virtual IEnumerable ObjectionableReferences(Decla protected virtual bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) => true; - protected IEnumerable DoGetInspectionResults(QualifiedModuleName module) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) { var finder = DeclarationFinderProvider.DeclarationFinder; var objectionableReferences = ObjectionableReferences(finder) @@ -112,7 +112,7 @@ protected virtual IEnumerable ObjectionableReferences(Decla .SelectMany(declaration => declaration.References); } - protected IEnumerable DoGetInspectionResults(QualifiedModuleName module) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) { var finder = DeclarationFinderProvider.DeclarationFinder; var objectionableReferences = ObjectionableReferences(finder) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs index 857bd2373e..fbfaed44d0 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs @@ -68,6 +68,7 @@ protected InspectionBase(IDeclarationFinderProvider declarationFinderProvider) public int CompareTo(object obj) => CompareTo(obj as IInspection); protected abstract IEnumerable DoGetInspectionResults(); + protected abstract IEnumerable DoGetInspectionResults(QualifiedModuleName module); /// /// A method that inspects the parser state and returns all issues it can find. @@ -88,6 +89,26 @@ public IEnumerable GetInspectionResults(CancellationToken tok return result; } + /// + /// A method that inspects the parser state and returns all issues in it can find in a module. + /// + /// The module for which to get inspection results + /// + /// + public IEnumerable GetInspectionResults(QualifiedModuleName module, CancellationToken token) + { + var stopwatch = new Stopwatch(); + stopwatch.Start(); + var declarationFinder = DeclarationFinderProvider.DeclarationFinder; + var result = DoGetInspectionResults(module) + .Where(ir => !ir.IsIgnoringInspectionResult(declarationFinder)) + .ToList(); + stopwatch.Stop(); + Logger.Trace("Intercepted invocation of '{0}.{1}' returned {2} objects.", GetType().Name, nameof(DoGetInspectionResults), result.Count); + Logger.Trace("Intercepted invocation of '{0}.{1}' ran for {2}ms", GetType().Name, nameof(DoGetInspectionResults), stopwatch.ElapsedMilliseconds); + return result; + } + public virtual bool ChangesInvalidateResult(IInspectionResult result, ICollection modifiedModules) { return true; diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs index 304570c781..37e0c2ea37 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs @@ -28,7 +28,7 @@ protected override IEnumerable DoGetInspectionResults() return DoGetInspectionResults(Listener.Contexts()); } - private IEnumerable DoGetInspectionResults(QualifiedModuleName module) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) { return DoGetInspectionResults(Listener.Contexts(module)); } @@ -72,7 +72,7 @@ protected override IEnumerable DoGetInspectionResults() return DoGetInspectionResults(Listener.Contexts()); } - private IEnumerable DoGetInspectionResults(QualifiedModuleName module) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) { return DoGetInspectionResults(Listener.Contexts(module)); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs index b4c1f34024..cc73679428 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs @@ -60,7 +60,7 @@ protected override IEnumerable DoGetInspectionResults() .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder)); } - private IEnumerable DoGetInspectionResults(QualifiedModuleName module) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) { var finder = DeclarationFinderProvider.DeclarationFinder; return DoGetInspectionResults(module, finder); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs index 9789682069..7c7fb93f9a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs @@ -70,7 +70,7 @@ protected override IEnumerable DoGetInspectionResults() .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName)); } - private IEnumerable DoGetInspectionResults(QualifiedModuleName module) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) { var finder = DeclarationFinderProvider.DeclarationFinder; return DoGetInspectionResults(module, finder); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs index 2758a142ad..f609c62011 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs @@ -48,7 +48,7 @@ protected override IEnumerable DoGetInspectionResults() .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder)); } - private IEnumerable DoGetInspectionResults(QualifiedModuleName module) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) { var finder = DeclarationFinderProvider.DeclarationFinder; return DoGetInspectionResults(module, finder); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs index 087f0d7b59..9c53d9b6a6 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs @@ -60,7 +60,7 @@ protected override IEnumerable DoGetInspectionResults() .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder)); } - private IEnumerable DoGetInspectionResults(QualifiedModuleName module) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) { var finder = DeclarationFinderProvider.DeclarationFinder; return DoGetInspectionResults(module, finder); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs index 07e22a7571..39c8244853 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs @@ -156,7 +156,7 @@ protected override IEnumerable DoGetInspectionResults() .ToList(); } - private IEnumerable DoGetInspectionResults(QualifiedModuleName module) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) { var finder = DeclarationFinderProvider.DeclarationFinder; return DoGetInspectionResults(module, finder); diff --git a/Rubberduck.Parsing/Inspections/Abstract/IInspection.cs b/Rubberduck.Parsing/Inspections/Abstract/IInspection.cs index 34e5343deb..519cca52b2 100644 --- a/Rubberduck.Parsing/Inspections/Abstract/IInspection.cs +++ b/Rubberduck.Parsing/Inspections/Abstract/IInspection.cs @@ -17,6 +17,14 @@ public interface IInspection : IInspectionModel, IComparable, IComp /// Returns inspection results, if any. IEnumerable GetInspectionResults(CancellationToken token); + /// + /// Runs code inspection for a module and returns inspection results. + /// + /// The module for which to get inspection results + /// + /// + IEnumerable GetInspectionResults(QualifiedModuleName module, CancellationToken token); + /// /// Specifies whether an inspection result is deemed invalid after the specified modules have changed. /// From 03bf899bd5d0fe3f65c3050f6494dd468e6f2d1e Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Thu, 27 Feb 2020 20:36:48 +0100 Subject: [PATCH 261/461] Fix an NRE in UnreachableCaseInspector Also refactors the class a bit and fixes several possible multiple enumeration issues. --- .../UnreachableCaseInspector.cs | 111 ++++++++++-------- 1 file changed, 59 insertions(+), 52 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs index 7e85389685..bcae189c71 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs @@ -11,7 +11,6 @@ public interface IUnreachableCaseInspector { void InspectForUnreachableCases(); string SelectExpressionTypeName { get; } - Func GetVariableDeclarationTypeName { set; get; } List UnreachableCases { get; } List InherentlyUnreachableCases { get; } List MismatchTypeCases { get; } @@ -24,23 +23,22 @@ public class UnreachableCaseInspector : IUnreachableCaseInspector private readonly IEnumerable _caseClauses; private readonly ParserRuleContext _caseElseContext; private readonly IParseTreeValueFactory _valueFactory; + private readonly Func _getVariableDeclarationTypeName; private IParseTreeValue _selectExpressionValue; public UnreachableCaseInspector(VBAParser.SelectCaseStmtContext selectCaseContext, IParseTreeVisitorResults inspValues, IParseTreeValueFactory valueFactory, - Func GetVariableTypeName = null) + Func getVariableTypeName = null) { _valueFactory = valueFactory; _caseClauses = selectCaseContext.caseClause(); _caseElseContext = selectCaseContext.caseElseClause(); - GetVariableDeclarationTypeName = GetVariableTypeName; + _getVariableDeclarationTypeName = getVariableTypeName; ParseTreeValueResults = inspValues; - SetSelectExpressionTypeName(selectCaseContext as ParserRuleContext, inspValues); + SetSelectExpressionTypeName(selectCaseContext, inspValues); } - public Func GetVariableDeclarationTypeName { set; get; } - public List UnreachableCases { set; get; } = new List(); public List MismatchTypeCases { set; get; } = new List(); @@ -53,7 +51,7 @@ public UnreachableCaseInspector(VBAParser.SelectCaseStmtContext selectCaseContex public string SelectExpressionTypeName { private set; get; } = string.Empty; - private IParseTreeVisitorResults ParseTreeValueResults { set; get; } + private IParseTreeVisitorResults ParseTreeValueResults { get; } public void InspectForUnreachableCases() { @@ -71,7 +69,9 @@ public void InspectForUnreachableCases() foreach ( var range in caseClause.rangeClause()) { var childResults = ParseTreeValueResults.GetChildResults(range); - var childValues = childResults.Select(ch => ParseTreeValueResults.GetValue(ch)); + var childValues = childResults + .Select(ch => ParseTreeValueResults.GetValue(ch)) + .ToList(); if (childValues.Any(chr => chr.IsMismatchExpression)) { containsMismatch = true; @@ -136,16 +136,16 @@ private IExpressionFilter BuildRangeClauseFilter(IEnumerable() + .Where(IsResultContext) + .Select(inspValues.GetValueType); caseClauseTypeNames.AddRange(typeNames); caseClauseTypeNames.RemoveAll(tp => !InspectableTypes.Contains(tp)); @@ -198,17 +198,21 @@ where context is ParserRuleContext } } - if (TryGetSelectExpressionTypeNameFromTypes(caseClauseTypeNames, out string evalTypeName)) + if (TryGetSelectExpressionTypeNameFromTypes(caseClauseTypeNames, out var evalTypeName)) { return evalTypeName; } + return string.Empty; } - private static bool TryGetSelectExpressionTypeNameFromTypes(IEnumerable typeNames, out string typeName) + private static bool TryGetSelectExpressionTypeNameFromTypes(ICollection typeNames, out string typeName) { typeName = string.Empty; - if (!typeNames.Any()) { return false; } + if (!typeNames.Any()) + { + return false; + } //If everything is declared as a Variant , we do not attempt to inspect the selectStatement if (typeNames.All(tn => tn.Equals(Tokens.Variant))) @@ -229,7 +233,7 @@ private static bool TryGetSelectExpressionTypeNameFromTypes(IEnumerable return true; } - //Mix of Integertypes and rational number types will be evaluated using Double or Currency + //Mix of Integer types and rational number types will be evaluated using Double or Currency if (typeNames.All(tn => new List() { Tokens.Long, Tokens.Integer, Tokens.Byte, Tokens.Single, Tokens.Double, Tokens.Currency }.Contains(tn))) { typeName = typeNames.Any(tk => tk.Equals(Tokens.Currency)) ? Tokens.Currency : Tokens.Double; @@ -246,7 +250,7 @@ private static bool TryDetectTypeHint(string content, out string typeName) return false; } - if (SymbolList.TypeHintToTypeName.Keys.Any(th => content.EndsWith(th))) + if (SymbolList.TypeHintToTypeName.Keys.Any(content.EndsWith)) { var lastChar = content.Substring(content.Length - 1); typeName = SymbolList.TypeHintToTypeName[lastChar]; @@ -257,9 +261,10 @@ private static bool TryDetectTypeHint(string content, out string typeName) private IRangeClauseExpression GetRangeClauseExpression(VBAParser.RangeClauseContext rangeClause) { - var resultContexts = from ctxt in rangeClause.children - where ctxt is ParserRuleContext && IsResultContext(ctxt) - select ctxt as ParserRuleContext; + var resultContexts = rangeClause.children + .OfType() + .Where(IsResultContext) + .ToList(); if (!resultContexts.Any()) { @@ -272,41 +277,43 @@ private IRangeClauseExpression GetRangeClauseExpression(VBAParser.RangeClauseCon var rangeEndValue = ParseTreeValueResults.GetValue(rangeClause.GetChild()); return new RangeOfValuesExpression((rangeStartValue, rangeEndValue)); } - else if (rangeClause.IS() != null) + + if (rangeClause.IS() != null) { - var clauseValue = ParseTreeValueResults.GetValue(resultContexts.First()); + var isClauseValue = ParseTreeValueResults.GetValue(resultContexts.First()); var opSymbol = rangeClause.GetChild().GetText(); - return new IsClauseExpression(clauseValue, opSymbol); + return new IsClauseExpression(isClauseValue, opSymbol); } - else if (TryGetLogicSymbol(resultContexts.First(), out string symbol)) + + if (!TryGetLogicSymbol(resultContexts.First(), out string symbol)) { - var resultContext = resultContexts.First(); - var clauseValue = ParseTreeValueResults.GetValue(resultContext); - if (clauseValue.ParsesToConstantValue) - { - return new ValueExpression(clauseValue); - } + return new ValueExpression(ParseTreeValueResults.GetValue(resultContexts.First())); + } - if (resultContext is VBAParser.LogicalNotOpContext) - { + var resultContext = resultContexts.First(); + var clauseValue = ParseTreeValueResults.GetValue(resultContext); + if (clauseValue.ParsesToConstantValue) + { + return new ValueExpression(clauseValue); + } + + switch (resultContext) + { + case VBAParser.LogicalNotOpContext _: return new UnaryExpression(clauseValue, symbol); - } - else if (resultContext is VBAParser.RelationalOpContext - || resultContext is VBAParser.LogicalEqvOpContext - || resultContext is VBAParser.LogicalImpOpContext) + case VBAParser.RelationalOpContext _: + case VBAParser.LogicalEqvOpContext _: + case VBAParser.LogicalImpOpContext _: { - (IParseTreeValue lhs, IParseTreeValue rhs) = CreateLogicPair(clauseValue, symbol, _valueFactory); + var (lhs, rhs) = CreateLogicPair(clauseValue, symbol, _valueFactory); if (symbol.Equals(Tokens.Like)) { return new LikeExpression(lhs, rhs); } return new BinaryExpression(lhs, rhs, symbol); } - return null; - } - else - { - return new ValueExpression(ParseTreeValueResults.GetValue(resultContexts.First())); + default: + return null; } } @@ -323,8 +330,8 @@ private static bool TryGetLogicSymbol(ParserRuleContext context, out string opSy private static (IParseTreeValue lhs, IParseTreeValue rhs) CreateLogicPair(IParseTreeValue value, string opSymbol, IParseTreeValueFactory factory) { - var operands = value.Token.Split(new string[] { opSymbol }, StringSplitOptions.None); - if (operands.Count() == 2) + var operands = value.Token.Split(new [] { opSymbol }, StringSplitOptions.None); + if (operands.Length == 2) { var lhs = factory.Create(operands[0].Trim()); var rhs = factory.Create(operands[1].Trim()); @@ -335,7 +342,7 @@ private static (IParseTreeValue lhs, IParseTreeValue rhs) return (lhs, rhs); } - if (operands.Count() == 1) + if (operands.Length == 1) { var lhs = factory.Create(operands[0].Trim()); return (lhs, null); @@ -358,7 +365,7 @@ private static bool IsResultContext(TContext context) || context is VBAParser.SelectEndValueContext; } - private static List InspectableTypes = new List() + private static readonly IReadOnlyList InspectableTypes = new List { Tokens.Byte, Tokens.Integer, From 9fed0b3c72442b1e66fe2bc14024a10fd96c484c Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Thu, 27 Feb 2020 22:04:19 +0100 Subject: [PATCH 262/461] Add RequiredArguments to IAnnotation It specifies the minimal number of arguments for the annotation. --- .../Annotations/AnnotationBase.cs | 4 +++- .../FixedAttributeValueAnnotationBase.cs | 21 ++++++++----------- .../FlexibleAttributeAnnotationBase.cs | 6 ++---- .../FlexibleAttributeValueAnnotationBase.cs | 4 +--- .../Annotations/Concrete/FolderAnnotation.cs | 11 +++------- .../Annotations/Concrete/IgnoreAnnotation.cs | 11 +++------- .../Concrete/IgnoreModuleAnnotation.cs | 11 +++------- .../Concrete/IgnoreTestAnnotation.cs | 6 +----- .../Concrete/InterfaceAnnotation.cs | 2 +- .../Concrete/ModuleCleanupAnnotation.cs | 8 ++----- .../Concrete/ModuleInitializeAnnotation.cs | 8 ++----- .../Concrete/NoIndentAnnotation.cs | 2 +- .../Concrete/NotRecognizedAnnotation.cs | 8 ++----- .../Concrete/ObsoleteAnnotation.cs | 17 ++++++++++----- .../Concrete/TestCleanupAnnotation.cs | 9 ++------ .../Concrete/TestInitializeAnnotation.cs | 6 +----- .../Concrete/TestMethodAnnotation.cs | 7 ++----- .../Concrete/TestModuleAnnotation.cs | 8 ++----- Rubberduck.Parsing/Annotations/IAnnotation.cs | 13 ++++++++++++ .../Annotations/ParseTreeAnnotation.cs | 2 -- 20 files changed, 65 insertions(+), 99 deletions(-) diff --git a/Rubberduck.Parsing/Annotations/AnnotationBase.cs b/Rubberduck.Parsing/Annotations/AnnotationBase.cs index 076e7c5a02..9eee9a09f0 100644 --- a/Rubberduck.Parsing/Annotations/AnnotationBase.cs +++ b/Rubberduck.Parsing/Annotations/AnnotationBase.cs @@ -6,14 +6,16 @@ namespace Rubberduck.Parsing.Annotations public abstract class AnnotationBase : IAnnotation { public bool AllowMultiple { get; } + public int RequiredArguments { get; } public string Name { get; } public AnnotationTarget Target { get; } - protected AnnotationBase(string name, AnnotationTarget target, bool allowMultiple = false) + protected AnnotationBase(string name, AnnotationTarget target, int requiredArguments = 0, bool allowMultiple = false) { Name = name; Target = target; AllowMultiple = allowMultiple; + RequiredArguments = requiredArguments; } public virtual IReadOnlyList ProcessAnnotationArguments(IEnumerable arguments) diff --git a/Rubberduck.Parsing/Annotations/Concrete/FixedAttributeValueAnnotationBase.cs b/Rubberduck.Parsing/Annotations/Concrete/FixedAttributeValueAnnotationBase.cs index 901475a37f..6e7d1faabd 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/FixedAttributeValueAnnotationBase.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/FixedAttributeValueAnnotationBase.cs @@ -1,32 +1,29 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; -using Rubberduck.Parsing.Grammar; -using Rubberduck.VBEditor; namespace Rubberduck.Parsing.Annotations { public abstract class FixedAttributeValueAnnotationBase : AnnotationBase, IAttributeAnnotation { - private readonly string attribute; - private readonly IReadOnlyList attributeValues; + private readonly string _attribute; + private readonly IReadOnlyList _attributeValues; protected FixedAttributeValueAnnotationBase(string name, AnnotationTarget target, string attribute, IEnumerable attributeValues, bool allowMultiple = false) - : base(name, target, allowMultiple) + : base(name, target, allowMultiple: allowMultiple) { // IEnumerable makes specifying the compile-time constant list easier on us - this.attributeValues = attributeValues.ToList(); - this.attribute = attribute; + _attributeValues = attributeValues.ToList(); + _attribute = attribute; } public IReadOnlyList AnnotationToAttributeValues(IReadOnlyList annotationValues) { - return attributeValues; + return _attributeValues; } public string Attribute(IReadOnlyList annotationValues) { - return attribute; + return _attribute; } public IReadOnlyList AttributeToAnnotationValues(IReadOnlyList attributeValues) @@ -37,7 +34,7 @@ public IReadOnlyList AttributeToAnnotationValues(IReadOnlyList a public bool MatchesAttributeDefinition(string attributeName, IReadOnlyList attributeValues) { - return attribute == attributeName && this.attributeValues.SequenceEqual(attributeValues); + return _attribute == attributeName && this._attributeValues.SequenceEqual(attributeValues); } } } \ No newline at end of file diff --git a/Rubberduck.Parsing/Annotations/Concrete/FlexibleAttributeAnnotationBase.cs b/Rubberduck.Parsing/Annotations/Concrete/FlexibleAttributeAnnotationBase.cs index f440c52795..163fba354f 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/FlexibleAttributeAnnotationBase.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/FlexibleAttributeAnnotationBase.cs @@ -1,16 +1,14 @@ using System.Collections.Generic; using System.Linq; using Rubberduck.Common; -using Rubberduck.Parsing.Grammar; -using Rubberduck.VBEditor; namespace Rubberduck.Parsing.Annotations { public abstract class FlexibleAttributeAnnotationBase : AnnotationBase, IAttributeAnnotation { protected FlexibleAttributeAnnotationBase(string name, AnnotationTarget target, bool allowMultiple = false) - : base(name, target, allowMultiple) - { } + : base(name, target, 2, allowMultiple) //We need at least the attribute name and one value for it. + {} public IReadOnlyList AnnotationToAttributeValues(IReadOnlyList annotationValues) { diff --git a/Rubberduck.Parsing/Annotations/Concrete/FlexibleAttributeValueAnnotationBase.cs b/Rubberduck.Parsing/Annotations/Concrete/FlexibleAttributeValueAnnotationBase.cs index f01b17a69b..22cbac1f5f 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/FlexibleAttributeValueAnnotationBase.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/FlexibleAttributeValueAnnotationBase.cs @@ -2,8 +2,6 @@ using System.Collections.Generic; using System.Linq; using Rubberduck.Common; -using Rubberduck.Parsing.Grammar; -using Rubberduck.VBEditor; namespace Rubberduck.Parsing.Annotations { @@ -13,7 +11,7 @@ public abstract class FlexibleAttributeValueAnnotationBase : AnnotationBase, IAt private readonly int _numberOfValues; protected FlexibleAttributeValueAnnotationBase(string name, AnnotationTarget target, string attribute, int numberOfValues) - : base(name, target) + : base(name, target, numberOfValues) { _attribute = attribute; _numberOfValues = numberOfValues; diff --git a/Rubberduck.Parsing/Annotations/Concrete/FolderAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/FolderAnnotation.cs index 85bcc0c611..13cc21fa02 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/FolderAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/FolderAnnotation.cs @@ -1,9 +1,4 @@ -using Rubberduck.VBEditor; -using System.Collections.Generic; -using System.Linq; -using Rubberduck.Parsing.Grammar; - -namespace Rubberduck.Parsing.Annotations +namespace Rubberduck.Parsing.Annotations { /// /// Used for specifying the Code Explorer folder a appears under. @@ -11,7 +6,7 @@ namespace Rubberduck.Parsing.Annotations public sealed class FolderAnnotation : AnnotationBase { public FolderAnnotation() - : base("Folder", AnnotationTarget.Module) - { } + : base("Folder", AnnotationTarget.Module, 1) + {} } } diff --git a/Rubberduck.Parsing/Annotations/Concrete/IgnoreAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/IgnoreAnnotation.cs index bacb9cf0e8..b21dad15c0 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/IgnoreAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/IgnoreAnnotation.cs @@ -1,9 +1,4 @@ -using Rubberduck.VBEditor; -using System.Collections.Generic; -using System.Linq; -using Rubberduck.Parsing.Grammar; - -namespace Rubberduck.Parsing.Annotations +namespace Rubberduck.Parsing.Annotations { /// /// Used for ignoring specific inspection results from a specified set of inspections. @@ -11,7 +6,7 @@ namespace Rubberduck.Parsing.Annotations public sealed class IgnoreAnnotation : AnnotationBase { public IgnoreAnnotation() - : base("Ignore", AnnotationTarget.General, true) - { } + : base("Ignore", AnnotationTarget.General, 1, true) + {} } } diff --git a/Rubberduck.Parsing/Annotations/Concrete/IgnoreModuleAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/IgnoreModuleAnnotation.cs index 7a73829931..9f8804bd36 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/IgnoreModuleAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/IgnoreModuleAnnotation.cs @@ -1,9 +1,4 @@ -using System.Collections.Generic; -using System.Linq; -using Rubberduck.Parsing.Grammar; -using Rubberduck.VBEditor; - -namespace Rubberduck.Parsing.Annotations +namespace Rubberduck.Parsing.Annotations { /// /// This annotation allows ignoring inspection results of defined inspections for a whole module @@ -11,7 +6,7 @@ namespace Rubberduck.Parsing.Annotations public sealed class IgnoreModuleAnnotation : AnnotationBase { public IgnoreModuleAnnotation() - : base("IgnoreModule", AnnotationTarget.Module, true) - { } + : base("IgnoreModule", AnnotationTarget.Module, 1, true) + {} } } \ No newline at end of file diff --git a/Rubberduck.Parsing/Annotations/Concrete/IgnoreTestAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/IgnoreTestAnnotation.cs index 747e1a73af..3bcdda9422 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/IgnoreTestAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/IgnoreTestAnnotation.cs @@ -1,8 +1,4 @@ -using System.Collections.Generic; -using Rubberduck.Parsing.Grammar; -using Rubberduck.VBEditor; - -namespace Rubberduck.Parsing.Annotations +namespace Rubberduck.Parsing.Annotations { /// /// Used to indicate the test engine that a unit test is to be ignored. diff --git a/Rubberduck.Parsing/Annotations/Concrete/InterfaceAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/InterfaceAnnotation.cs index 1c526737c1..664ee683aa 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/InterfaceAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/InterfaceAnnotation.cs @@ -7,6 +7,6 @@ public sealed class InterfaceAnnotation : AnnotationBase { public InterfaceAnnotation() : base("Interface", AnnotationTarget.Module) - { } + {} } } \ No newline at end of file diff --git a/Rubberduck.Parsing/Annotations/Concrete/ModuleCleanupAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/ModuleCleanupAnnotation.cs index b0b0253e04..d433b4d162 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/ModuleCleanupAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/ModuleCleanupAnnotation.cs @@ -1,8 +1,4 @@ -using Rubberduck.VBEditor; -using System.Collections.Generic; -using Rubberduck.Parsing.Grammar; - -namespace Rubberduck.Parsing.Annotations +namespace Rubberduck.Parsing.Annotations { /// /// Marks a method that the test engine will execute after all unit tests in a test module have executed. @@ -11,6 +7,6 @@ public sealed class ModuleCleanupAnnotation : AnnotationBase, ITestAnnotation { public ModuleCleanupAnnotation() : base("ModuleCleanup", AnnotationTarget.Member) - { } + {} } } diff --git a/Rubberduck.Parsing/Annotations/Concrete/ModuleInitializeAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/ModuleInitializeAnnotation.cs index 6ed55372ce..2a6ed07564 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/ModuleInitializeAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/ModuleInitializeAnnotation.cs @@ -1,8 +1,4 @@ -using Rubberduck.VBEditor; -using System.Collections.Generic; -using Rubberduck.Parsing.Grammar; - -namespace Rubberduck.Parsing.Annotations +namespace Rubberduck.Parsing.Annotations { /// /// Marks a method that the test engine will execute before executing the first unit test in a test module. @@ -11,6 +7,6 @@ public sealed class ModuleInitializeAnnotation : AnnotationBase, ITestAnnotation { public ModuleInitializeAnnotation() : base("ModuleInitialize", AnnotationTarget.Member) - { } + {} } } diff --git a/Rubberduck.Parsing/Annotations/Concrete/NoIndentAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/NoIndentAnnotation.cs index 4b85464ec4..516005a4a6 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/NoIndentAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/NoIndentAnnotation.cs @@ -7,6 +7,6 @@ public sealed class NoIndentAnnotation : AnnotationBase { public NoIndentAnnotation() : base("NoIndent", AnnotationTarget.Module) - { } + {} } } diff --git a/Rubberduck.Parsing/Annotations/Concrete/NotRecognizedAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/NotRecognizedAnnotation.cs index 8c5e12d81f..599b8759b4 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/NotRecognizedAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/NotRecognizedAnnotation.cs @@ -1,8 +1,4 @@ -using Rubberduck.VBEditor; -using System.Collections.Generic; -using Rubberduck.Parsing.Grammar; - -namespace Rubberduck.Parsing.Annotations +namespace Rubberduck.Parsing.Annotations { /// /// Used for all annotations not recognized by RD. @@ -12,6 +8,6 @@ public sealed class NotRecognizedAnnotation : AnnotationBase { public NotRecognizedAnnotation() : base("NotRecognized", 0) - { } + {} } } \ No newline at end of file diff --git a/Rubberduck.Parsing/Annotations/Concrete/ObsoleteAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/ObsoleteAnnotation.cs index d7112303c3..e8fb064a53 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/ObsoleteAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/ObsoleteAnnotation.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.Parsing.Grammar; -using Rubberduck.VBEditor; namespace Rubberduck.Parsing.Annotations { @@ -10,12 +8,21 @@ namespace Rubberduck.Parsing.Annotations /// public sealed class ObsoleteAnnotation : AnnotationBase { - public string ReplacementDocumentation { get; } + public string ReplacementDocumentation { get; private set; } public ObsoleteAnnotation() : base("Obsolete", AnnotationTarget.Member | AnnotationTarget.Variable) - { } + {} - // FIXME correctly handle the fact that the replacement documentation is only the first parameter! + public override IReadOnlyList ProcessAnnotationArguments(IEnumerable arguments) + { + var args = arguments.ToList(); + + ReplacementDocumentation = args.Any() + ? args[0] + : string.Empty; + + return base.ProcessAnnotationArguments(args); + } } } \ No newline at end of file diff --git a/Rubberduck.Parsing/Annotations/Concrete/TestCleanupAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/TestCleanupAnnotation.cs index 943f396564..d99184cf9a 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/TestCleanupAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/TestCleanupAnnotation.cs @@ -1,8 +1,4 @@ -using Rubberduck.VBEditor; -using System.Collections.Generic; -using Rubberduck.Parsing.Grammar; - -namespace Rubberduck.Parsing.Annotations +namespace Rubberduck.Parsing.Annotations { /// /// Marks a method that the test engine will execute after executing each unit test in a test module. @@ -11,7 +7,6 @@ public sealed class TestCleanupAnnotation : AnnotationBase, ITestAnnotation { public TestCleanupAnnotation() : base("TestCleanup", AnnotationTarget.Member) - { - } + {} } } diff --git a/Rubberduck.Parsing/Annotations/Concrete/TestInitializeAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/TestInitializeAnnotation.cs index 6c0124f747..95a51bde6e 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/TestInitializeAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/TestInitializeAnnotation.cs @@ -1,8 +1,4 @@ -using Rubberduck.VBEditor; -using System.Collections.Generic; -using Rubberduck.Parsing.Grammar; - -namespace Rubberduck.Parsing.Annotations +namespace Rubberduck.Parsing.Annotations { /// /// Marks a method that the test engine will execute before executing each unit test in a test module. diff --git a/Rubberduck.Parsing/Annotations/Concrete/TestMethodAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/TestMethodAnnotation.cs index 55541052d0..223e775fc0 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/TestMethodAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/TestMethodAnnotation.cs @@ -1,8 +1,5 @@ -using System; -using Rubberduck.VBEditor; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; -using Rubberduck.Parsing.Grammar; using Rubberduck.Common; namespace Rubberduck.Parsing.Annotations @@ -14,7 +11,7 @@ public sealed class TestMethodAnnotation : AnnotationBase, ITestAnnotation { public TestMethodAnnotation() : base("TestMethod", AnnotationTarget.Member) - { } + {} public IReadOnlyList ProcessAnnotationArguments(IEnumerable arguments) { diff --git a/Rubberduck.Parsing/Annotations/Concrete/TestModuleAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/TestModuleAnnotation.cs index 4faa351d8a..fb89d38349 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/TestModuleAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/TestModuleAnnotation.cs @@ -1,8 +1,4 @@ -using Rubberduck.VBEditor; -using System.Collections.Generic; -using Rubberduck.Parsing.Grammar; - -namespace Rubberduck.Parsing.Annotations +namespace Rubberduck.Parsing.Annotations { /// /// Marks a module that the test engine treat as a test module. @@ -14,6 +10,6 @@ public sealed class TestModuleAnnotation : AnnotationBase { public TestModuleAnnotation() : base("TestModule", AnnotationTarget.Module) - { } + {} } } diff --git a/Rubberduck.Parsing/Annotations/IAnnotation.cs b/Rubberduck.Parsing/Annotations/IAnnotation.cs index 84139d0bfb..6e62d0b7a8 100644 --- a/Rubberduck.Parsing/Annotations/IAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/IAnnotation.cs @@ -6,9 +6,22 @@ namespace Rubberduck.Parsing.Annotations public interface IAnnotation { string Name { get; } + + /// + /// The kind of object this annotation can be applied to + /// AnnotationTarget Target { get; } + + /// + /// Specifies whether there can be multiple instances of the annotation on the same target. + /// bool AllowMultiple { get; } + /// + /// The minimal number of arguments that must be provided to for this annotation + /// + int RequiredArguments { get; } + IReadOnlyList ProcessAnnotationArguments(IEnumerable arguments); } diff --git a/Rubberduck.Parsing/Annotations/ParseTreeAnnotation.cs b/Rubberduck.Parsing/Annotations/ParseTreeAnnotation.cs index 2455152416..9992334d4d 100644 --- a/Rubberduck.Parsing/Annotations/ParseTreeAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/ParseTreeAnnotation.cs @@ -3,8 +3,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Rubberduck.Parsing.Annotations { From 8c2fae86804ca97aac52d673711847bceb61777a Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Thu, 27 Feb 2020 23:12:37 +0100 Subject: [PATCH 263/461] Make MissingAnnotationArguments use only the annotations Also adds an overload of DeclarationFinder.FindAnnotations providing all annotations in a module. IllegalAnnotationInspection now uses this in favor of RubberduckParserState.GetAnnotations, which allows to remove the dependency on the state. --- .../Concrete/IllegalAnnotationInspection.cs | 12 +-- .../MissingAnnotationArgumentInspection.cs | 75 +++++++++++-------- .../QuickFixes/IgnoreOnceQuickFix.cs | 6 +- .../DeclarationCaching/DeclarationFinder.cs | 21 +++++- 4 files changed, 68 insertions(+), 46 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs index cc73679428..20e988c7cd 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs @@ -43,13 +43,9 @@ namespace Rubberduck.Inspections.Concrete /// public sealed class IllegalAnnotationInspection : InspectionBase { - private readonly RubberduckParserState _state; - - public IllegalAnnotationInspection(RubberduckParserState state) - : base(state) - { - _state = state; - } + public IllegalAnnotationInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} protected override IEnumerable DoGetInspectionResults() { @@ -70,7 +66,7 @@ private IEnumerable DoGetInspectionResults(QualifiedModuleNam { var userDeclarations = finder.Members(module).ToList(); var identifierReferences = finder.IdentifierReferences(module).ToList(); - var annotations = _state.GetAnnotations(module); + var annotations = finder.FindAnnotations(module); var unboundAnnotations = UnboundAnnotations(annotations, userDeclarations, identifierReferences) .Where(annotation => !annotation.Annotation.Target.HasFlag(AnnotationTarget.General) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs index d4e76e81b7..fa55df7562 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs @@ -1,11 +1,15 @@ -using Antlr4.Runtime; +using System.Collections.Generic; +using System.Linq; using Rubberduck.Inspections.Abstract; +using Rubberduck.Inspections.Results; using Rubberduck.Parsing; -using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Parsing.Symbols; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.VBA.Parsing; +using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete { @@ -31,48 +35,57 @@ namespace Rubberduck.Inspections.Concrete /// ' ... /// ]]> /// - public sealed class MissingAnnotationArgumentInspection : ParseTreeInspectionBase + public sealed class MissingAnnotationArgumentInspection : InspectionBase { - private readonly RubberduckParserState _state; + public MissingAnnotationArgumentInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} - public MissingAnnotationArgumentInspection(RubberduckParserState state) - : base(state) + protected override IEnumerable DoGetInspectionResults() { - _state = state; + var finder = DeclarationFinderProvider.DeclarationFinder; + + return finder.UserDeclarations(DeclarationType.Module) + .Where(module => module != null) + .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder)) + .ToList(); } - public override CodeKind TargetKindOfCode => CodeKind.AttributesCode; + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) + { + var finder = DeclarationFinderProvider.DeclarationFinder; + return DoGetInspectionResults(module, finder); + } + + private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + { + var objectionableAnnotations = finder.FindAnnotations(module) + .Where(IsResultAnnotation); - public override IInspectionListener Listener { get; } = - new InvalidAnnotationStatementListener(); + return objectionableAnnotations + .Select(InspectionResult) + .ToList(); + } - protected override string ResultDescription(QualifiedContext context) + private static bool IsResultAnnotation(IParseTreeAnnotation pta) { - var expressionText = ((VBAParser.AnnotationContext) context.Context).annotationName().GetText(); - return string.Format( - InspectionResults.MissingAnnotationArgumentInspection, - expressionText); + return pta.Annotation.RequiredArguments > pta.AnnotationArguments.Count; } - protected override bool IsResultContext(QualifiedContext context) + private IInspectionResult InspectionResult(IParseTreeAnnotation pta) { - // FIXME don't actually use listeners here, iterate the Annotations instead - // FIXME don't maintain a separate list for annotations that require arguments, instead use AnnotationAttribute to store that information - var annotationContext = (VBAParser.AnnotationContext) context.Context; - return (annotationContext.annotationName().GetText() == "Ignore" - || annotationContext.annotationName().GetText() == "Folder") - && annotationContext.annotationArgList() == null; + var qualifiedContext = new QualifiedContext(pta.QualifiedSelection.QualifiedName, pta.Context); + return new QualifiedContextInspectionResult( + this, + ResultDescription(pta), + qualifiedContext); } - public class InvalidAnnotationStatementListener : InspectionListenerBase + private static string ResultDescription(IParseTreeAnnotation pta) { - public override void ExitAnnotation(VBAParser.AnnotationContext context) - { - if (context.annotationName() != null) - { - SaveContext(context); - } - } + return string.Format( + InspectionResults.MissingAnnotationArgumentInspection, + pta.Annotation.Name); } } } diff --git a/Rubberduck.CodeAnalysis/QuickFixes/IgnoreOnceQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/IgnoreOnceQuickFix.cs index ddea996549..f066084850 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/IgnoreOnceQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/IgnoreOnceQuickFix.cs @@ -68,9 +68,9 @@ private void FixNonModule(IInspectionResult result, IRewriteSession rewriteSessi { var module = result.QualifiedSelection.QualifiedName; var lineToAnnotate = result.QualifiedSelection.Selection.StartLine; - var existingIgnoreAnnotation = _state.DeclarationFinder.FindAnnotations(module, lineToAnnotate) - .Where(pta => pta.Annotation is IgnoreAnnotation) - .FirstOrDefault(); + var existingIgnoreAnnotation = _state.DeclarationFinder + .FindAnnotations(module, lineToAnnotate) + .FirstOrDefault(pta => pta.Annotation is IgnoreAnnotation); var annotationInfo = new IgnoreAnnotation(); if (existingIgnoreAnnotation != null) diff --git a/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs b/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs index f745f96be1..5b5ee86114 100644 --- a/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs +++ b/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs @@ -31,7 +31,7 @@ public class DeclarationFinder private readonly ConcurrentDictionary _newFailedResolutionStores; private readonly ConcurrentDictionary<(QualifiedMemberName memberName, DeclarationType declarationType), ConcurrentBag> _newUndeclared; - private IDictionary<(QualifiedModuleName module, int annotatedLine), List> _annotations; + private IDictionary>> _annotations; private IDictionary> _parametersByParent; private IDictionary> _userDeclarationsByType; @@ -97,8 +97,9 @@ private List CollectionConstructionActions(IReadOnlyList de { () => _annotations = annotations - .Where(a => a.AnnotatedLine.HasValue) - .GroupBy(a => (a.QualifiedSelection.QualifiedName, a.AnnotatedLine.Value)) + .GroupBy(annotation => annotation.QualifiedSelection.QualifiedName) + .SelectMany(grp1 => grp1.GroupBy(annotation => annotation.AnnotatedLine.GetValueOrDefault(-1)), (grp1, grp2) => (grp1, grp2)) + .GroupBy(tpl => tpl.grp1.Key, tpl => tpl.grp2) .ToDictionary(), () => _declarations = declarations @@ -518,11 +519,23 @@ public IEnumerable FindMemberMatches(Declaration parent, string mem public IEnumerable FindAnnotations(QualifiedModuleName module, int annotatedLine) { - return _annotations.TryGetValue((module, annotatedLine), out var result) + if(!_annotations.TryGetValue(module, out var annotationsByLineInModule)) + { + return Enumerable.Empty(); + } + + return annotationsByLineInModule.TryGetValue(annotatedLine, out var result) ? result : Enumerable.Empty(); } + public IEnumerable FindAnnotations(QualifiedModuleName module) + { + return _annotations.TryGetValue(module, out var annotationsByLineInModule) + ? annotationsByLineInModule.AllValues() + : Enumerable.Empty(); + } + public IEnumerable FindAnnotations(QualifiedModuleName module, int annotatedLine, Type annotationType) { return FindAnnotations(module, annotatedLine).Where(pta => pta.Annotation.GetType() == annotationType); From d21dacf2f5e1f2770324458d12fd20c1dab7b3e3 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Thu, 27 Feb 2020 23:38:51 +0100 Subject: [PATCH 264/461] Unquote the replacement documentation on ObsoleteAnnotation --- Rubberduck.Parsing/Annotations/Concrete/ObsoleteAnnotation.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Rubberduck.Parsing/Annotations/Concrete/ObsoleteAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/ObsoleteAnnotation.cs index e8fb064a53..6cc8bcaa31 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/ObsoleteAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/ObsoleteAnnotation.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.Common; namespace Rubberduck.Parsing.Annotations { @@ -19,7 +20,7 @@ public override IReadOnlyList ProcessAnnotationArguments(IEnumerable Date: Fri, 28 Feb 2020 01:38:32 +0100 Subject: [PATCH 265/461] Add SuperfluousAnnotationArgumentsInspection Also add allowed number of arguments to IAnnotation interface. --- .../MissingAnnotationArgumentInspection.cs | 4 +- ...SuperfluousAnnotationArgumentInspection.cs | 93 +++++++++++++++++++ .../Annotations/AnnotationBase.cs | 4 +- .../FlexibleAttributeAnnotationBase.cs | 2 +- .../FlexibleAttributeValueAnnotationBase.cs | 5 +- .../Annotations/Concrete/FolderAnnotation.cs | 2 +- .../Annotations/Concrete/IgnoreAnnotation.cs | 2 +- .../Concrete/IgnoreModuleAnnotation.cs | 2 +- .../Concrete/IgnoreTestAnnotation.cs | 4 +- .../Concrete/ObsoleteAnnotation.cs | 2 +- .../Concrete/TestInitializeAnnotation.cs | 2 +- Rubberduck.Parsing/Annotations/IAnnotation.cs | 5 + .../Inspections/InspectionInfo.Designer.cs | 9 ++ .../Inspections/InspectionInfo.de.resx | 5 +- .../Inspections/InspectionInfo.resx | 3 + .../Inspections/InspectionNames.Designer.cs | 9 ++ .../Inspections/InspectionNames.de.resx | 3 + .../Inspections/InspectionNames.resx | 3 + .../Inspections/InspectionResults.Designer.cs | 11 ++- .../Inspections/InspectionResults.de.resx | 5 +- .../Inspections/InspectionResults.resx | 7 +- ...issingAnnotationArgumentInspectionTests.cs | 61 ++++++++++++ ...fluousAnnotationArgumentInspectionTests.cs | 62 +++++++++++++ 23 files changed, 287 insertions(+), 18 deletions(-) create mode 100644 Rubberduck.CodeAnalysis/Inspections/Concrete/SuperfluousAnnotationArgumentInspection.cs create mode 100644 RubberduckTests/Inspections/MissingAnnotationArgumentInspectionTests.cs create mode 100644 RubberduckTests/Inspections/SuperfluousAnnotationArgumentInspectionTests.cs diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs index fa55df7562..31cdf70cfd 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs @@ -14,10 +14,10 @@ namespace Rubberduck.Inspections.Concrete { /// - /// Warns about a malformed Rubberduck annotation that is missing an argument. + /// Warns about a malformed Rubberduck annotation that is missing one or more arguments. /// /// - /// Some annotations require arguments; if the argument isn't specified, the annotation is nothing more than an obscure comment. + /// Some annotations require arguments; if the required number of arguments isn't specified, the annotation is nothing more than an obscure comment. /// /// /// + /// Warns about Rubberduck annotations with more arguments than allowed. + /// + /// + /// Most annotations only process a limited number of arguments; superfluous arguments are ignored. + /// + /// + /// + /// + /// + /// + /// + public sealed class SuperfluousAnnotationArgumentInspection : InspectionBase + { + public SuperfluousAnnotationArgumentInspection(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} + + protected override IEnumerable DoGetInspectionResults() + { + var finder = DeclarationFinderProvider.DeclarationFinder; + + return finder.UserDeclarations(DeclarationType.Module) + .Where(module => module != null) + .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder)) + .ToList(); + } + + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) + { + var finder = DeclarationFinderProvider.DeclarationFinder; + return DoGetInspectionResults(module, finder); + } + + private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + { + var objectionableAnnotations = finder.FindAnnotations(module) + .Where(IsResultAnnotation); + + return objectionableAnnotations + .Select(InspectionResult) + .ToList(); + } + + private static bool IsResultAnnotation(IParseTreeAnnotation pta) + { + var allowedArguments = pta.Annotation.AllowedArguments; + return allowedArguments.HasValue && allowedArguments.Value < pta.AnnotationArguments.Count; + } + + private IInspectionResult InspectionResult(IParseTreeAnnotation pta) + { + var qualifiedContext = new QualifiedContext(pta.QualifiedSelection.QualifiedName, pta.Context); + return new QualifiedContextInspectionResult( + this, + ResultDescription(pta), + qualifiedContext); + } + + private static string ResultDescription(IParseTreeAnnotation pta) + { + return string.Format( + InspectionResults.SuperfluousAnnotationArgumentInspection, + pta.Annotation.Name); + } + } +} diff --git a/Rubberduck.Parsing/Annotations/AnnotationBase.cs b/Rubberduck.Parsing/Annotations/AnnotationBase.cs index 9eee9a09f0..52614ec88e 100644 --- a/Rubberduck.Parsing/Annotations/AnnotationBase.cs +++ b/Rubberduck.Parsing/Annotations/AnnotationBase.cs @@ -7,15 +7,17 @@ public abstract class AnnotationBase : IAnnotation { public bool AllowMultiple { get; } public int RequiredArguments { get; } + public int? AllowedArguments { get; } public string Name { get; } public AnnotationTarget Target { get; } - protected AnnotationBase(string name, AnnotationTarget target, int requiredArguments = 0, bool allowMultiple = false) + protected AnnotationBase(string name, AnnotationTarget target, int requiredArguments = 0, int? allowedArguments = 0, bool allowMultiple = false) { Name = name; Target = target; AllowMultiple = allowMultiple; RequiredArguments = requiredArguments; + AllowedArguments = allowedArguments; } public virtual IReadOnlyList ProcessAnnotationArguments(IEnumerable arguments) diff --git a/Rubberduck.Parsing/Annotations/Concrete/FlexibleAttributeAnnotationBase.cs b/Rubberduck.Parsing/Annotations/Concrete/FlexibleAttributeAnnotationBase.cs index 163fba354f..dca41c6827 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/FlexibleAttributeAnnotationBase.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/FlexibleAttributeAnnotationBase.cs @@ -7,7 +7,7 @@ namespace Rubberduck.Parsing.Annotations public abstract class FlexibleAttributeAnnotationBase : AnnotationBase, IAttributeAnnotation { protected FlexibleAttributeAnnotationBase(string name, AnnotationTarget target, bool allowMultiple = false) - : base(name, target, 2, allowMultiple) //We need at least the attribute name and one value for it. + : base(name, target, 2, null, allowMultiple) //We need at least the attribute name and one value for it. {} public IReadOnlyList AnnotationToAttributeValues(IReadOnlyList annotationValues) diff --git a/Rubberduck.Parsing/Annotations/Concrete/FlexibleAttributeValueAnnotationBase.cs b/Rubberduck.Parsing/Annotations/Concrete/FlexibleAttributeValueAnnotationBase.cs index 22cbac1f5f..141e4f5b87 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/FlexibleAttributeValueAnnotationBase.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/FlexibleAttributeValueAnnotationBase.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using Rubberduck.Common; @@ -11,7 +10,7 @@ public abstract class FlexibleAttributeValueAnnotationBase : AnnotationBase, IAt private readonly int _numberOfValues; protected FlexibleAttributeValueAnnotationBase(string name, AnnotationTarget target, string attribute, int numberOfValues) - : base(name, target, numberOfValues) + : base(name, target, numberOfValues, numberOfValues) { _attribute = attribute; _numberOfValues = numberOfValues; diff --git a/Rubberduck.Parsing/Annotations/Concrete/FolderAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/FolderAnnotation.cs index 13cc21fa02..ea8200337f 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/FolderAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/FolderAnnotation.cs @@ -6,7 +6,7 @@ public sealed class FolderAnnotation : AnnotationBase { public FolderAnnotation() - : base("Folder", AnnotationTarget.Module, 1) + : base("Folder", AnnotationTarget.Module, 1, 1) {} } } diff --git a/Rubberduck.Parsing/Annotations/Concrete/IgnoreAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/IgnoreAnnotation.cs index b21dad15c0..736a0d6b3a 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/IgnoreAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/IgnoreAnnotation.cs @@ -6,7 +6,7 @@ public sealed class IgnoreAnnotation : AnnotationBase { public IgnoreAnnotation() - : base("Ignore", AnnotationTarget.General, 1, true) + : base("Ignore", AnnotationTarget.General, 1, null, true) {} } } diff --git a/Rubberduck.Parsing/Annotations/Concrete/IgnoreModuleAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/IgnoreModuleAnnotation.cs index 9f8804bd36..70c9a3902e 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/IgnoreModuleAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/IgnoreModuleAnnotation.cs @@ -6,7 +6,7 @@ public sealed class IgnoreModuleAnnotation : AnnotationBase { public IgnoreModuleAnnotation() - : base("IgnoreModule", AnnotationTarget.Module, 1, true) + : base("IgnoreModule", AnnotationTarget.Module, allowedArguments: null, allowMultiple: true) {} } } \ No newline at end of file diff --git a/Rubberduck.Parsing/Annotations/Concrete/IgnoreTestAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/IgnoreTestAnnotation.cs index 3bcdda9422..0a788bdecd 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/IgnoreTestAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/IgnoreTestAnnotation.cs @@ -6,7 +6,7 @@ public sealed class IgnoreTestAnnotation : AnnotationBase { public IgnoreTestAnnotation() - : base("IgnoreTest", AnnotationTarget.Member) - { } + : base("IgnoreTest", AnnotationTarget.Member, allowedArguments: 1) + {} } } \ No newline at end of file diff --git a/Rubberduck.Parsing/Annotations/Concrete/ObsoleteAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/ObsoleteAnnotation.cs index 6cc8bcaa31..c5a3afe90b 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/ObsoleteAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/ObsoleteAnnotation.cs @@ -12,7 +12,7 @@ public sealed class ObsoleteAnnotation : AnnotationBase public string ReplacementDocumentation { get; private set; } public ObsoleteAnnotation() - : base("Obsolete", AnnotationTarget.Member | AnnotationTarget.Variable) + : base("Obsolete", AnnotationTarget.Member | AnnotationTarget.Variable, allowedArguments: 1) {} public override IReadOnlyList ProcessAnnotationArguments(IEnumerable arguments) diff --git a/Rubberduck.Parsing/Annotations/Concrete/TestInitializeAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/TestInitializeAnnotation.cs index 95a51bde6e..b028245dc5 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/TestInitializeAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/TestInitializeAnnotation.cs @@ -7,6 +7,6 @@ public sealed class TestInitializeAnnotation : AnnotationBase, ITestAnnotation { public TestInitializeAnnotation() : base("TestInitialize", AnnotationTarget.Member) - { } + {} } } diff --git a/Rubberduck.Parsing/Annotations/IAnnotation.cs b/Rubberduck.Parsing/Annotations/IAnnotation.cs index 6e62d0b7a8..d205abf1ae 100644 --- a/Rubberduck.Parsing/Annotations/IAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/IAnnotation.cs @@ -22,6 +22,11 @@ public interface IAnnotation /// int RequiredArguments { get; } + /// + /// The maximal number of arguments that must be provided to for this annotation; null means that there is no limit. + /// + int? AllowedArguments { get; } + IReadOnlyList ProcessAnnotationArguments(IEnumerable arguments); } diff --git a/Rubberduck.Resources/Inspections/InspectionInfo.Designer.cs b/Rubberduck.Resources/Inspections/InspectionInfo.Designer.cs index 29273a1de8..c660df48e2 100644 --- a/Rubberduck.Resources/Inspections/InspectionInfo.Designer.cs +++ b/Rubberduck.Resources/Inspections/InspectionInfo.Designer.cs @@ -879,6 +879,15 @@ public static string StopKeywordInspection { } } + /// + /// Looks up a localized string similar to An annotation has more arguments than allowed; superfluous arguments are ignored.. + /// + public static string SuperfluousAnnotationArgumentInspection { + get { + return ResourceManager.GetString("SuperfluousAnnotationArgumentInspection", resourceCulture); + } + } + /// /// Looks up a localized string similar to Whenever both sides of an assignment without Set are objects, there is an assignment from the default member of the RHS to the one on the LHS. Although this might be intentional, in many situations it will just mask an erroneously forgotten Set.. /// diff --git a/Rubberduck.Resources/Inspections/InspectionInfo.de.resx b/Rubberduck.Resources/Inspections/InspectionInfo.de.resx index e028a267ed..cee0d8c7be 100644 --- a/Rubberduck.Resources/Inspections/InspectionInfo.de.resx +++ b/Rubberduck.Resources/Inspections/InspectionInfo.de.resx @@ -218,7 +218,7 @@ Falls der Parameter 'null' sein kann, bitte dieses Auftreten ignorieren. 'null' Rubberduck hat festgestellt, dass die Variable eine Objektvariable ist, die ohne 'Set'-Schlüsselwort zugewiesen wird. Dies führt zu dem Laufzeitfehler 91 'Objektvariable oder With-Blockvariable nicht festgelegt' oder 438 'Objekt unterstützt diese Eigenschaft oder Methode nicht' abhängig davon, ob die Variable den Wert 'Nothing' hat oder nicht. - Eine Annotation in einem Kommentar konnte nicht gelesen werden. Die korrekte Syntax ist: '@Annotation([parameter])'\nBeispiel: '@Folder("Parent.Child")' + Einer Annotation in einem Kommentar fehlt ein Argument oder sie konnte nicht gelesen werden. Die korrekte Syntax ist: '@Annotation([parameter])'\nBeispiel: '@Folder("Parent.Child")' Code, der undeklarierte Variablen verwendet, kompiliert nicht wenn 'Option Explicit' spezifiziert wird. Undeklarierte Variablen sind immer vom Typ 'Variant', was unnötige Zusatzkosten in Ausführungszeit und Speicherverbauch verursacht. @@ -439,4 +439,7 @@ Falls der Parameter 'null' sein kann, bitte dieses Auftreten ignorieren. 'null' Wird keine Typdeklaration verwendet wird der Datentyp einer Konstante implizit bestimmt. Erwägen Sie eine explizite 'As <Datentyp>'-Deklaration zu verwenden um die Lesbarkeit zu verbessern, wobei '<Datentyp>' der erwünschte Datentyp der Konstante ist. + + Eine Annotation hat mehr Argumente als erlaubt. Die überzähligen Argumente werden ignoriert. + \ No newline at end of file diff --git a/Rubberduck.Resources/Inspections/InspectionInfo.resx b/Rubberduck.Resources/Inspections/InspectionInfo.resx index ecfe565c9c..4357b594ea 100644 --- a/Rubberduck.Resources/Inspections/InspectionInfo.resx +++ b/Rubberduck.Resources/Inspections/InspectionInfo.resx @@ -439,4 +439,7 @@ If the parameter can be null, ignore this inspection result; passing a null valu If the as type clause for a Const isn't included it is implicitly typed. Include an explicit ' As <Type>' replacing '<Type>' with the correct data type to explicitly type your const value. + + An annotation has more arguments than allowed; superfluous arguments are ignored. + \ No newline at end of file diff --git a/Rubberduck.Resources/Inspections/InspectionNames.Designer.cs b/Rubberduck.Resources/Inspections/InspectionNames.Designer.cs index 415c6b6001..1507d76e4e 100644 --- a/Rubberduck.Resources/Inspections/InspectionNames.Designer.cs +++ b/Rubberduck.Resources/Inspections/InspectionNames.Designer.cs @@ -879,6 +879,15 @@ public static string StopKeywordInspection { } } + /// + /// Looks up a localized string similar to Superfluous annotation arguments. + /// + public static string SuperfluousAnnotationArgumentInspection { + get { + return ResourceManager.GetString("SuperfluousAnnotationArgumentInspection", resourceCulture); + } + } + /// /// Looks up a localized string similar to Suspicious Let assignment. /// diff --git a/Rubberduck.Resources/Inspections/InspectionNames.de.resx b/Rubberduck.Resources/Inspections/InspectionNames.de.resx index 06e9add69d..d7365697ac 100644 --- a/Rubberduck.Resources/Inspections/InspectionNames.de.resx +++ b/Rubberduck.Resources/Inspections/InspectionNames.de.resx @@ -423,4 +423,7 @@ Konstante mit implizit bestimmtem Datentyp + + Überflüssige Annotationsargumente + \ No newline at end of file diff --git a/Rubberduck.Resources/Inspections/InspectionNames.resx b/Rubberduck.Resources/Inspections/InspectionNames.resx index d1ded96ad5..f4179e95af 100644 --- a/Rubberduck.Resources/Inspections/InspectionNames.resx +++ b/Rubberduck.Resources/Inspections/InspectionNames.resx @@ -443,4 +443,7 @@ Implicitly typed Const + + Superfluous annotation arguments + \ No newline at end of file diff --git a/Rubberduck.Resources/Inspections/InspectionResults.Designer.cs b/Rubberduck.Resources/Inspections/InspectionResults.Designer.cs index 3eb1f8de2c..a20861d6c1 100644 --- a/Rubberduck.Resources/Inspections/InspectionResults.Designer.cs +++ b/Rubberduck.Resources/Inspections/InspectionResults.Designer.cs @@ -520,7 +520,7 @@ public static string MemberNotOnInterfaceInspection { } /// - /// Looks up a localized string similar to Expression '{0}' was expected to contain a parameter, but none was specified.. + /// Looks up a localized string similar to The annotation '{0}' was expected to have more arguments.. /// public static string MissingAnnotationArgumentInspection { get { @@ -906,6 +906,15 @@ public static string StopKeywordInspection { } } + /// + /// Looks up a localized string similar to The annotation '{0}' was expected to have less arguments.. + /// + public static string SuperfluousAnnotationArgumentInspection { + get { + return ResourceManager.GetString("SuperfluousAnnotationArgumentInspection", resourceCulture); + } + } + /// /// Looks up a localized string similar to There is an assignment from the default member of the result of expression '{1}' to that of the expression '{0}'.. /// diff --git a/Rubberduck.Resources/Inspections/InspectionResults.de.resx b/Rubberduck.Resources/Inspections/InspectionResults.de.resx index 8608bb9ed7..1ace9a322a 100644 --- a/Rubberduck.Resources/Inspections/InspectionResults.de.resx +++ b/Rubberduck.Resources/Inspections/InspectionResults.de.resx @@ -222,7 +222,7 @@ Instruktion enthält Mehrfachdeklaration. - Ausdruck '{0}' sollte einen Parameter enthalten, es wurde aber keiner angegeben. + Die Annotation '{0}' erwartet mehr Argumente. Die lokale Variable '{0}' wurde nicht deklariert. @@ -464,4 +464,7 @@ In Memoriam, 1972-2018 Der Datentyp der Konstante '{0}' ist implizit bestimmt. + + Die Annotation '{0}' erwartet weniger Argumente. + \ No newline at end of file diff --git a/Rubberduck.Resources/Inspections/InspectionResults.resx b/Rubberduck.Resources/Inspections/InspectionResults.resx index a675ca3eee..dc82bdf92d 100644 --- a/Rubberduck.Resources/Inspections/InspectionResults.resx +++ b/Rubberduck.Resources/Inspections/InspectionResults.resx @@ -230,7 +230,8 @@ {0} '{1}' is implicitly 'Variant'. - Expression '{0}' was expected to contain a parameter, but none was specified. + The annotation '{0}' was expected to have more arguments. + {0} annotation name Module-level variable '{0}' is declared with the 'Dim' keyword. @@ -508,4 +509,8 @@ In memoriam, 1972-2018 Constant '{0}' is implicitly typed. + + The annotation '{0}' was expected to have less arguments. + {0} annotation name + \ No newline at end of file diff --git a/RubberduckTests/Inspections/MissingAnnotationArgumentInspectionTests.cs b/RubberduckTests/Inspections/MissingAnnotationArgumentInspectionTests.cs new file mode 100644 index 0000000000..7c58e48734 --- /dev/null +++ b/RubberduckTests/Inspections/MissingAnnotationArgumentInspectionTests.cs @@ -0,0 +1,61 @@ +using System.Linq; +using NUnit.Framework; +using Rubberduck.Inspections.Concrete; +using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Parsing.VBA; +using Rubberduck.VBEditor.SafeComWrappers; + +namespace RubberduckTests.Inspections +{ + [TestFixture] + public class MissingAnnotationArgumentInspectionTests : InspectionTestsBase + { + [Test] + [Category("Inspections")] + [TestCase("ModuleDescription", "")] + [TestCase("ModuleAttribute", "AttributeName")] + [TestCase("Folder", "")] + [TestCase("Ignore", "")] + public void TooFewArguments_ReturnsResult(string annotationName, string argumentsText) + { + var class1 = + $@" + +'@{annotationName} {argumentsText} + +"; + + var inspectionResults = InspectionResultsForModules(("Class1", class1, ComponentType.ClassModule)); + + Assert.AreEqual(1, inspectionResults.Count()); + } + + [Test] + [Category("Inspections")] + [TestCase("PredeclaredId", "")] + [TestCase("ModuleDescription", @"""MyModule""")] + [TestCase("ModuleAttribute", @"AttributeName, 42")] + [TestCase("Folder", @"""MyModule""")] + [TestCase("IgnoreModule", @"Inspection1")] + [TestCase("IgnoreModule", "")] + public void NotTooFewArguments_DoesNotReturnResult(string annotationName, string argumentsText) + { + var class1 = + $@" + +'@{annotationName} {argumentsText} + +"; + + var inspectionResults = InspectionResultsForModules(("Class1", class1, ComponentType.ClassModule)); + + Assert.AreEqual(0, inspectionResults.Count()); + } + + protected override IInspection InspectionUnderTest(RubberduckParserState state) + { + return new MissingAnnotationArgumentInspection(state); + } + + } +} \ No newline at end of file diff --git a/RubberduckTests/Inspections/SuperfluousAnnotationArgumentInspectionTests.cs b/RubberduckTests/Inspections/SuperfluousAnnotationArgumentInspectionTests.cs new file mode 100644 index 0000000000..75cd2e2344 --- /dev/null +++ b/RubberduckTests/Inspections/SuperfluousAnnotationArgumentInspectionTests.cs @@ -0,0 +1,62 @@ +using System.Linq; +using NUnit.Framework; +using Rubberduck.Inspections.Concrete; +using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.Parsing.VBA; +using Rubberduck.VBEditor.SafeComWrappers; + +namespace RubberduckTests.Inspections +{ + [TestFixture] + public class SuperfluousAnnotationArgumentInspectionTests : InspectionTestsBase + { + [Test] + [Category("Inspections")] + [TestCase("PredeclaredId", "False")] + [TestCase("PredeclaredId", "True")] + [TestCase("Exposed", "False")] + [TestCase("Exposed", "True")] + [TestCase("ModuleDescription", @"""MyModule"", ""SomethingElse""")] + [TestCase("Folder", @"""MyModule"", ""SomethingElse""")] + public void TooManyArguments_ReturnsResult(string annotationName, string argumentsText) + { + var class1 = + $@" + +'@{annotationName} {argumentsText} + +"; + + var inspectionResults = InspectionResultsForModules(("Class1", class1, ComponentType.ClassModule)); + + Assert.AreEqual(1, inspectionResults.Count()); + } + + [Test] + [Category("Inspections")] + [TestCase("PredeclaredId", "")] + [TestCase("Exposed", "")] + [TestCase("ModuleDescription", @"""MyModule""")] + [TestCase("Folder", @"""MyModule""")] + [TestCase("IgnoreTest", @"""Reasons""")] + [TestCase("IgnoreModule", @"Inspection1, Inspection2, Inspection3, Inspection4, Inspection5, Inspection6")] + public void NotTooManyArguments_DoesNotReturnResult(string annotationName, string argumentsText) + { + var class1 = + $@" + +'@{annotationName} {argumentsText} + +"; + + var inspectionResults = InspectionResultsForModules(("Class1", class1, ComponentType.ClassModule)); + + Assert.AreEqual(0, inspectionResults.Count()); + } + + protected override IInspection InspectionUnderTest(RubberduckParserState state) + { + return new SuperfluousAnnotationArgumentInspection(state); + } + } +} \ No newline at end of file From e280debe04c2d67660bca6904b6ca82d28af0c42 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sun, 1 Mar 2020 17:06:15 +0100 Subject: [PATCH 266/461] Stop using stale state in UnreachableCaseInspection Also removes the special testing interface from ParseTreeValueVisitor. --- .../ParseTreeValueVisitor.cs | 59 ++++------ .../ParseTreeValueVisitorFactory.cs | 28 +++++ .../ParseTreeVisitorResults.cs | 26 ++--- .../UnreachableCaseInspection.cs | 103 +++++++++--------- ...nreachableCaseInspectionFactoryProvider.cs | 8 +- .../UnreachableCaseInspector.cs | 31 ++++-- .../UnreachableCaseInspectorFactory.cs | 15 ++- .../Root/RubberduckIoCInstaller.cs | 19 ++++ .../UnreachableCaseInspectionTests.cs | 78 +++++++------ 9 files changed, 210 insertions(+), 157 deletions(-) create mode 100644 Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitorFactory.cs diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs index eaae74b389..5fed290888 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs @@ -10,16 +10,9 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { public interface IParseTreeValueVisitor : IParseTreeVisitor - { - event EventHandler OnValueResultCreated; - } - - public interface ITestParseTreeVisitor - { - void InjectValuedDeclarationEvaluator(Func func); - } + {} - public class ParseTreeValueVisitor : IParseTreeValueVisitor, ITestParseTreeVisitor + public class ParseTreeValueVisitor : IParseTreeValueVisitor { private class EnumMember { @@ -29,28 +22,31 @@ public EnumMember(VBAParser.EnumerationStmt_ConstantContext constContext, long i Value = initValue; HasAssignment = constContext.children.Any(ch => ch.Equals(constContext.GetToken(VBAParser.EQ, 0))); } - public VBAParser.EnumerationStmt_ConstantContext ConstantContext { set; get; } + public VBAParser.EnumerationStmt_ConstantContext ConstantContext { get; } public long Value { set; get; } - public bool HasAssignment { set; get; } + public bool HasAssignment { get; } } - private IParseTreeVisitorResults _contextValues; - private IParseTreeValueFactory _inspValueFactory; - private IReadOnlyList _enumStmtContexts; + private readonly IParseTreeVisitorResults _contextValues; + private readonly IParseTreeValueFactory _inspValueFactory; + private readonly IReadOnlyList _enumStmtContexts; private List _enumMembers; + private Func _valueDeclarationEvaluator; - public ParseTreeValueVisitor(IParseTreeValueFactory valueFactory, IReadOnlyList allEnums, Func idRefRetriever) + public ParseTreeValueVisitor( + IParseTreeValueFactory valueFactory, + IReadOnlyList allEnums, + Func idRefRetriever, + Func valueDeclarationEvaluator = null) { _inspValueFactory = valueFactory; IdRefRetriever = idRefRetriever; _contextValues = new ParseTreeVisitorResults(); - OnValueResultCreated += _contextValues.OnNewValueResult; _enumStmtContexts = allEnums; + _valueDeclarationEvaluator = valueDeclarationEvaluator ?? GetValuedDeclaration; } - private Func IdRefRetriever { set; get; } = null; - - public event EventHandler OnValueResultCreated; + private Func IdRefRetriever { get; } public virtual IParseTreeVisitorResults Visit(IParseTree tree) { @@ -85,7 +81,7 @@ public virtual IParseTreeVisitorResults VisitErrorNode(IErrorNode node) private void StoreVisitResult(ParserRuleContext context, IParseTreeValue inspValue) { - OnValueResultCreated(this, new ValueResultEventArgs(context, inspValue)); + _contextValues.AddIfNotPresent(context, inspValue); } private bool HasResult(ParserRuleContext context) @@ -141,7 +137,6 @@ private void Visit(VBAParser.LExprContext context) } else { - var smplNameExprTypeName = string.Empty; var smplName = context.GetDescendent(); if (TryGetIdentifierReferenceForContext(smplName, out IdentifierReference idRef)) { @@ -286,20 +281,6 @@ private bool TryGetLExprValue(VBAParser.LExprContext lExprContext, out string ex return false; } - private Func _valueDeclarationEvaluator; - private Func ValuedDeclarationEvaluator - { - set - { - _valueDeclarationEvaluator = value; - } - get - { - return _valueDeclarationEvaluator ?? GetValuedDeclaration; - } - } - - private (bool IsType, string ExpressionValue, string TypeName) GetValuedDeclaration(Declaration declaration) { if (declaration is ValuedDeclaration valuedDeclaration) @@ -321,7 +302,7 @@ private void GetContextValue(ParserRuleContext context, out string declaredTypeN expressionValue = rangeClauseIdentifierReference.IdentifierName; declaredTypeName = GetBaseTypeForDeclaration(declaration); - (bool IsValuedDeclaration, string ExpressionValue, string TypeName) = ValuedDeclarationEvaluator(declaration); + (bool IsValuedDeclaration, string ExpressionValue, string TypeName) = _valueDeclarationEvaluator(declaration); if( IsValuedDeclaration) { @@ -334,7 +315,8 @@ private void GetContextValue(ParserRuleContext context, out string declaredTypeN declaredTypeName = Tokens.String; return; } - else if (long.TryParse(expressionValue, out _)) + + if (long.TryParse(expressionValue, out _)) { return; } @@ -437,9 +419,6 @@ private static bool IsBinaryOpEvaluationContext(T context) return false; } - public void InjectValuedDeclarationEvaluator( Func func) - => ValuedDeclarationEvaluator = func; - private void LoadEnumMemberValues() { _enumMembers = new List(); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitorFactory.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitorFactory.cs new file mode 100644 index 0000000000..b465f02ac3 --- /dev/null +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitorFactory.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using Antlr4.Runtime; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Symbols; + +namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection +{ + public interface IParseTreeValueVisitorFactory + { + IParseTreeValueVisitor Create(IReadOnlyList allEnums, Func idRefRetriever); + } + + public class ParseTreeValueVisitorFactory : IParseTreeValueVisitorFactory + { + private readonly IParseTreeValueFactory _valueFactory; + + public ParseTreeValueVisitorFactory(IParseTreeValueFactory valueFactory) + { + _valueFactory = valueFactory; + } + + public IParseTreeValueVisitor Create(IReadOnlyList allEnums, Func identifierReferenceRetriever) + { + return new ParseTreeValueVisitor(_valueFactory, allEnums, identifierReferenceRetriever); + } + } +} \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeVisitorResults.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeVisitorResults.cs index a761bd42d4..074c0d680a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeVisitorResults.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeVisitorResults.cs @@ -1,6 +1,7 @@ using Antlr4.Runtime; using System; using System.Collections.Generic; +using System.Linq; namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { @@ -12,7 +13,7 @@ public interface IParseTreeVisitorResults string GetToken(ParserRuleContext context); bool Contains(ParserRuleContext context); bool TryGetValue(ParserRuleContext context, out IParseTreeValue value); - void OnNewValueResult(object sender, ValueResultEventArgs e); + void AddIfNotPresent(ParserRuleContext context, IParseTreeValue value); } public class ParseTreeVisitorResults : IParseTreeVisitorResults @@ -35,18 +36,15 @@ public IParseTreeValue GetValue(ParserRuleContext context) public List GetChildResults(ParserRuleContext parent) { - var results = new List(); - if (!(parent is null) || Contains(parent)) + if (parent is null) { - foreach (var child in parent.children) - { - if (child is ParserRuleContext prCtxt && Contains(prCtxt)) - { - results.Add(prCtxt); - } - } + return new List(); } - return results; + + return parent.children + .OfType() + .Where(Contains) + .ToList(); } public string GetValueType(ParserRuleContext context) @@ -69,11 +67,11 @@ public bool TryGetValue(ParserRuleContext context, out IParseTreeValue value) return _parseTreeValues.TryGetValue(context, out value); } - public void OnNewValueResult(object sender, ValueResultEventArgs e) + public void AddIfNotPresent(ParserRuleContext context, IParseTreeValue value) { - if (!_parseTreeValues.ContainsKey(e.Context)) + if (!_parseTreeValues.ContainsKey(context)) { - _parseTreeValues.Add(e.Context, e.Value); + _parseTreeValues.Add(context, value); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs index 39c8244853..8f2df8b9c5 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs @@ -117,100 +117,95 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection public sealed class UnreachableCaseInspection : InspectionBase, IParseTreeInspection { private readonly IUnreachableCaseInspectorFactory _unreachableCaseInspectorFactory; - private readonly IParseTreeValueFactory _valueFactory; + private readonly IParseTreeValueVisitorFactory _parseTreeValueVisitorFactory; + private readonly UnreachableCaseInspectionListener _listener; - private enum CaseInspectionResult { Unreachable, InherentlyUnreachable, MismatchType, Overflow, CaseElse }; - - private static readonly Dictionary ResultMessages = new Dictionary() + public enum CaseInspectionResultType { - [CaseInspectionResult.Unreachable] = InspectionResults.UnreachableCaseInspection_Unreachable, - [CaseInspectionResult.InherentlyUnreachable] = InspectionResults.UnreachableCaseInspection_InherentlyUnreachable, - [CaseInspectionResult.MismatchType] = InspectionResults.UnreachableCaseInspection_TypeMismatch, - [CaseInspectionResult.Overflow] = InspectionResults.UnreachableCaseInspection_Overflow, - [CaseInspectionResult.CaseElse] = InspectionResults.UnreachableCaseInspection_CaseElse - }; + Unreachable, + InherentlyUnreachable, + MismatchType, + Overflow, + CaseElse + } - public UnreachableCaseInspection(IDeclarationFinderProvider declarationFinderProvider) + public UnreachableCaseInspection(IDeclarationFinderProvider declarationFinderProvider, IUnreachableCaseInspectionFactoryProvider factoryProvider) : base(declarationFinderProvider) { - var factoryProvider = new UnreachableCaseInspectionFactoryProvider(); - _unreachableCaseInspectorFactory = factoryProvider.CreateIUnreachableInspectorFactory(); - _valueFactory = factoryProvider.CreateIParseTreeValueFactory(); + _parseTreeValueVisitorFactory = factoryProvider.CreateParseTreeValueVisitorFactory(); + _listener = new UnreachableCaseInspectionListener(); } public CodeKind TargetKindOfCode => CodeKind.CodePaneCode; - public IInspectionListener Listener { get; } = - new UnreachableCaseInspectionListener(); - - private ParseTreeVisitorResults ValueResults { get; } = new ParseTreeVisitorResults(); + public IInspectionListener Listener => _listener; protected override IEnumerable DoGetInspectionResults() { var finder = DeclarationFinderProvider.DeclarationFinder; + var enumStmts = _listener.EnumerationStmtContexts(); + var parseTreeValueVisitor = CreateParseTreeValueVisitor(enumStmts, GetIdentifierReferenceForContext); return finder.UserDeclarations(DeclarationType.Module) .Where(module => module != null) - .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder)) + .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder, parseTreeValueVisitor)) .ToList(); } protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) { var finder = DeclarationFinderProvider.DeclarationFinder; - return DoGetInspectionResults(module, finder); + var enumStmts = _listener.EnumerationStmtContexts(); + var parseTreeValueVisitor = CreateParseTreeValueVisitor(enumStmts, GetIdentifierReferenceForContext); + return DoGetInspectionResults(module, finder, parseTreeValueVisitor); } - private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder, IParseTreeValueVisitor parseTreeValueVisitor) { var qualifiedSelectCaseStmts = Listener.Contexts(module) // ignore filtering here to make the search space smaller .Where(result => !result.IsIgnoringInspectionResultFor(finder, AnnotationName)); - ParseTreeValueVisitor.OnValueResultCreated += ValueResults.OnNewValueResult; - return qualifiedSelectCaseStmts - .SelectMany(ResultsForContext) + .SelectMany(context => ResultsForContext(context, finder, parseTreeValueVisitor)) .ToList(); } - private IEnumerable ResultsForContext(QualifiedContext qualifiedSelectCaseStmt) + private IEnumerable ResultsForContext(QualifiedContext qualifiedSelectCaseStmt, DeclarationFinder finder, IParseTreeValueVisitor parseTreeValueVisitor) { - qualifiedSelectCaseStmt.Context.Accept(ParseTreeValueVisitor); - var selectCaseInspector = _unreachableCaseInspectorFactory.Create((VBAParser.SelectCaseStmtContext)qualifiedSelectCaseStmt.Context, ValueResults, _valueFactory, GetVariableTypeName); + var contextValues = qualifiedSelectCaseStmt.Context.Accept(parseTreeValueVisitor); + var selectCaseInspector = _unreachableCaseInspectorFactory.Create((VBAParser.SelectCaseStmtContext)qualifiedSelectCaseStmt.Context, contextValues, GetVariableTypeName); - selectCaseInspector.InspectForUnreachableCases(); + var results = selectCaseInspector.InspectForUnreachableCases(); - return selectCaseInspector - .UnreachableCases - .Select(uc => CreateInspectionResult(qualifiedSelectCaseStmt, uc, ResultMessages[CaseInspectionResult.Unreachable])) - .Concat(selectCaseInspector - .MismatchTypeCases - .Select(mm => CreateInspectionResult(qualifiedSelectCaseStmt, mm, ResultMessages[CaseInspectionResult.MismatchType]))) - .Concat(selectCaseInspector - .OverflowCases - .Select(mm => CreateInspectionResult(qualifiedSelectCaseStmt, mm, ResultMessages[CaseInspectionResult.Overflow]))) - .Concat(selectCaseInspector - .InherentlyUnreachableCases - .Select(mm => CreateInspectionResult(qualifiedSelectCaseStmt, mm, ResultMessages[CaseInspectionResult.InherentlyUnreachable]))) - .Concat(selectCaseInspector - .UnreachableCaseElseCases - .Select(ce => CreateInspectionResult(qualifiedSelectCaseStmt, ce, ResultMessages[CaseInspectionResult.CaseElse]))) + return results + .Select(resultTpl => CreateInspectionResult(qualifiedSelectCaseStmt, resultTpl.context, resultTpl.resultType)) .ToList(); } - private IParseTreeValueVisitor _parseTreeValueVisitor; - public IParseTreeValueVisitor ParseTreeValueVisitor + private IInspectionResult CreateInspectionResult(QualifiedContext selectStmt, ParserRuleContext unreachableBlock, CaseInspectionResultType resultType) { - get + return CreateInspectionResult(selectStmt, unreachableBlock, ResultMessage(resultType)); + } + + //This cannot be a dictionary because the strings have to change after a change in the selected language. + private static string ResultMessage(CaseInspectionResultType resultType) + { + switch (resultType) { - if (_parseTreeValueVisitor is null) - { - var listener = (UnreachableCaseInspectionListener)Listener; - _parseTreeValueVisitor = CreateParseTreeValueVisitor(_valueFactory, listener.EnumerationStmtContexts(), GetIdentifierReferenceForContext); - } - return _parseTreeValueVisitor; + case CaseInspectionResultType.Unreachable: + return InspectionResults.UnreachableCaseInspection_Unreachable; + case CaseInspectionResultType.InherentlyUnreachable: + return InspectionResults.UnreachableCaseInspection_InherentlyUnreachable; + case CaseInspectionResultType.MismatchType: + return InspectionResults.UnreachableCaseInspection_TypeMismatch; + case CaseInspectionResultType.Overflow: + return InspectionResults.UnreachableCaseInspection_Overflow; + case CaseInspectionResultType.CaseElse: + return InspectionResults.UnreachableCaseInspection_CaseElse; + default: + throw new ArgumentOutOfRangeException(nameof(resultType), resultType, null); } } @@ -221,8 +216,8 @@ private IInspectionResult CreateInspectionResult(QualifiedContext(selectStmt.ModuleName, unreachableBlock)); } - public static IParseTreeValueVisitor CreateParseTreeValueVisitor(IParseTreeValueFactory valueFactory, IReadOnlyList allEnums, Func func) - => new ParseTreeValueVisitor(valueFactory, allEnums, func); + public IParseTreeValueVisitor CreateParseTreeValueVisitor(IReadOnlyList allEnums, Func func) + => _parseTreeValueVisitorFactory.Create(allEnums, func); //Method is used as a delegate to avoid propagating RubberduckParserState beyond this class private (bool success, IdentifierReference idRef) GetIdentifierReferenceForContext(ParserRuleContext context) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspectionFactoryProvider.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspectionFactoryProvider.cs index 78d8673564..58c4cccb1b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspectionFactoryProvider.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspectionFactoryProvider.cs @@ -5,6 +5,7 @@ public interface IUnreachableCaseInspectionFactoryProvider { IParseTreeValueFactory CreateIParseTreeValueFactory(); IUnreachableCaseInspectorFactory CreateIUnreachableInspectorFactory(); + IParseTreeValueVisitorFactory CreateParseTreeValueVisitorFactory(); } public class UnreachableCaseInspectionFactoryProvider : IUnreachableCaseInspectionFactoryProvider @@ -16,7 +17,12 @@ public IParseTreeValueFactory CreateIParseTreeValueFactory() public IUnreachableCaseInspectorFactory CreateIUnreachableInspectorFactory() { - return new UnreachableCaseInspectorFactory(); + return new UnreachableCaseInspectorFactory(CreateIParseTreeValueFactory()); + } + + public IParseTreeValueVisitorFactory CreateParseTreeValueVisitorFactory() + { + return new ParseTreeValueVisitorFactory(CreateIParseTreeValueFactory()); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs index bcae189c71..5715e980de 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs @@ -9,13 +9,8 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { public interface IUnreachableCaseInspector { - void InspectForUnreachableCases(); + ICollection<(UnreachableCaseInspection.CaseInspectionResultType resultType, ParserRuleContext context)> InspectForUnreachableCases(); string SelectExpressionTypeName { get; } - List UnreachableCases { get; } - List InherentlyUnreachableCases { get; } - List MismatchTypeCases { get; } - List OverflowCases { get; } - List UnreachableCaseElseCases { get; } } public class UnreachableCaseInspector : IUnreachableCaseInspector @@ -49,15 +44,30 @@ public UnreachableCaseInspector(VBAParser.SelectCaseStmtContext selectCaseContex public List UnreachableCaseElseCases { set; get; } = new List(); + public ICollection<(UnreachableCaseInspection.CaseInspectionResultType resultType, ParserRuleContext context)> + AllResults => + WithType(UnreachableCaseInspection.CaseInspectionResultType.Unreachable, UnreachableCases) + .Concat(WithType(UnreachableCaseInspection.CaseInspectionResultType.InherentlyUnreachable, InherentlyUnreachableCases)) + .Concat(WithType(UnreachableCaseInspection.CaseInspectionResultType.MismatchType, MismatchTypeCases)) + .Concat(WithType(UnreachableCaseInspection.CaseInspectionResultType.Overflow, OverflowCases)) + .Concat(WithType(UnreachableCaseInspection.CaseInspectionResultType.CaseElse, UnreachableCaseElseCases)) + .ToList(); + + private static IEnumerable<(UnreachableCaseInspection.CaseInspectionResultType type, ParserRuleContext context)> + WithType(UnreachableCaseInspection.CaseInspectionResultType type, IEnumerable source) + { + return source.Select(context => (type, context)); + } + public string SelectExpressionTypeName { private set; get; } = string.Empty; private IParseTreeVisitorResults ParseTreeValueResults { get; } - public void InspectForUnreachableCases() + public ICollection<(UnreachableCaseInspection.CaseInspectionResultType resultType, ParserRuleContext context)> InspectForUnreachableCases() { if (!InspectableTypes.Contains(SelectExpressionTypeName)) { - return; + return new List<(UnreachableCaseInspection.CaseInspectionResultType resultType, ParserRuleContext context)>(); } var remainingCasesToInspect = new List(); @@ -130,6 +140,8 @@ public void InspectForUnreachableCases() { UnreachableCaseElseCases.Add(_caseElseContext); } + + return AllResults; } private IExpressionFilter BuildRangeClauseFilter(IEnumerable caseClauses) @@ -327,8 +339,7 @@ private static bool TryGetLogicSymbol(ParserRuleContext context, out string opSy return false; } - private static (IParseTreeValue lhs, IParseTreeValue rhs) - CreateLogicPair(IParseTreeValue value, string opSymbol, IParseTreeValueFactory factory) + private static (IParseTreeValue lhs, IParseTreeValue rhs) CreateLogicPair(IParseTreeValue value, string opSymbol, IParseTreeValueFactory factory) { var operands = value.Token.Split(new [] { opSymbol }, StringSplitOptions.None); if (operands.Length == 2) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspectorFactory.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspectorFactory.cs index d75cf95271..46174d8efa 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspectorFactory.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspectorFactory.cs @@ -6,17 +6,24 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { public interface IUnreachableCaseInspectorFactory { - IUnreachableCaseInspector Create(VBAParser.SelectCaseStmtContext selectStmt, + IUnreachableCaseInspector Create( + VBAParser.SelectCaseStmtContext selectStmt, IParseTreeVisitorResults results, - IParseTreeValueFactory valueFactory, Func func = null); } public class UnreachableCaseInspectorFactory : IUnreachableCaseInspectorFactory { - public IUnreachableCaseInspector Create(VBAParser.SelectCaseStmtContext selectStmt, IParseTreeVisitorResults results, IParseTreeValueFactory valueFactory, Func func = null) + private readonly IParseTreeValueFactory _valueFactory; + + public UnreachableCaseInspectorFactory(IParseTreeValueFactory valueFactory) + { + _valueFactory = valueFactory; + } + + public IUnreachableCaseInspector Create(VBAParser.SelectCaseStmtContext selectStmt, IParseTreeVisitorResults results, Func func = null) { - return new UnreachableCaseInspector(selectStmt, results, valueFactory, func); + return new UnreachableCaseInspector(selectStmt, results, _valueFactory, func); } } } diff --git a/Rubberduck.Main/Root/RubberduckIoCInstaller.cs b/Rubberduck.Main/Root/RubberduckIoCInstaller.cs index e66968d120..2213c7ec13 100644 --- a/Rubberduck.Main/Root/RubberduckIoCInstaller.cs +++ b/Rubberduck.Main/Root/RubberduckIoCInstaller.cs @@ -16,6 +16,7 @@ using Rubberduck.ComClientLibrary.UnitTesting; using Rubberduck.Common; using Rubberduck.Common.Hotkeys; +using Rubberduck.Inspections.Concrete.UnreachableCaseInspection; using Rubberduck.Inspections.Rubberduck.Inspections; using Rubberduck.Parsing; using Rubberduck.Parsing.Common; @@ -373,8 +374,26 @@ private void RegisterSpecialFactories(IWindsorContainer container) container.Register(Component.For() .ImplementedBy() .LifestyleSingleton()); + RegisterUnreachableCaseFactories(container); } + private void RegisterUnreachableCaseFactories(IWindsorContainer container) + { + container.Register(Component.For() + .ImplementedBy() + .LifestyleSingleton()); + container.Register(Component.For() + .ImplementedBy() + .LifestyleSingleton()); + container.Register(Component.For() + .ImplementedBy() + .LifestyleSingleton()); + container.Register(Component.For() + .ImplementedBy() + .LifestyleSingleton()); + } + + private void RegisterQuickFixes(IWindsorContainer container, Assembly[] assembliesToRegister) { foreach (var assembly in assembliesToRegister) diff --git a/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs b/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs index 2819a0da79..1899463129 100644 --- a/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs +++ b/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs @@ -1,4 +1,5 @@ -using Antlr4.Runtime; +using System; +using Antlr4.Runtime; using NUnit.Framework; using Rubberduck.Inspections.Concrete.UnreachableCaseInspection; using Rubberduck.Parsing; @@ -12,29 +13,13 @@ using System.Collections.Generic; using System.Linq; using System.Threading; +using Moq; namespace RubberduckTests.Inspections.UnreachableCase { [TestFixture] public class UnreachableCaseInspectionTests : InspectionTestsBase { - private IUnreachableCaseInspectionFactoryProvider _factoryProvider; - - private IUnreachableCaseInspectionFactoryProvider FactoryProvider - { - get - { - if (_factoryProvider is null) - { - _factoryProvider = new UnreachableCaseInspectionFactoryProvider(); - } - return _factoryProvider; - } - } - - private IUnreachableCaseInspectorFactory IUnreachableCaseInspectorFactory => FactoryProvider.CreateIUnreachableInspectorFactory(); - private IParseTreeValueFactory ValueFactory => FactoryProvider.CreateIParseTreeValueFactory(); - [TestCase("Dim Hint$\r\nSelect Case Hint$", @"""Here"" To ""Eternity"",""Forever""", "String")] //String [TestCase("Dim Hint#\r\nHint#= 1.0\r\nSelect Case Hint#", "10.00 To 30.00, 20.00", "Double")] //Double [TestCase("Dim Hint!\r\nHint! = 1.0\r\nSelect Case Hint!", "10.00 To 30.00,20.00", "Single")] //Single @@ -2473,10 +2458,8 @@ End Sub var actualResults = Enumerable.Empty(); using (var state = MockParser.CreateAndParse(vbe.Object)) { - var inspection = new UnreachableCaseInspection(state); - var parseTreeValueVisitor = inspection.ParseTreeValueVisitor as ITestParseTreeVisitor; - - parseTreeValueVisitor.InjectValuedDeclarationEvaluator(TestGetValuedDeclaration); + var factoryProvider = SpecialValueDeclarationEvaluatorFactoryProvider(TestGetValuedDeclaration); + var inspection = new UnreachableCaseInspection(state, factoryProvider); var inspector = InspectionsHelper.GetInspector(inspection); actualResults = inspector.FindIssuesAsync(state, CancellationToken.None).Result; @@ -2527,10 +2510,8 @@ End Sub var actualResults = Enumerable.Empty(); using (var state = MockParser.CreateAndParse(vbe.Object)) { - var inspection = new UnreachableCaseInspection(state); - var parseTreeValueVisitor = inspection.ParseTreeValueVisitor as ITestParseTreeVisitor; - - parseTreeValueVisitor.InjectValuedDeclarationEvaluator(TestGetValuedDeclaration); + var factoryProvider = SpecialValueDeclarationEvaluatorFactoryProvider(TestGetValuedDeclaration); + var inspection = new UnreachableCaseInspection(state, factoryProvider); var inspector = InspectionsHelper.GetInspector(inspection); actualResults = inspector.FindIssuesAsync(state, CancellationToken.None).Result; @@ -2541,6 +2522,34 @@ End Sub Assert.AreEqual(expectedUnreachableCount, actualUnreachable.Count()); } + private IUnreachableCaseInspectionFactoryProvider _factoryProvider; + private IUnreachableCaseInspectionFactoryProvider FactoryProvider => _factoryProvider ?? (_factoryProvider = new UnreachableCaseInspectionFactoryProvider()); + + private IUnreachableCaseInspectorFactory UnreachableCaseInspectorFactory => FactoryProvider.CreateIUnreachableInspectorFactory(); + private IParseTreeValueVisitorFactory ParseTreeValueVisitorFactory => FactoryProvider.CreateParseTreeValueVisitorFactory(); + + private IUnreachableCaseInspectionFactoryProvider SpecialValueDeclarationEvaluatorFactoryProvider(Func valueDeclarationEvaluator) + { + var baseFactoryProvider = FactoryProvider; + var factoryProviderMock = new Mock(); + factoryProviderMock.Setup(m => m.CreateIParseTreeValueFactory()).Returns(() => baseFactoryProvider.CreateIParseTreeValueFactory()); + factoryProviderMock.Setup(m => m.CreateIUnreachableInspectorFactory()).Returns(() => baseFactoryProvider.CreateIUnreachableInspectorFactory()); + factoryProviderMock.Setup(m => m.CreateParseTreeValueVisitorFactory()).Returns(() => + SpecialValueDeclarationEvaluatorParseTreeValueVisitorFactory(baseFactoryProvider.CreateIParseTreeValueFactory(), valueDeclarationEvaluator)); + return factoryProviderMock.Object; + } + + private IParseTreeValueVisitorFactory SpecialValueDeclarationEvaluatorParseTreeValueVisitorFactory(IParseTreeValueFactory valueFactory, Func valueDeclarationEvaluator) + { + var factoryMock = new Mock(); + factoryMock.Setup(m => m.Create( + It.IsAny>(), + It.IsAny>())) + .Returns, Func>((allEnums, identifierReferenceRetriever) => + new ParseTreeValueVisitor(valueFactory, allEnums, identifierReferenceRetriever, valueDeclarationEvaluator)); + return factoryMock.Object; + } + private static Dictionary _vbConstConversions = new Dictionary() { ["vbNewLine"] = ("Chr$(13) & Chr$(10)", Tokens.String), @@ -2611,7 +2620,7 @@ private string GetSelectExpressionType(string inputCode) { var selectStmtValueResults = GetParseTreeValueResults(inputCode, out VBAParser.SelectCaseStmtContext selectStmtContext); - var inspector = IUnreachableCaseInspectorFactory.Create(selectStmtContext, selectStmtValueResults, ValueFactory); + var inspector = UnreachableCaseInspectorFactory.Create(selectStmtContext, selectStmtValueResults); return inspector.SelectExpressionTypeName; } @@ -2622,13 +2631,13 @@ private IParseTreeVisitorResults GetParseTreeValueResults(string inputCode, out var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out var _); using (var state = MockParser.CreateAndParse(vbe.Object)) { - var firstParserRuleContext = (ParserRuleContext)state.ParseTrees.Where(pt => pt.Value is ParserRuleContext).First().Value; + var firstParserRuleContext = (ParserRuleContext)state.ParseTrees + .First(pt => pt.Value is ParserRuleContext) + .Value; selectStmt = firstParserRuleContext.GetDescendent(); - var visitor = UnreachableCaseInspection.CreateParseTreeValueVisitor - ( ValueFactory, new List(), - (ParserRuleContext context) => - { return UnreachableCaseInspection.GetIdentifierReferenceForContext(context, state); } - ); + var visitor = ParseTreeValueVisitorFactory.Create( + new List(), + context => UnreachableCaseInspection.GetIdentifierReferenceForContext(context, state)); valueResults = selectStmt.Accept(visitor); } return valueResults; @@ -2636,7 +2645,8 @@ private IParseTreeVisitorResults GetParseTreeValueResults(string inputCode, out protected override IInspection InspectionUnderTest(RubberduckParserState state) { - return new UnreachableCaseInspection(state); + var factoryProvider = new UnreachableCaseInspectionFactoryProvider(); + return new UnreachableCaseInspection(state, factoryProvider); } } } From ca77a8de4a76482f6a33816f3739486ec8e64aec Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sun, 1 Mar 2020 17:58:40 +0100 Subject: [PATCH 267/461] Allow to clear inspection listener contexts by module --- .../Abstract/ParseTreeInspectionBase.cs | 5 +++++ .../Concrete/OptionExplicitInspection.cs | 6 ++++++ .../UnhandledOnErrorResumeNextInspection.cs | 14 ++++++++++++++ .../UnreachableCaseInspection.cs | 10 ++++++---- .../Inspections/Abstract/IInpsectionListener.cs | 1 + 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs index 37e0c2ea37..399b823111 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs @@ -139,6 +139,11 @@ public virtual void ClearContexts() _contexts.Clear(); } + public virtual void ClearContexts(QualifiedModuleName module) + { + _contexts.Remove(module); + } + protected void SaveContext(ParserRuleContext context) { var module = CurrentModuleName; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs index 2db49524e8..8e6140338a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs @@ -69,6 +69,12 @@ public override void ClearContexts() base.ClearContexts(); } + public override void ClearContexts(QualifiedModuleName module) + { + _hasOptionExplicit.Remove(module); + base.ClearContexts(module); + } + public override void EnterModuleDeclarations(VBAParser.ModuleDeclarationsContext context) { _hasOptionExplicit[CurrentModuleName] = false; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs index 1c2db0e70d..e8962954e1 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs @@ -7,6 +7,7 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; +using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete { @@ -74,6 +75,19 @@ public override void ClearContexts() base.ClearContexts(); } + public override void ClearContexts(QualifiedModuleName module) + { + var keysInModule = _unhandledContextsMap.Keys + .Where(context => context.ModuleName.Equals(module)); + + foreach (var key in keysInModule) + { + _unhandledContextsMap.Remove(key); + } + + base.ClearContexts(module); + } + public override void ExitModuleBodyElement(VBAParser.ModuleBodyElementContext context) { if (_unhandledContexts.Any()) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs index 8f2df8b9c5..ad33433043 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs @@ -279,10 +279,6 @@ public class UnreachableCaseInspectionListener : InspectionListenerBase { private readonly IDictionary> _enumStmts = new Dictionary>(); public IReadOnlyList EnumerationStmtContexts() => _enumStmts.AllValues().ToList(); - public IReadOnlyList EnumerationStmtContexts(QualifiedModuleName module) => - _enumStmts.TryGetValue(module, out var stmts) - ? stmts - : new List(); public override void ClearContexts() { @@ -290,6 +286,12 @@ public override void ClearContexts() base.ClearContexts(); } + public override void ClearContexts(QualifiedModuleName module) + { + _enumStmts.Remove(module); + base.ClearContexts(module); + } + public override void EnterSelectCaseStmt([NotNull] VBAParser.SelectCaseStmtContext context) { SaveContext(context); diff --git a/Rubberduck.Parsing/Inspections/Abstract/IInpsectionListener.cs b/Rubberduck.Parsing/Inspections/Abstract/IInpsectionListener.cs index bd0484aadf..c64f12b865 100644 --- a/Rubberduck.Parsing/Inspections/Abstract/IInpsectionListener.cs +++ b/Rubberduck.Parsing/Inspections/Abstract/IInpsectionListener.cs @@ -10,6 +10,7 @@ public interface IInspectionListener: IParseTreeListener IReadOnlyList> Contexts(); IReadOnlyList> Contexts(QualifiedModuleName module); void ClearContexts(); + void ClearContexts(QualifiedModuleName module); QualifiedModuleName CurrentModuleName { get; set; } } } \ No newline at end of file From 04aa26279678c978ff234d4dc243ad7b1ed95a02 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sun, 1 Mar 2020 23:20:44 +0100 Subject: [PATCH 268/461] Stop using inspector for parse tree inspections The inspector swallows exceptions, which we really do not want in tests. --- .../RestoreErrorHandlingQuickFix.cs | 5 ++- .../Inspections/InspectionTestsBase.cs | 37 ++++++++++++++-- .../ThunderCode/ThunderCodeInspectionTests.cs | 44 ++++++++++++++++++- .../QuickFixes/QuickFixTestBase.cs | 33 ++++++++++++-- .../RestoreErrorHandlingQuickFixTests.cs | 8 ++-- 5 files changed, 112 insertions(+), 15 deletions(-) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs index 4706372e81..8f12b0b7f2 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using System.Threading; using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Concrete; @@ -93,7 +94,9 @@ public override void Fix(IInspectionResult result, IRewriteSession rewriteSessio var rewriter = rewriteSession.CheckOutModuleRewriter(result.QualifiedSelection.QualifiedName); var context = (VBAParser.OnErrorStmtContext)result.Context; - var labels = bodyElementContext.GetDescendents().ToArray(); + var labels = bodyElementContext.GetDescendents() + .OrderBy(labelContext => labelContext.GetSelection()) + .ToArray(); var maximumExistingLabelIndex = GetMaximumExistingLabelIndex(labels); var unhandledContexts = resultProperties.Properties; var offset = unhandledContexts.IndexOf(result.Context); diff --git a/RubberduckTests/Inspections/InspectionTestsBase.cs b/RubberduckTests/Inspections/InspectionTestsBase.cs index 4ada1584d3..9d39e059bd 100644 --- a/RubberduckTests/Inspections/InspectionTestsBase.cs +++ b/RubberduckTests/Inspections/InspectionTestsBase.cs @@ -1,7 +1,12 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Threading; +using Antlr4.Runtime.Tree; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.Parsing; +using Rubberduck.VBEditor; +using Rubberduck.VBEditor.Extensions; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; using RubberduckTests.Mocks; @@ -53,13 +58,37 @@ public IEnumerable InspectionResults(IVBE vbe) private static IEnumerable InspectionResults(IInspection inspection, RubberduckParserState state) { - if (inspection is IParseTreeInspection) + if (inspection is IParseTreeInspection parseTreeInspection) { - var inspector = InspectionsHelper.GetInspector(inspection); - return inspector.FindIssuesAsync(state, CancellationToken.None).Result; + WalkTrees(parseTreeInspection, state); } return inspection.GetInspectionResults(CancellationToken.None); } + + protected static void WalkTrees(IParseTreeInspection inspection, RubberduckParserState state) + { + var codeKind = inspection.TargetKindOfCode; + var listener = inspection.Listener; + + List> trees; + switch (codeKind) + { + case CodeKind.AttributesCode: + trees = state.AttributeParseTrees; + break; + case CodeKind.CodePaneCode: + trees = state.ParseTrees; + break; + default: + throw new ArgumentOutOfRangeException(nameof(codeKind), codeKind, null); + } + + foreach (var (module, tree) in trees) + { + listener.CurrentModuleName = module; + ParseTreeWalker.Default.Walk(listener, tree); + } + } } } \ No newline at end of file diff --git a/RubberduckTests/Inspections/ThunderCode/ThunderCodeInspectionTests.cs b/RubberduckTests/Inspections/ThunderCode/ThunderCodeInspectionTests.cs index 9e70612a12..6ce5db6fad 100644 --- a/RubberduckTests/Inspections/ThunderCode/ThunderCodeInspectionTests.cs +++ b/RubberduckTests/Inspections/ThunderCode/ThunderCodeInspectionTests.cs @@ -1,10 +1,16 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Threading; +using Antlr4.Runtime.Tree; using NUnit.Framework; using Rubberduck.Inspections.Inspections.Concrete.ThunderCode; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.Parsing; +using Rubberduck.Resources.Inspections; +using Rubberduck.VBEditor; +using Rubberduck.VBEditor.Extensions; using RubberduckTests.Mocks; namespace RubberduckTests.Inspections.ThunderCode @@ -275,11 +281,45 @@ private static void ThunderCatsGo(Func inspe using (var state = MockParser.CreateAndParse(vbe.Object)) { var inspection = inspectionFunction(state); - var inspector = InspectionsHelper.GetInspector(inspection); - var actualResults = inspector.FindIssuesAsync(state, CancellationToken.None).Result; + var actualResults = InspectionResults(inspection, state); Assert.AreEqual(expectedCount, actualResults.Count()); } } + + private static IEnumerable InspectionResults(IInspection inspection, RubberduckParserState state) + { + if (inspection is IParseTreeInspection parseTreeInspection) + { + WalkTrees(parseTreeInspection, state); + } + + return inspection.GetInspectionResults(CancellationToken.None); + } + + private static void WalkTrees(IParseTreeInspection inspection, RubberduckParserState state) + { + var codeKind = inspection.TargetKindOfCode; + var listener = inspection.Listener; + + List> trees; + switch (codeKind) + { + case CodeKind.AttributesCode: + trees = state.AttributeParseTrees; + break; + case CodeKind.CodePaneCode: + trees = state.ParseTrees; + break; + default: + throw new ArgumentOutOfRangeException(nameof(codeKind), codeKind, null); + } + + foreach (var (module, tree) in trees) + { + listener.CurrentModuleName = module; + ParseTreeWalker.Default.Walk(listener, tree); + } + } } } diff --git a/RubberduckTests/QuickFixes/QuickFixTestBase.cs b/RubberduckTests/QuickFixes/QuickFixTestBase.cs index 691792bb63..163d3c6c5b 100644 --- a/RubberduckTests/QuickFixes/QuickFixTestBase.cs +++ b/RubberduckTests/QuickFixes/QuickFixTestBase.cs @@ -2,14 +2,15 @@ using System.Collections.Generic; using System.Linq; using System.Threading; +using Antlr4.Runtime.Tree; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.Parsing; using Rubberduck.VBEditor; +using Rubberduck.VBEditor.Extensions; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; -using RubberduckTests.Inspections; using RubberduckTests.Mocks; namespace RubberduckTests.QuickFixes @@ -90,15 +91,39 @@ private string ApplyQuickFixToAppropriateInspectionResults( private IEnumerable InspectionResults(IInspection inspection, RubberduckParserState state) { - if (inspection is IParseTreeInspection) + if (inspection is IParseTreeInspection parseTreeInspection) { - var inspector = InspectionsHelper.GetInspector(inspection); - return inspector.FindIssuesAsync(state, CancellationToken.None).Result; + WalkTrees(parseTreeInspection, state); } return inspection.GetInspectionResults(CancellationToken.None); } + private static void WalkTrees(IParseTreeInspection inspection, RubberduckParserState state) + { + var codeKind = inspection.TargetKindOfCode; + var listener = inspection.Listener; + + List> trees; + switch (codeKind) + { + case CodeKind.AttributesCode: + trees = state.AttributeParseTrees; + break; + case CodeKind.CodePaneCode: + trees = state.ParseTrees; + break; + default: + throw new ArgumentOutOfRangeException(nameof(codeKind), codeKind, null); + } + + foreach (var (module, tree) in trees) + { + listener.CurrentModuleName = module; + ParseTreeWalker.Default.Walk(listener, tree); + } + } + private void ApplyToFirstResult(IQuickFix quickFix, IEnumerable inspectionResults, IRewriteSession rewriteSession) { var resultToFix = inspectionResults.First(); diff --git a/RubberduckTests/QuickFixes/RestoreErrorHandlingQuickFixTests.cs b/RubberduckTests/QuickFixes/RestoreErrorHandlingQuickFixTests.cs index 7d8f7b325b..d61a032ddc 100644 --- a/RubberduckTests/QuickFixes/RestoreErrorHandlingQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RestoreErrorHandlingQuickFixTests.cs @@ -129,14 +129,14 @@ On Error GoTo ErrorHandler On Error GoTo ErrorHandler1 Exit Sub -ErrorHandler1: +ErrorHandler: If Err.Number > 0 Then 'TODO: handle specific error Err.Clear Resume Next End If Exit Sub -ErrorHandler: +ErrorHandler1: If Err.Number > 0 Then 'TODO: handle specific error Err.Clear Resume Next @@ -167,14 +167,14 @@ On Error GoTo ErrorHandler3 ErrorHandler1: Exit Sub -ErrorHandler3: +ErrorHandler2: If Err.Number > 0 Then 'TODO: handle specific error Err.Clear Resume Next End If Exit Sub -ErrorHandler2: +ErrorHandler3: If Err.Number > 0 Then 'TODO: handle specific error Err.Clear Resume Next From e5efb4885118abe91c7a511e850642a2f396138d Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Mon, 2 Mar 2020 00:48:39 +0100 Subject: [PATCH 269/461] Pass declaration finder along in UnreacableCaseInspection --- .../UnreachableCaseInspection.cs | 84 +++++++++++-------- .../UnreachableCaseInspector.cs | 3 +- .../UnreachableCaseInspectionTests.cs | 24 +++--- 3 files changed, 67 insertions(+), 44 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs index ad33433043..23db741d2a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs @@ -144,29 +144,28 @@ public UnreachableCaseInspection(IDeclarationFinderProvider declarationFinderPro protected override IEnumerable DoGetInspectionResults() { var finder = DeclarationFinderProvider.DeclarationFinder; - var enumStmts = _listener.EnumerationStmtContexts(); - var parseTreeValueVisitor = CreateParseTreeValueVisitor(enumStmts, GetIdentifierReferenceForContext); return finder.UserDeclarations(DeclarationType.Module) .Where(module => module != null) - .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder, parseTreeValueVisitor)) + .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder)) .ToList(); } protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) { var finder = DeclarationFinderProvider.DeclarationFinder; - var enumStmts = _listener.EnumerationStmtContexts(); - var parseTreeValueVisitor = CreateParseTreeValueVisitor(enumStmts, GetIdentifierReferenceForContext); - return DoGetInspectionResults(module, finder, parseTreeValueVisitor); + return DoGetInspectionResults(module, finder); } - private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder, IParseTreeValueVisitor parseTreeValueVisitor) + private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { var qualifiedSelectCaseStmts = Listener.Contexts(module) // ignore filtering here to make the search space smaller .Where(result => !result.IsIgnoringInspectionResultFor(finder, AnnotationName)); + var enumStmts = _listener.EnumerationStmtContexts(); + var parseTreeValueVisitor = CreateParseTreeValueVisitor(enumStmts, context => GetIdentifierReferenceForContextFunction(finder)(module, context)); + return qualifiedSelectCaseStmts .SelectMany(context => ResultsForContext(context, finder, parseTreeValueVisitor)) .ToList(); @@ -174,8 +173,9 @@ private IEnumerable DoGetInspectionResults(QualifiedModuleNam private IEnumerable ResultsForContext(QualifiedContext qualifiedSelectCaseStmt, DeclarationFinder finder, IParseTreeValueVisitor parseTreeValueVisitor) { - var contextValues = qualifiedSelectCaseStmt.Context.Accept(parseTreeValueVisitor); - var selectCaseInspector = _unreachableCaseInspectorFactory.Create((VBAParser.SelectCaseStmtContext)qualifiedSelectCaseStmt.Context, contextValues, GetVariableTypeName); + var module = qualifiedSelectCaseStmt.ModuleName; + var contextValues = parseTreeValueVisitor.VisitChildren(qualifiedSelectCaseStmt.Context); + var selectCaseInspector = _unreachableCaseInspectorFactory.Create((VBAParser.SelectCaseStmtContext)qualifiedSelectCaseStmt.Context, contextValues, GetVariableTypeNameFunction(module, finder)); var results = selectCaseInspector.InspectForUnreachableCases(); @@ -216,28 +216,33 @@ private IInspectionResult CreateInspectionResult(QualifiedContext(selectStmt.ModuleName, unreachableBlock)); } - public IParseTreeValueVisitor CreateParseTreeValueVisitor(IReadOnlyList allEnums, Func func) - => _parseTreeValueVisitorFactory.Create(allEnums, func); + public IParseTreeValueVisitor CreateParseTreeValueVisitor( + IReadOnlyList> allEnums, + Func func) + { + var enums = allEnums.Select(item => item.Context).ToList(); + return _parseTreeValueVisitorFactory.Create(enums, func); + } - //Method is used as a delegate to avoid propagating RubberduckParserState beyond this class - private (bool success, IdentifierReference idRef) GetIdentifierReferenceForContext(ParserRuleContext context) + private Func GetIdentifierReferenceForContextFunction(DeclarationFinder finder) { - return GetIdentifierReferenceForContext(context, DeclarationFinderProvider); + return (module, context) => GetIdentifierReferenceForContext(module, context, finder); } //public static to support tests //FIXME There should not be additional public methods just for tests. This class seems to want to be split or at least reorganized. - public static (bool success, IdentifierReference idRef) GetIdentifierReferenceForContext(ParserRuleContext context, IDeclarationFinderProvider declarationFinderProvider) + public static (bool success, IdentifierReference idRef) GetIdentifierReferenceForContext(QualifiedModuleName module, ParserRuleContext context, DeclarationFinder finder) { if (context == null) { return (false, null); } - //FIXME Get the declaration finder only once inside the inspection to avoid the possibility of inconsistent state due to a reparse while inspections run. - var finder = declarationFinderProvider.DeclarationFinder; - var identifierReferences = finder.MatchName(context.GetText()) - .SelectMany(declaration => declaration.References) + var qualifiedSelection = new QualifiedSelection(module, context.GetSelection()); + + var identifierReferences = + finder + .IdentifierReferences(qualifiedSelection) .Where(reference => reference.Context == context) .ToList(); @@ -246,19 +251,31 @@ public static (bool success, IdentifierReference idRef) GetIdentifierReferenceFo : (false, null); } - //Method is used as a delegate to avoid propogating RubberduckParserState beyond this class - private string GetVariableTypeName(string variableName, ParserRuleContext ancestor) + private Func GetVariableTypeNameFunction(QualifiedModuleName module, DeclarationFinder finder) { - var descendents = ancestor.GetDescendents().Where(desc => desc.GetText().Equals(variableName)).ToList(); - if (descendents.Any()) + return (variableName, ancestor) => GetVariableTypeName(module, variableName, ancestor, finder); + } + + private string GetVariableTypeName(QualifiedModuleName module, string variableName, ParserRuleContext ancestor, DeclarationFinder finder) + { + if (ancestor == null) { - (bool success, IdentifierReference idRef) = GetIdentifierReferenceForContext(descendents.First(), DeclarationFinderProvider); - if (success) - { - return GetBaseTypeForDeclaration(idRef.Declaration); - } + return string.Empty; + } + + var descendents = ancestor.GetDescendents() + .Where(desc => desc.GetText().Equals(variableName)) + .ToList(); + if (!descendents.Any()) + { + return string.Empty; } - return string.Empty; + + var firstDescendent = descendents.First(); + var (success, reference) = GetIdentifierReferenceForContext(module, firstDescendent, finder); + return success ? + GetBaseTypeForDeclaration(reference.Declaration) + : string.Empty; } private string GetBaseTypeForDeclaration(Declaration declaration) @@ -277,8 +294,8 @@ private string GetBaseTypeForDeclaration(Declaration declaration) #region UnreachableCaseInspectionListeners public class UnreachableCaseInspectionListener : InspectionListenerBase { - private readonly IDictionary> _enumStmts = new Dictionary>(); - public IReadOnlyList EnumerationStmtContexts() => _enumStmts.AllValues().ToList(); + private readonly IDictionary>> _enumStmts = new Dictionary>>(); + public IReadOnlyList> EnumerationStmtContexts() => _enumStmts.AllValues().ToList(); public override void ClearContexts() { @@ -305,13 +322,14 @@ public override void EnterEnumerationStmt([NotNull] VBAParser.EnumerationStmtCon private void SaveEnumStmt(VBAParser.EnumerationStmtContext context) { var module = CurrentModuleName; + var qualifiedContext = new QualifiedContext(module, context); if (_enumStmts.TryGetValue(module, out var stmts)) { - stmts.Add(context); + stmts.Add(qualifiedContext); } else { - _enumStmts.Add(module, new List { context }); + _enumStmts.Add(module, new List> { qualifiedContext }); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs index 5715e980de..3327b7423c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs @@ -21,7 +21,8 @@ public class UnreachableCaseInspector : IUnreachableCaseInspector private readonly Func _getVariableDeclarationTypeName; private IParseTreeValue _selectExpressionValue; - public UnreachableCaseInspector(VBAParser.SelectCaseStmtContext selectCaseContext, + public UnreachableCaseInspector( + VBAParser.SelectCaseStmtContext selectCaseContext, IParseTreeVisitorResults inspValues, IParseTreeValueFactory valueFactory, Func getVariableTypeName = null) diff --git a/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs b/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs index 1899463129..2a2e920d15 100644 --- a/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs +++ b/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs @@ -13,7 +13,11 @@ using System.Collections.Generic; using System.Linq; using System.Threading; +using Antlr4.Runtime.Tree; using Moq; +using Rubberduck.Parsing.VBA.Parsing; +using Rubberduck.VBEditor; +using Rubberduck.VBEditor.Extensions; namespace RubberduckTests.Inspections.UnreachableCase { @@ -2461,8 +2465,8 @@ End Sub var factoryProvider = SpecialValueDeclarationEvaluatorFactoryProvider(TestGetValuedDeclaration); var inspection = new UnreachableCaseInspection(state, factoryProvider); - var inspector = InspectionsHelper.GetInspector(inspection); - actualResults = inspector.FindIssuesAsync(state, CancellationToken.None).Result; + WalkTrees(inspection, state); + actualResults = inspection.GetInspectionResults(CancellationToken.None); } var actualUnreachable = actualResults.Where(ar => ar.Description.Equals(Rubberduck.Resources.Inspections.InspectionResults.UnreachableCaseInspection_Unreachable)); @@ -2513,8 +2517,8 @@ End Sub var factoryProvider = SpecialValueDeclarationEvaluatorFactoryProvider(TestGetValuedDeclaration); var inspection = new UnreachableCaseInspection(state, factoryProvider); - var inspector = InspectionsHelper.GetInspector(inspection); - actualResults = inspector.FindIssuesAsync(state, CancellationToken.None).Result; + WalkTrees(inspection, state); + actualResults = inspection.GetInspectionResults(CancellationToken.None); } var actualUnreachable = actualResults.Where(ar => ar.Description.Equals(Rubberduck.Resources.Inspections.InspectionResults.UnreachableCaseInspection_Unreachable)); @@ -2631,14 +2635,14 @@ private IParseTreeVisitorResults GetParseTreeValueResults(string inputCode, out var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out var _); using (var state = MockParser.CreateAndParse(vbe.Object)) { - var firstParserRuleContext = (ParserRuleContext)state.ParseTrees - .First(pt => pt.Value is ParserRuleContext) - .Value; - selectStmt = firstParserRuleContext.GetDescendent(); + var finder = state.DeclarationFinder; + var (parseTreeModule, moduleParseTree) = state.ParseTrees + .First(pt => pt.Value is ParserRuleContext); + selectStmt = ((ParserRuleContext)moduleParseTree).GetDescendent(); var visitor = ParseTreeValueVisitorFactory.Create( new List(), - context => UnreachableCaseInspection.GetIdentifierReferenceForContext(context, state)); - valueResults = selectStmt.Accept(visitor); + (context) => UnreachableCaseInspection.GetIdentifierReferenceForContext(parseTreeModule, context, finder)); + valueResults = visitor.VisitChildren(selectStmt); } return valueResults; } From deea59fcb7b07d2eee3b772a549e3ba3cb6ace64 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Tue, 3 Mar 2020 01:28:35 +0100 Subject: [PATCH 270/461] Refactor ParseTreeValueVisitor It now correctly depends on the module and passes along the found results instead of aggregating them in an instance variable. --- .../ParseTreeValueVisitor.cs | 409 ++++++++++-------- .../ParseTreeValueVisitorFactory.cs | 6 +- .../UnreachableCaseInspection.cs | 22 +- .../UnreachableCaseInspector.cs | 10 +- .../UnreachableCaseInspectorFactory.cs | 9 +- .../UnreachableCaseInspectionTests.cs | 21 +- 6 files changed, 260 insertions(+), 217 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs index 5fed290888..3268dd01d1 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs @@ -6,11 +6,14 @@ using System; using System.Collections.Generic; using System.Linq; +using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { - public interface IParseTreeValueVisitor : IParseTreeVisitor - {} + public interface IParseTreeValueVisitor + { + IParseTreeVisitorResults VisitChildren(QualifiedModuleName module, IRuleNode node); + } public class ParseTreeValueVisitor : IParseTreeValueVisitor { @@ -27,195 +30,198 @@ public EnumMember(VBAParser.EnumerationStmt_ConstantContext constContext, long i public bool HasAssignment { get; } } - private readonly IParseTreeVisitorResults _contextValues; - private readonly IParseTreeValueFactory _inspValueFactory; - private readonly IReadOnlyList _enumStmtContexts; - private List _enumMembers; - private Func _valueDeclarationEvaluator; + private readonly IParseTreeValueFactory _valueFactory; + private readonly Func _valueDeclarationEvaluator; + private readonly IReadOnlyList> _enumStmtContexts; public ParseTreeValueVisitor( - IParseTreeValueFactory valueFactory, - IReadOnlyList allEnums, - Func idRefRetriever, + IParseTreeValueFactory valueFactory, + IReadOnlyList> allEnums, + Func identifierReferenceRetriever, Func valueDeclarationEvaluator = null) { - _inspValueFactory = valueFactory; - IdRefRetriever = idRefRetriever; - _contextValues = new ParseTreeVisitorResults(); + _valueFactory = valueFactory; + IdentifierReferenceRetriever = identifierReferenceRetriever; _enumStmtContexts = allEnums; _valueDeclarationEvaluator = valueDeclarationEvaluator ?? GetValuedDeclaration; } - private Func IdRefRetriever { get; } + //This does not use a qualified context in order to avoid constant boxing and unboxing. + private Func IdentifierReferenceRetriever { get; } - public virtual IParseTreeVisitorResults Visit(IParseTree tree) + public IParseTreeVisitorResults VisitChildren(QualifiedModuleName module, IRuleNode ruleNode) { - if (tree is ParserRuleContext context && !(context is VBAParser.WhiteSpaceContext)) - { - Visit(context); - } - return _contextValues; + var newResults = new ParseTreeVisitorResults(); + return VisitChildren(module, ruleNode, newResults); } - public virtual IParseTreeVisitorResults VisitChildren(IRuleNode node) + //The known results get passed along instead of aggregating from the bottom since other contexts can get already visited when resolving the value of other contexts. + //Passing the results along avoids performing the resolution multiple times. + private IParseTreeVisitorResults VisitChildren(QualifiedModuleName module, IRuleNode node, IParseTreeVisitorResults knownResults) { - if (node is ParserRuleContext context) + if (!(node is ParserRuleContext context)) { - foreach (var child in context.children) - { - Visit(child); - } + return knownResults; } - return _contextValues; - } - public virtual IParseTreeVisitorResults VisitTerminal(ITerminalNode node) - { - return _contextValues; - } + var valueResults = knownResults; + foreach (var child in context.children) + { + valueResults = Visit(module, child, valueResults); + } - public virtual IParseTreeVisitorResults VisitErrorNode(IErrorNode node) - { - return _contextValues; + return valueResults; } - private void StoreVisitResult(ParserRuleContext context, IParseTreeValue inspValue) + private IParseTreeVisitorResults Visit(QualifiedModuleName module, IParseTree tree, IParseTreeVisitorResults knownResults) { - _contextValues.AddIfNotPresent(context, inspValue); - } + var valueResults = knownResults; + if (tree is ParserRuleContext context && !(context is VBAParser.WhiteSpaceContext)) + { + valueResults = Visit(module, context, valueResults); + } - private bool HasResult(ParserRuleContext context) - => _contextValues.Contains(context); + return valueResults; + } - private void Visit(ParserRuleContext parserRuleContext) + private IParseTreeVisitorResults Visit(QualifiedModuleName module, ParserRuleContext parserRuleContext, IParseTreeVisitorResults knownResults) { switch (parserRuleContext) { case VBAParser.LExprContext lExpr: - Visit(lExpr); - return; + return Visit(module, lExpr, knownResults); case VBAParser.LiteralExprContext litExpr: - Visit(litExpr); - return; + return Visit(litExpr, knownResults); case VBAParser.CaseClauseContext caseClause: - VisitChildren(caseClause); - StoreVisitResult(caseClause, _inspValueFactory.Create(caseClause.GetText())); - return; + var caseClauseResults = VisitChildren(module, caseClause, knownResults); + caseClauseResults.AddIfNotPresent(caseClause, _valueFactory.Create(caseClause.GetText())); + return caseClauseResults; case VBAParser.RangeClauseContext rangeClause: - VisitChildren(rangeClause); - StoreVisitResult(rangeClause, _inspValueFactory.Create(rangeClause.GetText())); - return; + var rangeClauseResults = VisitChildren(module, rangeClause, knownResults); + rangeClauseResults.AddIfNotPresent(rangeClause, _valueFactory.Create(rangeClause.GetText())); + return rangeClauseResults; + case VBAParser.LogicalNotOpContext _: + case VBAParser.UnaryMinusOpContext _: + return VisitUnaryOpEvaluationContext(module, parserRuleContext, knownResults); default: if (IsUnaryResultContext(parserRuleContext)) { - VisitUnaryResultContext(parserRuleContext); + return VisitUnaryResultContext(module, parserRuleContext, knownResults); } - else if (IsBinaryOpEvaluationContext(parserRuleContext)) + if (IsBinaryOpEvaluationContext(parserRuleContext)) { - VisitBinaryOpEvaluationContext(parserRuleContext); + return VisitBinaryOpEvaluationContext(module, parserRuleContext, knownResults); } - else if (parserRuleContext is VBAParser.LogicalNotOpContext - || parserRuleContext is VBAParser.UnaryMinusOpContext) - { - VisitUnaryOpEvaluationContext(parserRuleContext); - } - return; + + return knownResults; } } - private void Visit(VBAParser.LExprContext context) + private IParseTreeVisitorResults Visit(QualifiedModuleName module, VBAParser.LExprContext context, IParseTreeVisitorResults knownResults) { - if (HasResult(context)) + if (knownResults.Contains(context)) { - return; + return knownResults; } + var valueResults = knownResults; + IParseTreeValue newResult = null; - if (TryGetLExprValue(context, out string lexprValue, out string declaredType)) + if (TryGetLExprValue(module, context, ref valueResults, out string lExprValue, out string declaredType)) { - newResult = _inspValueFactory.CreateDeclaredType(lexprValue, declaredType); + newResult = _valueFactory.CreateDeclaredType(lExprValue, declaredType); } else { - var smplName = context.GetDescendent(); - if (TryGetIdentifierReferenceForContext(smplName, out IdentifierReference idRef)) + var simpleName = context.GetDescendent(); + if (TryGetIdentifierReferenceForContext(module, simpleName, out var reference)) { - var declarationTypeName = GetBaseTypeForDeclaration(idRef.Declaration); - newResult = _inspValueFactory.CreateDeclaredType(context.GetText(), declarationTypeName); + var declarationTypeName = GetBaseTypeForDeclaration(reference.Declaration); + newResult = _valueFactory.CreateDeclaredType(context.GetText(), declarationTypeName); } } if (newResult != null) { - StoreVisitResult(context, newResult); + valueResults.AddIfNotPresent(context, newResult); } + + return valueResults; } - private void Visit(VBAParser.LiteralExprContext context) + private IParseTreeVisitorResults Visit(VBAParser.LiteralExprContext context, IParseTreeVisitorResults knownResults) { - if (!HasResult(context)) + if (knownResults.Contains(context)) { - var nResult = _inspValueFactory.Create(context.GetText()); - StoreVisitResult(context, nResult); + return knownResults; } + + var valueResults = knownResults; + var nResult = _valueFactory.Create(context.GetText()); + valueResults.AddIfNotPresent(context, nResult); + + return valueResults; } - private void VisitBinaryOpEvaluationContext(ParserRuleContext context) + private IParseTreeVisitorResults VisitBinaryOpEvaluationContext(QualifiedModuleName module, ParserRuleContext context, IParseTreeVisitorResults knownResults) { - VisitChildren(context); + var valueResults = VisitChildren(module, context, knownResults); - RetrieveOpEvaluationElements(context, out (IParseTreeValue LHS, IParseTreeValue RHS, string Symbol) binaryData); - if (binaryData.LHS is null || binaryData.RHS is null) + var (lhs, rhs, operatorSymbol) = RetrieveOpEvaluationElements(context, valueResults); + if (lhs is null || rhs is null) { - return; + return valueResults; } - if (binaryData.LHS.IsOverflowExpression) + if (lhs.IsOverflowExpression) { - StoreVisitResult(context, binaryData.LHS); - return; + valueResults.AddIfNotPresent(context, lhs); + return valueResults; } - if (binaryData.RHS.IsOverflowExpression) + if (rhs.IsOverflowExpression) { - StoreVisitResult(context, binaryData.RHS); - return; + valueResults.AddIfNotPresent(context, rhs); + return valueResults; } - var calculator = new ParseTreeExpressionEvaluator(_inspValueFactory, context.IsOptionCompareBinary()); - var result = calculator.Evaluate(binaryData.LHS, binaryData.RHS, binaryData.Symbol); + var calculator = new ParseTreeExpressionEvaluator(_valueFactory, context.IsOptionCompareBinary()); + var result = calculator.Evaluate(lhs, rhs, operatorSymbol); + valueResults.AddIfNotPresent(context, result); - StoreVisitResult(context, result); + return valueResults; } - private void VisitUnaryOpEvaluationContext(ParserRuleContext context) + private IParseTreeVisitorResults VisitUnaryOpEvaluationContext(QualifiedModuleName module, ParserRuleContext context, IParseTreeVisitorResults knownResults) { - VisitChildren(context); + var valueResults = VisitChildren(module, context, knownResults); - RetrieveOpEvaluationElements(context, out (IParseTreeValue LHS, IParseTreeValue RHS, string Symbol) unaryData); - if (unaryData.LHS is null || unaryData.RHS != null) + var (lhs, rhs, operatorSymbol) = RetrieveOpEvaluationElements(context, valueResults); + if (lhs is null || rhs != null) { - return; + return valueResults; } - var calculator = new ParseTreeExpressionEvaluator(_inspValueFactory, context.IsOptionCompareBinary()); - var result = calculator.Evaluate(unaryData.LHS, unaryData.Symbol); - StoreVisitResult(context, result); + var calculator = new ParseTreeExpressionEvaluator(_valueFactory, context.IsOptionCompareBinary()); + var result = calculator.Evaluate(lhs, operatorSymbol); + valueResults.AddIfNotPresent(context, result); + + return valueResults; } - private void RetrieveOpEvaluationElements(ParserRuleContext context, out (IParseTreeValue LHS, IParseTreeValue RHS, string Symbol) operandElements) + private static (IParseTreeValue LHS, IParseTreeValue RHS, string Symbol) RetrieveOpEvaluationElements(ParserRuleContext context, IParseTreeVisitorResults knownResults) { - operandElements = (null, null, string.Empty); + (IParseTreeValue LHS, IParseTreeValue RHS, string Symbol) operandElements = (null, null, string.Empty); foreach (var child in NonWhitespaceChildren(context)) { - if (child is ParserRuleContext ctxt) + if (child is ParserRuleContext childContext) { if (operandElements.LHS is null) { - operandElements.LHS = _contextValues.GetValue(ctxt); + operandElements.LHS = knownResults.GetValue(childContext); } else if (operandElements.RHS is null) { - operandElements.RHS = _contextValues.GetValue(ctxt); + operandElements.RHS = knownResults.GetValue(childContext); } } else @@ -223,28 +229,39 @@ private void RetrieveOpEvaluationElements(ParserRuleContext context, out (IParse operandElements.Symbol = child.GetText(); } } + + return operandElements; } - private void VisitUnaryResultContext(ParserRuleContext parserRuleContext) + private IParseTreeVisitorResults VisitUnaryResultContext(QualifiedModuleName module, ParserRuleContext parserRuleContext, IParseTreeVisitorResults knownResults) { - VisitChildren(parserRuleContext); + var valueResults = VisitChildren(module, parserRuleContext, knownResults); + + var firstChildWithValue = ParserRuleContextChildren(parserRuleContext) + .FirstOrDefault(childContext => valueResults.Contains(childContext)); - foreach (var ctxt in ParserRuleContextChildren(parserRuleContext).Where(ct => HasResult(ct))) + if (firstChildWithValue != null) { - StoreVisitResult(parserRuleContext, _contextValues.GetValue(ctxt)); - return; + valueResults.AddIfNotPresent(parserRuleContext, valueResults.GetValue(firstChildWithValue)); } + + return valueResults; } - private void VisitChildren(ParserRuleContext context) + private IParseTreeVisitorResults VisitChildren(QualifiedModuleName module, ParserRuleContext context, IParseTreeVisitorResults knownResults) { - if (!HasResult(context)) + if (knownResults.Contains(context)) { - foreach (var ctxt in ParserRuleContextChildren(context)) - { - Visit(ctxt); - } + return knownResults; } + + var valueResults = knownResults; + foreach (var childContext in ParserRuleContextChildren(context)) + { + valueResults = Visit(module, childContext, valueResults); + } + + return valueResults; } private static IEnumerable ParserRuleContextChildren(ParserRuleContext ptParent) @@ -253,20 +270,26 @@ private static IEnumerable ParserRuleContextChildren(ParserRu private static IEnumerable NonWhitespaceChildren(ParserRuleContext ptParent) => ptParent.children.Where(ch => !(ch is VBAParser.WhiteSpaceContext)); - private bool TryGetLExprValue(VBAParser.LExprContext lExprContext, out string expressionValue, out string declaredTypeName) + private bool TryGetLExprValue(QualifiedModuleName module, VBAParser.LExprContext lExprContext, ref IParseTreeVisitorResults knownResults, out string expressionValue, out string declaredTypeName) { expressionValue = string.Empty; declaredTypeName = string.Empty; if (lExprContext.TryGetChildContext(out VBAParser.MemberAccessExprContext memberAccess)) { var member = memberAccess.GetChild(); - GetContextValue(member, out declaredTypeName, out expressionValue); + var (typeName, valueText, resultValues) = GetContextValue(module, member, knownResults); + knownResults = resultValues; + declaredTypeName = typeName; + expressionValue = valueText; return true; } if (lExprContext.TryGetChildContext(out VBAParser.SimpleNameExprContext smplName)) { - GetContextValue(smplName, out declaredTypeName, out expressionValue); + var (typeName, valueText, resultValues) = GetContextValue(module, smplName, knownResults); + knownResults = resultValues; + declaredTypeName = typeName; + expressionValue = valueText; return true; } @@ -283,90 +306,91 @@ private bool TryGetLExprValue(VBAParser.LExprContext lExprContext, out string ex private (bool IsType, string ExpressionValue, string TypeName) GetValuedDeclaration(Declaration declaration) { - if (declaration is ValuedDeclaration valuedDeclaration) + if (!(declaration is ValuedDeclaration valuedDeclaration)) { - var typeName = GetBaseTypeForDeclaration(declaration); - return (true, valuedDeclaration.Expression, typeName); + return (false, null, null); } - return (false, null, null); + + var typeName = GetBaseTypeForDeclaration(declaration); + return (true, valuedDeclaration.Expression, typeName); } - private void GetContextValue(ParserRuleContext context, out string declaredTypeName, out string expressionValue) + private (string declarationTypeName, string expressionValue, IParseTreeVisitorResults resultValues) GetContextValue(QualifiedModuleName module, ParserRuleContext context, IParseTreeVisitorResults knownResults) { - expressionValue = context.GetText(); - declaredTypeName = string.Empty; - - if (TryGetIdentifierReferenceForContext(context, out IdentifierReference rangeClauseIdentifierReference)) + if (!TryGetIdentifierReferenceForContext(module, context, out var rangeClauseIdentifierReference)) { - var declaration = rangeClauseIdentifierReference.Declaration; - expressionValue = rangeClauseIdentifierReference.IdentifierName; - declaredTypeName = GetBaseTypeForDeclaration(declaration); + return (string.Empty, context.GetText(), knownResults); + } + + var declaration = rangeClauseIdentifierReference.Declaration; + var expressionValue = rangeClauseIdentifierReference.IdentifierName; + var declaredTypeName = GetBaseTypeForDeclaration(declaration); - (bool IsValuedDeclaration, string ExpressionValue, string TypeName) = _valueDeclarationEvaluator(declaration); + var (isValuedDeclaration, valuedExpressionValue, typeName) = _valueDeclarationEvaluator(declaration); + if (isValuedDeclaration) + { + if (ParseTreeValue.TryGetNonPrintingControlCharCompareToken(valuedExpressionValue, out string resolvedValue)) + { + return (Tokens.String, resolvedValue, knownResults); + } - if( IsValuedDeclaration) + if (long.TryParse(valuedExpressionValue, out _)) { - expressionValue = ExpressionValue; - declaredTypeName = TypeName; + return (typeName, valuedExpressionValue, knownResults); + } - if (ParseTreeValue.TryGetNonPrintingControlCharCompareToken(expressionValue, out string resolvedValue)) - { - expressionValue = resolvedValue; - declaredTypeName = Tokens.String; - return; - } + expressionValue = valuedExpressionValue; + declaredTypeName = typeName; + } - if (long.TryParse(expressionValue, out _)) - { - return; - } - } + if (declaration.DeclarationType.HasFlag(DeclarationType.Constant)) + { + var (constantTokenExpressionValue, resultValues) = GetConstantContextValueToken(module, declaration.Context, knownResults); + return (declaredTypeName, constantTokenExpressionValue, resultValues); + } - if (declaration.DeclarationType.HasFlag(DeclarationType.Constant)) + if (declaration.DeclarationType.HasFlag(DeclarationType.EnumerationMember)) + { + var (constantExpressionValue, resultValues) = GetConstantContextValueToken(module, declaration.Context, knownResults); + if (!constantExpressionValue.Equals(string.Empty)) { - expressionValue = GetConstantContextValueToken(declaration.Context); - } - else if (declaration.DeclarationType.HasFlag(DeclarationType.EnumerationMember)) - { - declaredTypeName = Tokens.Long; - expressionValue = GetConstantContextValueToken(declaration.Context); - if (expressionValue.Equals(string.Empty)) - { - if (_enumMembers is null) - { - LoadEnumMemberValues(); - } - var enumValue = _enumMembers.SingleOrDefault(dt => dt.ConstantContext == declaration.Context); - expressionValue = enumValue?.Value.ToString() ?? string.Empty; - } + return (Tokens.Long, constantExpressionValue, resultValues); } + + var (enumMembers, valueResults) = EnumMembers(resultValues); + var enumValue = enumMembers.SingleOrDefault(dt => dt.ConstantContext == declaration.Context); + var enumExpressionValue = enumValue?.Value.ToString() ?? string.Empty; + return (Tokens.Long, enumExpressionValue, valueResults); } + + return (declaredTypeName, expressionValue, knownResults); } - private bool TryGetIdentifierReferenceForContext(ParserRuleContext context, out IdentifierReference idRef) + private bool TryGetIdentifierReferenceForContext(QualifiedModuleName module, ParserRuleContext context, out IdentifierReference referenceForContext) { - idRef = null; - if (IdRefRetriever != null) + if (IdentifierReferenceRetriever == null) { - (bool success, IdentifierReference idReference) = IdRefRetriever(context); - idRef = idReference; - return success; + referenceForContext = null; + return false; } - return false; + + var (success, reference) = IdentifierReferenceRetriever(module, context); + referenceForContext = reference; + return success; } - private string GetConstantContextValueToken(ParserRuleContext context) + private (string valueText, IParseTreeVisitorResults valueResults) GetConstantContextValueToken(QualifiedModuleName module, ParserRuleContext context, IParseTreeVisitorResults knownResults) { if (context is null) { - return string.Empty; + return (string.Empty, knownResults); } var declarationContextChildren = context.children.ToList(); var equalsSymbolIndex = declarationContextChildren.FindIndex(ch => ch.Equals(context.GetToken(VBAParser.EQ, 0))); var contextsOfInterest = new List(); - for (int idx = equalsSymbolIndex + 1; idx < declarationContextChildren.Count(); idx++) + for (int idx = equalsSymbolIndex + 1; idx < declarationContextChildren.Count; idx++) { var childCtxt = declarationContextChildren[idx]; if (!(childCtxt is VBAParser.WhiteSpaceContext)) @@ -377,13 +401,13 @@ private string GetConstantContextValueToken(ParserRuleContext context) foreach (var child in contextsOfInterest) { - Visit(child); - if (_contextValues.TryGetValue(child, out IParseTreeValue value)) + knownResults = Visit(module, child, knownResults); + if (knownResults.TryGetValue(child, out var value)) { - return value.Token; + return (value.Token, knownResults); } } - return string.Empty; + return (string.Empty, knownResults); } private string GetBaseTypeForDeclaration(Declaration declaration) @@ -419,22 +443,41 @@ private static bool IsBinaryOpEvaluationContext(T context) return false; } - private void LoadEnumMemberValues() + private List _enumMembers; + private (IReadOnlyList enumMembers, IParseTreeVisitorResults resultValues) EnumMembers(IParseTreeVisitorResults knownResults) + { + if (_enumMembers != null) + { + return (_enumMembers, knownResults); + } + + var resultValues = LoadEnumMemberValues(_enumStmtContexts, knownResults); + return (_enumMembers, resultValues); + } + + //This procedure loads the list _enumMembers. + //The incrementally added values are used within the call to Visit. + private IParseTreeVisitorResults LoadEnumMemberValues(IReadOnlyList> enumStmtContexts, IParseTreeVisitorResults knownResults) { + var valueResults = knownResults; _enumMembers = new List(); - foreach (var enumStmt in _enumStmtContexts) + foreach (var qualifiedEnumStmt in enumStmtContexts) { + var module = qualifiedEnumStmt.ModuleName; + var enumStmt = qualifiedEnumStmt.Context; long enumAssignedValue = -1; - var enumConstContexts = enumStmt.children.Where(ch => ch is VBAParser.EnumerationStmt_ConstantContext).Cast(); + var enumConstContexts = enumStmt.children + .OfType(); foreach (var enumConstContext in enumConstContexts) { enumAssignedValue++; var enumMember = new EnumMember(enumConstContext, enumAssignedValue); if (enumMember.HasAssignment) { - Visit(enumMember.ConstantContext); + valueResults = Visit(module, enumMember.ConstantContext, valueResults); - var valueText = GetConstantContextValueToken(enumMember.ConstantContext); + var (valueText, resultValues) = GetConstantContextValueToken(module, enumMember.ConstantContext, valueResults); + valueResults = resultValues; if (!valueText.Equals(string.Empty)) { enumMember.Value = long.Parse(valueText); @@ -444,18 +487,8 @@ private void LoadEnumMemberValues() _enumMembers.Add(enumMember); } } - } - } - public class ValueResultEventArgs : EventArgs - { - public ValueResultEventArgs(ParserRuleContext context, IParseTreeValue value) - { - Context = context; - Value = value; + return valueResults; } - - public ParserRuleContext Context { set; get; } - public IParseTreeValue Value { set; get; } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitorFactory.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitorFactory.cs index b465f02ac3..37d3d23270 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitorFactory.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitorFactory.cs @@ -1,14 +1,16 @@ using System; using System.Collections.Generic; using Antlr4.Runtime; +using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; +using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { public interface IParseTreeValueVisitorFactory { - IParseTreeValueVisitor Create(IReadOnlyList allEnums, Func idRefRetriever); + IParseTreeValueVisitor Create(IReadOnlyList> allEnums, Func idRefRetriever); } public class ParseTreeValueVisitorFactory : IParseTreeValueVisitorFactory @@ -20,7 +22,7 @@ public ParseTreeValueVisitorFactory(IParseTreeValueFactory valueFactory) _valueFactory = valueFactory; } - public IParseTreeValueVisitor Create(IReadOnlyList allEnums, Func identifierReferenceRetriever) + public IParseTreeValueVisitor Create(IReadOnlyList> allEnums, Func identifierReferenceRetriever) { return new ParseTreeValueVisitor(_valueFactory, allEnums, identifierReferenceRetriever); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs index 23db741d2a..1e69385d4e 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs @@ -164,7 +164,7 @@ private IEnumerable DoGetInspectionResults(QualifiedModuleNam .Where(result => !result.IsIgnoringInspectionResultFor(finder, AnnotationName)); var enumStmts = _listener.EnumerationStmtContexts(); - var parseTreeValueVisitor = CreateParseTreeValueVisitor(enumStmts, context => GetIdentifierReferenceForContextFunction(finder)(module, context)); + var parseTreeValueVisitor = CreateParseTreeValueVisitor(enumStmts, GetIdentifierReferenceForContextFunction(finder)); return qualifiedSelectCaseStmts .SelectMany(context => ResultsForContext(context, finder, parseTreeValueVisitor)) @@ -174,8 +174,8 @@ private IEnumerable DoGetInspectionResults(QualifiedModuleNam private IEnumerable ResultsForContext(QualifiedContext qualifiedSelectCaseStmt, DeclarationFinder finder, IParseTreeValueVisitor parseTreeValueVisitor) { var module = qualifiedSelectCaseStmt.ModuleName; - var contextValues = parseTreeValueVisitor.VisitChildren(qualifiedSelectCaseStmt.Context); - var selectCaseInspector = _unreachableCaseInspectorFactory.Create((VBAParser.SelectCaseStmtContext)qualifiedSelectCaseStmt.Context, contextValues, GetVariableTypeNameFunction(module, finder)); + var contextValues = parseTreeValueVisitor.VisitChildren(module, qualifiedSelectCaseStmt.Context); + var selectCaseInspector = _unreachableCaseInspectorFactory.Create(module, (VBAParser.SelectCaseStmtContext)qualifiedSelectCaseStmt.Context, contextValues, GetVariableTypeNameFunction(finder)); var results = selectCaseInspector.InspectForUnreachableCases(); @@ -218,13 +218,12 @@ private IInspectionResult CreateInspectionResult(QualifiedContext> allEnums, - Func func) + Func func) { - var enums = allEnums.Select(item => item.Context).ToList(); - return _parseTreeValueVisitorFactory.Create(enums, func); + return _parseTreeValueVisitorFactory.Create(allEnums, func); } - private Func GetIdentifierReferenceForContextFunction(DeclarationFinder finder) + private Func GetIdentifierReferenceForContextFunction(DeclarationFinder finder) { return (module, context) => GetIdentifierReferenceForContext(module, context, finder); } @@ -251,12 +250,13 @@ public static (bool success, IdentifierReference idRef) GetIdentifierReferenceFo : (false, null); } - private Func GetVariableTypeNameFunction(QualifiedModuleName module, DeclarationFinder finder) + private Func GetVariableTypeNameFunction(DeclarationFinder finder) { - return (variableName, ancestor) => GetVariableTypeName(module, variableName, ancestor, finder); + var referenceRetriever = GetIdentifierReferenceForContextFunction(finder); + return (variableName, module, ancestor) => GetVariableTypeName(module, variableName, ancestor, referenceRetriever); } - private string GetVariableTypeName(QualifiedModuleName module, string variableName, ParserRuleContext ancestor, DeclarationFinder finder) + private string GetVariableTypeName(QualifiedModuleName module, string variableName, ParserRuleContext ancestor, Func referenceRetriever) { if (ancestor == null) { @@ -272,7 +272,7 @@ private string GetVariableTypeName(QualifiedModuleName module, string variableNa } var firstDescendent = descendents.First(); - var (success, reference) = GetIdentifierReferenceForContext(module, firstDescendent, finder); + var (success, reference) = referenceRetriever(module, firstDescendent); return success ? GetBaseTypeForDeclaration(reference.Declaration) : string.Empty; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs index 3327b7423c..a999502ad3 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { @@ -18,18 +19,21 @@ public class UnreachableCaseInspector : IUnreachableCaseInspector private readonly IEnumerable _caseClauses; private readonly ParserRuleContext _caseElseContext; private readonly IParseTreeValueFactory _valueFactory; - private readonly Func _getVariableDeclarationTypeName; + private readonly Func _getVariableDeclarationTypeName; + private readonly QualifiedModuleName _module; private IParseTreeValue _selectExpressionValue; public UnreachableCaseInspector( + QualifiedModuleName module, VBAParser.SelectCaseStmtContext selectCaseContext, IParseTreeVisitorResults inspValues, IParseTreeValueFactory valueFactory, - Func getVariableTypeName = null) + Func getVariableTypeName = null) { _valueFactory = valueFactory; _caseClauses = selectCaseContext.caseClause(); _caseElseContext = selectCaseContext.caseElseClause(); + _module = module; _getVariableDeclarationTypeName = getVariableTypeName; ParseTreeValueResults = inspValues; SetSelectExpressionTypeName(selectCaseContext, inspValues); @@ -158,7 +162,7 @@ private IExpressionFilter BuildRangeClauseFilter(IEnumerable func = null); + Func func = null); } public class UnreachableCaseInspectorFactory : IUnreachableCaseInspectorFactory @@ -21,9 +24,9 @@ public UnreachableCaseInspectorFactory(IParseTreeValueFactory valueFactory) _valueFactory = valueFactory; } - public IUnreachableCaseInspector Create(VBAParser.SelectCaseStmtContext selectStmt, IParseTreeVisitorResults results, Func func = null) + public IUnreachableCaseInspector Create(QualifiedModuleName module, VBAParser.SelectCaseStmtContext selectStmt, IParseTreeVisitorResults results, Func func = null) { - return new UnreachableCaseInspector(selectStmt, results, _valueFactory, func); + return new UnreachableCaseInspector(module, selectStmt, results, _valueFactory, func); } } } diff --git a/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs b/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs index 2a2e920d15..af2a02aab2 100644 --- a/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs +++ b/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs @@ -1464,7 +1464,7 @@ Case 4 'Unreachable End Select End Sub"; - (string expectedMsg, string actualMsg) = CheckActualResultsEqualsExpected(inputCode, unreachable: 1); + var (expectedMsg, actualMsg) = CheckActualResultsEqualsExpected(inputCode, unreachable: 1); Assert.AreEqual(expectedMsg, actualMsg); } @@ -2547,9 +2547,9 @@ private IParseTreeValueVisitorFactory SpecialValueDeclarationEvaluatorParseTreeV { var factoryMock = new Mock(); factoryMock.Setup(m => m.Create( - It.IsAny>(), - It.IsAny>())) - .Returns, Func>((allEnums, identifierReferenceRetriever) => + It.IsAny>>(), + It.IsAny>())) + .Returns>, Func>((allEnums, identifierReferenceRetriever) => new ParseTreeValueVisitor(valueFactory, allEnums, identifierReferenceRetriever, valueDeclarationEvaluator)); return factoryMock.Object; } @@ -2622,13 +2622,13 @@ private static string BuildResultString(int unreachableCount, int mismatchCount, private string GetSelectExpressionType(string inputCode) { - var selectStmtValueResults = GetParseTreeValueResults(inputCode, out VBAParser.SelectCaseStmtContext selectStmtContext); + var selectStmtValueResults = GetParseTreeValueResults(inputCode, out VBAParser.SelectCaseStmtContext selectStmtContext, out var module); - var inspector = UnreachableCaseInspectorFactory.Create(selectStmtContext, selectStmtValueResults); + var inspector = UnreachableCaseInspectorFactory.Create(module, selectStmtContext, selectStmtValueResults); return inspector.SelectExpressionTypeName; } - private IParseTreeVisitorResults GetParseTreeValueResults(string inputCode, out VBAParser.SelectCaseStmtContext selectStmt) + private IParseTreeVisitorResults GetParseTreeValueResults(string inputCode, out VBAParser.SelectCaseStmtContext selectStmt, out QualifiedModuleName contextModule) { selectStmt = null; IParseTreeVisitorResults valueResults = null; @@ -2640,9 +2640,10 @@ private IParseTreeVisitorResults GetParseTreeValueResults(string inputCode, out .First(pt => pt.Value is ParserRuleContext); selectStmt = ((ParserRuleContext)moduleParseTree).GetDescendent(); var visitor = ParseTreeValueVisitorFactory.Create( - new List(), - (context) => UnreachableCaseInspection.GetIdentifierReferenceForContext(parseTreeModule, context, finder)); - valueResults = visitor.VisitChildren(selectStmt); + new List>(), + (module, context) => UnreachableCaseInspection.GetIdentifierReferenceForContext(module, context, finder)); + valueResults = visitor.VisitChildren(parseTreeModule, selectStmt); + contextModule = parseTreeModule; } return valueResults; } From 5eda095319f72e648bd3e0c9397daf6b07713342 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Tue, 3 Mar 2020 01:46:56 +0100 Subject: [PATCH 271/461] Make the enum members part of the ParseTreeVisitorResults This allows to remove the corresponding state from the ParseTreeValueVisitor. --- .../ParseTreeValueVisitor.cs | 65 +++++++++---------- .../ParseTreeVisitorResults.cs | 22 +++++-- 2 files changed, 46 insertions(+), 41 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs index 3268dd01d1..b455798834 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs @@ -15,21 +15,21 @@ public interface IParseTreeValueVisitor IParseTreeVisitorResults VisitChildren(QualifiedModuleName module, IRuleNode node); } - public class ParseTreeValueVisitor : IParseTreeValueVisitor + public class EnumMember { - private class EnumMember + public EnumMember(VBAParser.EnumerationStmt_ConstantContext constContext, long initValue) { - public EnumMember(VBAParser.EnumerationStmt_ConstantContext constContext, long initValue) - { - ConstantContext = constContext; - Value = initValue; - HasAssignment = constContext.children.Any(ch => ch.Equals(constContext.GetToken(VBAParser.EQ, 0))); - } - public VBAParser.EnumerationStmt_ConstantContext ConstantContext { get; } - public long Value { set; get; } - public bool HasAssignment { get; } + ConstantContext = constContext; + Value = initValue; + HasAssignment = constContext.children.Any(ch => ch.Equals(constContext.GetToken(VBAParser.EQ, 0))); } + public VBAParser.EnumerationStmt_ConstantContext ConstantContext { get; } + public long Value { set; get; } + public bool HasAssignment { get; } + } + public class ParseTreeValueVisitor : IParseTreeValueVisitor + { private readonly IParseTreeValueFactory _valueFactory; private readonly Func _valueDeclarationEvaluator; private readonly IReadOnlyList> _enumStmtContexts; @@ -57,7 +57,7 @@ public IParseTreeVisitorResults VisitChildren(QualifiedModuleName module, IRuleN //The known results get passed along instead of aggregating from the bottom since other contexts can get already visited when resolving the value of other contexts. //Passing the results along avoids performing the resolution multiple times. - private IParseTreeVisitorResults VisitChildren(QualifiedModuleName module, IRuleNode node, IParseTreeVisitorResults knownResults) + private IMutableParseTreeVisitorResults VisitChildren(QualifiedModuleName module, IRuleNode node, IMutableParseTreeVisitorResults knownResults) { if (!(node is ParserRuleContext context)) { @@ -73,7 +73,7 @@ private IParseTreeVisitorResults VisitChildren(QualifiedModuleName module, IRule return valueResults; } - private IParseTreeVisitorResults Visit(QualifiedModuleName module, IParseTree tree, IParseTreeVisitorResults knownResults) + private IMutableParseTreeVisitorResults Visit(QualifiedModuleName module, IParseTree tree, IMutableParseTreeVisitorResults knownResults) { var valueResults = knownResults; if (tree is ParserRuleContext context && !(context is VBAParser.WhiteSpaceContext)) @@ -84,7 +84,7 @@ private IParseTreeVisitorResults Visit(QualifiedModuleName module, IParseTree tr return valueResults; } - private IParseTreeVisitorResults Visit(QualifiedModuleName module, ParserRuleContext parserRuleContext, IParseTreeVisitorResults knownResults) + private IMutableParseTreeVisitorResults Visit(QualifiedModuleName module, ParserRuleContext parserRuleContext, IMutableParseTreeVisitorResults knownResults) { switch (parserRuleContext) { @@ -117,7 +117,7 @@ private IParseTreeVisitorResults Visit(QualifiedModuleName module, ParserRuleCon } } - private IParseTreeVisitorResults Visit(QualifiedModuleName module, VBAParser.LExprContext context, IParseTreeVisitorResults knownResults) + private IMutableParseTreeVisitorResults Visit(QualifiedModuleName module, VBAParser.LExprContext context, IMutableParseTreeVisitorResults knownResults) { if (knownResults.Contains(context)) { @@ -149,7 +149,7 @@ private IParseTreeVisitorResults Visit(QualifiedModuleName module, VBAParser.LEx return valueResults; } - private IParseTreeVisitorResults Visit(VBAParser.LiteralExprContext context, IParseTreeVisitorResults knownResults) + private IMutableParseTreeVisitorResults Visit(VBAParser.LiteralExprContext context, IMutableParseTreeVisitorResults knownResults) { if (knownResults.Contains(context)) { @@ -163,7 +163,7 @@ private IParseTreeVisitorResults Visit(VBAParser.LiteralExprContext context, IPa return valueResults; } - private IParseTreeVisitorResults VisitBinaryOpEvaluationContext(QualifiedModuleName module, ParserRuleContext context, IParseTreeVisitorResults knownResults) + private IMutableParseTreeVisitorResults VisitBinaryOpEvaluationContext(QualifiedModuleName module, ParserRuleContext context, IMutableParseTreeVisitorResults knownResults) { var valueResults = VisitChildren(module, context, knownResults); @@ -191,7 +191,7 @@ private IParseTreeVisitorResults VisitBinaryOpEvaluationContext(QualifiedModuleN return valueResults; } - private IParseTreeVisitorResults VisitUnaryOpEvaluationContext(QualifiedModuleName module, ParserRuleContext context, IParseTreeVisitorResults knownResults) + private IMutableParseTreeVisitorResults VisitUnaryOpEvaluationContext(QualifiedModuleName module, ParserRuleContext context, IMutableParseTreeVisitorResults knownResults) { var valueResults = VisitChildren(module, context, knownResults); @@ -208,7 +208,7 @@ private IParseTreeVisitorResults VisitUnaryOpEvaluationContext(QualifiedModuleNa return valueResults; } - private static (IParseTreeValue LHS, IParseTreeValue RHS, string Symbol) RetrieveOpEvaluationElements(ParserRuleContext context, IParseTreeVisitorResults knownResults) + private static (IParseTreeValue LHS, IParseTreeValue RHS, string Symbol) RetrieveOpEvaluationElements(ParserRuleContext context, IMutableParseTreeVisitorResults knownResults) { (IParseTreeValue LHS, IParseTreeValue RHS, string Symbol) operandElements = (null, null, string.Empty); foreach (var child in NonWhitespaceChildren(context)) @@ -233,7 +233,7 @@ private static (IParseTreeValue LHS, IParseTreeValue RHS, string Symbol) Retriev return operandElements; } - private IParseTreeVisitorResults VisitUnaryResultContext(QualifiedModuleName module, ParserRuleContext parserRuleContext, IParseTreeVisitorResults knownResults) + private IMutableParseTreeVisitorResults VisitUnaryResultContext(QualifiedModuleName module, ParserRuleContext parserRuleContext, IMutableParseTreeVisitorResults knownResults) { var valueResults = VisitChildren(module, parserRuleContext, knownResults); @@ -248,7 +248,7 @@ private IParseTreeVisitorResults VisitUnaryResultContext(QualifiedModuleName mod return valueResults; } - private IParseTreeVisitorResults VisitChildren(QualifiedModuleName module, ParserRuleContext context, IParseTreeVisitorResults knownResults) + private IMutableParseTreeVisitorResults VisitChildren(QualifiedModuleName module, ParserRuleContext context, IMutableParseTreeVisitorResults knownResults) { if (knownResults.Contains(context)) { @@ -270,7 +270,7 @@ private static IEnumerable ParserRuleContextChildren(ParserRu private static IEnumerable NonWhitespaceChildren(ParserRuleContext ptParent) => ptParent.children.Where(ch => !(ch is VBAParser.WhiteSpaceContext)); - private bool TryGetLExprValue(QualifiedModuleName module, VBAParser.LExprContext lExprContext, ref IParseTreeVisitorResults knownResults, out string expressionValue, out string declaredTypeName) + private bool TryGetLExprValue(QualifiedModuleName module, VBAParser.LExprContext lExprContext, ref IMutableParseTreeVisitorResults knownResults, out string expressionValue, out string declaredTypeName) { expressionValue = string.Empty; declaredTypeName = string.Empty; @@ -315,7 +315,7 @@ private bool TryGetLExprValue(QualifiedModuleName module, VBAParser.LExprContext return (true, valuedDeclaration.Expression, typeName); } - private (string declarationTypeName, string expressionValue, IParseTreeVisitorResults resultValues) GetContextValue(QualifiedModuleName module, ParserRuleContext context, IParseTreeVisitorResults knownResults) + private (string declarationTypeName, string expressionValue, IMutableParseTreeVisitorResults resultValues) GetContextValue(QualifiedModuleName module, ParserRuleContext context, IMutableParseTreeVisitorResults knownResults) { if (!TryGetIdentifierReferenceForContext(module, context, out var rangeClauseIdentifierReference)) { @@ -379,7 +379,7 @@ private bool TryGetIdentifierReferenceForContext(QualifiedModuleName module, Par return success; } - private (string valueText, IParseTreeVisitorResults valueResults) GetConstantContextValueToken(QualifiedModuleName module, ParserRuleContext context, IParseTreeVisitorResults knownResults) + private (string valueText, IMutableParseTreeVisitorResults valueResults) GetConstantContextValueToken(QualifiedModuleName module, ParserRuleContext context, IMutableParseTreeVisitorResults knownResults) { if (context is null) { @@ -443,24 +443,21 @@ private static bool IsBinaryOpEvaluationContext(T context) return false; } - private List _enumMembers; - private (IReadOnlyList enumMembers, IParseTreeVisitorResults resultValues) EnumMembers(IParseTreeVisitorResults knownResults) + private (IReadOnlyList enumMembers, IMutableParseTreeVisitorResults resultValues) EnumMembers(IMutableParseTreeVisitorResults knownResults) { - if (_enumMembers != null) + if (knownResults.EnumMembers.Count > 0) { - return (_enumMembers, knownResults); + return (knownResults.EnumMembers, knownResults); } var resultValues = LoadEnumMemberValues(_enumStmtContexts, knownResults); - return (_enumMembers, resultValues); + return (resultValues.EnumMembers, resultValues); } - //This procedure loads the list _enumMembers. - //The incrementally added values are used within the call to Visit. - private IParseTreeVisitorResults LoadEnumMemberValues(IReadOnlyList> enumStmtContexts, IParseTreeVisitorResults knownResults) + //The enum members incrementally to the parse tree visitor result are used within the call to Visit. + private IMutableParseTreeVisitorResults LoadEnumMemberValues(IReadOnlyList> enumStmtContexts, IMutableParseTreeVisitorResults knownResults) { var valueResults = knownResults; - _enumMembers = new List(); foreach (var qualifiedEnumStmt in enumStmtContexts) { var module = qualifiedEnumStmt.ModuleName; @@ -484,7 +481,7 @@ private IParseTreeVisitorResults LoadEnumMemberValues(IReadOnlyList EnumMembers { get; } } - public class ParseTreeVisitorResults : IParseTreeVisitorResults + public interface IMutableParseTreeVisitorResults : IParseTreeVisitorResults { - private Dictionary _parseTreeValues; + void AddIfNotPresent(ParserRuleContext context, IParseTreeValue value); + void Add(EnumMember enumMember); + } - public ParseTreeVisitorResults() - { - _parseTreeValues = new Dictionary(); - } + public class ParseTreeVisitorResults : IMutableParseTreeVisitorResults + { + private readonly Dictionary _parseTreeValues = new Dictionary(); + private readonly List _enumMembers = new List(); public IParseTreeValue GetValue(ParserRuleContext context) { @@ -74,5 +76,11 @@ public void AddIfNotPresent(ParserRuleContext context, IParseTreeValue value) _parseTreeValues.Add(context, value); } } + + public IReadOnlyList EnumMembers => _enumMembers; + public void Add(EnumMember enumMember) + { + _enumMembers.Add(enumMember); + } } } From 5689b95d9d65d50a552615825f95c51f42cf6bd3 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Tue, 3 Mar 2020 21:18:16 +0100 Subject: [PATCH 272/461] Get enumeration statements from enumeration members instead of the listener in UnreachableCaseInspection --- .../ParseTreeValueVisitor.cs | 70 ++++++++++--------- .../ParseTreeValueVisitorFactory.cs | 9 +-- .../ParseTreeVisitorResults.cs | 32 +++++++-- .../UnreachableCaseInspection.cs | 53 ++------------ .../UnreachableCaseInspectionTests.cs | 24 +++---- 5 files changed, 82 insertions(+), 106 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs index b455798834..0b317f6d9d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs @@ -32,17 +32,14 @@ public class ParseTreeValueVisitor : IParseTreeValueVisitor { private readonly IParseTreeValueFactory _valueFactory; private readonly Func _valueDeclarationEvaluator; - private readonly IReadOnlyList> _enumStmtContexts; public ParseTreeValueVisitor( IParseTreeValueFactory valueFactory, - IReadOnlyList> allEnums, Func identifierReferenceRetriever, Func valueDeclarationEvaluator = null) { _valueFactory = valueFactory; IdentifierReferenceRetriever = identifierReferenceRetriever; - _enumStmtContexts = allEnums; _valueDeclarationEvaluator = valueDeclarationEvaluator ?? GetValuedDeclaration; } @@ -357,10 +354,15 @@ private bool TryGetLExprValue(QualifiedModuleName module, VBAParser.LExprContext return (Tokens.Long, constantExpressionValue, resultValues); } - var (enumMembers, valueResults) = EnumMembers(resultValues); - var enumValue = enumMembers.SingleOrDefault(dt => dt.ConstantContext == declaration.Context); - var enumExpressionValue = enumValue?.Value.ToString() ?? string.Empty; - return (Tokens.Long, enumExpressionValue, valueResults); + if (declaration.Context.Parent is VBAParser.EnumerationStmtContext enumStmt) + { + var (enumMembers, valueResults) = EnumMembers(module, enumStmt, resultValues); + var enumValue = enumMembers.SingleOrDefault(enumMember => enumMember.ConstantContext == declaration.Context); + var enumExpressionValue = enumValue?.Value.ToString() ?? string.Empty; + return (Tokens.Long, enumExpressionValue, valueResults); + } + + return (Tokens.Long, string.Empty, resultValues); } return (declaredTypeName, expressionValue, knownResults); @@ -443,46 +445,46 @@ private static bool IsBinaryOpEvaluationContext(T context) return false; } - private (IReadOnlyList enumMembers, IMutableParseTreeVisitorResults resultValues) EnumMembers(IMutableParseTreeVisitorResults knownResults) + private (IReadOnlyList enumMembers, IMutableParseTreeVisitorResults resultValues) EnumMembers(QualifiedModuleName enumModule, VBAParser.EnumerationStmtContext enumerationStmtContext, IMutableParseTreeVisitorResults knownResults) { - if (knownResults.EnumMembers.Count > 0) + if (knownResults.TryGetEnumMembers(enumerationStmtContext, out var enumMembers)) + { + return (enumMembers, knownResults); + } + + var resultValues = LoadEnumMemberValues(enumModule, enumerationStmtContext, knownResults); + if (knownResults.TryGetEnumMembers(enumerationStmtContext, out var newEnumMembers)) { - return (knownResults.EnumMembers, knownResults); + return (newEnumMembers, resultValues); } - var resultValues = LoadEnumMemberValues(_enumStmtContexts, knownResults); - return (resultValues.EnumMembers, resultValues); + return (new List(), resultValues); } //The enum members incrementally to the parse tree visitor result are used within the call to Visit. - private IMutableParseTreeVisitorResults LoadEnumMemberValues(IReadOnlyList> enumStmtContexts, IMutableParseTreeVisitorResults knownResults) + private IMutableParseTreeVisitorResults LoadEnumMemberValues(QualifiedModuleName enumModule, VBAParser.EnumerationStmtContext enumStmt, IMutableParseTreeVisitorResults knownResults) { var valueResults = knownResults; - foreach (var qualifiedEnumStmt in enumStmtContexts) - { - var module = qualifiedEnumStmt.ModuleName; - var enumStmt = qualifiedEnumStmt.Context; - long enumAssignedValue = -1; - var enumConstContexts = enumStmt.children - .OfType(); - foreach (var enumConstContext in enumConstContexts) + long enumAssignedValue = -1; + var enumConstContexts = enumStmt.children + .OfType(); + foreach (var enumConstContext in enumConstContexts) + { + enumAssignedValue++; + var enumMember = new EnumMember(enumConstContext, enumAssignedValue); + if (enumMember.HasAssignment) { - enumAssignedValue++; - var enumMember = new EnumMember(enumConstContext, enumAssignedValue); - if (enumMember.HasAssignment) + valueResults = Visit(enumModule, enumMember.ConstantContext, valueResults); + + var (valueText, resultValues) = GetConstantContextValueToken(enumModule, enumMember.ConstantContext, valueResults); + valueResults = resultValues; + if (!valueText.Equals(string.Empty)) { - valueResults = Visit(module, enumMember.ConstantContext, valueResults); - - var (valueText, resultValues) = GetConstantContextValueToken(module, enumMember.ConstantContext, valueResults); - valueResults = resultValues; - if (!valueText.Equals(string.Empty)) - { - enumMember.Value = long.Parse(valueText); - enumAssignedValue = enumMember.Value; - } + enumMember.Value = long.Parse(valueText); + enumAssignedValue = enumMember.Value; } - valueResults.Add(enumMember); } + valueResults.AddEnumMember(enumStmt, enumMember); } return valueResults; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitorFactory.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitorFactory.cs index 37d3d23270..0f54417f5e 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitorFactory.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitorFactory.cs @@ -1,8 +1,5 @@ using System; -using System.Collections.Generic; using Antlr4.Runtime; -using Rubberduck.Parsing; -using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.VBEditor; @@ -10,7 +7,7 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { public interface IParseTreeValueVisitorFactory { - IParseTreeValueVisitor Create(IReadOnlyList> allEnums, Func idRefRetriever); + IParseTreeValueVisitor Create(Func idRefRetriever); } public class ParseTreeValueVisitorFactory : IParseTreeValueVisitorFactory @@ -22,9 +19,9 @@ public ParseTreeValueVisitorFactory(IParseTreeValueFactory valueFactory) _valueFactory = valueFactory; } - public IParseTreeValueVisitor Create(IReadOnlyList> allEnums, Func identifierReferenceRetriever) + public IParseTreeValueVisitor Create(Func identifierReferenceRetriever) { - return new ParseTreeValueVisitor(_valueFactory, allEnums, identifierReferenceRetriever); + return new ParseTreeValueVisitor(_valueFactory, identifierReferenceRetriever); } } } \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeVisitorResults.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeVisitorResults.cs index a3f0a47f96..9c150ba38e 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeVisitorResults.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeVisitorResults.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Rubberduck.Parsing.Grammar; namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { @@ -13,19 +14,19 @@ public interface IParseTreeVisitorResults string GetToken(ParserRuleContext context); bool Contains(ParserRuleContext context); bool TryGetValue(ParserRuleContext context, out IParseTreeValue value); - IReadOnlyList EnumMembers { get; } + bool TryGetEnumMembers(VBAParser.EnumerationStmtContext enumerationStmtContext, out IReadOnlyList enumMembers); } public interface IMutableParseTreeVisitorResults : IParseTreeVisitorResults { void AddIfNotPresent(ParserRuleContext context, IParseTreeValue value); - void Add(EnumMember enumMember); + void AddEnumMember(VBAParser.EnumerationStmtContext enumerationStmtContext, EnumMember enumMember); } public class ParseTreeVisitorResults : IMutableParseTreeVisitorResults { private readonly Dictionary _parseTreeValues = new Dictionary(); - private readonly List _enumMembers = new List(); + private readonly Dictionary> _enumMembers = new Dictionary>(); public IParseTreeValue GetValue(ParserRuleContext context) { @@ -77,10 +78,29 @@ public void AddIfNotPresent(ParserRuleContext context, IParseTreeValue value) } } - public IReadOnlyList EnumMembers => _enumMembers; - public void Add(EnumMember enumMember) + public bool TryGetEnumMembers(VBAParser.EnumerationStmtContext enumerationStmtContext, out IReadOnlyList enumMembers) { - _enumMembers.Add(enumMember); + if (!_enumMembers.TryGetValue(enumerationStmtContext, out var enumMemberList)) + { + enumMembers = null; + return false; + } + + enumMembers = enumMemberList; + return true; + } + + public void AddEnumMember(VBAParser.EnumerationStmtContext enumerationStmtContext, EnumMember enumMember) + { + if (_enumMembers.TryGetValue(enumerationStmtContext, out var enumMemberList)) + { + enumMemberList.Add(enumMember); + } + else + { + enumMemberList = new List{enumMember}; + _enumMembers.Add(enumerationStmtContext, enumMemberList); + } } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs index 1e69385d4e..6e65b6c67c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs @@ -144,28 +144,27 @@ public UnreachableCaseInspection(IDeclarationFinderProvider declarationFinderPro protected override IEnumerable DoGetInspectionResults() { var finder = DeclarationFinderProvider.DeclarationFinder; + var parseTreeValueVisitor = CreateParseTreeValueVisitor(GetIdentifierReferenceForContextFunction(finder)); return finder.UserDeclarations(DeclarationType.Module) .Where(module => module != null) - .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder)) + .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder, parseTreeValueVisitor)) .ToList(); } protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) { var finder = DeclarationFinderProvider.DeclarationFinder; - return DoGetInspectionResults(module, finder); + var parseTreeValueVisitor = CreateParseTreeValueVisitor(GetIdentifierReferenceForContextFunction(finder)); + return DoGetInspectionResults(module, finder, parseTreeValueVisitor); } - private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder, IParseTreeValueVisitor parseTreeValueVisitor) { var qualifiedSelectCaseStmts = Listener.Contexts(module) // ignore filtering here to make the search space smaller .Where(result => !result.IsIgnoringInspectionResultFor(finder, AnnotationName)); - var enumStmts = _listener.EnumerationStmtContexts(); - var parseTreeValueVisitor = CreateParseTreeValueVisitor(enumStmts, GetIdentifierReferenceForContextFunction(finder)); - return qualifiedSelectCaseStmts .SelectMany(context => ResultsForContext(context, finder, parseTreeValueVisitor)) .ToList(); @@ -216,11 +215,9 @@ private IInspectionResult CreateInspectionResult(QualifiedContext(selectStmt.ModuleName, unreachableBlock)); } - public IParseTreeValueVisitor CreateParseTreeValueVisitor( - IReadOnlyList> allEnums, - Func func) + public IParseTreeValueVisitor CreateParseTreeValueVisitor(Func func) { - return _parseTreeValueVisitorFactory.Create(allEnums, func); + return _parseTreeValueVisitorFactory.Create(func); } private Func GetIdentifierReferenceForContextFunction(DeclarationFinder finder) @@ -291,48 +288,12 @@ private string GetBaseTypeForDeclaration(Declaration declaration) return localDeclaration is null ? declaration.AsTypeName : localDeclaration.AsTypeName; } - #region UnreachableCaseInspectionListeners public class UnreachableCaseInspectionListener : InspectionListenerBase { - private readonly IDictionary>> _enumStmts = new Dictionary>>(); - public IReadOnlyList> EnumerationStmtContexts() => _enumStmts.AllValues().ToList(); - - public override void ClearContexts() - { - _enumStmts.Clear(); - base.ClearContexts(); - } - - public override void ClearContexts(QualifiedModuleName module) - { - _enumStmts.Remove(module); - base.ClearContexts(module); - } - public override void EnterSelectCaseStmt([NotNull] VBAParser.SelectCaseStmtContext context) { SaveContext(context); } - - public override void EnterEnumerationStmt([NotNull] VBAParser.EnumerationStmtContext context) - { - SaveEnumStmt(context); - } - - private void SaveEnumStmt(VBAParser.EnumerationStmtContext context) - { - var module = CurrentModuleName; - var qualifiedContext = new QualifiedContext(module, context); - if (_enumStmts.TryGetValue(module, out var stmts)) - { - stmts.Add(qualifiedContext); - } - else - { - _enumStmts.Add(module, new List> { qualifiedContext }); - } - } } - #endregion } } \ No newline at end of file diff --git a/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs b/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs index af2a02aab2..21867dbcdf 100644 --- a/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs +++ b/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs @@ -839,7 +839,7 @@ Case x < y Case 95 'OK Case x > -3000 - 'Ureachable + 'Unreachable Case Else 'OK End Select @@ -2459,7 +2459,7 @@ End Sub var vbe = CreateStandardModuleProject(inputCode); - var actualResults = Enumerable.Empty(); + IEnumerable actualResults; using (var state = MockParser.CreateAndParse(vbe.Object)) { var factoryProvider = SpecialValueDeclarationEvaluatorFactoryProvider(TestGetValuedDeclaration); @@ -2511,7 +2511,7 @@ End Sub "; var vbe = CreateStandardModuleProject(inputCode); - var actualResults = Enumerable.Empty(); + IEnumerable actualResults; using (var state = MockParser.CreateAndParse(vbe.Object)) { var factoryProvider = SpecialValueDeclarationEvaluatorFactoryProvider(TestGetValuedDeclaration); @@ -2546,11 +2546,9 @@ private IUnreachableCaseInspectionFactoryProvider SpecialValueDeclarationEvaluat private IParseTreeValueVisitorFactory SpecialValueDeclarationEvaluatorParseTreeValueVisitorFactory(IParseTreeValueFactory valueFactory, Func valueDeclarationEvaluator) { var factoryMock = new Mock(); - factoryMock.Setup(m => m.Create( - It.IsAny>>(), - It.IsAny>())) - .Returns>, Func>((allEnums, identifierReferenceRetriever) => - new ParseTreeValueVisitor(valueFactory, allEnums, identifierReferenceRetriever, valueDeclarationEvaluator)); + factoryMock.Setup(m => m.Create(It.IsAny>())) + .Returns>((identifierReferenceRetriever) => + new ParseTreeValueVisitor(valueFactory, identifierReferenceRetriever, valueDeclarationEvaluator)); return factoryMock.Object; } @@ -2595,7 +2593,7 @@ private static (bool IsType, string ExpressionValue, string TypeName) TestGetVal { Rubberduck.Resources.Inspections.InspectionResults.UnreachableCaseInspection_CaseElse, caseElse }, }; - var actualResults = InspectionResultsForModules(components); + var actualResults = InspectionResultsForModules(components).ToList(); var actualUnreachable = actualResults.Where(ar => ar.Description.Equals(Rubberduck.Resources.Inspections.InspectionResults.UnreachableCaseInspection_Unreachable)); var actualMismatches = actualResults.Where(ar => ar.Description.Equals(Rubberduck.Resources.Inspections.InspectionResults.UnreachableCaseInspection_TypeMismatch)); @@ -2614,7 +2612,7 @@ private static (bool IsType, string ExpressionValue, string TypeName) TestGetVal return (expectedMsg, actualMsg); } - private Moq.Mock CreateStandardModuleProject(string inputCode) + private Mock CreateStandardModuleProject(string inputCode) => MockVbeBuilder.BuildFromModules(new List<(string moduleName, string inputCode, ComponentType componentType)>() { ("TestModule1", inputCode, ComponentType.StandardModule) }); private static string BuildResultString(int unreachableCount, int mismatchCount, int caseElseCount, int inherentCount, int overflowCount) @@ -2631,7 +2629,7 @@ private string GetSelectExpressionType(string inputCode) private IParseTreeVisitorResults GetParseTreeValueResults(string inputCode, out VBAParser.SelectCaseStmtContext selectStmt, out QualifiedModuleName contextModule) { selectStmt = null; - IParseTreeVisitorResults valueResults = null; + IParseTreeVisitorResults valueResults; var vbe = MockVbeBuilder.BuildFromSingleStandardModule(inputCode, out var _); using (var state = MockParser.CreateAndParse(vbe.Object)) { @@ -2639,9 +2637,7 @@ private IParseTreeVisitorResults GetParseTreeValueResults(string inputCode, out var (parseTreeModule, moduleParseTree) = state.ParseTrees .First(pt => pt.Value is ParserRuleContext); selectStmt = ((ParserRuleContext)moduleParseTree).GetDescendent(); - var visitor = ParseTreeValueVisitorFactory.Create( - new List>(), - (module, context) => UnreachableCaseInspection.GetIdentifierReferenceForContext(module, context, finder)); + var visitor = ParseTreeValueVisitorFactory.Create((module, context) => UnreachableCaseInspection.GetIdentifierReferenceForContext(module, context, finder)); valueResults = visitor.VisitChildren(parseTreeModule, selectStmt); contextModule = parseTreeModule; } From fbdcf005e67641dc8f7d3f1fd19b9bd5510292b8 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Wed, 4 Mar 2020 00:22:40 +0100 Subject: [PATCH 273/461] Remove most state from UnreachableCaseInspector --- .../ExpressionFilter.cs | 10 +- .../UnreachableCaseInspection.cs | 19 +- .../UnreachableCaseInspector.cs | 255 +++++++++--------- .../UnreachableCaseInspectorFactory.cs | 12 +- .../ExpressionFilterUnitTests.cs | 6 +- .../UnreachableCaseInspectionTests.cs | 4 +- 6 files changed, 153 insertions(+), 153 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilter.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilter.cs index 8ec5f36fcf..5b73fe5396 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilter.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilter.cs @@ -17,7 +17,7 @@ public enum VariableClauseTypes public interface IExpressionFilter { - void AddExpression(IRangeClauseExpression expression); + void CheckAndAddExpression(IRangeClauseExpression expression); void AddComparablePredicateFilter(string variable, string variableTypeName); bool HasFilters { get; } bool FiltersAllValues { get; } @@ -172,12 +172,12 @@ public virtual IParseTreeValue SelectExpressionValue set { _selectExpressionValue = value; - AddExpression(new IsClauseExpression(_selectExpressionValue, RelationalOperators.NEQ)); + CheckAndAddExpression(new IsClauseExpression(_selectExpressionValue, RelationalOperators.NEQ)); } get => _selectExpressionValue; } - public void AddExpression(IRangeClauseExpression expression) + public void CheckAndAddExpression(IRangeClauseExpression expression) { if (expression is null || expression.ToString().Equals(string.Empty) @@ -289,7 +289,7 @@ protected bool AddComparablePredicate(string lhs, IRangeClauseExpression express if (!positiveLogic.FiltersAllValues) { IRangeClauseExpression predicateExpression = new IsClauseExpression(parseTreeValue, expression.OpSymbol); - positiveLogic.AddExpression(predicateExpression); + positiveLogic.CheckAndAddExpression(predicateExpression); if (positiveLogic.FiltersAllValues) { AddSingleValue(_trueValue); @@ -301,7 +301,7 @@ protected bool AddComparablePredicate(string lhs, IRangeClauseExpression express { IRangeClauseExpression predicateExpressionInverse = new IsClauseExpression(parseTreeValue, RelationalInverse(expression.OpSymbol)); - negativeLogic.AddExpression(predicateExpressionInverse); + negativeLogic.CheckAndAddExpression(predicateExpressionInverse); if (negativeLogic.FiltersAllValues) { AddSingleValue(_falseValue); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs index 6e65b6c67c..bbf44083f2 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs @@ -13,7 +13,6 @@ using Rubberduck.Parsing.Symbols; using System; using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Parsing.VBA.Parsing; @@ -145,10 +144,11 @@ protected override IEnumerable DoGetInspectionResults() { var finder = DeclarationFinderProvider.DeclarationFinder; var parseTreeValueVisitor = CreateParseTreeValueVisitor(GetIdentifierReferenceForContextFunction(finder)); + var selectCaseInspector = _unreachableCaseInspectorFactory.Create(GetVariableTypeNameFunction(finder)); return finder.UserDeclarations(DeclarationType.Module) .Where(module => module != null) - .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder, parseTreeValueVisitor)) + .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder, parseTreeValueVisitor, selectCaseInspector)) .ToList(); } @@ -156,27 +156,28 @@ protected override IEnumerable DoGetInspectionResults(Qualifi { var finder = DeclarationFinderProvider.DeclarationFinder; var parseTreeValueVisitor = CreateParseTreeValueVisitor(GetIdentifierReferenceForContextFunction(finder)); - return DoGetInspectionResults(module, finder, parseTreeValueVisitor); + var selectCaseInspector = _unreachableCaseInspectorFactory.Create(GetVariableTypeNameFunction(finder)); + return DoGetInspectionResults(module, finder, parseTreeValueVisitor, selectCaseInspector); } - private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder, IParseTreeValueVisitor parseTreeValueVisitor) + private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder, IParseTreeValueVisitor parseTreeValueVisitor, IUnreachableCaseInspector selectCaseInspector) { var qualifiedSelectCaseStmts = Listener.Contexts(module) // ignore filtering here to make the search space smaller .Where(result => !result.IsIgnoringInspectionResultFor(finder, AnnotationName)); return qualifiedSelectCaseStmts - .SelectMany(context => ResultsForContext(context, finder, parseTreeValueVisitor)) + .SelectMany(context => ResultsForContext(context, parseTreeValueVisitor, selectCaseInspector)) .ToList(); } - private IEnumerable ResultsForContext(QualifiedContext qualifiedSelectCaseStmt, DeclarationFinder finder, IParseTreeValueVisitor parseTreeValueVisitor) + private IEnumerable ResultsForContext(QualifiedContext qualifiedSelectCaseStmt, IParseTreeValueVisitor parseTreeValueVisitor, IUnreachableCaseInspector selectCaseInspector) { var module = qualifiedSelectCaseStmt.ModuleName; - var contextValues = parseTreeValueVisitor.VisitChildren(module, qualifiedSelectCaseStmt.Context); - var selectCaseInspector = _unreachableCaseInspectorFactory.Create(module, (VBAParser.SelectCaseStmtContext)qualifiedSelectCaseStmt.Context, contextValues, GetVariableTypeNameFunction(finder)); + var selectStmt = (VBAParser.SelectCaseStmtContext)qualifiedSelectCaseStmt.Context; + var contextValues = parseTreeValueVisitor.VisitChildren(module, selectStmt); - var results = selectCaseInspector.InspectForUnreachableCases(); + var results = selectCaseInspector.InspectForUnreachableCases(module, selectStmt, contextValues); return results .Select(resultTpl => CreateInspectionResult(qualifiedSelectCaseStmt, resultTpl.context, resultTpl.resultType)) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs index a999502ad3..455005b36d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs @@ -10,188 +10,193 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { public interface IUnreachableCaseInspector { - ICollection<(UnreachableCaseInspection.CaseInspectionResultType resultType, ParserRuleContext context)> InspectForUnreachableCases(); - string SelectExpressionTypeName { get; } + ICollection<(UnreachableCaseInspection.CaseInspectionResultType resultType, ParserRuleContext context)> InspectForUnreachableCases( + QualifiedModuleName module, + VBAParser.SelectCaseStmtContext selectCaseContext, + IParseTreeVisitorResults parseTreeValues); + string SelectExpressionTypeName( + VBAParser.SelectCaseStmtContext selectCaseContext, + IParseTreeVisitorResults parseTreeValues); } public class UnreachableCaseInspector : IUnreachableCaseInspector { - private readonly IEnumerable _caseClauses; - private readonly ParserRuleContext _caseElseContext; private readonly IParseTreeValueFactory _valueFactory; private readonly Func _getVariableDeclarationTypeName; - private readonly QualifiedModuleName _module; - private IParseTreeValue _selectExpressionValue; public UnreachableCaseInspector( - QualifiedModuleName module, - VBAParser.SelectCaseStmtContext selectCaseContext, - IParseTreeVisitorResults inspValues, IParseTreeValueFactory valueFactory, Func getVariableTypeName = null) { _valueFactory = valueFactory; - _caseClauses = selectCaseContext.caseClause(); - _caseElseContext = selectCaseContext.caseElseClause(); - _module = module; _getVariableDeclarationTypeName = getVariableTypeName; - ParseTreeValueResults = inspValues; - SetSelectExpressionTypeName(selectCaseContext, inspValues); } - public List UnreachableCases { set; get; } = new List(); - - public List MismatchTypeCases { set; get; } = new List(); - - public List OverflowCases { set; get; } = new List(); - - public List InherentlyUnreachableCases { set; get; } = new List(); + public ICollection<(UnreachableCaseInspection.CaseInspectionResultType resultType, ParserRuleContext context)> InspectForUnreachableCases( + QualifiedModuleName module, + VBAParser.SelectCaseStmtContext selectCaseContext, + IParseTreeVisitorResults parseTreeValues) + { + var (selectExpressionTypeName, selectExpressionValue) = SelectExpressionTypeNameAndValue(selectCaseContext, parseTreeValues); - public List UnreachableCaseElseCases { set; get; } = new List(); + if (!InspectableTypes.Contains(selectExpressionTypeName)) + { + return new List<(UnreachableCaseInspection.CaseInspectionResultType resultType, ParserRuleContext context)>(); + } - public ICollection<(UnreachableCaseInspection.CaseInspectionResultType resultType, ParserRuleContext context)> - AllResults => - WithType(UnreachableCaseInspection.CaseInspectionResultType.Unreachable, UnreachableCases) - .Concat(WithType(UnreachableCaseInspection.CaseInspectionResultType.InherentlyUnreachable, InherentlyUnreachableCases)) - .Concat(WithType(UnreachableCaseInspection.CaseInspectionResultType.MismatchType, MismatchTypeCases)) - .Concat(WithType(UnreachableCaseInspection.CaseInspectionResultType.Overflow, OverflowCases)) - .Concat(WithType(UnreachableCaseInspection.CaseInspectionResultType.CaseElse, UnreachableCaseElseCases)) + var results = new List<(UnreachableCaseInspection.CaseInspectionResultType resultType, ParserRuleContext context)>(); + + var caseClausesWithInvalidTypeMarker = selectCaseContext.caseClause() + .Select(caseClause => WithInvalidValueType(caseClause, parseTreeValues)) .ToList(); - private static IEnumerable<(UnreachableCaseInspection.CaseInspectionResultType type, ParserRuleContext context)> - WithType(UnreachableCaseInspection.CaseInspectionResultType type, IEnumerable source) - { - return source.Select(context => (type, context)); - } + var invalidCaseClausesWithInvalidTypeMarker = caseClausesWithInvalidTypeMarker + .Where(tpl => tpl.invalidValueType.HasValue) + .Select(tpl => (tpl.invalidValueType.Value, (ParserRuleContext)tpl.caseClause)); - public string SelectExpressionTypeName { private set; get; } = string.Empty; + results.AddRange(invalidCaseClausesWithInvalidTypeMarker); - private IParseTreeVisitorResults ParseTreeValueResults { get; } + var remainingCasesToInspect = caseClausesWithInvalidTypeMarker + .Where(tpl => tpl.invalidValueType == null) + .Select(tpl => tpl.caseClause) + .ToList(); - public ICollection<(UnreachableCaseInspection.CaseInspectionResultType resultType, ParserRuleContext context)> InspectForUnreachableCases() - { - if (!InspectableTypes.Contains(SelectExpressionTypeName)) + var rangeClauseFilter = BuildRangeClauseFilter(module, remainingCasesToInspect, selectExpressionTypeName, parseTreeValues); + if (!(selectExpressionValue is null) && selectExpressionValue.ParsesToConstantValue) { - return new List<(UnreachableCaseInspection.CaseInspectionResultType resultType, ParserRuleContext context)>(); + rangeClauseFilter.SelectExpressionValue = selectExpressionValue; } - var remainingCasesToInspect = new List(); - - foreach (var caseClause in _caseClauses) + foreach (var caseClause in remainingCasesToInspect) { - var containsMismatch = false; - var containsOverflow = false; - foreach ( var range in caseClause.rangeClause()) - { - var childResults = ParseTreeValueResults.GetChildResults(range); - var childValues = childResults - .Select(ch => ParseTreeValueResults.GetValue(ch)) - .ToList(); - if (childValues.Any(chr => chr.IsMismatchExpression)) - { - containsMismatch = true; - } - if (childValues.Any(chr => chr.IsOverflowExpression)) - { - containsOverflow = true; - } - } - if (containsMismatch) - { - MismatchTypeCases.Add(caseClause); - } - else if (containsOverflow) + var rangeClauseExpressions = caseClause.rangeClause() + .Select(range => GetRangeClauseExpression(range, parseTreeValues)) + .ToList(); + + foreach (var expression in rangeClauseExpressions) { - OverflowCases.Add(caseClause); + rangeClauseFilter.CheckAndAddExpression(expression); } - else + + var invalidRangeType = InvalidRangeExpressionsType(rangeClauseExpressions); + if (invalidRangeType.HasValue) { - remainingCasesToInspect.Add(caseClause); + results.Add((invalidRangeType.Value, caseClause)); } } - var rangeClauseFilter = BuildRangeClauseFilter(remainingCasesToInspect); - if (!(_selectExpressionValue is null) && _selectExpressionValue.ParsesToConstantValue) + var caseElseClause = selectCaseContext.caseElseClause(); + if (caseElseClause != null && rangeClauseFilter.FiltersAllValues) { - rangeClauseFilter.SelectExpressionValue = _selectExpressionValue; + results.Add((UnreachableCaseInspection.CaseInspectionResultType.CaseElse, caseElseClause)); } - foreach (var caseClause in remainingCasesToInspect) + return results; + } + + private UnreachableCaseInspection.CaseInspectionResultType? InvalidRangeExpressionsType(ICollection rangeClauseExpressions) + { + if (rangeClauseExpressions.Any(expr => expr.IsMismatch)) + { + return UnreachableCaseInspection.CaseInspectionResultType.MismatchType; + } + + if (rangeClauseExpressions.Any(expr => expr.IsOverflow)) { - var rangeClauseExpressions = (from range in caseClause.rangeClause() - select GetRangeClauseExpression(range)).ToList(); + return UnreachableCaseInspection.CaseInspectionResultType.Overflow; + } - rangeClauseExpressions.ForEach(expr => rangeClauseFilter.AddExpression(expr)); + if (rangeClauseExpressions.All(expr => expr.IsInherentlyUnreachable)) + { + return UnreachableCaseInspection.CaseInspectionResultType.InherentlyUnreachable; + } - if (rangeClauseExpressions.Any(expr => expr.IsMismatch)) - { - MismatchTypeCases.Add(caseClause); - } - else if (rangeClauseExpressions.Any(expr => expr.IsOverflow)) - { - OverflowCases.Add(caseClause); - } - else if (rangeClauseExpressions.All(expr => expr.IsInherentlyUnreachable)) - { - InherentlyUnreachableCases.Add(caseClause); - } - else if (rangeClauseExpressions.All(expr => expr.IsUnreachable || expr.IsMismatch || expr.IsOverflow || expr.IsInherentlyUnreachable)) - { - UnreachableCases.Add(caseClause); - } + if (rangeClauseExpressions.All(expr => + expr.IsUnreachable || expr.IsMismatch || expr.IsOverflow || expr.IsInherentlyUnreachable)) + { + return UnreachableCaseInspection.CaseInspectionResultType.Unreachable; + } + + return null; + } + + private (UnreachableCaseInspection.CaseInspectionResultType? invalidValueType, VBAParser.CaseClauseContext caseClause) WithInvalidValueType(VBAParser.CaseClauseContext caseClause, IParseTreeVisitorResults parseTreeValues) + { + return (InvalidValueType(caseClause, parseTreeValues), caseClause); + } + + private UnreachableCaseInspection.CaseInspectionResultType? InvalidValueType(VBAParser.CaseClauseContext caseClause, IParseTreeVisitorResults parseTreeValues) + { + var rangeClauseChildValues = caseClause + .rangeClause() + .SelectMany(parseTreeValues.GetChildResults) + .Select(parseTreeValues.GetValue) + .ToList(); + + if (rangeClauseChildValues.Any(value => value.IsMismatchExpression)) + { + return UnreachableCaseInspection.CaseInspectionResultType.MismatchType; } - if (_caseElseContext != null && rangeClauseFilter.FiltersAllValues) + if (rangeClauseChildValues.Any(value => value.IsOverflowExpression)) { - UnreachableCaseElseCases.Add(_caseElseContext); + return UnreachableCaseInspection.CaseInspectionResultType.Overflow; } - return AllResults; + return null; } - private IExpressionFilter BuildRangeClauseFilter(IEnumerable caseClauses) + private IExpressionFilter BuildRangeClauseFilter(QualifiedModuleName module, IEnumerable caseClauses, string selectExpressionTypeName, IParseTreeVisitorResults parseTreeValues) { - var rangeClauseFilter = ExpressionFilterFactory.Create(SelectExpressionTypeName); + var rangeClauseFilter = ExpressionFilterFactory.Create(selectExpressionTypeName); - if (!(_getVariableDeclarationTypeName is null)) + if (_getVariableDeclarationTypeName is null) { - foreach (var caseClause in caseClauses) + return rangeClauseFilter; + } + + var rangeClauses = caseClauses.SelectMany(caseClause => caseClause.rangeClause()); + foreach (var rangeClause in rangeClauses) + { + var expression = GetRangeClauseExpression(rangeClause, parseTreeValues); + if (!expression?.LHS?.ParsesToConstantValue ?? false) { - foreach (var rangeClause in caseClause.rangeClause()) - { - var expression = GetRangeClauseExpression(rangeClause); - if (!expression?.LHS?.ParsesToConstantValue ?? false) - { - var typeName = _getVariableDeclarationTypeName(expression.LHS.Token, _module, rangeClause); - rangeClauseFilter.AddComparablePredicateFilter(expression.LHS.Token, typeName); - } - } + var typeName = _getVariableDeclarationTypeName(expression.LHS.Token, module, rangeClause); + rangeClauseFilter.AddComparablePredicateFilter(expression.LHS.Token, typeName); } } + return rangeClauseFilter; } - private void SetSelectExpressionTypeName(ParserRuleContext context, IParseTreeVisitorResults inspValues) + public string SelectExpressionTypeName( + VBAParser.SelectCaseStmtContext selectStmt, + IParseTreeVisitorResults parseTreeValues) + { + var (typeName, value) = SelectExpressionTypeNameAndValue(selectStmt, parseTreeValues); + return typeName; + } + + private (string typeName, IParseTreeValue value) SelectExpressionTypeNameAndValue( + VBAParser.SelectCaseStmtContext selectStmt, + IParseTreeVisitorResults parseTreeValues) { - var selectStmt = (VBAParser.SelectCaseStmtContext)context; if (TryDetectTypeHint(selectStmt.selectExpression().GetText(), out var typeName) && InspectableTypes.Contains(typeName)) { - SelectExpressionTypeName = typeName; + return (typeName, null); } - else if (inspValues.TryGetValue(selectStmt.selectExpression(), out var result) + + if (parseTreeValues.TryGetValue(selectStmt.selectExpression(), out var result) && InspectableTypes.Contains(result.ValueType)) { - _selectExpressionValue = result; - SelectExpressionTypeName = result.ValueType; - } - else - { - SelectExpressionTypeName = DeriveTypeFromCaseClauses(inspValues, selectStmt); + return (result.ValueType, result); } + + return (DeriveTypeFromCaseClauses(parseTreeValues, selectStmt), null); } - private string DeriveTypeFromCaseClauses(IParseTreeVisitorResults inspValues, VBAParser.SelectCaseStmtContext selectStmt) + private string DeriveTypeFromCaseClauses(IParseTreeVisitorResults parseTreeValues, VBAParser.SelectCaseStmtContext selectStmt) { var caseClauseTypeNames = new List(); foreach (var caseClause in selectStmt.caseClause()) @@ -207,7 +212,7 @@ private string DeriveTypeFromCaseClauses(IParseTreeVisitorResults inspValues, VB var typeNames = range.children .OfType() .Where(IsResultContext) - .Select(inspValues.GetValueType); + .Select(parseTreeValues.GetValueType); caseClauseTypeNames.AddRange(typeNames); caseClauseTypeNames.RemoveAll(tp => !InspectableTypes.Contains(tp)); @@ -276,7 +281,7 @@ private static bool TryDetectTypeHint(string content, out string typeName) return false; } - private IRangeClauseExpression GetRangeClauseExpression(VBAParser.RangeClauseContext rangeClause) + private IRangeClauseExpression GetRangeClauseExpression(VBAParser.RangeClauseContext rangeClause, IParseTreeVisitorResults parseTreeValues) { var resultContexts = rangeClause.children .OfType() @@ -290,25 +295,25 @@ private IRangeClauseExpression GetRangeClauseExpression(VBAParser.RangeClauseCon if (rangeClause.TO() != null) { - var rangeStartValue = ParseTreeValueResults.GetValue(rangeClause.GetChild()); - var rangeEndValue = ParseTreeValueResults.GetValue(rangeClause.GetChild()); + var rangeStartValue = parseTreeValues.GetValue(rangeClause.GetChild()); + var rangeEndValue = parseTreeValues.GetValue(rangeClause.GetChild()); return new RangeOfValuesExpression((rangeStartValue, rangeEndValue)); } if (rangeClause.IS() != null) { - var isClauseValue = ParseTreeValueResults.GetValue(resultContexts.First()); + var isClauseValue = parseTreeValues.GetValue(resultContexts.First()); var opSymbol = rangeClause.GetChild().GetText(); return new IsClauseExpression(isClauseValue, opSymbol); } if (!TryGetLogicSymbol(resultContexts.First(), out string symbol)) { - return new ValueExpression(ParseTreeValueResults.GetValue(resultContexts.First())); + return new ValueExpression(parseTreeValues.GetValue(resultContexts.First())); } var resultContext = resultContexts.First(); - var clauseValue = ParseTreeValueResults.GetValue(resultContext); + var clauseValue = parseTreeValues.GetValue(resultContext); if (clauseValue.ParsesToConstantValue) { return new ValueExpression(clauseValue); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspectorFactory.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspectorFactory.cs index 1a93dc17cb..bf573cb47f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspectorFactory.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspectorFactory.cs @@ -1,18 +1,12 @@ using Antlr4.Runtime; -using Rubberduck.Parsing.Grammar; using System; -using Rubberduck.Parsing; using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { public interface IUnreachableCaseInspectorFactory { - IUnreachableCaseInspector Create( - QualifiedModuleName module, - VBAParser.SelectCaseStmtContext selectStmt, - IParseTreeVisitorResults results, - Func func = null); + IUnreachableCaseInspector Create(Func func = null); } public class UnreachableCaseInspectorFactory : IUnreachableCaseInspectorFactory @@ -24,9 +18,9 @@ public UnreachableCaseInspectorFactory(IParseTreeValueFactory valueFactory) _valueFactory = valueFactory; } - public IUnreachableCaseInspector Create(QualifiedModuleName module, VBAParser.SelectCaseStmtContext selectStmt, IParseTreeVisitorResults results, Func func = null) + public IUnreachableCaseInspector Create(Func func = null) { - return new UnreachableCaseInspector(module, selectStmt, results, _valueFactory, func); + return new UnreachableCaseInspector(_valueFactory, func); } } } diff --git a/RubberduckTests/Inspections/UnreachableCase/ExpressionFilterUnitTests.cs b/RubberduckTests/Inspections/UnreachableCase/ExpressionFilterUnitTests.cs index a697b6d047..5f0c9d8c36 100644 --- a/RubberduckTests/Inspections/UnreachableCase/ExpressionFilterUnitTests.cs +++ b/RubberduckTests/Inspections/UnreachableCase/ExpressionFilterUnitTests.cs @@ -404,7 +404,7 @@ public void ExpressionFilter_MalformedRangeOfValues(string rangeClause, string f { var filter = ExpressionFilterFactory.Create(filterTypeName); var expression = RangeClauseTokensToExpressions(new string[] { rangeClause }, filterTypeName).First(); - filter.AddExpression(expression); + filter.CheckAndAddExpression(expression); Assert.IsTrue(expression.IsInherentlyUnreachable); } @@ -519,7 +519,7 @@ private IExpressionFilter RangeClauseTokensToFilter(IEnumerable rangeCla var expressions = RangeClauseTokensToExpressions(rangeClauses, filterTypeName); foreach (var expression in expressions) { - filter.AddExpression(expression); + filter.CheckAndAddExpression(expression); } return filter; } @@ -574,7 +574,7 @@ private IExpressionFilter FilterContentTokensToFilter(IEnumerable caseCl foreach (var expr in expressions) { - filter.AddExpression(expr); + filter.CheckAndAddExpression(expr); } return filter; } diff --git a/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs b/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs index 21867dbcdf..82b368d796 100644 --- a/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs +++ b/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs @@ -2622,8 +2622,8 @@ private string GetSelectExpressionType(string inputCode) { var selectStmtValueResults = GetParseTreeValueResults(inputCode, out VBAParser.SelectCaseStmtContext selectStmtContext, out var module); - var inspector = UnreachableCaseInspectorFactory.Create(module, selectStmtContext, selectStmtValueResults); - return inspector.SelectExpressionTypeName; + var inspector = UnreachableCaseInspectorFactory.Create(); + return inspector.SelectExpressionTypeName(selectStmtContext, selectStmtValueResults); } private IParseTreeVisitorResults GetParseTreeValueResults(string inputCode, out VBAParser.SelectCaseStmtContext selectStmt, out QualifiedModuleName contextModule) From 13e1547ad36eba9aa0e4640eb75dbfe7ecc62757 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Thu, 5 Mar 2020 20:24:49 +0100 Subject: [PATCH 274/461] Make inspection listener base and parse tree inspection base generic --- .../Abstract/ParseTreeInspectionBase.cs | 68 +++++++++++-------- .../BooleanAssignedInIfElseInspection.cs | 16 ++--- .../Concrete/DefTypeStatementInspection.cs | 12 ++-- .../EmptyBlockInspectionListenerBase.cs | 7 +- .../Concrete/EmptyCaseBlockInspection.cs | 14 ++-- .../Concrete/EmptyDoWhileBlockInspection.cs | 15 ++-- .../Concrete/EmptyElseBlockInspection.cs | 16 ++--- .../Concrete/EmptyForEachBlockInspection.cs | 16 ++--- .../Concrete/EmptyForLoopBlockInspection.cs | 16 ++--- .../Concrete/EmptyIfBlockInspection.cs | 11 +-- .../Concrete/EmptyStringLiteralInspection.cs | 16 ++--- .../Concrete/EmptyWhileWendBlockInspection.cs | 16 ++--- .../ModuleScopeDimKeywordInspection.cs | 16 +++-- .../Concrete/MultilineParameterInspection.cs | 17 ++--- .../MultipleDeclarationsInspection.cs | 12 ++-- .../ObsoleteCallStatementInspection.cs | 16 ++--- .../ObsoleteCallingConventionInspection.cs | 15 ++-- .../ObsoleteCommentSyntaxInspection.cs | 14 ++-- .../Concrete/ObsoleteErrorSyntaxInspection.cs | 14 ++-- .../ObsoleteLetStatementInspection.cs | 11 ++- .../ObsoleteWhileWendStatementInspection.cs | 12 ++-- .../Concrete/OnLocalErrorInspection.cs | 16 ++--- .../Concrete/OptionBaseInspection.cs | 12 ++-- .../Concrete/OptionExplicitInspection.cs | 26 +++---- .../Concrete/RedundantOptionInspection.cs | 9 +-- .../Concrete/StepIsNotSpecifiedInspection.cs | 14 ++-- .../Concrete/StepOneIsRedundantInspection.cs | 16 ++--- .../Concrete/StopKeywordInspection.cs | 16 ++--- ...neContinuationBetweenKeywordsInspection.cs | 10 +-- .../NegativeLineNumberInspection.cs | 10 +-- .../OnErrorGoToMinusOneInspection.cs | 17 +++-- .../UnhandledOnErrorResumeNextInspection.cs | 37 +++++----- .../UnreachableCaseInspection.cs | 12 ++-- .../RestoreErrorHandlingQuickFix.cs | 4 +- .../Abstract/IInpsectionListener.cs | 9 ++- 35 files changed, 286 insertions(+), 272 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs index 399b823111..8971273864 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs @@ -12,28 +12,32 @@ namespace Rubberduck.Inspections.Abstract { - public abstract class ParseTreeInspectionBase : InspectionBase, IParseTreeInspection + public abstract class ParseTreeInspectionBase : InspectionBase, IParseTreeInspection + where TContext : ParserRuleContext { protected ParseTreeInspectionBase(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) {} - public abstract IInspectionListener Listener { get; } - protected abstract string ResultDescription(QualifiedContext context); + public IInspectionListener Listener => ContextListener; - protected virtual bool IsResultContext(QualifiedContext context) => true; + protected abstract IInspectionListener ContextListener { get; } + + protected abstract string ResultDescription(QualifiedContext context); + + protected virtual bool IsResultContext(QualifiedContext context) => true; protected override IEnumerable DoGetInspectionResults() { - return DoGetInspectionResults(Listener.Contexts()); + return DoGetInspectionResults(ContextListener.Contexts()); } protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) { - return DoGetInspectionResults(Listener.Contexts(module)); + return DoGetInspectionResults(ContextListener.Contexts(module)); } - private IEnumerable DoGetInspectionResults(IEnumerable> contexts) + private IEnumerable DoGetInspectionResults(IEnumerable> contexts) { var objectionableContexts = contexts .Where(IsResultContext); @@ -43,7 +47,7 @@ private IEnumerable DoGetInspectionResults(IEnumerable context) + protected virtual IInspectionResult InspectionResult(QualifiedContext context) { return new QualifiedContextInspectionResult( this, @@ -52,32 +56,35 @@ protected virtual IInspectionResult InspectionResult(QualifiedContext DisabledQuickFixes(QualifiedContext context) => new List(); + protected virtual ICollection DisabledQuickFixes(QualifiedContext context) => new List(); public virtual CodeKind TargetKindOfCode => CodeKind.CodePaneCode; } - public abstract class ParseTreeInspectionBase : InspectionBase, IParseTreeInspection + public abstract class ParseTreeInspectionBase : InspectionBase, IParseTreeInspection + where TContext : ParserRuleContext { protected ParseTreeInspectionBase(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) {} - public abstract IInspectionListener Listener { get; } - protected abstract string ResultDescription(QualifiedContext context, T properties); - protected abstract (bool isResult, T properties) IsResultContextWithAdditionalProperties(QualifiedContext context); + public IInspectionListener Listener => ContextListener; + + protected abstract IInspectionListener ContextListener { get; } + protected abstract string ResultDescription(QualifiedContext context, TProperties properties); + protected abstract (bool isResult, TProperties properties) IsResultContextWithAdditionalProperties(QualifiedContext context); protected override IEnumerable DoGetInspectionResults() { - return DoGetInspectionResults(Listener.Contexts()); + return DoGetInspectionResults(ContextListener.Contexts()); } protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) { - return DoGetInspectionResults(Listener.Contexts(module)); + return DoGetInspectionResults(ContextListener.Contexts(module)); } - private IEnumerable DoGetInspectionResults(IEnumerable> contexts) + private IEnumerable DoGetInspectionResults(IEnumerable> contexts) { var objectionableContexts = contexts .Select(ContextsWithResultProperties) @@ -89,17 +96,17 @@ private IEnumerable DoGetInspectionResults(IEnumerable context, T properties)? ContextsWithResultProperties(QualifiedContext context) + private (QualifiedContext context, TProperties properties)? ContextsWithResultProperties(QualifiedContext context) { var (isResult, properties) = IsResultContextWithAdditionalProperties(context); return isResult ? (context, properties) - : ((QualifiedContext context, T properties)?) null; + : ((QualifiedContext context, TProperties properties)?) null; } - protected virtual IInspectionResult InspectionResult(QualifiedContext context, T properties) + protected virtual IInspectionResult InspectionResult(QualifiedContext context, TProperties properties) { - return new QualifiedContextInspectionResult( + return new QualifiedContextInspectionResult( this, ResultDescription(context, properties), context, @@ -107,31 +114,32 @@ protected virtual IInspectionResult InspectionResult(QualifiedContext DisabledQuickFixes(QualifiedContext context, T properties) => new List(); + protected virtual ICollection DisabledQuickFixes(QualifiedContext context, TProperties properties) => new List(); public virtual CodeKind TargetKindOfCode => CodeKind.CodePaneCode; } - public class InspectionListenerBase : VBAParserBaseListener, IInspectionListener + public class InspectionListenerBase : VBAParserBaseListener, IInspectionListener + where TContext : ParserRuleContext { - private readonly IDictionary>> _contexts; + private readonly IDictionary>> _contexts; public InspectionListenerBase() { - _contexts = new Dictionary>>(); + _contexts = new Dictionary>>(); } public QualifiedModuleName CurrentModuleName { get; set; } - public IReadOnlyList> Contexts() + public IReadOnlyList> Contexts() { return _contexts.AllValues().ToList(); } - public IReadOnlyList> Contexts(QualifiedModuleName module) + public IReadOnlyList> Contexts(QualifiedModuleName module) { return _contexts.TryGetValue(module, out var contexts) ? contexts - : new List>(); + : new List>(); } public virtual void ClearContexts() @@ -144,17 +152,17 @@ public virtual void ClearContexts(QualifiedModuleName module) _contexts.Remove(module); } - protected void SaveContext(ParserRuleContext context) + protected void SaveContext(TContext context) { var module = CurrentModuleName; - var qualifiedContext = new QualifiedContext(module, context); + var qualifiedContext = new QualifiedContext(module, context); if (_contexts.TryGetValue(module, out var contexts)) { contexts.Add(qualifiedContext); } else { - _contexts.Add(module, new List>{qualifiedContext}); + _contexts.Add(module, new List>{qualifiedContext}); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs index 15843f7214..a73d3b6575 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs @@ -1,5 +1,4 @@ using System.Linq; -using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; @@ -37,18 +36,19 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class BooleanAssignedInIfElseInspection : ParseTreeInspectionBase + public sealed class BooleanAssignedInIfElseInspection : ParseTreeInspectionBase { public BooleanAssignedInIfElseInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) - {} + { + ContextListener = new BooleanAssignedInIfElseListener(); + } - public override IInspectionListener Listener { get; } = - new BooleanAssignedInIfElseListener(); + protected override IInspectionListener ContextListener { get; } - protected override string ResultDescription(QualifiedContext context) + protected override string ResultDescription(QualifiedContext context) { - var literalText = ((VBAParser.IfStmtContext) context.Context) + var literalText = context.Context .block() .GetDescendent() .lExpression() @@ -59,7 +59,7 @@ protected override string ResultDescription(QualifiedContext literalText); } - public class BooleanAssignedInIfElseListener : InspectionListenerBase + public class BooleanAssignedInIfElseListener : InspectionListenerBase { public override void ExitIfStmt(VBAParser.IfStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs index 9fe14fcaf0..d08fa06888 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs @@ -4,7 +4,6 @@ using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Grammar; -using Antlr4.Runtime; using Rubberduck.Parsing; using Antlr4.Runtime.Misc; @@ -27,16 +26,17 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class DefTypeStatementInspection : ParseTreeInspectionBase + public sealed class DefTypeStatementInspection : ParseTreeInspectionBase { public DefTypeStatementInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) { - Listener = new DefTypeStatementInspectionListener(); + ContextListener = new DefTypeStatementInspectionListener(); } - public override IInspectionListener Listener { get; } - protected override string ResultDescription(QualifiedContext context) + protected override IInspectionListener ContextListener { get; } + + protected override string ResultDescription(QualifiedContext context) { var typeName = GetTypeOfDefType(context.Context.start.Text); var defStmtText = context.Context.start.Text; @@ -68,7 +68,7 @@ private string GetTypeOfDefType(string defType) { "DefVar", "Variant" } }; - public class DefTypeStatementInspectionListener : InspectionListenerBase + public class DefTypeStatementInspectionListener : InspectionListenerBase { public override void ExitDefType([NotNull] VBAParser.DefTypeContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlockInspectionListenerBase.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlockInspectionListenerBase.cs index bcd20c524c..7f5fe09a3a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlockInspectionListenerBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlockInspectionListenerBase.cs @@ -7,9 +7,10 @@ namespace Rubberduck.Inspections.Concrete { - public class EmptyBlockInspectionListenerBase : InspectionListenerBase + public class EmptyBlockInspectionListenerBase : InspectionListenerBase + where TContext : ParserRuleContext { - public void InspectBlockForExecutableStatements(VBAParser.BlockContext block, T context) where T : ParserRuleContext + public void InspectBlockForExecutableStatements(VBAParser.BlockContext block, T context) where T : TContext { if (!BlockContainsExecutableStatements(block)) { @@ -61,7 +62,7 @@ child is VBAParser.CommentOrAnnotationContext || return false; } - public void InspectBlockForExecutableStatements(VBAParser.UnterminatedBlockContext block, T context) where T : ParserRuleContext + public void InspectBlockForExecutableStatements(VBAParser.UnterminatedBlockContext block, T context) where T : TContext { if (!BlockContainsExecutableStatements(block)) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyCaseBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyCaseBlockInspection.cs index bbf47d810b..b5e46f4521 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyCaseBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyCaseBlockInspection.cs @@ -5,7 +5,6 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Antlr4.Runtime; using Rubberduck.Resources.Experimentals; using Rubberduck.Parsing; @@ -41,21 +40,22 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [Experimental(nameof(ExperimentalNames.EmptyBlockInspections))] - internal class EmptyCaseBlockInspection : ParseTreeInspectionBase + internal sealed class EmptyCaseBlockInspection : ParseTreeInspectionBase { public EmptyCaseBlockInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) - {} + { + ContextListener = new EmptyCaseBlockListener(); + } - public override IInspectionListener Listener { get; } = - new EmptyCaseBlockListener(); + protected override IInspectionListener ContextListener { get; } - protected override string ResultDescription(QualifiedContext context) + protected override string ResultDescription(QualifiedContext context) { return InspectionResults.EmptyCaseBlockInspection; } - public class EmptyCaseBlockListener : EmptyBlockInspectionListenerBase + public class EmptyCaseBlockListener : EmptyBlockInspectionListenerBase { public override void EnterCaseClause([NotNull] VBAParser.CaseClauseContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyDoWhileBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyDoWhileBlockInspection.cs index 06394f1ea2..df84b3df8a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyDoWhileBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyDoWhileBlockInspection.cs @@ -5,7 +5,6 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Antlr4.Runtime; using Rubberduck.Resources.Experimentals; using Rubberduck.Parsing; @@ -36,20 +35,22 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [Experimental(nameof(ExperimentalNames.EmptyBlockInspections))] - internal class EmptyDoWhileBlockInspection : ParseTreeInspectionBase + internal sealed class EmptyDoWhileBlockInspection : ParseTreeInspectionBase { public EmptyDoWhileBlockInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) - {} + { + ContextListener = new EmptyDoWhileBlockListener(); + } - protected override string ResultDescription(QualifiedContext context) + protected override IInspectionListener ContextListener { get; } + + protected override string ResultDescription(QualifiedContext context) { return InspectionResults.EmptyDoWhileBlockInspection; } - public override IInspectionListener Listener { get; } = new EmptyDoWhileBlockListener(); - - public class EmptyDoWhileBlockListener : EmptyBlockInspectionListenerBase + public class EmptyDoWhileBlockListener : EmptyBlockInspectionListenerBase { public override void EnterDoLoopStmt([NotNull] VBAParser.DoLoopStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyElseBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyElseBlockInspection.cs index 9eae15eba9..757d337378 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyElseBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyElseBlockInspection.cs @@ -5,7 +5,6 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Antlr4.Runtime; using Rubberduck.Resources.Experimentals; using Rubberduck.Parsing; @@ -38,21 +37,22 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [Experimental(nameof(ExperimentalNames.EmptyBlockInspections))] - internal class EmptyElseBlockInspection : ParseTreeInspectionBase + internal sealed class EmptyElseBlockInspection : ParseTreeInspectionBase { public EmptyElseBlockInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) - {} + { + ContextListener = new EmptyElseBlockListener(); + } + + protected override IInspectionListener ContextListener { get; } - protected override string ResultDescription(QualifiedContext context) + protected override string ResultDescription(QualifiedContext context) { return InspectionResults.EmptyElseBlockInspection; } - public override IInspectionListener Listener { get; } - = new EmptyElseBlockListener(); - - public class EmptyElseBlockListener : EmptyBlockInspectionListenerBase + public class EmptyElseBlockListener : EmptyBlockInspectionListenerBase { public override void EnterElseBlock([NotNull] VBAParser.ElseBlockContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForEachBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForEachBlockInspection.cs index e087cfe34f..b6615737df 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForEachBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForEachBlockInspection.cs @@ -5,7 +5,6 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Antlr4.Runtime; using Rubberduck.Resources.Experimentals; using Rubberduck.Parsing; @@ -38,21 +37,22 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [Experimental(nameof(ExperimentalNames.EmptyBlockInspections))] - internal class EmptyForEachBlockInspection : ParseTreeInspectionBase + internal sealed class EmptyForEachBlockInspection : ParseTreeInspectionBase { public EmptyForEachBlockInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) - {} + { + ContextListener = new EmptyForEachBlockListener(); + } - protected override string ResultDescription(QualifiedContext context) + protected override IInspectionListener ContextListener { get; } + + protected override string ResultDescription(QualifiedContext context) { return InspectionResults.EmptyForEachBlockInspection; } - public override IInspectionListener Listener { get; } = - new EmptyForEachBlockListener(); - - public class EmptyForEachBlockListener : EmptyBlockInspectionListenerBase + public class EmptyForEachBlockListener : EmptyBlockInspectionListenerBase { public override void EnterForEachStmt([NotNull] VBAParser.ForEachStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForLoopBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForLoopBlockInspection.cs index 3de874561c..7fac278f90 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForLoopBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForLoopBlockInspection.cs @@ -5,7 +5,6 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Antlr4.Runtime; using Rubberduck.Resources.Experimentals; using Rubberduck.Parsing; @@ -38,21 +37,22 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [Experimental(nameof(ExperimentalNames.EmptyBlockInspections))] - internal class EmptyForLoopBlockInspection : ParseTreeInspectionBase + internal sealed class EmptyForLoopBlockInspection : ParseTreeInspectionBase { public EmptyForLoopBlockInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) - {} + { + ContextListener = new EmptyForLoopBlockListener(); + } - protected override string ResultDescription(QualifiedContext context) + protected override IInspectionListener ContextListener { get; } + + protected override string ResultDescription(QualifiedContext context) { return InspectionResults.EmptyForLoopBlockInspection; } - public override IInspectionListener Listener { get; } = - new EmptyForLoopBlockListener(); - - public class EmptyForLoopBlockListener : EmptyBlockInspectionListenerBase + public class EmptyForLoopBlockListener : EmptyBlockInspectionListenerBase { public override void EnterForNextStmt([NotNull] VBAParser.ForNextStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyIfBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyIfBlockInspection.cs index 4c6f61a13a..2d3a313757 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyIfBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyIfBlockInspection.cs @@ -34,21 +34,22 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - internal class EmptyIfBlockInspection : ParseTreeInspectionBase + internal sealed class EmptyIfBlockInspection : ParseTreeInspectionBase { public EmptyIfBlockInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) - {} + { + ContextListener = new EmptyIfBlockListener(); + } protected override string ResultDescription(QualifiedContext context) { return InspectionResults.EmptyIfBlockInspection; } - public override IInspectionListener Listener { get; } = - new EmptyIfBlockListener(); + protected override IInspectionListener ContextListener { get; } - public class EmptyIfBlockListener : EmptyBlockInspectionListenerBase + public class EmptyIfBlockListener : EmptyBlockInspectionListenerBase { public override void EnterIfStmt([NotNull] VBAParser.IfStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs index dd0600413f..e1ec83719b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs @@ -1,5 +1,4 @@ -using Antlr4.Runtime; -using Rubberduck.Inspections.Abstract; +using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -34,21 +33,22 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class EmptyStringLiteralInspection : ParseTreeInspectionBase + public sealed class EmptyStringLiteralInspection : ParseTreeInspectionBase { public EmptyStringLiteralInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) - {} + { + ContextListener = new EmptyStringLiteralListener(); + } - public override IInspectionListener Listener { get; } = - new EmptyStringLiteralListener(); + protected override IInspectionListener ContextListener { get; } - protected override string ResultDescription(QualifiedContext context) + protected override string ResultDescription(QualifiedContext context) { return InspectionResults.EmptyStringLiteralInspection; } - public class EmptyStringLiteralListener : InspectionListenerBase + public class EmptyStringLiteralListener : InspectionListenerBase { public override void ExitLiteralExpression(VBAParser.LiteralExpressionContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyWhileWendBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyWhileWendBlockInspection.cs index cefa70155b..86cfda2cde 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyWhileWendBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyWhileWendBlockInspection.cs @@ -5,7 +5,6 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Antlr4.Runtime; using Rubberduck.Resources.Experimentals; using Rubberduck.Parsing; @@ -36,21 +35,22 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [Experimental(nameof(ExperimentalNames.EmptyBlockInspections))] - internal class EmptyWhileWendBlockInspection : ParseTreeInspectionBase + internal sealed class EmptyWhileWendBlockInspection : ParseTreeInspectionBase { public EmptyWhileWendBlockInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) - {} + { + ContextListener = new EmptyWhileWendBlockListener(); + } - protected override string ResultDescription(QualifiedContext context) + protected override IInspectionListener ContextListener { get; } + + protected override string ResultDescription(QualifiedContext context) { return InspectionResults.EmptyWhileWendBlockInspection; } - public override IInspectionListener Listener { get; } = - new EmptyWhileWendBlockListener(); - - public class EmptyWhileWendBlockListener : EmptyBlockInspectionListenerBase + public class EmptyWhileWendBlockListener : EmptyBlockInspectionListenerBase { public override void EnterWhileWendStmt([NotNull] VBAParser.WhileWendStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs index ace257f777..0bd1b3dfec 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs @@ -1,4 +1,3 @@ -using Antlr4.Runtime; using Antlr4.Runtime.Misc; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; @@ -30,22 +29,25 @@ namespace Rubberduck.Inspections.Concrete /// ' ... /// ]]> /// - public sealed class ModuleScopeDimKeywordInspection : ParseTreeInspectionBase + public sealed class ModuleScopeDimKeywordInspection : ParseTreeInspectionBase { public ModuleScopeDimKeywordInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) - {} + { + ContextListener = new ModuleScopedDimListener(); + } + + protected override IInspectionListener ContextListener { get; } - public override IInspectionListener Listener { get; } = new ModuleScopedDimListener(); - protected override string ResultDescription(QualifiedContext context) + protected override string ResultDescription(QualifiedContext context) { - var identifierName = ((VBAParser.VariableSubStmtContext) context.Context).identifier().GetText(); + var identifierName = context.Context.identifier().GetText(); return string.Format( InspectionResults.ModuleScopeDimKeywordInspection, identifierName); } - public class ModuleScopedDimListener : InspectionListenerBase + public class ModuleScopedDimListener : InspectionListenerBase { public override void ExitVariableStmt([NotNull] VBAParser.VariableStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs index e617dc11b8..9ff5d29e8f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs @@ -1,4 +1,3 @@ -using Antlr4.Runtime; using Antlr4.Runtime.Misc; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; @@ -31,25 +30,27 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class MultilineParameterInspection : ParseTreeInspectionBase + public sealed class MultilineParameterInspection : ParseTreeInspectionBase { public MultilineParameterInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) { - Listener = new ParameterListener(); + ContextListener = new ParameterListener(); } - public override IInspectionListener Listener { get; } - protected override string ResultDescription(QualifiedContext context) + protected override IInspectionListener ContextListener { get; } + + protected override string ResultDescription(QualifiedContext context) { - var parameterText = ((VBAParser.ArgContext) context.Context).unrestrictedIdentifier().GetText(); - return string.Format(context.Context.GetSelection().LineCount > 3 + var parameterText = context.Context.unrestrictedIdentifier().GetText(); + return string.Format( + context.Context.GetSelection().LineCount > 3 ? RubberduckUI.EasterEgg_Continuator : Resources.Inspections.InspectionResults.MultilineParameterInspection, parameterText); } - public class ParameterListener : InspectionListenerBase + public class ParameterListener : InspectionListenerBase { public override void ExitArg([NotNull] VBAParser.ArgContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs index 7e729d6f5a..6f6ccf3df0 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs @@ -26,20 +26,22 @@ namespace Rubberduck.Inspections.Concrete /// Dim bar As Long /// ]]> /// - public sealed class MultipleDeclarationsInspection : ParseTreeInspectionBase + public sealed class MultipleDeclarationsInspection : ParseTreeInspectionBase { public MultipleDeclarationsInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) - {} + { + ContextListener = new ParameterListListener(); + } + + protected override IInspectionListener ContextListener { get; } protected override string ResultDescription(QualifiedContext context) { return InspectionResults.MultipleDeclarationsInspection; } - public override IInspectionListener Listener { get; } = new ParameterListListener(); - - public class ParameterListListener : InspectionListenerBase + public class ParameterListListener : InspectionListenerBase { public override void ExitVariableListStmt([NotNull] VBAParser.VariableListStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs index 6d708289fc..2d36be43ce 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs @@ -1,12 +1,9 @@ -using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.VBA.Extensions; -using Rubberduck.VBEditor.ComManagement; namespace Rubberduck.Inspections.Concrete { @@ -38,21 +35,22 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ObsoleteCallStatementInspection : ParseTreeInspectionBase + public sealed class ObsoleteCallStatementInspection : ParseTreeInspectionBase { public ObsoleteCallStatementInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) { - Listener = new ObsoleteCallStatementListener(); + ContextListener = new ObsoleteCallStatementListener(); } - public override IInspectionListener Listener { get; } - protected override string ResultDescription(QualifiedContext context) + protected override IInspectionListener ContextListener { get; } + + protected override string ResultDescription(QualifiedContext context) { return InspectionResults.ObsoleteCallStatementInspection; } - protected override bool IsResultContext(QualifiedContext context) + protected override bool IsResultContext(QualifiedContext context) { if (!context.Context.TryGetFollowingContext(out VBAParser.IndividualNonEOFEndOfStatementContext followingEndOfStatement) || followingEndOfStatement.COLON() == null) @@ -69,7 +67,7 @@ protected override bool IsResultContext(QualifiedContext cont return false; } - public class ObsoleteCallStatementListener : InspectionListenerBase + public class ObsoleteCallStatementListener : InspectionListenerBase { public override void ExitCallStmt(VBAParser.CallStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs index 864f5b41d5..c4bc26ef47 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs @@ -1,5 +1,4 @@ -using Antlr4.Runtime; -using Rubberduck.Inspections.Abstract; +using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -25,17 +24,17 @@ namespace Rubberduck.Inspections.Inspections.Concrete /// Private Declare Sub Beep Lib "kernel32" (dwFreq As Any, dwDuration As Any) /// ]]> /// - public sealed class ObsoleteCallingConventionInspection : ParseTreeInspectionBase + public sealed class ObsoleteCallingConventionInspection : ParseTreeInspectionBase { public ObsoleteCallingConventionInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) { - Listener = new ObsoleteCallingConventionListener(); + ContextListener = new ObsoleteCallingConventionListener(); } - public override IInspectionListener Listener { get; } + protected override IInspectionListener ContextListener { get; } - protected override string ResultDescription(QualifiedContext context) + protected override string ResultDescription(QualifiedContext context) { var identifierName = ((VBAParser.DeclareStmtContext) context.Context).identifier().GetText(); return string.Format( @@ -43,12 +42,12 @@ protected override string ResultDescription(QualifiedContext identifierName); } - protected override bool IsResultContext(QualifiedContext context) + protected override bool IsResultContext(QualifiedContext context) { return ((VBAParser.DeclareStmtContext)context.Context).CDECL() != null; } - public class ObsoleteCallingConventionListener : InspectionListenerBase + public class ObsoleteCallingConventionListener : InspectionListenerBase { public override void ExitDeclareStmt(VBAParser.DeclareStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs index 2d9c39833d..9cb27834e6 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs @@ -1,5 +1,4 @@ -using Antlr4.Runtime; -using Rubberduck.Inspections.Abstract; +using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -28,21 +27,22 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ObsoleteCommentSyntaxInspection : ParseTreeInspectionBase + public sealed class ObsoleteCommentSyntaxInspection : ParseTreeInspectionBase { public ObsoleteCommentSyntaxInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) { - Listener = new ObsoleteCommentSyntaxListener(); + ContextListener = new ObsoleteCommentSyntaxListener(); } - public override IInspectionListener Listener { get; } - protected override string ResultDescription(QualifiedContext context) + protected override IInspectionListener ContextListener { get; } + + protected override string ResultDescription(QualifiedContext context) { return InspectionResults.ObsoleteCommentSyntaxInspection; } - public class ObsoleteCommentSyntaxListener : InspectionListenerBase + public class ObsoleteCommentSyntaxListener : InspectionListenerBase { public override void ExitRemComment(VBAParser.RemCommentContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs index 824e308a20..96057c0916 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs @@ -1,5 +1,4 @@ -using Antlr4.Runtime; -using Rubberduck.Inspections.Abstract; +using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -28,21 +27,22 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ObsoleteErrorSyntaxInspection : ParseTreeInspectionBase + public sealed class ObsoleteErrorSyntaxInspection : ParseTreeInspectionBase { public ObsoleteErrorSyntaxInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) { - Listener = new ObsoleteErrorSyntaxListener(); + ContextListener = new ObsoleteErrorSyntaxListener(); } - public override IInspectionListener Listener { get; } - protected override string ResultDescription(QualifiedContext context) + protected override IInspectionListener ContextListener { get; } + + protected override string ResultDescription(QualifiedContext context) { return InspectionResults.ObsoleteErrorSyntaxInspection; } - public class ObsoleteErrorSyntaxListener : InspectionListenerBase + public class ObsoleteErrorSyntaxListener : InspectionListenerBase { public override void ExitErrorStmt(VBAParser.ErrorStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs index 3865e230ce..6623141ae7 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs @@ -1,4 +1,3 @@ -using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; @@ -30,22 +29,22 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ObsoleteLetStatementInspection : ParseTreeInspectionBase + public sealed class ObsoleteLetStatementInspection : ParseTreeInspectionBase { public ObsoleteLetStatementInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) { - Listener = new ObsoleteLetStatementListener(); + ContextListener = new ObsoleteLetStatementListener(); } - public override IInspectionListener Listener { get; } + protected override IInspectionListener ContextListener { get; } - protected override string ResultDescription(QualifiedContext context) + protected override string ResultDescription(QualifiedContext context) { return InspectionResults.ObsoleteLetStatementInspection; } - public class ObsoleteLetStatementListener : InspectionListenerBase + public class ObsoleteLetStatementListener : InspectionListenerBase { public override void ExitLetStmt(VBAParser.LetStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs index 89a8c1064a..26fae13810 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs @@ -1,5 +1,4 @@ using Rubberduck.Inspections.Abstract; -using Antlr4.Runtime; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -33,21 +32,22 @@ namespace Rubberduck.CodeAnalysis.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ObsoleteWhileWendStatementInspection : ParseTreeInspectionBase + public sealed class ObsoleteWhileWendStatementInspection : ParseTreeInspectionBase { public ObsoleteWhileWendStatementInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) { - Listener = new ObsoleteWhileWendStatementListener(); + ContextListener = new ObsoleteWhileWendStatementListener(); } - public override IInspectionListener Listener { get; } - protected override string ResultDescription(QualifiedContext context) + protected override IInspectionListener ContextListener { get; } + + protected override string ResultDescription(QualifiedContext context) { return InspectionResults.ObsoleteWhileWendStatementInspection; } - public class ObsoleteWhileWendStatementListener : InspectionListenerBase + public class ObsoleteWhileWendStatementListener : InspectionListenerBase { public override void ExitWhileWendStmt(VBAParser.WhileWendStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs index 684944fa72..1b3e832375 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs @@ -1,5 +1,4 @@ -using Antlr4.Runtime; -using Rubberduck.Inspections.Abstract; +using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -37,21 +36,22 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class OnLocalErrorInspection : ParseTreeInspectionBase + public sealed class OnLocalErrorInspection : ParseTreeInspectionBase { public OnLocalErrorInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) - {} + { + ContextListener = new OnLocalErrorListener(); + } - public override IInspectionListener Listener { get; } = - new OnLocalErrorListener(); + protected override IInspectionListener ContextListener { get; } - protected override string ResultDescription(QualifiedContext context) + protected override string ResultDescription(QualifiedContext context) { return InspectionResults.OnLocalErrorInspection; } - public class OnLocalErrorListener : InspectionListenerBase + public class OnLocalErrorListener : InspectionListenerBase { public override void ExitOnErrorStmt([NotNull] VBAParser.OnErrorStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs index 48af628c74..1d0595d836 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs @@ -1,4 +1,3 @@ -using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; @@ -37,16 +36,17 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class OptionBaseInspection : ParseTreeInspectionBase + public sealed class OptionBaseInspection : ParseTreeInspectionBase { public OptionBaseInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) { - Listener = new OptionBaseStatementListener(); + ContextListener = new OptionBaseStatementListener(); } - public override IInspectionListener Listener { get; } - protected override string ResultDescription(QualifiedContext context) + protected override IInspectionListener ContextListener { get; } + + protected override string ResultDescription(QualifiedContext context) { var moduleName = context.ModuleName.ComponentName; return string.Format( @@ -54,7 +54,7 @@ protected override string ResultDescription(QualifiedContext moduleName); } - public class OptionBaseStatementListener : InspectionListenerBase + public class OptionBaseStatementListener : InspectionListenerBase { public override void ExitOptionBaseStmt(VBAParser.OptionBaseStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs index 8e6140338a..9502115843 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using Antlr4.Runtime; using Antlr4.Runtime.Misc; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; @@ -36,16 +35,23 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class OptionExplicitInspection : ParseTreeInspectionBase + public sealed class OptionExplicitInspection : ParseTreeInspectionBase { public OptionExplicitInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) { - Listener = new MissingOptionExplicitListener(); + ContextListener = new MissingOptionExplicitListener(); } - public override IInspectionListener Listener { get; } - protected override string ResultDescription(QualifiedContext context) + protected override IInspectionListener ContextListener { get; } + + protected override bool IsResultContext(QualifiedContext context) + { + var moduleBody = context.Context.moduleBody(); + return moduleBody != null && moduleBody.ChildCount != 0; + } + + protected override string ResultDescription(QualifiedContext context) { var moduleName = context.ModuleName.ComponentName; return string.Format( @@ -53,13 +59,7 @@ protected override string ResultDescription(QualifiedContext moduleName); } - protected override bool IsResultContext(QualifiedContext context) - { - var moduleBody = (context.Context as VBAParser.ModuleContext)?.moduleBody(); - return moduleBody != null && moduleBody.ChildCount != 0; - } - - public class MissingOptionExplicitListener : InspectionListenerBase + public class MissingOptionExplicitListener : InspectionListenerBase { private readonly IDictionary _hasOptionExplicit = new Dictionary(); @@ -89,7 +89,7 @@ public override void ExitModuleDeclarations([NotNull] VBAParser.ModuleDeclaratio { if (!_hasOptionExplicit.TryGetValue(CurrentModuleName, out var hasOptionExplicit) || !hasOptionExplicit) { - SaveContext((ParserRuleContext)context.Parent); + SaveContext((VBAParser.ModuleContext)context.Parent); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs index 8ad9c10f8a..f46ac808ba 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs @@ -33,15 +33,16 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class RedundantOptionInspection : ParseTreeInspectionBase + public sealed class RedundantOptionInspection : ParseTreeInspectionBase { public RedundantOptionInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) { - Listener = new RedundantModuleOptionListener(); + ContextListener = new RedundantModuleOptionListener(); } - public override IInspectionListener Listener { get; } + protected override IInspectionListener ContextListener { get; } + protected override string ResultDescription(QualifiedContext context) { return string.Format( @@ -49,7 +50,7 @@ protected override string ResultDescription(QualifiedContext context.Context.GetText()); } - public class RedundantModuleOptionListener : InspectionListenerBase + public class RedundantModuleOptionListener : InspectionListenerBase { public override void ExitOptionBaseStmt(VBAParser.OptionBaseStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs index 1cab0da37d..41a2927e20 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs @@ -3,7 +3,6 @@ using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Antlr4.Runtime.Misc; -using Antlr4.Runtime; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; @@ -36,22 +35,23 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class StepIsNotSpecifiedInspection : ParseTreeInspectionBase + public sealed class StepIsNotSpecifiedInspection : ParseTreeInspectionBase { public StepIsNotSpecifiedInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) - {} + { + ContextListener = new StepIsNotSpecifiedListener(); + } - protected override string ResultDescription(QualifiedContext context) + protected override string ResultDescription(QualifiedContext context) { return InspectionResults.StepIsNotSpecifiedInspection; } - public override IInspectionListener Listener { get; } = - new StepIsNotSpecifiedListener(); + protected override IInspectionListener ContextListener { get; } } - public class StepIsNotSpecifiedListener : InspectionListenerBase + public class StepIsNotSpecifiedListener : InspectionListenerBase { public override void EnterForNextStmt([NotNull] VBAParser.ForNextStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs index c323a94159..cf5dc5f1ce 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs @@ -3,7 +3,6 @@ using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Antlr4.Runtime.Misc; -using Antlr4.Runtime; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; @@ -36,22 +35,23 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class StepOneIsRedundantInspection : ParseTreeInspectionBase + public sealed class StepOneIsRedundantInspection : ParseTreeInspectionBase { public StepOneIsRedundantInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) - {} + { + ContextListener = new StepOneIsRedundantListener(); + } - protected override string ResultDescription(QualifiedContext context) + protected override IInspectionListener ContextListener { get; } + + protected override string ResultDescription(QualifiedContext context) { return InspectionResults.StepOneIsRedundantInspection; } - - public override IInspectionListener Listener { get; } = - new StepOneIsRedundantListener(); } - public class StepOneIsRedundantListener : InspectionListenerBase + public class StepOneIsRedundantListener : InspectionListenerBase { public override void EnterForNextStmt([NotNull] VBAParser.ForNextStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs index 0e87196b0f..cb3174711d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs @@ -1,5 +1,4 @@ -using Antlr4.Runtime; -using Antlr4.Runtime.Misc; +using Antlr4.Runtime.Misc; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; @@ -33,21 +32,22 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class StopKeywordInspection : ParseTreeInspectionBase + public sealed class StopKeywordInspection : ParseTreeInspectionBase { public StopKeywordInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) - {} + { + ContextListener = new StopKeywordListener(); + } - public override IInspectionListener Listener { get; } = - new StopKeywordListener(); + protected override IInspectionListener ContextListener { get; } - protected override string ResultDescription(QualifiedContext context) + protected override string ResultDescription(QualifiedContext context) { return InspectionResults.StopKeywordInspection; } - public class StopKeywordListener : InspectionListenerBase + public class StopKeywordListener : InspectionListenerBase { public override void ExitStopStmt([NotNull] VBAParser.StopStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/LineContinuationBetweenKeywordsInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/LineContinuationBetweenKeywordsInspection.cs index 713461beba..1790855129 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/LineContinuationBetweenKeywordsInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/LineContinuationBetweenKeywordsInspection.cs @@ -21,22 +21,22 @@ namespace Rubberduck.Inspections.Inspections.Concrete.ThunderCode /// Note that the inspection only checks a subset of possible "evil" line continatuions /// for both simplicity and performance reasons. Exhaustive inspection would likely take too much effort. /// - public class LineContinuationBetweenKeywordsInspection : ParseTreeInspectionBase + public sealed class LineContinuationBetweenKeywordsInspection : ParseTreeInspectionBase { public LineContinuationBetweenKeywordsInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) { - Listener = new LineContinuationBetweenKeywordsListener(); + ContextListener = new LineContinuationBetweenKeywordsListener(); } + protected override IInspectionListener ContextListener { get; } + protected override string ResultDescription(QualifiedContext context) { return InspectionResults.LineContinuationBetweenKeywordsInspection.ThunderCodeFormat(); } - public override IInspectionListener Listener { get; } - - public class LineContinuationBetweenKeywordsListener : InspectionListenerBase + public class LineContinuationBetweenKeywordsListener : InspectionListenerBase { public override void EnterSubStmt(VBAParser.SubStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NegativeLineNumberInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NegativeLineNumberInspection.cs index 302540f9c7..3ff5e9d790 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NegativeLineNumberInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NegativeLineNumberInspection.cs @@ -17,22 +17,22 @@ namespace Rubberduck.Inspections.Inspections.Concrete.ThunderCode /// code our friend Andrew Jackson would have written to confuse Rubberduck's parser and/or resolver. /// The VBE does allow rather strange and unbelievable things to happen. /// - public class NegativeLineNumberInspection : ParseTreeInspectionBase + public sealed class NegativeLineNumberInspection : ParseTreeInspectionBase { public NegativeLineNumberInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) { - Listener = new NegativeLineNumberKeywordsListener(); + ContextListener = new NegativeLineNumberKeywordsListener(); } + protected override IInspectionListener ContextListener { get; } + protected override string ResultDescription(QualifiedContext context) { return InspectionResults.NegativeLineNumberInspection.ThunderCodeFormat(); } - public override IInspectionListener Listener { get; } - - public class NegativeLineNumberKeywordsListener : InspectionListenerBase + public class NegativeLineNumberKeywordsListener : InspectionListenerBase { public override void EnterOnErrorStmt(VBAParser.OnErrorStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs index 42447c9183..abbc0bcc3b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs @@ -1,5 +1,4 @@ -using Antlr4.Runtime; -using Antlr4.Runtime.Tree; +using Antlr4.Runtime.Tree; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; @@ -17,22 +16,22 @@ namespace Rubberduck.Inspections.Inspections.Concrete.ThunderCode /// code our friend Andrew Jackson would have written to confuse Rubberduck's parser and/or resolver. /// 'On Error GoTo -1' is poorly documented and uselessly complicates error handling. /// - public class OnErrorGoToMinusOneInspection : ParseTreeInspectionBase + public sealed class OnErrorGoToMinusOneInspection : ParseTreeInspectionBase { public OnErrorGoToMinusOneInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) { - Listener = new OnErrorGoToMinusOneListener(); + ContextListener = new OnErrorGoToMinusOneListener(); } - protected override string ResultDescription(QualifiedContext context) + protected override IInspectionListener ContextListener { get; } + + protected override string ResultDescription(QualifiedContext context) { return InspectionResults.OnErrorGoToMinusOneInspection.ThunderCodeFormat(); } - public override IInspectionListener Listener { get; } - - public class OnErrorGoToMinusOneListener : InspectionListenerBase + public class OnErrorGoToMinusOneListener : InspectionListenerBase { public override void EnterOnErrorStmt(VBAParser.OnErrorStmtContext context) { @@ -40,7 +39,7 @@ public override void EnterOnErrorStmt(VBAParser.OnErrorStmtContext context) base.EnterOnErrorStmt(context); } - private void CheckContext(ParserRuleContext context, IParseTree expression) + private void CheckContext(VBAParser.OnErrorStmtContext context, IParseTree expression) { var target = expression?.GetText().Trim() ?? string.Empty; if (target.StartsWith("-") && int.TryParse(target.Substring(1), out var result) && result == 1) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs index e8962954e1..bd7802f627 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; @@ -36,37 +35,37 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public class UnhandledOnErrorResumeNextInspection : ParseTreeInspectionBase> + public sealed class UnhandledOnErrorResumeNextInspection : ParseTreeInspectionBase> { - private readonly Dictionary, List> _unhandledContextsMap = - new Dictionary, List>(); + private readonly OnErrorStatementListener _listener = new OnErrorStatementListener(); public UnhandledOnErrorResumeNextInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) - { - Listener = new OnErrorStatementListener(_unhandledContextsMap); - } + {} + + protected override IInspectionListener ContextListener => _listener; - public override IInspectionListener Listener { get; } - protected override string ResultDescription(QualifiedContext context, IReadOnlyList properties) + protected override string ResultDescription(QualifiedContext context, IReadOnlyList properties) { return InspectionResults.UnhandledOnErrorResumeNextInspection; } - protected override (bool isResult, IReadOnlyList properties) IsResultContextWithAdditionalProperties(QualifiedContext context) + protected override (bool isResult, IReadOnlyList properties) IsResultContextWithAdditionalProperties(QualifiedContext context) { - return (true, _unhandledContextsMap[context]); + return (true, _listener.UnhandledContexts(context)); } } - public class OnErrorStatementListener : InspectionListenerBase + public class OnErrorStatementListener : InspectionListenerBase { - private readonly List> _unhandledContexts = new List>(); - private readonly Dictionary, List> _unhandledContextsMap; + private readonly List> _unhandledContexts = new List>(); + private readonly Dictionary, List> _unhandledContextsMap = new Dictionary, List>(); - public OnErrorStatementListener(Dictionary, List> unhandledContextsMap) + public IReadOnlyList UnhandledContexts(QualifiedContext context) { - _unhandledContextsMap = unhandledContextsMap; + return _unhandledContextsMap.TryGetValue(context, out var unhandledContexts) + ? unhandledContexts + : new List(); } public override void ClearContexts() @@ -94,7 +93,7 @@ public override void ExitModuleBodyElement(VBAParser.ModuleBodyElementContext co { foreach (var errorContext in _unhandledContexts) { - _unhandledContextsMap.Add(errorContext, new List(_unhandledContexts.Select(ctx => ctx.Context))); + _unhandledContextsMap.Add(errorContext, new List(_unhandledContexts.Select(ctx => ctx.Context))); SaveContext(errorContext.Context); } @@ -114,10 +113,10 @@ public override void ExitOnErrorStmt(VBAParser.OnErrorStmtContext context) } } - private void SaveUnhandledContext(ParserRuleContext context) + private void SaveUnhandledContext(VBAParser.OnErrorStmtContext context) { var module = CurrentModuleName; - var qualifiedContext = new QualifiedContext(module, context); + var qualifiedContext = new QualifiedContext(module, context); _unhandledContexts.Add(qualifiedContext); } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs index bbf44083f2..9811dced45 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs @@ -162,7 +162,7 @@ protected override IEnumerable DoGetInspectionResults(Qualifi private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder, IParseTreeValueVisitor parseTreeValueVisitor, IUnreachableCaseInspector selectCaseInspector) { - var qualifiedSelectCaseStmts = Listener.Contexts(module) + var qualifiedSelectCaseStmts = _listener.Contexts(module) // ignore filtering here to make the search space smaller .Where(result => !result.IsIgnoringInspectionResultFor(finder, AnnotationName)); @@ -171,10 +171,10 @@ private IEnumerable DoGetInspectionResults(QualifiedModuleNam .ToList(); } - private IEnumerable ResultsForContext(QualifiedContext qualifiedSelectCaseStmt, IParseTreeValueVisitor parseTreeValueVisitor, IUnreachableCaseInspector selectCaseInspector) + private IEnumerable ResultsForContext(QualifiedContext qualifiedSelectCaseStmt, IParseTreeValueVisitor parseTreeValueVisitor, IUnreachableCaseInspector selectCaseInspector) { var module = qualifiedSelectCaseStmt.ModuleName; - var selectStmt = (VBAParser.SelectCaseStmtContext)qualifiedSelectCaseStmt.Context; + var selectStmt = qualifiedSelectCaseStmt.Context; var contextValues = parseTreeValueVisitor.VisitChildren(module, selectStmt); var results = selectCaseInspector.InspectForUnreachableCases(module, selectStmt, contextValues); @@ -184,7 +184,7 @@ private IEnumerable ResultsForContext(QualifiedContext selectStmt, ParserRuleContext unreachableBlock, CaseInspectionResultType resultType) + private IInspectionResult CreateInspectionResult(QualifiedContext selectStmt, ParserRuleContext unreachableBlock, CaseInspectionResultType resultType) { return CreateInspectionResult(selectStmt, unreachableBlock, ResultMessage(resultType)); } @@ -209,7 +209,7 @@ private static string ResultMessage(CaseInspectionResultType resultType) } } - private IInspectionResult CreateInspectionResult(QualifiedContext selectStmt, ParserRuleContext unreachableBlock, string message) + private IInspectionResult CreateInspectionResult(QualifiedContext selectStmt, ParserRuleContext unreachableBlock, string message) { return new QualifiedContextInspectionResult(this, message, @@ -289,7 +289,7 @@ private string GetBaseTypeForDeclaration(Declaration declaration) return localDeclaration is null ? declaration.AsTypeName : localDeclaration.AsTypeName; } - public class UnreachableCaseInspectionListener : InspectionListenerBase + public class UnreachableCaseInspectionListener : InspectionListenerBase { public override void EnterSelectCaseStmt([NotNull] VBAParser.SelectCaseStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs index 8f12b0b7f2..225c2088f4 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; using System.Linq; -using System.Threading; -using Antlr4.Runtime; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.JunkDrawer.Extensions; @@ -57,7 +55,7 @@ public RestoreErrorHandlingQuickFix() public override void Fix(IInspectionResult result, IRewriteSession rewriteSession) { - if (!(result is IWithInspectionResultProperties> resultProperties)) + if (!(result is IWithInspectionResultProperties> resultProperties)) { return; } diff --git a/Rubberduck.Parsing/Inspections/Abstract/IInpsectionListener.cs b/Rubberduck.Parsing/Inspections/Abstract/IInpsectionListener.cs index c64f12b865..ff45d862a2 100644 --- a/Rubberduck.Parsing/Inspections/Abstract/IInpsectionListener.cs +++ b/Rubberduck.Parsing/Inspections/Abstract/IInpsectionListener.cs @@ -7,10 +7,15 @@ namespace Rubberduck.Parsing.Inspections.Abstract { public interface IInspectionListener: IParseTreeListener { - IReadOnlyList> Contexts(); - IReadOnlyList> Contexts(QualifiedModuleName module); void ClearContexts(); void ClearContexts(QualifiedModuleName module); QualifiedModuleName CurrentModuleName { get; set; } } + + public interface IInspectionListener : IInspectionListener + where TContext : ParserRuleContext + { + IReadOnlyList> Contexts(); + IReadOnlyList> Contexts(QualifiedModuleName module); + } } \ No newline at end of file From 42a602a363d1cf9df0379d24b2212e90e46871c1 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Thu, 5 Mar 2020 20:36:37 +0100 Subject: [PATCH 275/461] Let IdentifierReferenceInspectionResult take a DeclarationFinder instead of the provider --- .../IdentifierReferenceInspectionBase.cs | 12 ++++++------ ...ierReferenceInspectionFromDeclarationsBase.cs | 16 ++++++++-------- .../ObjectWhereProcedureIsRequiredInspection.cs | 12 ++++++------ .../Concrete/ObsoleteTypeHintInspection.cs | 6 +++--- .../SuspiciousLetAssignmentInspection.cs | 8 ++++---- .../IdentifierReferenceInspectionResult.cs | 13 +++++++------ .../Inspections/InspectionResultTests.cs | 12 ++++-------- 7 files changed, 38 insertions(+), 41 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs index 27eebf3f5a..9c85d7a7b0 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs @@ -36,7 +36,7 @@ protected IEnumerable DoGetInspectionResults(QualifiedModuleN .Where(reference => IsResultReference(reference, finder)); return objectionableReferences - .Select(reference => InspectionResult(reference, DeclarationFinderProvider)) + .Select(reference => InspectionResult(reference, finder)) .ToList(); } @@ -51,12 +51,12 @@ protected virtual IEnumerable ReferencesInModule(QualifiedM return finder.IdentifierReferences(module); } - protected virtual IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider) + protected virtual IInspectionResult InspectionResult(IdentifierReference reference, DeclarationFinder finder) { return new IdentifierReferenceInspectionResult( this, ResultDescription(reference), - declarationFinderProvider, + finder, reference, DisabledQuickFixes(reference)); } @@ -90,7 +90,7 @@ protected IEnumerable DoGetInspectionResults(QualifiedModuleN .Select(result => result.Value); return objectionableReferencesWithProperties - .Select(tpl => InspectionResult(tpl.reference, DeclarationFinderProvider, tpl.properties)) + .Select(tpl => InspectionResult(tpl.reference, finder, tpl.properties)) .ToList(); } @@ -113,12 +113,12 @@ protected virtual IEnumerable ReferencesInModule(QualifiedM return finder.IdentifierReferences(module); } - protected virtual IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider, T properties) + protected virtual IInspectionResult InspectionResult(IdentifierReference reference, DeclarationFinder finder, T properties) { return new IdentifierReferenceInspectionResult( this, ResultDescription(reference, properties), - declarationFinderProvider, + finder, reference, properties, DisabledQuickFixes(reference, properties)); diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs index c2440cde62..2f2d070ab3 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs @@ -26,7 +26,7 @@ protected override IEnumerable DoGetInspectionResults() var objectionableReferences = ObjectionableReferences(finder); var resultReferences = ResultReferences(objectionableReferences, finder); return resultReferences - .Select(reference => InspectionResult(reference, DeclarationFinderProvider)) + .Select(reference => InspectionResult(reference, finder)) .ToList(); } @@ -52,16 +52,16 @@ protected override IEnumerable DoGetInspectionResults(Qualifi .Where(reference => reference.QualifiedModuleName.Equals(module)); var resultReferences = ResultReferences(objectionableReferences, finder); return resultReferences - .Select(reference => InspectionResult(reference, DeclarationFinderProvider)) + .Select(reference => InspectionResult(reference, finder)) .ToList(); } - protected virtual IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider) + protected virtual IInspectionResult InspectionResult(IdentifierReference reference, DeclarationFinder finder) { return new IdentifierReferenceInspectionResult( this, ResultDescription(reference), - declarationFinderProvider, + finder, reference, DisabledQuickFixes(reference)); } @@ -85,7 +85,7 @@ protected override IEnumerable DoGetInspectionResults() var objectionableReferences = ObjectionableReferences(finder); var resultReferences = ResultReferences(objectionableReferences, finder); return resultReferences - .Select(tpl => InspectionResult(tpl.reference, DeclarationFinderProvider, tpl.properties)) + .Select(tpl => InspectionResult(tpl.reference, finder, tpl.properties)) .ToList(); } @@ -119,16 +119,16 @@ protected override IEnumerable DoGetInspectionResults(Qualifi .Where(reference => reference.QualifiedModuleName.Equals(module)); var resultReferences = ResultReferences(objectionableReferences, finder); return resultReferences - .Select(tpl => InspectionResult(tpl.reference, DeclarationFinderProvider, tpl.properties)) + .Select(tpl => InspectionResult(tpl.reference, finder, tpl.properties)) .ToList(); } - protected virtual IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider, T properties) + protected virtual IInspectionResult InspectionResult(IdentifierReference reference, DeclarationFinder finder, T properties) { return new IdentifierReferenceInspectionResult( this, ResultDescription(reference, properties), - declarationFinderProvider, + finder, reference, properties, DisabledQuickFixes(reference, properties)); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs index 7c7fb93f9a..7b40b4898b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs @@ -89,7 +89,7 @@ private IEnumerable BoundInspectionResults(QualifiedModuleNam .Where(IsResultReference); return objectionableReferences - .Select(reference => BoundInspectionResult(reference, DeclarationFinderProvider)) + .Select(reference => BoundInspectionResult(reference, finder)) .ToList(); } @@ -98,12 +98,12 @@ private static bool IsResultReference(IdentifierReference reference) return reference.IsProcedureCoercion; } - private IInspectionResult BoundInspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider) + private IInspectionResult BoundInspectionResult(IdentifierReference reference, DeclarationFinder finder) { return new IdentifierReferenceInspectionResult( this, BoundResultDescription(reference), - declarationFinderProvider, + finder, reference); } @@ -121,17 +121,17 @@ private IEnumerable UnboundInspectionResults(QualifiedModuleN .Where(IsResultReference); return objectionableReferences - .Select(reference => UnboundInspectionResult(reference, DeclarationFinderProvider)) + .Select(reference => UnboundInspectionResult(reference, finder)) .ToList(); } - private IInspectionResult UnboundInspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider) + private IInspectionResult UnboundInspectionResult(IdentifierReference reference, DeclarationFinder finder) { var disabledQuickFixes = new List{ "ExpandDefaultMemberQuickFix" }; return new IdentifierReferenceInspectionResult( this, UnboundResultDescription(reference), - declarationFinderProvider, + finder, reference, disabledQuickFixes); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs index f609c62011..5a6e227513 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs @@ -95,15 +95,15 @@ private IEnumerable ReferenceResults(QualifiedModuleName modu && reference.Declaration.IsUserDefined && reference.HasTypeHint()); return objectionableReferences - .Select(reference => InspectionResult(reference, DeclarationFinderProvider)); + .Select(reference => InspectionResult(reference, finder)); } - private IInspectionResult InspectionResult(IdentifierReference reference, IDeclarationFinderProvider declarationFinderProvider) + private IInspectionResult InspectionResult(IdentifierReference reference, DeclarationFinder finder) { return new IdentifierReferenceInspectionResult( this, ResultDescription(reference), - declarationFinderProvider, + finder, reference); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs index 9c53d9b6a6..be1cd483d3 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs @@ -86,7 +86,7 @@ private IEnumerable BoundLhsInspectionResults(QualifiedModule if (rhsDefaultMemberAccess != null) { - var result = InspectionResult(assignment, rhsDefaultMemberAccess, isUnbound); + var result = InspectionResult(assignment, rhsDefaultMemberAccess, isUnbound, finder); results.Add(result); } } @@ -127,7 +127,7 @@ private bool IsImplicitDefaultMemberAssignment(IdentifierReference reference) return (unboundRhsDefaultMemberAccess, true); } - private IInspectionResult InspectionResult(IdentifierReference lhsReference, IdentifierReference rhsReference, bool isUnbound) + private IInspectionResult InspectionResult(IdentifierReference lhsReference, IdentifierReference rhsReference, bool isUnbound, DeclarationFinder finder) { var disabledQuickFixes = isUnbound ? new List {"ExpandDefaultMemberQuickFix"} @@ -135,7 +135,7 @@ private IInspectionResult InspectionResult(IdentifierReference lhsReference, Ide return new IdentifierReferenceInspectionResult( this, ResultDescription(lhsReference, rhsReference), - DeclarationFinderProvider, + finder, lhsReference, rhsReference, disabledQuickFixes); @@ -161,7 +161,7 @@ private IEnumerable UnboundLhsInspectionResults(QualifiedModu if (rhsDefaultMemberAccess != null) { - var result = InspectionResult(assignment, rhsDefaultMemberAccess, true); + var result = InspectionResult(assignment, rhsDefaultMemberAccess, true, finder); results.Add(result); } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Results/IdentifierReferenceInspectionResult.cs b/Rubberduck.CodeAnalysis/Inspections/Results/IdentifierReferenceInspectionResult.cs index 58167ee8d6..02bdf3b81a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Results/IdentifierReferenceInspectionResult.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Results/IdentifierReferenceInspectionResult.cs @@ -5,6 +5,7 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Results @@ -16,7 +17,7 @@ public class IdentifierReferenceInspectionResult : InspectionResultBase public IdentifierReferenceInspectionResult( IInspection inspection, string description, - IDeclarationFinderProvider declarationFinderProvider, + DeclarationFinder finder, IdentifierReference reference, ICollection disabledQuickFixes = null) : base(inspection, @@ -25,15 +26,15 @@ public IdentifierReferenceInspectionResult( reference.Context, reference.Declaration, new QualifiedSelection(reference.QualifiedModuleName, reference.Context.GetSelection()), - GetQualifiedMemberName(declarationFinderProvider, reference), + GetQualifiedMemberName(finder, reference), disabledQuickFixes) { Reference = reference; } - private static QualifiedMemberName? GetQualifiedMemberName(IDeclarationFinderProvider declarationFinderProvider, IdentifierReference reference) + private static QualifiedMemberName? GetQualifiedMemberName(DeclarationFinder finder, IdentifierReference reference) { - var members = declarationFinderProvider.DeclarationFinder.Members(reference.QualifiedModuleName); + var members = finder.Members(reference.QualifiedModuleName); return members.SingleOrDefault(m => reference.Context.IsDescendentOf(m.Context))?.QualifiedName; } @@ -49,14 +50,14 @@ public class IdentifierReferenceInspectionResult : IdentifierReferenceInspect public IdentifierReferenceInspectionResult( IInspection inspection, string description, - IDeclarationFinderProvider declarationFinderProvider, + DeclarationFinder finder, IdentifierReference reference, T properties, ICollection disabledQuickFixes = null) : base( inspection, description, - declarationFinderProvider, + finder, reference, disabledQuickFixes) { diff --git a/RubberduckTests/Inspections/InspectionResultTests.cs b/RubberduckTests/Inspections/InspectionResultTests.cs index 4eef6b2415..8511e18072 100644 --- a/RubberduckTests/Inspections/InspectionResultTests.cs +++ b/RubberduckTests/Inspections/InspectionResultTests.cs @@ -140,13 +140,11 @@ public void IdentifierRefereneceInspectionResultsAreDeemedInvalidatedIfTheModule var identifierReference = new IdentifierReference(module, null, null, "test", default, null, declaration); var modifiedModules = new HashSet { declarationModule }; - var declarationFinderProviderMock = new Mock(); - var declaratioFinder = new DeclarationFinder( + var finder = new DeclarationFinder( new List(), new List(), new Dictionary()); - declarationFinderProviderMock.SetupGet(m => m.DeclarationFinder).Returns(declaratioFinder); - var inspectionResult = new IdentifierReferenceInspectionResult(inspectionMock.Object, string.Empty, declarationFinderProviderMock.Object, identifierReference); + var inspectionResult = new IdentifierReferenceInspectionResult(inspectionMock.Object, string.Empty, finder, identifierReference); Assert.IsTrue(inspectionResult.ChangesInvalidateResult(modifiedModules)); } @@ -171,13 +169,11 @@ public void IdentifierReferenceInspectionResultsAreNotDeemedInvalidatedIfNeither var identifierReference = new IdentifierReference(module, null, null, "test", default, null, declaration); var modifiedModules = new HashSet { otherModule }; - var declarationFinderProviderMock = new Mock(); - var declarationFinder = new DeclarationFinder( + var finder = new DeclarationFinder( new List(), new List(), new Dictionary()); - declarationFinderProviderMock.SetupGet(m => m.DeclarationFinder).Returns(declarationFinder); - var inspectionResult = new IdentifierReferenceInspectionResult(inspectionMock.Object, string.Empty, declarationFinderProviderMock.Object, identifierReference); + var inspectionResult = new IdentifierReferenceInspectionResult(inspectionMock.Object, string.Empty, finder, identifierReference); Assert.IsFalse(inspectionResult.ChangesInvalidateResult(modifiedModules)); } From ab922fd87ee22ea44218dbd131cfa88e5d38aaed Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Fri, 6 Mar 2020 00:59:28 +0100 Subject: [PATCH 276/461] Let hand down the declaration finder in InspectionBase to the implementations as method parameter Before, the provider was protected and that was used, getting a new one in all base classes for the different kinds of inspections. --- .../Abstract/DeclarationInspectionBaseBase.cs | 30 +++++-------- ...nspectionUsingGlobalInformationBaseBase.cs | 6 +-- .../IdentifierReferenceInspectionBase.cs | 24 ++-------- ...ReferenceInspectionFromDeclarationsBase.cs | 12 ++--- .../Inspections/Abstract/InspectionBase.cs | 21 ++++----- .../Abstract/ParseTreeInspectionBase.cs | 33 +++++++------- ...elUdfNameIsValidCellReferenceInspection.cs | 44 +++++-------------- .../Concrete/IllegalAnnotationInspection.cs | 12 +---- .../MissingAnnotationArgumentInspection.cs | 12 +---- ...bjectWhereProcedureIsRequiredInspection.cs | 14 ++---- .../ObsoleteCallStatementInspection.cs | 3 +- .../ObsoleteCallingConventionInspection.cs | 3 +- .../Concrete/ObsoleteTypeHintInspection.cs | 12 +---- .../Concrete/OptionExplicitInspection.cs | 3 +- ...SuperfluousAnnotationArgumentInspection.cs | 12 +---- .../SuspiciousLetAssignmentInspection.cs | 12 +---- .../UnhandledOnErrorResumeNextInspection.cs | 3 +- .../UnreachableCaseInspection.cs | 6 +-- .../IdentifierReferenceInspectionResult.cs | 1 - 19 files changed, 82 insertions(+), 181 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs index 6a8346b006..21c17da6f7 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs @@ -10,29 +10,25 @@ namespace Rubberduck.Inspections.Abstract { public abstract class DeclarationInspectionBaseBase : InspectionBase { - protected readonly DeclarationType[] RelevantDeclarationTypes; - protected readonly DeclarationType[] ExcludeDeclarationTypes; + private readonly DeclarationType[] _relevantDeclarationTypes; + private readonly DeclarationType[] _excludeDeclarationTypes; protected DeclarationInspectionBaseBase(IDeclarationFinderProvider declarationFinderProvider, params DeclarationType[] relevantDeclarationTypes) : base(declarationFinderProvider) { - RelevantDeclarationTypes = relevantDeclarationTypes; - ExcludeDeclarationTypes = new DeclarationType[0]; + _relevantDeclarationTypes = relevantDeclarationTypes; + _excludeDeclarationTypes = new DeclarationType[0]; } protected DeclarationInspectionBaseBase(IDeclarationFinderProvider declarationFinderProvider, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes) : base(declarationFinderProvider) { - RelevantDeclarationTypes = relevantDeclarationTypes; - ExcludeDeclarationTypes = excludeDeclarationTypes; + _relevantDeclarationTypes = relevantDeclarationTypes; + _excludeDeclarationTypes = excludeDeclarationTypes; } - protected abstract IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder); - - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable DoGetInspectionResults(DeclarationFinder finder) { - var finder = DeclarationFinderProvider.DeclarationFinder; - return finder.UserDeclarations(DeclarationType.Module) .Concat(finder.UserDeclarations(DeclarationType.Project)) .Where(declaration => declaration != null) @@ -40,21 +36,15 @@ protected override IEnumerable DoGetInspectionResults() .ToList(); } - protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) - { - var finder = DeclarationFinderProvider.DeclarationFinder; - return DoGetInspectionResults(module, finder); - } - protected virtual IEnumerable RelevantDeclarationsInModule(QualifiedModuleName module, DeclarationFinder finder) { - var potentiallyRelevantDeclarations = RelevantDeclarationTypes.Length == 0 + var potentiallyRelevantDeclarations = _relevantDeclarationTypes.Length == 0 ? finder.Members(module) - : RelevantDeclarationTypes + : _relevantDeclarationTypes .SelectMany(declarationType => finder.Members(module, declarationType)) .Distinct(); return potentiallyRelevantDeclarations - .Where(declaration => !ExcludeDeclarationTypes.Contains(declaration.DeclarationType)); + .Where(declaration => !_excludeDeclarationTypes.Contains(declaration.DeclarationType)); } } } \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs index c86f2f2b5f..9848592caa 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs @@ -38,9 +38,8 @@ protected virtual T GlobalInformation(QualifiedModuleName module, DeclarationFin return GlobalInformation(finder); } - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable DoGetInspectionResults(DeclarationFinder finder) { - var finder = DeclarationFinderProvider.DeclarationFinder; var globalInformation = GlobalInformation(finder); return finder.UserDeclarations(DeclarationType.Module) @@ -50,9 +49,8 @@ protected override IEnumerable DoGetInspectionResults() .ToList(); } - protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { - var finder = DeclarationFinderProvider.DeclarationFinder; var globalInformation = GlobalInformation(module, finder); return DoGetInspectionResults(module, finder, globalInformation); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs index 9c85d7a7b0..5162e686f5 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs @@ -20,17 +20,15 @@ protected IdentifierReferenceInspectionBase(IDeclarationFinderProvider declarati protected virtual ICollection DisabledQuickFixes(IdentifierReference reference) => new List(); - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable DoGetInspectionResults(DeclarationFinder finder) { - var finder = DeclarationFinderProvider.DeclarationFinder; - return finder.UserDeclarations(DeclarationType.Module) .Where(declaration => declaration != null) .SelectMany(declaration => DoGetInspectionResults(declaration.QualifiedModuleName, finder)) .ToList(); } - protected IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { var objectionableReferences = ReferencesInModule(module, finder) .Where(reference => IsResultReference(reference, finder)); @@ -40,12 +38,6 @@ protected IEnumerable DoGetInspectionResults(QualifiedModuleN .ToList(); } - protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) - { - var finder = DeclarationFinderProvider.DeclarationFinder; - return DoGetInspectionResults(module, finder); - } - protected virtual IEnumerable ReferencesInModule(QualifiedModuleName module, DeclarationFinder finder) { return finder.IdentifierReferences(module); @@ -73,16 +65,14 @@ protected IdentifierReferenceInspectionBase(IDeclarationFinderProvider declarati protected virtual ICollection DisabledQuickFixes(IdentifierReference reference, T properties) => new List(); - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable DoGetInspectionResults(DeclarationFinder finder) { - var finder = DeclarationFinderProvider.DeclarationFinder; - return finder.UserDeclarations(DeclarationType.Module) .Where(module => module != null) .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder)); } - protected IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { var objectionableReferencesWithProperties = ReferencesInModule(module, finder) .Select(reference => ReferenceWithResultProperties(reference, finder)) @@ -102,12 +92,6 @@ protected IEnumerable DoGetInspectionResults(QualifiedModuleN : ((IdentifierReference reference, T properties)?)null; } - protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) - { - var finder = DeclarationFinderProvider.DeclarationFinder; - return DoGetInspectionResults(module, finder); - } - protected virtual IEnumerable ReferencesInModule(QualifiedModuleName module, DeclarationFinder finder) { return finder.IdentifierReferences(module); diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs index 2f2d070ab3..e18696a37f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs @@ -20,9 +20,8 @@ protected IdentifierReferenceInspectionFromDeclarationsBase(IDeclarationFinderPr protected virtual ICollection DisabledQuickFixes(IdentifierReference reference) => new List(); - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable DoGetInspectionResults(DeclarationFinder finder) { - var finder = DeclarationFinderProvider.DeclarationFinder; var objectionableReferences = ObjectionableReferences(finder); var resultReferences = ResultReferences(objectionableReferences, finder); return resultReferences @@ -45,9 +44,8 @@ protected virtual IEnumerable ObjectionableReferences(Decla protected virtual bool IsResultReference(IdentifierReference reference, DeclarationFinder finder) => true; - protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { - var finder = DeclarationFinderProvider.DeclarationFinder; var objectionableReferences = ObjectionableReferences(finder) .Where(reference => reference.QualifiedModuleName.Equals(module)); var resultReferences = ResultReferences(objectionableReferences, finder); @@ -79,9 +77,8 @@ protected IdentifierReferenceInspectionFromDeclarationsBase(IDeclarationFinderPr protected virtual ICollection DisabledQuickFixes(IdentifierReference reference, T properties) => new List(); - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable DoGetInspectionResults(DeclarationFinder finder) { - var finder = DeclarationFinderProvider.DeclarationFinder; var objectionableReferences = ObjectionableReferences(finder); var resultReferences = ResultReferences(objectionableReferences, finder); return resultReferences @@ -112,9 +109,8 @@ protected virtual IEnumerable ObjectionableReferences(Decla .SelectMany(declaration => declaration.References); } - protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { - var finder = DeclarationFinderProvider.DeclarationFinder; var objectionableReferences = ObjectionableReferences(finder) .Where(reference => reference.QualifiedModuleName.Equals(module)); var resultReferences = ResultReferences(objectionableReferences, finder); diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs index fbfaed44d0..c0760a4f32 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs @@ -10,12 +10,13 @@ using NLog; using Rubberduck.Parsing.Inspections; using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Abstract { public abstract class InspectionBase : IInspection { - protected readonly IDeclarationFinderProvider DeclarationFinderProvider; + private readonly IDeclarationFinderProvider _declarationFinderProvider; protected readonly ILogger Logger; @@ -23,7 +24,7 @@ protected InspectionBase(IDeclarationFinderProvider declarationFinderProvider) { Logger = LogManager.GetLogger(GetType().FullName); - DeclarationFinderProvider = declarationFinderProvider; + _declarationFinderProvider = declarationFinderProvider; Name = GetType().Name; } @@ -67,8 +68,8 @@ protected InspectionBase(IDeclarationFinderProvider declarationFinderProvider) public int CompareTo(IInspection other) => string.Compare(InspectionType + Name, other.InspectionType + other.Name, StringComparison.Ordinal); public int CompareTo(object obj) => CompareTo(obj as IInspection); - protected abstract IEnumerable DoGetInspectionResults(); - protected abstract IEnumerable DoGetInspectionResults(QualifiedModuleName module); + protected abstract IEnumerable DoGetInspectionResults(DeclarationFinder finder); + protected abstract IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder); /// /// A method that inspects the parser state and returns all issues it can find. @@ -79,9 +80,9 @@ public IEnumerable GetInspectionResults(CancellationToken tok { var stopwatch = new Stopwatch(); stopwatch.Start(); - var declarationFinder = DeclarationFinderProvider.DeclarationFinder; - var result = DoGetInspectionResults() - .Where(ir => !ir.IsIgnoringInspectionResult(declarationFinder)) + var finder = _declarationFinderProvider.DeclarationFinder; + var result = DoGetInspectionResults(finder) + .Where(ir => !ir.IsIgnoringInspectionResult(finder)) .ToList(); stopwatch.Stop(); Logger.Trace("Intercepted invocation of '{0}.{1}' returned {2} objects.", GetType().Name, nameof(DoGetInspectionResults), result.Count); @@ -99,9 +100,9 @@ public IEnumerable GetInspectionResults(QualifiedModuleName m { var stopwatch = new Stopwatch(); stopwatch.Start(); - var declarationFinder = DeclarationFinderProvider.DeclarationFinder; - var result = DoGetInspectionResults(module) - .Where(ir => !ir.IsIgnoringInspectionResult(declarationFinder)) + var finder = _declarationFinderProvider.DeclarationFinder; + var result = DoGetInspectionResults(module, finder) + .Where(ir => !ir.IsIgnoringInspectionResult(finder)) .ToList(); stopwatch.Stop(); Logger.Trace("Intercepted invocation of '{0}.{1}' returned {2} objects.", GetType().Name, nameof(DoGetInspectionResults), result.Count); diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs index 8971273864..e8f2fd3c49 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs @@ -7,6 +7,7 @@ using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Parsing.VBA.Parsing; using Rubberduck.VBEditor; @@ -25,22 +26,22 @@ protected ParseTreeInspectionBase(IDeclarationFinderProvider declarationFinderPr protected abstract string ResultDescription(QualifiedContext context); - protected virtual bool IsResultContext(QualifiedContext context) => true; + protected virtual bool IsResultContext(QualifiedContext context, DeclarationFinder finder) => true; - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable DoGetInspectionResults(DeclarationFinder finder) { - return DoGetInspectionResults(ContextListener.Contexts()); + return DoGetInspectionResults(ContextListener.Contexts(), finder); } - protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { - return DoGetInspectionResults(ContextListener.Contexts(module)); + return DoGetInspectionResults(ContextListener.Contexts(module), finder); } - private IEnumerable DoGetInspectionResults(IEnumerable> contexts) + private IEnumerable DoGetInspectionResults(IEnumerable> contexts, DeclarationFinder finder) { var objectionableContexts = contexts - .Where(IsResultContext); + .Where(context => IsResultContext(context, finder)); return objectionableContexts .Select(InspectionResult) @@ -72,22 +73,22 @@ protected ParseTreeInspectionBase(IDeclarationFinderProvider declarationFinderPr protected abstract IInspectionListener ContextListener { get; } protected abstract string ResultDescription(QualifiedContext context, TProperties properties); - protected abstract (bool isResult, TProperties properties) IsResultContextWithAdditionalProperties(QualifiedContext context); + protected abstract (bool isResult, TProperties properties) IsResultContextWithAdditionalProperties(QualifiedContext context, DeclarationFinder finder); - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable DoGetInspectionResults(DeclarationFinder finder) { - return DoGetInspectionResults(ContextListener.Contexts()); + return DoGetInspectionResults(ContextListener.Contexts(), finder); } - protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { - return DoGetInspectionResults(ContextListener.Contexts(module)); + return DoGetInspectionResults(ContextListener.Contexts(module), finder); } - private IEnumerable DoGetInspectionResults(IEnumerable> contexts) + private IEnumerable DoGetInspectionResults(IEnumerable> contexts, DeclarationFinder finder) { var objectionableContexts = contexts - .Select(ContextsWithResultProperties) + .Select(context => ContextsWithResultProperties(context, finder)) .Where(result => result.HasValue) .Select(result => result.Value); @@ -96,9 +97,9 @@ private IEnumerable DoGetInspectionResults(IEnumerable context, TProperties properties)? ContextsWithResultProperties(QualifiedContext context) + private (QualifiedContext context, TProperties properties)? ContextsWithResultProperties(QualifiedContext context, DeclarationFinder finder) { - var (isResult, properties) = IsResultContextWithAdditionalProperties(context); + var (isResult, properties) = IsResultContextWithAdditionalProperties(context, finder); return isResult ? (context, properties) : ((QualifiedContext context, TProperties properties)?) null; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs index daa54ceb8c..0da3951c6f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs @@ -35,43 +35,15 @@ namespace Rubberduck.Inspections.Inspections.Concrete /// ]]> /// [RequiredLibrary("Excel")] - public class ExcelUdfNameIsValidCellReferenceInspection : DeclarationInspectionBase + public class ExcelUdfNameIsValidCellReferenceInspection : DeclarationInspectionUsingGlobalInformationBase { public ExcelUdfNameIsValidCellReferenceInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, new []{DeclarationType.Function}, new []{DeclarationType.PropertyGet, DeclarationType.LibraryFunction}) {} - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder, bool excelIsReferenced) { - //FIXME As-is, both this method and the base method get a declaration finder. - var finder = DeclarationFinderProvider.DeclarationFinder; - - if (!finder.Projects.Any(project => !project.IsUserDefined - && project.IdentifierName == "Excel")) - { - return Enumerable.Empty(); - } - - return base.DoGetInspectionResults(); - } - - protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) - { - //FIXME As-is, both this method and the base method get a declaration finder. - var finder = DeclarationFinderProvider.DeclarationFinder; - - if (!finder.Projects.Any(project => !project.IsUserDefined - && project.IdentifierName == "Excel")) - { - return Enumerable.Empty(); - } - - return base.DoGetInspectionResults(module); - } - - protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) - { - if (module.ComponentType != ComponentType.StandardModule) + if (!excelIsReferenced || module.ComponentType != ComponentType.StandardModule) { return Enumerable.Empty(); } @@ -85,10 +57,16 @@ protected override IEnumerable DoGetInspectionResults(Qualifi return Enumerable.Empty(); } - return base.DoGetInspectionResults(module, finder); + return base.DoGetInspectionResults(module, finder, excelIsReferenced); + } + + protected override bool GlobalInformation(DeclarationFinder finder) + { + return finder.Projects.Any(project => !project.IsUserDefined + && project.IdentifierName == "Excel"); } - protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder) + protected override bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder, bool globalInfo) { if (!VisibleAsUdf.Contains(declaration.Accessibility)) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs index 20e988c7cd..50c4a41f68 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs @@ -47,22 +47,14 @@ public IllegalAnnotationInspection(IDeclarationFinderProvider declarationFinderP : base(declarationFinderProvider) {} - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable DoGetInspectionResults(DeclarationFinder finder) { - var finder = DeclarationFinderProvider.DeclarationFinder; - return finder.UserDeclarations(DeclarationType.Module) .Where(module => module != null) .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder)); } - protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) - { - var finder = DeclarationFinderProvider.DeclarationFinder; - return DoGetInspectionResults(module, finder); - } - - private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { var userDeclarations = finder.Members(module).ToList(); var identifierReferences = finder.IdentifierReferences(module).ToList(); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs index 31cdf70cfd..e6eb5aba0a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs @@ -41,23 +41,15 @@ public MissingAnnotationArgumentInspection(IDeclarationFinderProvider declaratio : base(declarationFinderProvider) {} - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable DoGetInspectionResults(DeclarationFinder finder) { - var finder = DeclarationFinderProvider.DeclarationFinder; - return finder.UserDeclarations(DeclarationType.Module) .Where(module => module != null) .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder)) .ToList(); } - protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) - { - var finder = DeclarationFinderProvider.DeclarationFinder; - return DoGetInspectionResults(module, finder); - } - - private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { var objectionableAnnotations = finder.FindAnnotations(module) .Where(IsResultAnnotation); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs index 7b40b4898b..518ad1f241 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs @@ -61,22 +61,14 @@ public ObjectWhereProcedureIsRequiredInspection(IDeclarationFinderProvider decla Severity = CodeInspectionSeverity.Warning; } - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable DoGetInspectionResults(DeclarationFinder finder) { - var finder = DeclarationFinderProvider.DeclarationFinder; - return finder.UserDeclarations(DeclarationType.Module) .Where(module => module != null) - .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName)); - } - - protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) - { - var finder = DeclarationFinderProvider.DeclarationFinder; - return DoGetInspectionResults(module, finder); + .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder)); } - private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { return BoundInspectionResults(module, finder) .Concat(UnboundInspectionResults(module, finder)); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs index 2d36be43ce..057c91b508 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs @@ -4,6 +4,7 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete { @@ -50,7 +51,7 @@ protected override string ResultDescription(QualifiedContext context) + protected override bool IsResultContext(QualifiedContext context, DeclarationFinder finder) { if (!context.Context.TryGetFollowingContext(out VBAParser.IndividualNonEOFEndOfStatementContext followingEndOfStatement) || followingEndOfStatement.COLON() == null) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs index c4bc26ef47..e120534934 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs @@ -3,6 +3,7 @@ using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; namespace Rubberduck.Inspections.Inspections.Concrete @@ -42,7 +43,7 @@ protected override string ResultDescription(QualifiedContext context) + protected override bool IsResultContext(QualifiedContext context, DeclarationFinder finder) { return ((VBAParser.DeclareStmtContext)context.Context).CDECL() != null; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs index 5a6e227513..dc954e775d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs @@ -39,22 +39,14 @@ public ObsoleteTypeHintInspection(IDeclarationFinderProvider declarationFinderPr : base(declarationFinderProvider) {} - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable DoGetInspectionResults(DeclarationFinder finder) { - var finder = DeclarationFinderProvider.DeclarationFinder; - return finder.UserDeclarations(DeclarationType.Module) .Where(module => module != null) .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder)); } - protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) - { - var finder = DeclarationFinderProvider.DeclarationFinder; - return DoGetInspectionResults(module, finder); - } - - private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { var declarationResults = DeclarationResults(module, finder); var referenceResults = ReferenceResults(module, finder); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs index 9502115843..d833fd8030 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs @@ -6,6 +6,7 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete @@ -45,7 +46,7 @@ public OptionExplicitInspection(IDeclarationFinderProvider declarationFinderProv protected override IInspectionListener ContextListener { get; } - protected override bool IsResultContext(QualifiedContext context) + protected override bool IsResultContext(QualifiedContext context, DeclarationFinder finder) { var moduleBody = context.Context.moduleBody(); return moduleBody != null && moduleBody.ChildCount != 0; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuperfluousAnnotationArgumentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuperfluousAnnotationArgumentInspection.cs index ff3a945613..fc298ea15d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuperfluousAnnotationArgumentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuperfluousAnnotationArgumentInspection.cs @@ -42,23 +42,15 @@ public SuperfluousAnnotationArgumentInspection(IDeclarationFinderProvider declar : base(declarationFinderProvider) {} - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable DoGetInspectionResults(DeclarationFinder finder) { - var finder = DeclarationFinderProvider.DeclarationFinder; - return finder.UserDeclarations(DeclarationType.Module) .Where(module => module != null) .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder)) .ToList(); } - protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) - { - var finder = DeclarationFinderProvider.DeclarationFinder; - return DoGetInspectionResults(module, finder); - } - - private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { var objectionableAnnotations = finder.FindAnnotations(module) .Where(IsResultAnnotation); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs index be1cd483d3..551cdd196a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs @@ -51,22 +51,14 @@ public SuspiciousLetAssignmentInspection(IDeclarationFinderProvider declarationF Severity = CodeInspectionSeverity.Warning; } - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable DoGetInspectionResults(DeclarationFinder finder) { - var finder = DeclarationFinderProvider.DeclarationFinder; - return finder.UserDeclarations(DeclarationType.Module) .Where(module => module != null) .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder)); } - protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) - { - var finder = DeclarationFinderProvider.DeclarationFinder; - return DoGetInspectionResults(module, finder); - } - - private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { return BoundLhsInspectionResults(module, finder) .Concat(UnboundLhsInspectionResults(module, finder)); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs index bd7802f627..5406d3b9f9 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs @@ -6,6 +6,7 @@ using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete @@ -50,7 +51,7 @@ protected override string ResultDescription(QualifiedContext properties) IsResultContextWithAdditionalProperties(QualifiedContext context) + protected override (bool isResult, IReadOnlyList properties) IsResultContextWithAdditionalProperties(QualifiedContext context, DeclarationFinder finder) { return (true, _listener.UnhandledContexts(context)); } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs index 9811dced45..fa40eb406d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs @@ -140,9 +140,8 @@ public UnreachableCaseInspection(IDeclarationFinderProvider declarationFinderPro public IInspectionListener Listener => _listener; - protected override IEnumerable DoGetInspectionResults() + protected override IEnumerable DoGetInspectionResults(DeclarationFinder finder) { - var finder = DeclarationFinderProvider.DeclarationFinder; var parseTreeValueVisitor = CreateParseTreeValueVisitor(GetIdentifierReferenceForContextFunction(finder)); var selectCaseInspector = _unreachableCaseInspectorFactory.Create(GetVariableTypeNameFunction(finder)); @@ -152,9 +151,8 @@ protected override IEnumerable DoGetInspectionResults() .ToList(); } - protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module) + protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { - var finder = DeclarationFinderProvider.DeclarationFinder; var parseTreeValueVisitor = CreateParseTreeValueVisitor(GetIdentifierReferenceForContextFunction(finder)); var selectCaseInspector = _unreachableCaseInspectorFactory.Create(GetVariableTypeNameFunction(finder)); return DoGetInspectionResults(module, finder, parseTreeValueVisitor, selectCaseInspector); diff --git a/Rubberduck.CodeAnalysis/Inspections/Results/IdentifierReferenceInspectionResult.cs b/Rubberduck.CodeAnalysis/Inspections/Results/IdentifierReferenceInspectionResult.cs index 02bdf3b81a..c3cdeef75a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Results/IdentifierReferenceInspectionResult.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Results/IdentifierReferenceInspectionResult.cs @@ -4,7 +4,6 @@ using Rubberduck.Parsing; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; -using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.VBEditor; From b26b8f4d03e00557c133fc5a878b4b1fc309404f Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Fri, 6 Mar 2020 23:40:03 +0100 Subject: [PATCH 277/461] Make ParseTreeValueVisitor.VisitChildren pure Also turns the ParseTreeValueVisitor in UnreachableCaseInspection into a constructor injected field. --- .../ParseTreeValueVisitor.cs | 183 ++++++++++++------ .../ParseTreeValueVisitorFactory.cs | 27 --- .../UnreachableCaseInspection.cs | 29 ++- ...nreachableCaseInspectionFactoryProvider.cs | 6 - .../Root/RubberduckIoCInstaller.cs | 3 - .../UnreachableCaseInspectionTests.cs | 46 ++--- 6 files changed, 154 insertions(+), 140 deletions(-) delete mode 100644 Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitorFactory.cs diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs index 0b317f6d9d..bd46d9000c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs @@ -6,13 +6,14 @@ using System; using System.Collections.Generic; using System.Linq; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { public interface IParseTreeValueVisitor { - IParseTreeVisitorResults VisitChildren(QualifiedModuleName module, IRuleNode node); + IParseTreeVisitorResults VisitChildren(QualifiedModuleName module, IRuleNode node, DeclarationFinder finder); } public class EnumMember @@ -35,26 +36,21 @@ public class ParseTreeValueVisitor : IParseTreeValueVisitor public ParseTreeValueVisitor( IParseTreeValueFactory valueFactory, - Func identifierReferenceRetriever, Func valueDeclarationEvaluator = null) { _valueFactory = valueFactory; - IdentifierReferenceRetriever = identifierReferenceRetriever; _valueDeclarationEvaluator = valueDeclarationEvaluator ?? GetValuedDeclaration; } - //This does not use a qualified context in order to avoid constant boxing and unboxing. - private Func IdentifierReferenceRetriever { get; } - - public IParseTreeVisitorResults VisitChildren(QualifiedModuleName module, IRuleNode ruleNode) + public IParseTreeVisitorResults VisitChildren(QualifiedModuleName module, IRuleNode ruleNode, DeclarationFinder finder) { var newResults = new ParseTreeVisitorResults(); - return VisitChildren(module, ruleNode, newResults); + return VisitChildren(module, ruleNode, newResults, finder); } //The known results get passed along instead of aggregating from the bottom since other contexts can get already visited when resolving the value of other contexts. //Passing the results along avoids performing the resolution multiple times. - private IMutableParseTreeVisitorResults VisitChildren(QualifiedModuleName module, IRuleNode node, IMutableParseTreeVisitorResults knownResults) + private IMutableParseTreeVisitorResults VisitChildren(QualifiedModuleName module, IRuleNode node, IMutableParseTreeVisitorResults knownResults, DeclarationFinder finder) { if (!(node is ParserRuleContext context)) { @@ -64,57 +60,79 @@ private IMutableParseTreeVisitorResults VisitChildren(QualifiedModuleName module var valueResults = knownResults; foreach (var child in context.children) { - valueResults = Visit(module, child, valueResults); + valueResults = Visit(module, child, valueResults, finder); } return valueResults; } - private IMutableParseTreeVisitorResults Visit(QualifiedModuleName module, IParseTree tree, IMutableParseTreeVisitorResults knownResults) + private IMutableParseTreeVisitorResults Visit(QualifiedModuleName module, IParseTree tree, IMutableParseTreeVisitorResults knownResults, DeclarationFinder finder) { var valueResults = knownResults; if (tree is ParserRuleContext context && !(context is VBAParser.WhiteSpaceContext)) { - valueResults = Visit(module, context, valueResults); + valueResults = Visit(module, context, valueResults, finder); } return valueResults; } - private IMutableParseTreeVisitorResults Visit(QualifiedModuleName module, ParserRuleContext parserRuleContext, IMutableParseTreeVisitorResults knownResults) + private IMutableParseTreeVisitorResults Visit(QualifiedModuleName module, ParserRuleContext parserRuleContext, IMutableParseTreeVisitorResults knownResults, DeclarationFinder finder) { switch (parserRuleContext) { case VBAParser.LExprContext lExpr: - return Visit(module, lExpr, knownResults); + return Visit(module, lExpr, knownResults, finder); case VBAParser.LiteralExprContext litExpr: return Visit(litExpr, knownResults); case VBAParser.CaseClauseContext caseClause: - var caseClauseResults = VisitChildren(module, caseClause, knownResults); - caseClauseResults.AddIfNotPresent(caseClause, _valueFactory.Create(caseClause.GetText())); - return caseClauseResults; + return VisitCaseClause(module, caseClause, knownResults, finder); case VBAParser.RangeClauseContext rangeClause: - var rangeClauseResults = VisitChildren(module, rangeClause, knownResults); - rangeClauseResults.AddIfNotPresent(rangeClause, _valueFactory.Create(rangeClause.GetText())); - return rangeClauseResults; + return VisitRangeClause(module, rangeClause, knownResults, finder); case VBAParser.LogicalNotOpContext _: case VBAParser.UnaryMinusOpContext _: - return VisitUnaryOpEvaluationContext(module, parserRuleContext, knownResults); + return VisitUnaryOpEvaluationContext(module, parserRuleContext, knownResults, finder); default: if (IsUnaryResultContext(parserRuleContext)) { - return VisitUnaryResultContext(module, parserRuleContext, knownResults); + return VisitUnaryResultContext(module, parserRuleContext, knownResults, finder); } if (IsBinaryOpEvaluationContext(parserRuleContext)) { - return VisitBinaryOpEvaluationContext(module, parserRuleContext, knownResults); + return VisitBinaryOpEvaluationContext(module, parserRuleContext, knownResults, finder); } return knownResults; } } - private IMutableParseTreeVisitorResults Visit(QualifiedModuleName module, VBAParser.LExprContext context, IMutableParseTreeVisitorResults knownResults) + private IMutableParseTreeVisitorResults VisitRangeClause( + QualifiedModuleName module, + VBAParser.RangeClauseContext rangeClause, + IMutableParseTreeVisitorResults knownResults, + DeclarationFinder finder) + { + var rangeClauseResults = VisitChildren(module, rangeClause, knownResults, finder); + rangeClauseResults.AddIfNotPresent(rangeClause, _valueFactory.Create(rangeClause.GetText())); + return rangeClauseResults; + } + + private IMutableParseTreeVisitorResults VisitCaseClause( + QualifiedModuleName module, + VBAParser.CaseClauseContext caseClause, + IMutableParseTreeVisitorResults knownResults, + DeclarationFinder finder) + { + var caseClauseResults = VisitChildren(module, caseClause, knownResults, finder); + caseClauseResults.AddIfNotPresent(caseClause, _valueFactory.Create(caseClause.GetText())); + return caseClauseResults; + } + + private IMutableParseTreeVisitorResults Visit( + QualifiedModuleName module, + VBAParser.LExprContext context, + IMutableParseTreeVisitorResults knownResults, + DeclarationFinder finder) { if (knownResults.Contains(context)) { @@ -124,14 +142,14 @@ private IMutableParseTreeVisitorResults Visit(QualifiedModuleName module, VBAPar var valueResults = knownResults; IParseTreeValue newResult = null; - if (TryGetLExprValue(module, context, ref valueResults, out string lExprValue, out string declaredType)) + if (TryGetLExprValue(module, context, ref valueResults, finder, out string lExprValue, out string declaredType)) { newResult = _valueFactory.CreateDeclaredType(lExprValue, declaredType); } else { var simpleName = context.GetDescendent(); - if (TryGetIdentifierReferenceForContext(module, simpleName, out var reference)) + if (TryGetIdentifierReferenceForContext(module, simpleName, finder, out var reference)) { var declarationTypeName = GetBaseTypeForDeclaration(reference.Declaration); newResult = _valueFactory.CreateDeclaredType(context.GetText(), declarationTypeName); @@ -160,9 +178,13 @@ private IMutableParseTreeVisitorResults Visit(VBAParser.LiteralExprContext conte return valueResults; } - private IMutableParseTreeVisitorResults VisitBinaryOpEvaluationContext(QualifiedModuleName module, ParserRuleContext context, IMutableParseTreeVisitorResults knownResults) + private IMutableParseTreeVisitorResults VisitBinaryOpEvaluationContext( + QualifiedModuleName module, + ParserRuleContext context, + IMutableParseTreeVisitorResults knownResults, + DeclarationFinder finder) { - var valueResults = VisitChildren(module, context, knownResults); + var valueResults = VisitChildren(module, context, knownResults, finder); var (lhs, rhs, operatorSymbol) = RetrieveOpEvaluationElements(context, valueResults); if (lhs is null || rhs is null) @@ -188,9 +210,13 @@ private IMutableParseTreeVisitorResults VisitBinaryOpEvaluationContext(Qualified return valueResults; } - private IMutableParseTreeVisitorResults VisitUnaryOpEvaluationContext(QualifiedModuleName module, ParserRuleContext context, IMutableParseTreeVisitorResults knownResults) + private IMutableParseTreeVisitorResults VisitUnaryOpEvaluationContext( + QualifiedModuleName module, + ParserRuleContext context, + IMutableParseTreeVisitorResults knownResults, + DeclarationFinder finder) { - var valueResults = VisitChildren(module, context, knownResults); + var valueResults = VisitChildren(module, context, knownResults, finder); var (lhs, rhs, operatorSymbol) = RetrieveOpEvaluationElements(context, valueResults); if (lhs is null || rhs != null) @@ -230,9 +256,13 @@ private static (IParseTreeValue LHS, IParseTreeValue RHS, string Symbol) Retriev return operandElements; } - private IMutableParseTreeVisitorResults VisitUnaryResultContext(QualifiedModuleName module, ParserRuleContext parserRuleContext, IMutableParseTreeVisitorResults knownResults) + private IMutableParseTreeVisitorResults VisitUnaryResultContext( + QualifiedModuleName module, + ParserRuleContext parserRuleContext, + IMutableParseTreeVisitorResults knownResults, + DeclarationFinder finder) { - var valueResults = VisitChildren(module, parserRuleContext, knownResults); + var valueResults = VisitChildren(module, parserRuleContext, knownResults, finder); var firstChildWithValue = ParserRuleContextChildren(parserRuleContext) .FirstOrDefault(childContext => valueResults.Contains(childContext)); @@ -245,7 +275,11 @@ private IMutableParseTreeVisitorResults VisitUnaryResultContext(QualifiedModuleN return valueResults; } - private IMutableParseTreeVisitorResults VisitChildren(QualifiedModuleName module, ParserRuleContext context, IMutableParseTreeVisitorResults knownResults) + private IMutableParseTreeVisitorResults VisitChildren( + QualifiedModuleName module, + ParserRuleContext context, + IMutableParseTreeVisitorResults knownResults, + DeclarationFinder finder) { if (knownResults.Contains(context)) { @@ -255,7 +289,7 @@ private IMutableParseTreeVisitorResults VisitChildren(QualifiedModuleName module var valueResults = knownResults; foreach (var childContext in ParserRuleContextChildren(context)) { - valueResults = Visit(module, childContext, valueResults); + valueResults = Visit(module, childContext, valueResults, finder); } return valueResults; @@ -267,14 +301,14 @@ private static IEnumerable ParserRuleContextChildren(ParserRu private static IEnumerable NonWhitespaceChildren(ParserRuleContext ptParent) => ptParent.children.Where(ch => !(ch is VBAParser.WhiteSpaceContext)); - private bool TryGetLExprValue(QualifiedModuleName module, VBAParser.LExprContext lExprContext, ref IMutableParseTreeVisitorResults knownResults, out string expressionValue, out string declaredTypeName) + private bool TryGetLExprValue(QualifiedModuleName module, VBAParser.LExprContext lExprContext, ref IMutableParseTreeVisitorResults knownResults, DeclarationFinder finder, out string expressionValue, out string declaredTypeName) { expressionValue = string.Empty; declaredTypeName = string.Empty; if (lExprContext.TryGetChildContext(out VBAParser.MemberAccessExprContext memberAccess)) { var member = memberAccess.GetChild(); - var (typeName, valueText, resultValues) = GetContextValue(module, member, knownResults); + var (typeName, valueText, resultValues) = GetContextValue(module, member, knownResults, finder); knownResults = resultValues; declaredTypeName = typeName; expressionValue = valueText; @@ -283,7 +317,7 @@ private bool TryGetLExprValue(QualifiedModuleName module, VBAParser.LExprContext if (lExprContext.TryGetChildContext(out VBAParser.SimpleNameExprContext smplName)) { - var (typeName, valueText, resultValues) = GetContextValue(module, smplName, knownResults); + var (typeName, valueText, resultValues) = GetContextValue(module, smplName, knownResults, finder); knownResults = resultValues; declaredTypeName = typeName; expressionValue = valueText; @@ -312,9 +346,13 @@ private bool TryGetLExprValue(QualifiedModuleName module, VBAParser.LExprContext return (true, valuedDeclaration.Expression, typeName); } - private (string declarationTypeName, string expressionValue, IMutableParseTreeVisitorResults resultValues) GetContextValue(QualifiedModuleName module, ParserRuleContext context, IMutableParseTreeVisitorResults knownResults) + private (string declarationTypeName, string expressionValue, IMutableParseTreeVisitorResults resultValues) GetContextValue( + QualifiedModuleName module, + ParserRuleContext context, + IMutableParseTreeVisitorResults knownResults, + DeclarationFinder finder) { - if (!TryGetIdentifierReferenceForContext(module, context, out var rangeClauseIdentifierReference)) + if (!TryGetIdentifierReferenceForContext(module, context, finder, out var rangeClauseIdentifierReference)) { return (string.Empty, context.GetText(), knownResults); } @@ -342,13 +380,13 @@ private bool TryGetLExprValue(QualifiedModuleName module, VBAParser.LExprContext if (declaration.DeclarationType.HasFlag(DeclarationType.Constant)) { - var (constantTokenExpressionValue, resultValues) = GetConstantContextValueToken(module, declaration.Context, knownResults); + var (constantTokenExpressionValue, resultValues) = GetConstantContextValueToken(module, declaration.Context, knownResults, finder); return (declaredTypeName, constantTokenExpressionValue, resultValues); } if (declaration.DeclarationType.HasFlag(DeclarationType.EnumerationMember)) { - var (constantExpressionValue, resultValues) = GetConstantContextValueToken(module, declaration.Context, knownResults); + var (constantExpressionValue, resultValues) = GetConstantContextValueToken(module, declaration.Context, knownResults, finder); if (!constantExpressionValue.Equals(string.Empty)) { return (Tokens.Long, constantExpressionValue, resultValues); @@ -356,7 +394,7 @@ private bool TryGetLExprValue(QualifiedModuleName module, VBAParser.LExprContext if (declaration.Context.Parent is VBAParser.EnumerationStmtContext enumStmt) { - var (enumMembers, valueResults) = EnumMembers(module, enumStmt, resultValues); + var (enumMembers, valueResults) = EnumMembers(module, enumStmt, resultValues, finder); var enumValue = enumMembers.SingleOrDefault(enumMember => enumMember.ConstantContext == declaration.Context); var enumExpressionValue = enumValue?.Value.ToString() ?? string.Empty; return (Tokens.Long, enumExpressionValue, valueResults); @@ -368,20 +406,45 @@ private bool TryGetLExprValue(QualifiedModuleName module, VBAParser.LExprContext return (declaredTypeName, expressionValue, knownResults); } - private bool TryGetIdentifierReferenceForContext(QualifiedModuleName module, ParserRuleContext context, out IdentifierReference referenceForContext) + private bool TryGetIdentifierReferenceForContext( + QualifiedModuleName module, + ParserRuleContext context, + DeclarationFinder finder, + out IdentifierReference referenceForContext) + { + var (success, reference) = GetIdentifierReferenceForContext(module, context, finder); + referenceForContext = reference; + return success; + } + + public static (bool success, IdentifierReference idRef) GetIdentifierReferenceForContext( + QualifiedModuleName module, + ParserRuleContext context, + DeclarationFinder finder) { - if (IdentifierReferenceRetriever == null) + if (context == null) { - referenceForContext = null; - return false; + return (false, null); } - var (success, reference) = IdentifierReferenceRetriever(module, context); - referenceForContext = reference; - return success; + var qualifiedSelection = new QualifiedSelection(module, context.GetSelection()); + + var identifierReferences = + finder + .IdentifierReferences(qualifiedSelection) + .Where(reference => reference.Context == context) + .ToList(); + + return identifierReferences.Count == 1 + ? (true, identifierReferences.First()) + : (false, null); } - private (string valueText, IMutableParseTreeVisitorResults valueResults) GetConstantContextValueToken(QualifiedModuleName module, ParserRuleContext context, IMutableParseTreeVisitorResults knownResults) + private (string valueText, IMutableParseTreeVisitorResults valueResults) GetConstantContextValueToken( + QualifiedModuleName module, + ParserRuleContext context, + IMutableParseTreeVisitorResults knownResults, + DeclarationFinder finder) { if (context is null) { @@ -403,7 +466,7 @@ private bool TryGetIdentifierReferenceForContext(QualifiedModuleName module, Par foreach (var child in contextsOfInterest) { - knownResults = Visit(module, child, knownResults); + knownResults = Visit(module, child, knownResults, finder); if (knownResults.TryGetValue(child, out var value)) { return (value.Token, knownResults); @@ -445,14 +508,18 @@ private static bool IsBinaryOpEvaluationContext(T context) return false; } - private (IReadOnlyList enumMembers, IMutableParseTreeVisitorResults resultValues) EnumMembers(QualifiedModuleName enumModule, VBAParser.EnumerationStmtContext enumerationStmtContext, IMutableParseTreeVisitorResults knownResults) + private (IReadOnlyList enumMembers, IMutableParseTreeVisitorResults resultValues) EnumMembers( + QualifiedModuleName enumModule, + VBAParser.EnumerationStmtContext enumerationStmtContext, + IMutableParseTreeVisitorResults knownResults, + DeclarationFinder finder) { if (knownResults.TryGetEnumMembers(enumerationStmtContext, out var enumMembers)) { return (enumMembers, knownResults); } - var resultValues = LoadEnumMemberValues(enumModule, enumerationStmtContext, knownResults); + var resultValues = LoadEnumMemberValues(enumModule, enumerationStmtContext, knownResults, finder); if (knownResults.TryGetEnumMembers(enumerationStmtContext, out var newEnumMembers)) { return (newEnumMembers, resultValues); @@ -462,7 +529,11 @@ private static bool IsBinaryOpEvaluationContext(T context) } //The enum members incrementally to the parse tree visitor result are used within the call to Visit. - private IMutableParseTreeVisitorResults LoadEnumMemberValues(QualifiedModuleName enumModule, VBAParser.EnumerationStmtContext enumStmt, IMutableParseTreeVisitorResults knownResults) + private IMutableParseTreeVisitorResults LoadEnumMemberValues( + QualifiedModuleName enumModule, + VBAParser.EnumerationStmtContext enumStmt, + IMutableParseTreeVisitorResults knownResults, + DeclarationFinder finder) { var valueResults = knownResults; long enumAssignedValue = -1; @@ -474,9 +545,9 @@ private IMutableParseTreeVisitorResults LoadEnumMemberValues(QualifiedModuleName var enumMember = new EnumMember(enumConstContext, enumAssignedValue); if (enumMember.HasAssignment) { - valueResults = Visit(enumModule, enumMember.ConstantContext, valueResults); + valueResults = Visit(enumModule, enumMember.ConstantContext, valueResults, finder); - var (valueText, resultValues) = GetConstantContextValueToken(enumModule, enumMember.ConstantContext, valueResults); + var (valueText, resultValues) = GetConstantContextValueToken(enumModule, enumMember.ConstantContext, valueResults, finder); valueResults = resultValues; if (!valueText.Equals(string.Empty)) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitorFactory.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitorFactory.cs deleted file mode 100644 index 0f54417f5e..0000000000 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitorFactory.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using Antlr4.Runtime; -using Rubberduck.Parsing.Symbols; -using Rubberduck.VBEditor; - -namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection -{ - public interface IParseTreeValueVisitorFactory - { - IParseTreeValueVisitor Create(Func idRefRetriever); - } - - public class ParseTreeValueVisitorFactory : IParseTreeValueVisitorFactory - { - private readonly IParseTreeValueFactory _valueFactory; - - public ParseTreeValueVisitorFactory(IParseTreeValueFactory valueFactory) - { - _valueFactory = valueFactory; - } - - public IParseTreeValueVisitor Create(Func identifierReferenceRetriever) - { - return new ParseTreeValueVisitor(_valueFactory, identifierReferenceRetriever); - } - } -} \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs index fa40eb406d..ae7212dbc5 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs @@ -116,8 +116,8 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection public sealed class UnreachableCaseInspection : InspectionBase, IParseTreeInspection { private readonly IUnreachableCaseInspectorFactory _unreachableCaseInspectorFactory; - private readonly IParseTreeValueVisitorFactory _parseTreeValueVisitorFactory; - private readonly UnreachableCaseInspectionListener _listener; + private readonly IParseTreeValueVisitor _parseTreeValueVisitor; + private readonly IInspectionListener _listener; public enum CaseInspectionResultType { @@ -128,11 +128,11 @@ public enum CaseInspectionResultType CaseElse } - public UnreachableCaseInspection(IDeclarationFinderProvider declarationFinderProvider, IUnreachableCaseInspectionFactoryProvider factoryProvider) + public UnreachableCaseInspection(IDeclarationFinderProvider declarationFinderProvider, IUnreachableCaseInspectionFactoryProvider factoryProvider, IParseTreeValueVisitor parseTreeValueVisitor) : base(declarationFinderProvider) { _unreachableCaseInspectorFactory = factoryProvider.CreateIUnreachableInspectorFactory(); - _parseTreeValueVisitorFactory = factoryProvider.CreateParseTreeValueVisitorFactory(); + _parseTreeValueVisitor = parseTreeValueVisitor; _listener = new UnreachableCaseInspectionListener(); } @@ -142,38 +142,36 @@ public UnreachableCaseInspection(IDeclarationFinderProvider declarationFinderPro protected override IEnumerable DoGetInspectionResults(DeclarationFinder finder) { - var parseTreeValueVisitor = CreateParseTreeValueVisitor(GetIdentifierReferenceForContextFunction(finder)); var selectCaseInspector = _unreachableCaseInspectorFactory.Create(GetVariableTypeNameFunction(finder)); return finder.UserDeclarations(DeclarationType.Module) .Where(module => module != null) - .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder, parseTreeValueVisitor, selectCaseInspector)) + .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder, selectCaseInspector)) .ToList(); } protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) { - var parseTreeValueVisitor = CreateParseTreeValueVisitor(GetIdentifierReferenceForContextFunction(finder)); var selectCaseInspector = _unreachableCaseInspectorFactory.Create(GetVariableTypeNameFunction(finder)); - return DoGetInspectionResults(module, finder, parseTreeValueVisitor, selectCaseInspector); + return DoGetInspectionResults(module, finder, selectCaseInspector); } - private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder, IParseTreeValueVisitor parseTreeValueVisitor, IUnreachableCaseInspector selectCaseInspector) + private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder, IUnreachableCaseInspector selectCaseInspector) { var qualifiedSelectCaseStmts = _listener.Contexts(module) // ignore filtering here to make the search space smaller .Where(result => !result.IsIgnoringInspectionResultFor(finder, AnnotationName)); return qualifiedSelectCaseStmts - .SelectMany(context => ResultsForContext(context, parseTreeValueVisitor, selectCaseInspector)) + .SelectMany(context => ResultsForContext(context, selectCaseInspector, finder)) .ToList(); } - private IEnumerable ResultsForContext(QualifiedContext qualifiedSelectCaseStmt, IParseTreeValueVisitor parseTreeValueVisitor, IUnreachableCaseInspector selectCaseInspector) + private IEnumerable ResultsForContext(QualifiedContext qualifiedSelectCaseStmt, IUnreachableCaseInspector selectCaseInspector, DeclarationFinder finder) { var module = qualifiedSelectCaseStmt.ModuleName; var selectStmt = qualifiedSelectCaseStmt.Context; - var contextValues = parseTreeValueVisitor.VisitChildren(module, selectStmt); + var contextValues = _parseTreeValueVisitor.VisitChildren(module, selectStmt, finder); var results = selectCaseInspector.InspectForUnreachableCases(module, selectStmt, contextValues); @@ -214,11 +212,6 @@ private IInspectionResult CreateInspectionResult(QualifiedContext(selectStmt.ModuleName, unreachableBlock)); } - public IParseTreeValueVisitor CreateParseTreeValueVisitor(Func func) - { - return _parseTreeValueVisitorFactory.Create(func); - } - private Func GetIdentifierReferenceForContextFunction(DeclarationFinder finder) { return (module, context) => GetIdentifierReferenceForContext(module, context, finder); @@ -287,7 +280,7 @@ private string GetBaseTypeForDeclaration(Declaration declaration) return localDeclaration is null ? declaration.AsTypeName : localDeclaration.AsTypeName; } - public class UnreachableCaseInspectionListener : InspectionListenerBase + private class UnreachableCaseInspectionListener : InspectionListenerBase { public override void EnterSelectCaseStmt([NotNull] VBAParser.SelectCaseStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspectionFactoryProvider.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspectionFactoryProvider.cs index 58c4cccb1b..a045b1f582 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspectionFactoryProvider.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspectionFactoryProvider.cs @@ -5,7 +5,6 @@ public interface IUnreachableCaseInspectionFactoryProvider { IParseTreeValueFactory CreateIParseTreeValueFactory(); IUnreachableCaseInspectorFactory CreateIUnreachableInspectorFactory(); - IParseTreeValueVisitorFactory CreateParseTreeValueVisitorFactory(); } public class UnreachableCaseInspectionFactoryProvider : IUnreachableCaseInspectionFactoryProvider @@ -19,10 +18,5 @@ public IUnreachableCaseInspectorFactory CreateIUnreachableInspectorFactory() { return new UnreachableCaseInspectorFactory(CreateIParseTreeValueFactory()); } - - public IParseTreeValueVisitorFactory CreateParseTreeValueVisitorFactory() - { - return new ParseTreeValueVisitorFactory(CreateIParseTreeValueFactory()); - } } } diff --git a/Rubberduck.Main/Root/RubberduckIoCInstaller.cs b/Rubberduck.Main/Root/RubberduckIoCInstaller.cs index 2213c7ec13..867c1849bd 100644 --- a/Rubberduck.Main/Root/RubberduckIoCInstaller.cs +++ b/Rubberduck.Main/Root/RubberduckIoCInstaller.cs @@ -385,9 +385,6 @@ private void RegisterUnreachableCaseFactories(IWindsorContainer container) container.Register(Component.For() .ImplementedBy() .LifestyleSingleton()); - container.Register(Component.For() - .ImplementedBy() - .LifestyleSingleton()); container.Register(Component.For() .ImplementedBy() .LifestyleSingleton()); diff --git a/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs b/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs index 82b368d796..695b331c57 100644 --- a/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs +++ b/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs @@ -13,9 +13,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; -using Antlr4.Runtime.Tree; using Moq; -using Rubberduck.Parsing.VBA.Parsing; using Rubberduck.VBEditor; using Rubberduck.VBEditor.Extensions; @@ -2462,8 +2460,9 @@ End Sub IEnumerable actualResults; using (var state = MockParser.CreateAndParse(vbe.Object)) { - var factoryProvider = SpecialValueDeclarationEvaluatorFactoryProvider(TestGetValuedDeclaration); - var inspection = new UnreachableCaseInspection(state, factoryProvider); + var factoryProvider = FactoryProvider; + var parseTreeVisitor = TestParseTreeValueVisitor(TestGetValuedDeclaration); + var inspection = new UnreachableCaseInspection(state, factoryProvider, parseTreeVisitor); WalkTrees(inspection, state); actualResults = inspection.GetInspectionResults(CancellationToken.None); @@ -2514,8 +2513,9 @@ End Sub IEnumerable actualResults; using (var state = MockParser.CreateAndParse(vbe.Object)) { - var factoryProvider = SpecialValueDeclarationEvaluatorFactoryProvider(TestGetValuedDeclaration); - var inspection = new UnreachableCaseInspection(state, factoryProvider); + var factoryProvider = FactoryProvider; + var parseTreeVisitor = TestParseTreeValueVisitor(TestGetValuedDeclaration); + var inspection = new UnreachableCaseInspection(state, factoryProvider, parseTreeVisitor); WalkTrees(inspection, state); actualResults = inspection.GetInspectionResults(CancellationToken.None); @@ -2530,27 +2530,6 @@ End Sub private IUnreachableCaseInspectionFactoryProvider FactoryProvider => _factoryProvider ?? (_factoryProvider = new UnreachableCaseInspectionFactoryProvider()); private IUnreachableCaseInspectorFactory UnreachableCaseInspectorFactory => FactoryProvider.CreateIUnreachableInspectorFactory(); - private IParseTreeValueVisitorFactory ParseTreeValueVisitorFactory => FactoryProvider.CreateParseTreeValueVisitorFactory(); - - private IUnreachableCaseInspectionFactoryProvider SpecialValueDeclarationEvaluatorFactoryProvider(Func valueDeclarationEvaluator) - { - var baseFactoryProvider = FactoryProvider; - var factoryProviderMock = new Mock(); - factoryProviderMock.Setup(m => m.CreateIParseTreeValueFactory()).Returns(() => baseFactoryProvider.CreateIParseTreeValueFactory()); - factoryProviderMock.Setup(m => m.CreateIUnreachableInspectorFactory()).Returns(() => baseFactoryProvider.CreateIUnreachableInspectorFactory()); - factoryProviderMock.Setup(m => m.CreateParseTreeValueVisitorFactory()).Returns(() => - SpecialValueDeclarationEvaluatorParseTreeValueVisitorFactory(baseFactoryProvider.CreateIParseTreeValueFactory(), valueDeclarationEvaluator)); - return factoryProviderMock.Object; - } - - private IParseTreeValueVisitorFactory SpecialValueDeclarationEvaluatorParseTreeValueVisitorFactory(IParseTreeValueFactory valueFactory, Func valueDeclarationEvaluator) - { - var factoryMock = new Mock(); - factoryMock.Setup(m => m.Create(It.IsAny>())) - .Returns>((identifierReferenceRetriever) => - new ParseTreeValueVisitor(valueFactory, identifierReferenceRetriever, valueDeclarationEvaluator)); - return factoryMock.Object; - } private static Dictionary _vbConstConversions = new Dictionary() { @@ -2637,17 +2616,24 @@ private IParseTreeVisitorResults GetParseTreeValueResults(string inputCode, out var (parseTreeModule, moduleParseTree) = state.ParseTrees .First(pt => pt.Value is ParserRuleContext); selectStmt = ((ParserRuleContext)moduleParseTree).GetDescendent(); - var visitor = ParseTreeValueVisitorFactory.Create((module, context) => UnreachableCaseInspection.GetIdentifierReferenceForContext(module, context, finder)); - valueResults = visitor.VisitChildren(parseTreeModule, selectStmt); + var visitor = TestParseTreeValueVisitor(); + valueResults = visitor.VisitChildren(parseTreeModule, selectStmt, finder); contextModule = parseTreeModule; } return valueResults; } + private ParseTreeValueVisitor TestParseTreeValueVisitor(Func valueDeclarationEvaluator = null) + { + var valueFactory = new ParseTreeValueFactory(); + return new ParseTreeValueVisitor(valueFactory, valueDeclarationEvaluator); + } + protected override IInspection InspectionUnderTest(RubberduckParserState state) { var factoryProvider = new UnreachableCaseInspectionFactoryProvider(); - return new UnreachableCaseInspection(state, factoryProvider); + var parseTeeValueVisitor = new ParseTreeValueVisitor(factoryProvider.CreateIParseTreeValueFactory()); + return new UnreachableCaseInspection(state, factoryProvider, parseTeeValueVisitor); } } } From 6a17bf78692c3fd6b095f68b58860e8c6f21ff37 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sat, 7 Mar 2020 00:33:04 +0100 Subject: [PATCH 278/461] Make UnreachableCaseInspector.InspectForUnreachableCases pure Also turns the inspector in UnreachableCaseInspection into a constructor injected field. --- .../UnreachableCaseInspection.cs | 93 ++----------------- ...nreachableCaseInspectionFactoryProvider.cs | 22 ----- .../UnreachableCaseInspector.cs | 79 +++++++++++++--- .../UnreachableCaseInspectorFactory.cs | 26 ------ .../Root/RubberduckIoCInstaller.cs | 6 -- .../ExpressionFilterUnitTests.cs | 28 +----- .../ParseTreeExpressionEvaluatorUnitTests.cs | 40 ++------ .../ParseTreeValueUnitTests.cs | 27 +----- .../UnreachableCaseInspectionTests.cs | 36 +++---- 9 files changed, 105 insertions(+), 252 deletions(-) delete mode 100644 Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspectionFactoryProvider.cs delete mode 100644 Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspectorFactory.cs diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs index ae7212dbc5..87086ed004 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs @@ -115,7 +115,7 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection /// public sealed class UnreachableCaseInspection : InspectionBase, IParseTreeInspection { - private readonly IUnreachableCaseInspectorFactory _unreachableCaseInspectorFactory; + private readonly IUnreachableCaseInspector _inspector; private readonly IParseTreeValueVisitor _parseTreeValueVisitor; private readonly IInspectionListener _listener; @@ -128,10 +128,13 @@ public enum CaseInspectionResultType CaseElse } - public UnreachableCaseInspection(IDeclarationFinderProvider declarationFinderProvider, IUnreachableCaseInspectionFactoryProvider factoryProvider, IParseTreeValueVisitor parseTreeValueVisitor) + public UnreachableCaseInspection( + IDeclarationFinderProvider declarationFinderProvider, + IUnreachableCaseInspector inspector, + IParseTreeValueVisitor parseTreeValueVisitor) : base(declarationFinderProvider) { - _unreachableCaseInspectorFactory = factoryProvider.CreateIUnreachableInspectorFactory(); + _inspector = inspector; _parseTreeValueVisitor = parseTreeValueVisitor; _listener = new UnreachableCaseInspectionListener(); } @@ -142,38 +145,30 @@ public UnreachableCaseInspection(IDeclarationFinderProvider declarationFinderPro protected override IEnumerable DoGetInspectionResults(DeclarationFinder finder) { - var selectCaseInspector = _unreachableCaseInspectorFactory.Create(GetVariableTypeNameFunction(finder)); - return finder.UserDeclarations(DeclarationType.Module) .Where(module => module != null) - .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder, selectCaseInspector)) + .SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder)) .ToList(); } protected override IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) - { - var selectCaseInspector = _unreachableCaseInspectorFactory.Create(GetVariableTypeNameFunction(finder)); - return DoGetInspectionResults(module, finder, selectCaseInspector); - } - - private IEnumerable DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder, IUnreachableCaseInspector selectCaseInspector) { var qualifiedSelectCaseStmts = _listener.Contexts(module) // ignore filtering here to make the search space smaller .Where(result => !result.IsIgnoringInspectionResultFor(finder, AnnotationName)); return qualifiedSelectCaseStmts - .SelectMany(context => ResultsForContext(context, selectCaseInspector, finder)) + .SelectMany(context => ResultsForContext(context, finder)) .ToList(); } - private IEnumerable ResultsForContext(QualifiedContext qualifiedSelectCaseStmt, IUnreachableCaseInspector selectCaseInspector, DeclarationFinder finder) + private IEnumerable ResultsForContext(QualifiedContext qualifiedSelectCaseStmt, DeclarationFinder finder) { var module = qualifiedSelectCaseStmt.ModuleName; var selectStmt = qualifiedSelectCaseStmt.Context; var contextValues = _parseTreeValueVisitor.VisitChildren(module, selectStmt, finder); - var results = selectCaseInspector.InspectForUnreachableCases(module, selectStmt, contextValues); + var results = _inspector.InspectForUnreachableCases(module, selectStmt, contextValues, finder); return results .Select(resultTpl => CreateInspectionResult(qualifiedSelectCaseStmt, resultTpl.context, resultTpl.resultType)) @@ -212,74 +207,6 @@ private IInspectionResult CreateInspectionResult(QualifiedContext(selectStmt.ModuleName, unreachableBlock)); } - private Func GetIdentifierReferenceForContextFunction(DeclarationFinder finder) - { - return (module, context) => GetIdentifierReferenceForContext(module, context, finder); - } - - //public static to support tests - //FIXME There should not be additional public methods just for tests. This class seems to want to be split or at least reorganized. - public static (bool success, IdentifierReference idRef) GetIdentifierReferenceForContext(QualifiedModuleName module, ParserRuleContext context, DeclarationFinder finder) - { - if (context == null) - { - return (false, null); - } - - var qualifiedSelection = new QualifiedSelection(module, context.GetSelection()); - - var identifierReferences = - finder - .IdentifierReferences(qualifiedSelection) - .Where(reference => reference.Context == context) - .ToList(); - - return identifierReferences.Count == 1 - ? (true, identifierReferences.First()) - : (false, null); - } - - private Func GetVariableTypeNameFunction(DeclarationFinder finder) - { - var referenceRetriever = GetIdentifierReferenceForContextFunction(finder); - return (variableName, module, ancestor) => GetVariableTypeName(module, variableName, ancestor, referenceRetriever); - } - - private string GetVariableTypeName(QualifiedModuleName module, string variableName, ParserRuleContext ancestor, Func referenceRetriever) - { - if (ancestor == null) - { - return string.Empty; - } - - var descendents = ancestor.GetDescendents() - .Where(desc => desc.GetText().Equals(variableName)) - .ToList(); - if (!descendents.Any()) - { - return string.Empty; - } - - var firstDescendent = descendents.First(); - var (success, reference) = referenceRetriever(module, firstDescendent); - return success ? - GetBaseTypeForDeclaration(reference.Declaration) - : string.Empty; - } - - private string GetBaseTypeForDeclaration(Declaration declaration) - { - var localDeclaration = declaration; - var iterationGuard = 0; - while (!(localDeclaration is null) - && !localDeclaration.AsTypeIsBaseType - && iterationGuard++ < 5) - { - localDeclaration = localDeclaration.AsTypeDeclaration; - } - return localDeclaration is null ? declaration.AsTypeName : localDeclaration.AsTypeName; - } - private class UnreachableCaseInspectionListener : InspectionListenerBase { public override void EnterSelectCaseStmt([NotNull] VBAParser.SelectCaseStmtContext context) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspectionFactoryProvider.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspectionFactoryProvider.cs deleted file mode 100644 index a045b1f582..0000000000 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspectionFactoryProvider.cs +++ /dev/null @@ -1,22 +0,0 @@ - -namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection -{ - public interface IUnreachableCaseInspectionFactoryProvider - { - IParseTreeValueFactory CreateIParseTreeValueFactory(); - IUnreachableCaseInspectorFactory CreateIUnreachableInspectorFactory(); - } - - public class UnreachableCaseInspectionFactoryProvider : IUnreachableCaseInspectionFactoryProvider - { - public IParseTreeValueFactory CreateIParseTreeValueFactory() - { - return new ParseTreeValueFactory(); - } - - public IUnreachableCaseInspectorFactory CreateIUnreachableInspectorFactory() - { - return new UnreachableCaseInspectorFactory(CreateIParseTreeValueFactory()); - } - } -} diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs index 455005b36d..951de0c174 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs @@ -4,6 +4,8 @@ using System; using System.Collections.Generic; using System.Linq; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection @@ -13,7 +15,8 @@ public interface IUnreachableCaseInspector ICollection<(UnreachableCaseInspection.CaseInspectionResultType resultType, ParserRuleContext context)> InspectForUnreachableCases( QualifiedModuleName module, VBAParser.SelectCaseStmtContext selectCaseContext, - IParseTreeVisitorResults parseTreeValues); + IParseTreeVisitorResults parseTreeValues, + DeclarationFinder finder); string SelectExpressionTypeName( VBAParser.SelectCaseStmtContext selectCaseContext, IParseTreeVisitorResults parseTreeValues); @@ -22,20 +25,18 @@ string SelectExpressionTypeName( public class UnreachableCaseInspector : IUnreachableCaseInspector { private readonly IParseTreeValueFactory _valueFactory; - private readonly Func _getVariableDeclarationTypeName; public UnreachableCaseInspector( - IParseTreeValueFactory valueFactory, - Func getVariableTypeName = null) + IParseTreeValueFactory valueFactory) { _valueFactory = valueFactory; - _getVariableDeclarationTypeName = getVariableTypeName; } public ICollection<(UnreachableCaseInspection.CaseInspectionResultType resultType, ParserRuleContext context)> InspectForUnreachableCases( QualifiedModuleName module, VBAParser.SelectCaseStmtContext selectCaseContext, - IParseTreeVisitorResults parseTreeValues) + IParseTreeVisitorResults parseTreeValues, + DeclarationFinder finder) { var (selectExpressionTypeName, selectExpressionValue) = SelectExpressionTypeNameAndValue(selectCaseContext, parseTreeValues); @@ -61,7 +62,7 @@ public UnreachableCaseInspector( .Select(tpl => tpl.caseClause) .ToList(); - var rangeClauseFilter = BuildRangeClauseFilter(module, remainingCasesToInspect, selectExpressionTypeName, parseTreeValues); + var rangeClauseFilter = BuildRangeClauseFilter(module, remainingCasesToInspect, selectExpressionTypeName, parseTreeValues, finder); if (!(selectExpressionValue is null) && selectExpressionValue.ParsesToConstantValue) { rangeClauseFilter.SelectExpressionValue = selectExpressionValue; @@ -146,22 +147,17 @@ public UnreachableCaseInspector( return null; } - private IExpressionFilter BuildRangeClauseFilter(QualifiedModuleName module, IEnumerable caseClauses, string selectExpressionTypeName, IParseTreeVisitorResults parseTreeValues) + private IExpressionFilter BuildRangeClauseFilter(QualifiedModuleName module, IEnumerable caseClauses, string selectExpressionTypeName, IParseTreeVisitorResults parseTreeValues, DeclarationFinder finder) { var rangeClauseFilter = ExpressionFilterFactory.Create(selectExpressionTypeName); - if (_getVariableDeclarationTypeName is null) - { - return rangeClauseFilter; - } - var rangeClauses = caseClauses.SelectMany(caseClause => caseClause.rangeClause()); foreach (var rangeClause in rangeClauses) { var expression = GetRangeClauseExpression(rangeClause, parseTreeValues); if (!expression?.LHS?.ParsesToConstantValue ?? false) { - var typeName = _getVariableDeclarationTypeName(expression.LHS.Token, module, rangeClause); + var typeName = GetVariableTypeName(module, expression.LHS.Token, rangeClause, finder); rangeClauseFilter.AddComparablePredicateFilter(expression.LHS.Token, typeName); } } @@ -169,6 +165,61 @@ private IExpressionFilter BuildRangeClauseFilter(QualifiedModuleName module, IEn return rangeClauseFilter; } + private string GetVariableTypeName(QualifiedModuleName module, string variableName, ParserRuleContext ancestor, DeclarationFinder finder) + { + if (ancestor == null) + { + return string.Empty; + } + + var descendents = ancestor.GetDescendents() + .Where(desc => desc.GetText().Equals(variableName)) + .ToList(); + if (!descendents.Any()) + { + return string.Empty; + } + + var firstDescendent = descendents.First(); + var (success, reference) = GetIdentifierReferenceForContext(module, firstDescendent, finder); + return success ? + GetBaseTypeForDeclaration(reference.Declaration) + : string.Empty; + } + + private static (bool success, IdentifierReference idRef) GetIdentifierReferenceForContext(QualifiedModuleName module, ParserRuleContext context, DeclarationFinder finder) + { + if (context == null) + { + return (false, null); + } + + var qualifiedSelection = new QualifiedSelection(module, context.GetSelection()); + + var identifierReferences = + finder + .IdentifierReferences(qualifiedSelection) + .Where(reference => reference.Context == context) + .ToList(); + + return identifierReferences.Count == 1 + ? (true, identifierReferences.First()) + : (false, null); + } + + private string GetBaseTypeForDeclaration(Declaration declaration) + { + var localDeclaration = declaration; + var iterationGuard = 0; + while (!(localDeclaration is null) + && !localDeclaration.AsTypeIsBaseType + && iterationGuard++ < 5) + { + localDeclaration = localDeclaration.AsTypeDeclaration; + } + return localDeclaration is null ? declaration.AsTypeName : localDeclaration.AsTypeName; + } + public string SelectExpressionTypeName( VBAParser.SelectCaseStmtContext selectStmt, IParseTreeVisitorResults parseTreeValues) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspectorFactory.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspectorFactory.cs deleted file mode 100644 index bf573cb47f..0000000000 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspectorFactory.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Antlr4.Runtime; -using System; -using Rubberduck.VBEditor; - -namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection -{ - public interface IUnreachableCaseInspectorFactory - { - IUnreachableCaseInspector Create(Func func = null); - } - - public class UnreachableCaseInspectorFactory : IUnreachableCaseInspectorFactory - { - private readonly IParseTreeValueFactory _valueFactory; - - public UnreachableCaseInspectorFactory(IParseTreeValueFactory valueFactory) - { - _valueFactory = valueFactory; - } - - public IUnreachableCaseInspector Create(Func func = null) - { - return new UnreachableCaseInspector(_valueFactory, func); - } - } -} diff --git a/Rubberduck.Main/Root/RubberduckIoCInstaller.cs b/Rubberduck.Main/Root/RubberduckIoCInstaller.cs index 867c1849bd..45ec8c401c 100644 --- a/Rubberduck.Main/Root/RubberduckIoCInstaller.cs +++ b/Rubberduck.Main/Root/RubberduckIoCInstaller.cs @@ -382,12 +382,6 @@ private void RegisterUnreachableCaseFactories(IWindsorContainer container) container.Register(Component.For() .ImplementedBy() .LifestyleSingleton()); - container.Register(Component.For() - .ImplementedBy() - .LifestyleSingleton()); - container.Register(Component.For() - .ImplementedBy() - .LifestyleSingleton()); } diff --git a/RubberduckTests/Inspections/UnreachableCase/ExpressionFilterUnitTests.cs b/RubberduckTests/Inspections/UnreachableCase/ExpressionFilterUnitTests.cs index 5f0c9d8c36..8c17e18698 100644 --- a/RubberduckTests/Inspections/UnreachableCase/ExpressionFilterUnitTests.cs +++ b/RubberduckTests/Inspections/UnreachableCase/ExpressionFilterUnitTests.cs @@ -39,32 +39,8 @@ public class ExpressionFilterUnitTests private const string CLAUSETYPE_VALUE_DELIMITER = "!"; private const string RANGE_STARTEND_DELIMITER = ":"; - private IUnreachableCaseInspectionFactoryProvider _factoryProvider; - private IParseTreeValueFactory _valueFactory; - - private IUnreachableCaseInspectionFactoryProvider FactoryProvider - { - get - { - if (_factoryProvider is null) - { - _factoryProvider = new UnreachableCaseInspectionFactoryProvider(); - } - return _factoryProvider; - } - } - - private IParseTreeValueFactory ValueFactory - { - get - { - if (_valueFactory is null) - { - _valueFactory = FactoryProvider.CreateIParseTreeValueFactory(); - } - return _valueFactory; - } - } + private readonly Lazy _valueFactory = new Lazy(() => new ParseTreeValueFactory()); + private IParseTreeValueFactory ValueFactory => _valueFactory.Value; [TestCase("Min!-5000", "", "Min(-5000)Max(typeMax)")] [TestCase("Min!-5000,Max!5000", "", "Min(-5000)Max(5000)")] diff --git a/RubberduckTests/Inspections/UnreachableCase/ParseTreeExpressionEvaluatorUnitTests.cs b/RubberduckTests/Inspections/UnreachableCase/ParseTreeExpressionEvaluatorUnitTests.cs index 0fb6971913..e0ecf6b976 100644 --- a/RubberduckTests/Inspections/UnreachableCase/ParseTreeExpressionEvaluatorUnitTests.cs +++ b/RubberduckTests/Inspections/UnreachableCase/ParseTreeExpressionEvaluatorUnitTests.cs @@ -31,45 +31,17 @@ public class ParseTreeExpressionEvaluatorUnitTests private const string VALUE_TYPE_SEPARATOR = "?"; private const string OPERAND_SEPARATOR = "_"; - private IUnreachableCaseInspectionFactoryProvider _factoryProvider; - private IParseTreeValueFactory _valueFactory; - private IParseTreeExpressionEvaluator _calculator; + private readonly Lazy _valueFactory = new Lazy(() => new ParseTreeValueFactory()); + private readonly Lazy _calculator; - private IUnreachableCaseInspectionFactoryProvider FactoryProvider + public ParseTreeExpressionEvaluatorUnitTests() { - get - { - if (_factoryProvider is null) - { - _factoryProvider = new UnreachableCaseInspectionFactoryProvider(); - } - return _factoryProvider; - } + _calculator = new Lazy(() => new ParseTreeExpressionEvaluator(ValueFactory)); } - private IParseTreeValueFactory ValueFactory - { - get - { - if (_valueFactory is null) - { - _valueFactory = FactoryProvider.CreateIParseTreeValueFactory(); - } - return _valueFactory; - } - } + private IParseTreeValueFactory ValueFactory => _valueFactory.Value; + private IParseTreeExpressionEvaluator Calculator => _calculator.Value; - private IParseTreeExpressionEvaluator Calculator - { - get - { - if (_calculator is null) - { - _calculator = new ParseTreeExpressionEvaluator(ValueFactory); - } - return _calculator; - } - } [TestCase("Boolean", "Byte", "Integer")] [TestCase("Boolean", "Boolean", "Integer")] diff --git a/RubberduckTests/Inspections/UnreachableCase/ParseTreeValueUnitTests.cs b/RubberduckTests/Inspections/UnreachableCase/ParseTreeValueUnitTests.cs index 2a5d2725fe..f91464a555 100644 --- a/RubberduckTests/Inspections/UnreachableCase/ParseTreeValueUnitTests.cs +++ b/RubberduckTests/Inspections/UnreachableCase/ParseTreeValueUnitTests.cs @@ -18,31 +18,8 @@ public class ParseTreeValueUnitTests { private const string VALUE_TYPE_SEPARATOR = "?"; - private IUnreachableCaseInspectionFactoryProvider _factoryProvider; - private IParseTreeValueFactory _valueFactory; - private IUnreachableCaseInspectionFactoryProvider FactoryProvider - { - get - { - if (_factoryProvider is null) - { - _factoryProvider = new UnreachableCaseInspectionFactoryProvider(); - } - return _factoryProvider; - } - } - - private IParseTreeValueFactory ValueFactory - { - get - { - if (_valueFactory is null) - { - _valueFactory = FactoryProvider.CreateIParseTreeValueFactory(); - } - return _valueFactory; - } - } + private readonly Lazy _valueFactory = new Lazy(() => new ParseTreeValueFactory()); + private IParseTreeValueFactory ValueFactory => _valueFactory.Value; [TestCase("2", "2")] [TestCase("2.54", "2.54")] diff --git a/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs b/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs index 695b331c57..13adaa416d 100644 --- a/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs +++ b/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs @@ -2460,9 +2460,7 @@ End Sub IEnumerable actualResults; using (var state = MockParser.CreateAndParse(vbe.Object)) { - var factoryProvider = FactoryProvider; - var parseTreeVisitor = TestParseTreeValueVisitor(TestGetValuedDeclaration); - var inspection = new UnreachableCaseInspection(state, factoryProvider, parseTreeVisitor); + var inspection = InspectionUnderTest(state, TestGetValuedDeclaration); WalkTrees(inspection, state); actualResults = inspection.GetInspectionResults(CancellationToken.None); @@ -2513,9 +2511,7 @@ End Sub IEnumerable actualResults; using (var state = MockParser.CreateAndParse(vbe.Object)) { - var factoryProvider = FactoryProvider; - var parseTreeVisitor = TestParseTreeValueVisitor(TestGetValuedDeclaration); - var inspection = new UnreachableCaseInspection(state, factoryProvider, parseTreeVisitor); + var inspection = InspectionUnderTest(state, TestGetValuedDeclaration); WalkTrees(inspection, state); actualResults = inspection.GetInspectionResults(CancellationToken.None); @@ -2526,11 +2522,6 @@ End Sub Assert.AreEqual(expectedUnreachableCount, actualUnreachable.Count()); } - private IUnreachableCaseInspectionFactoryProvider _factoryProvider; - private IUnreachableCaseInspectionFactoryProvider FactoryProvider => _factoryProvider ?? (_factoryProvider = new UnreachableCaseInspectionFactoryProvider()); - - private IUnreachableCaseInspectorFactory UnreachableCaseInspectorFactory => FactoryProvider.CreateIUnreachableInspectorFactory(); - private static Dictionary _vbConstConversions = new Dictionary() { ["vbNewLine"] = ("Chr$(13) & Chr$(10)", Tokens.String), @@ -2601,7 +2592,7 @@ private string GetSelectExpressionType(string inputCode) { var selectStmtValueResults = GetParseTreeValueResults(inputCode, out VBAParser.SelectCaseStmtContext selectStmtContext, out var module); - var inspector = UnreachableCaseInspectorFactory.Create(); + var inspector = TestUnreachableCaseInspector(); return inspector.SelectExpressionTypeName(selectStmtContext, selectStmtValueResults); } @@ -2623,17 +2614,30 @@ private IParseTreeVisitorResults GetParseTreeValueResults(string inputCode, out return valueResults; } - private ParseTreeValueVisitor TestParseTreeValueVisitor(Func valueDeclarationEvaluator = null) + private IParseTreeValueVisitor TestParseTreeValueVisitor(Func valueDeclarationEvaluator = null) { var valueFactory = new ParseTreeValueFactory(); return new ParseTreeValueVisitor(valueFactory, valueDeclarationEvaluator); } + private IUnreachableCaseInspector TestUnreachableCaseInspector() + { + var valueFactory = new ParseTreeValueFactory(); + return new UnreachableCaseInspector(valueFactory); + } + + private IParseTreeInspection InspectionUnderTest(RubberduckParserState state, Func valueDeclarationEvaluator) + { + var inspector = TestUnreachableCaseInspector(); + var parseTeeValueVisitor = TestParseTreeValueVisitor(valueDeclarationEvaluator); + return new UnreachableCaseInspection(state, inspector, parseTeeValueVisitor); + } + protected override IInspection InspectionUnderTest(RubberduckParserState state) { - var factoryProvider = new UnreachableCaseInspectionFactoryProvider(); - var parseTeeValueVisitor = new ParseTreeValueVisitor(factoryProvider.CreateIParseTreeValueFactory()); - return new UnreachableCaseInspection(state, factoryProvider, parseTeeValueVisitor); + var inspector = TestUnreachableCaseInspector(); + var parseTeeValueVisitor = TestParseTreeValueVisitor(); + return new UnreachableCaseInspection(state, inspector, parseTeeValueVisitor); } } } From af2b026bd1758f2943e58577222889a98abf175f Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sat, 7 Mar 2020 00:46:17 +0100 Subject: [PATCH 279/461] Make all concrete inspection listeners private --- .../Abstract/DeclarationInspectionBaseBase.cs | 3 + .../BooleanAssignedInIfElseInspection.cs | 2 +- .../Concrete/DefTypeStatementInspection.cs | 2 +- .../EmptyBlockInspectionListenerBase.cs | 2 +- .../Concrete/EmptyCaseBlockInspection.cs | 2 +- .../Concrete/EmptyDoWhileBlockInspection.cs | 2 +- .../Concrete/EmptyElseBlockInspection.cs | 2 +- .../Concrete/EmptyForEachBlockInspection.cs | 2 +- .../Concrete/EmptyForLoopBlockInspection.cs | 2 +- .../Concrete/EmptyIfBlockInspection.cs | 2 +- .../Concrete/EmptyStringLiteralInspection.cs | 2 +- .../Concrete/EmptyWhileWendBlockInspection.cs | 2 +- .../ModuleScopeDimKeywordInspection.cs | 2 +- .../Concrete/MultilineParameterInspection.cs | 2 +- .../MultipleDeclarationsInspection.cs | 2 +- .../ObsoleteCallStatementInspection.cs | 2 +- .../ObsoleteCallingConventionInspection.cs | 2 +- .../ObsoleteCommentSyntaxInspection.cs | 2 +- .../Concrete/ObsoleteErrorSyntaxInspection.cs | 2 +- .../ObsoleteLetStatementInspection.cs | 2 +- .../ObsoleteWhileWendStatementInspection.cs | 2 +- .../Concrete/OnLocalErrorInspection.cs | 2 +- .../Concrete/OptionBaseInspection.cs | 2 +- .../Concrete/OptionExplicitInspection.cs | 2 +- .../Concrete/RedundantOptionInspection.cs | 2 +- .../Concrete/StepIsNotSpecifiedInspection.cs | 20 ++-- .../Concrete/StepOneIsRedundantInspection.cs | 26 +++--- .../Concrete/StopKeywordInspection.cs | 2 +- ...neContinuationBetweenKeywordsInspection.cs | 2 +- .../NegativeLineNumberInspection.cs | 2 +- .../OnErrorGoToMinusOneInspection.cs | 2 +- .../UnhandledOnErrorResumeNextInspection.cs | 92 +++++++++---------- 32 files changed, 100 insertions(+), 97 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs index 21c17da6f7..a621ddb2e8 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs @@ -8,6 +8,9 @@ namespace Rubberduck.Inspections.Abstract { + /// + /// This is a base class for the other declaration inspection base classes. It should not be implemented directly by concrete inspections. + /// public abstract class DeclarationInspectionBaseBase : InspectionBase { private readonly DeclarationType[] _relevantDeclarationTypes; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs index a73d3b6575..34945abe34 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs @@ -59,7 +59,7 @@ protected override string ResultDescription(QualifiedContext + private class BooleanAssignedInIfElseListener : InspectionListenerBase { public override void ExitIfStmt(VBAParser.IfStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs index d08fa06888..808838f200 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs @@ -68,7 +68,7 @@ private string GetTypeOfDefType(string defType) { "DefVar", "Variant" } }; - public class DefTypeStatementInspectionListener : InspectionListenerBase + private class DefTypeStatementInspectionListener : InspectionListenerBase { public override void ExitDefType([NotNull] VBAParser.DefTypeContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlockInspectionListenerBase.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlockInspectionListenerBase.cs index 7f5fe09a3a..d5d56a63ef 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlockInspectionListenerBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlockInspectionListenerBase.cs @@ -7,7 +7,7 @@ namespace Rubberduck.Inspections.Concrete { - public class EmptyBlockInspectionListenerBase : InspectionListenerBase + internal class EmptyBlockInspectionListenerBase : InspectionListenerBase where TContext : ParserRuleContext { public void InspectBlockForExecutableStatements(VBAParser.BlockContext block, T context) where T : TContext diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyCaseBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyCaseBlockInspection.cs index b5e46f4521..cb6dd07ccc 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyCaseBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyCaseBlockInspection.cs @@ -55,7 +55,7 @@ protected override string ResultDescription(QualifiedContext + private class EmptyCaseBlockListener : EmptyBlockInspectionListenerBase { public override void EnterCaseClause([NotNull] VBAParser.CaseClauseContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyDoWhileBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyDoWhileBlockInspection.cs index df84b3df8a..e59fb3ca30 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyDoWhileBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyDoWhileBlockInspection.cs @@ -50,7 +50,7 @@ protected override string ResultDescription(QualifiedContext + private class EmptyDoWhileBlockListener : EmptyBlockInspectionListenerBase { public override void EnterDoLoopStmt([NotNull] VBAParser.DoLoopStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyElseBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyElseBlockInspection.cs index 757d337378..7a7ebeb824 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyElseBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyElseBlockInspection.cs @@ -52,7 +52,7 @@ protected override string ResultDescription(QualifiedContext + private class EmptyElseBlockListener : EmptyBlockInspectionListenerBase { public override void EnterElseBlock([NotNull] VBAParser.ElseBlockContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForEachBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForEachBlockInspection.cs index b6615737df..87e29d7337 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForEachBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForEachBlockInspection.cs @@ -52,7 +52,7 @@ protected override string ResultDescription(QualifiedContext + private class EmptyForEachBlockListener : EmptyBlockInspectionListenerBase { public override void EnterForEachStmt([NotNull] VBAParser.ForEachStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForLoopBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForLoopBlockInspection.cs index 7fac278f90..c14948a015 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForLoopBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForLoopBlockInspection.cs @@ -52,7 +52,7 @@ protected override string ResultDescription(QualifiedContext + private class EmptyForLoopBlockListener : EmptyBlockInspectionListenerBase { public override void EnterForNextStmt([NotNull] VBAParser.ForNextStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyIfBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyIfBlockInspection.cs index 2d3a313757..1733320bb6 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyIfBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyIfBlockInspection.cs @@ -49,7 +49,7 @@ protected override string ResultDescription(QualifiedContext protected override IInspectionListener ContextListener { get; } - public class EmptyIfBlockListener : EmptyBlockInspectionListenerBase + private class EmptyIfBlockListener : EmptyBlockInspectionListenerBase { public override void EnterIfStmt([NotNull] VBAParser.IfStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs index e1ec83719b..7fb2ad3d41 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs @@ -48,7 +48,7 @@ protected override string ResultDescription(QualifiedContext + private class EmptyStringLiteralListener : InspectionListenerBase { public override void ExitLiteralExpression(VBAParser.LiteralExpressionContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyWhileWendBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyWhileWendBlockInspection.cs index 86cfda2cde..19391e5ce5 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyWhileWendBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyWhileWendBlockInspection.cs @@ -50,7 +50,7 @@ protected override string ResultDescription(QualifiedContext + private class EmptyWhileWendBlockListener : EmptyBlockInspectionListenerBase { public override void EnterWhileWendStmt([NotNull] VBAParser.WhileWendStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs index 0bd1b3dfec..3e8f0c2888 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs @@ -47,7 +47,7 @@ protected override string ResultDescription(QualifiedContext + private class ModuleScopedDimListener : InspectionListenerBase { public override void ExitVariableStmt([NotNull] VBAParser.VariableStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs index 9ff5d29e8f..daf865cb8f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs @@ -50,7 +50,7 @@ protected override string ResultDescription(QualifiedContext + private class ParameterListener : InspectionListenerBase { public override void ExitArg([NotNull] VBAParser.ArgContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs index 6f6ccf3df0..cf9f7fb34d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs @@ -41,7 +41,7 @@ protected override string ResultDescription(QualifiedContext return InspectionResults.MultipleDeclarationsInspection; } - public class ParameterListListener : InspectionListenerBase + private class ParameterListListener : InspectionListenerBase { public override void ExitVariableListStmt([NotNull] VBAParser.VariableListStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs index 057c91b508..92f406e7a3 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs @@ -68,7 +68,7 @@ protected override bool IsResultContext(QualifiedContext + private class ObsoleteCallStatementListener : InspectionListenerBase { public override void ExitCallStmt(VBAParser.CallStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs index e120534934..12b9adfa3b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs @@ -48,7 +48,7 @@ protected override bool IsResultContext(QualifiedContext + private class ObsoleteCallingConventionListener : InspectionListenerBase { public override void ExitDeclareStmt(VBAParser.DeclareStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs index 9cb27834e6..cb63e95d53 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs @@ -42,7 +42,7 @@ protected override string ResultDescription(QualifiedContext + private class ObsoleteCommentSyntaxListener : InspectionListenerBase { public override void ExitRemComment(VBAParser.RemCommentContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs index 96057c0916..21f13d8637 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs @@ -42,7 +42,7 @@ protected override string ResultDescription(QualifiedContext + private class ObsoleteErrorSyntaxListener : InspectionListenerBase { public override void ExitErrorStmt(VBAParser.ErrorStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs index 6623141ae7..4ca5292265 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs @@ -44,7 +44,7 @@ protected override string ResultDescription(QualifiedContext + private class ObsoleteLetStatementListener : InspectionListenerBase { public override void ExitLetStmt(VBAParser.LetStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs index 26fae13810..518d1e33f3 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs @@ -47,7 +47,7 @@ protected override string ResultDescription(QualifiedContext + private class ObsoleteWhileWendStatementListener : InspectionListenerBase { public override void ExitWhileWendStmt(VBAParser.WhileWendStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs index 1b3e832375..21ba603b8d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs @@ -51,7 +51,7 @@ protected override string ResultDescription(QualifiedContext + private class OnLocalErrorListener : InspectionListenerBase { public override void ExitOnErrorStmt([NotNull] VBAParser.OnErrorStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs index 1d0595d836..9362f21989 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs @@ -54,7 +54,7 @@ protected override string ResultDescription(QualifiedContext + private class OptionBaseStatementListener : InspectionListenerBase { public override void ExitOptionBaseStmt(VBAParser.OptionBaseStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs index d833fd8030..4724806eb7 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs @@ -60,7 +60,7 @@ protected override string ResultDescription(QualifiedContext + private class MissingOptionExplicitListener : InspectionListenerBase { private readonly IDictionary _hasOptionExplicit = new Dictionary(); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs index f46ac808ba..a981a59ede 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs @@ -50,7 +50,7 @@ protected override string ResultDescription(QualifiedContext context.Context.GetText()); } - public class RedundantModuleOptionListener : InspectionListenerBase + private class RedundantModuleOptionListener : InspectionListenerBase { public override void ExitOptionBaseStmt(VBAParser.OptionBaseStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs index 41a2927e20..351a5f9090 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs @@ -43,23 +43,23 @@ public StepIsNotSpecifiedInspection(IDeclarationFinderProvider declarationFinder ContextListener = new StepIsNotSpecifiedListener(); } + protected override IInspectionListener ContextListener { get; } + protected override string ResultDescription(QualifiedContext context) { return InspectionResults.StepIsNotSpecifiedInspection; } - protected override IInspectionListener ContextListener { get; } - } - - public class StepIsNotSpecifiedListener : InspectionListenerBase - { - public override void EnterForNextStmt([NotNull] VBAParser.ForNextStmtContext context) + private class StepIsNotSpecifiedListener : InspectionListenerBase { - var stepStatement = context.stepStmt(); - - if (stepStatement == null) + public override void EnterForNextStmt([NotNull] VBAParser.ForNextStmtContext context) { - SaveContext(context); + var stepStatement = context.stepStmt(); + + if (stepStatement == null) + { + SaveContext(context); + } } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs index cf5dc5f1ce..a5d16d7457 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs @@ -49,24 +49,24 @@ protected override string ResultDescription(QualifiedContext - { - public override void EnterForNextStmt([NotNull] VBAParser.ForNextStmtContext context) + private class StepOneIsRedundantListener : InspectionListenerBase { - var stepStatement = context.stepStmt(); - - if (stepStatement == null) + public override void EnterForNextStmt([NotNull] VBAParser.ForNextStmtContext context) { - return; - } + var stepStatement = context.stepStmt(); - var stepText = stepStatement.expression().GetText(); + if (stepStatement == null) + { + return; + } - if(stepText == "1") - { - SaveContext(stepStatement); + var stepText = stepStatement.expression().GetText(); + + if (stepText == "1") + { + SaveContext(stepStatement); + } } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs index cb3174711d..e7c5eb6a36 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs @@ -47,7 +47,7 @@ protected override string ResultDescription(QualifiedContext + private class StopKeywordListener : InspectionListenerBase { public override void ExitStopStmt([NotNull] VBAParser.StopStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/LineContinuationBetweenKeywordsInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/LineContinuationBetweenKeywordsInspection.cs index 1790855129..8c447da2a1 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/LineContinuationBetweenKeywordsInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/LineContinuationBetweenKeywordsInspection.cs @@ -36,7 +36,7 @@ protected override string ResultDescription(QualifiedContext return InspectionResults.LineContinuationBetweenKeywordsInspection.ThunderCodeFormat(); } - public class LineContinuationBetweenKeywordsListener : InspectionListenerBase + private class LineContinuationBetweenKeywordsListener : InspectionListenerBase { public override void EnterSubStmt(VBAParser.SubStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NegativeLineNumberInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NegativeLineNumberInspection.cs index 3ff5e9d790..ebcc48793f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NegativeLineNumberInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NegativeLineNumberInspection.cs @@ -32,7 +32,7 @@ protected override string ResultDescription(QualifiedContext return InspectionResults.NegativeLineNumberInspection.ThunderCodeFormat(); } - public class NegativeLineNumberKeywordsListener : InspectionListenerBase + private class NegativeLineNumberKeywordsListener : InspectionListenerBase { public override void EnterOnErrorStmt(VBAParser.OnErrorStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs index abbc0bcc3b..a5fcff9c07 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs @@ -31,7 +31,7 @@ protected override string ResultDescription(QualifiedContext + private class OnErrorGoToMinusOneListener : InspectionListenerBase { public override void EnterOnErrorStmt(VBAParser.OnErrorStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs index 5406d3b9f9..625dce6b4e 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs @@ -55,70 +55,70 @@ protected override (bool isResult, IReadOnlyList p { return (true, _listener.UnhandledContexts(context)); } - } - - public class OnErrorStatementListener : InspectionListenerBase - { - private readonly List> _unhandledContexts = new List>(); - private readonly Dictionary, List> _unhandledContextsMap = new Dictionary, List>(); - - public IReadOnlyList UnhandledContexts(QualifiedContext context) - { - return _unhandledContextsMap.TryGetValue(context, out var unhandledContexts) - ? unhandledContexts - : new List(); - } - - public override void ClearContexts() - { - _unhandledContextsMap.Clear(); - base.ClearContexts(); - } - public override void ClearContexts(QualifiedModuleName module) + private class OnErrorStatementListener : InspectionListenerBase { - var keysInModule = _unhandledContextsMap.Keys - .Where(context => context.ModuleName.Equals(module)); + private readonly List> _unhandledContexts = new List>(); + private readonly Dictionary, List> _unhandledContextsMap = new Dictionary, List>(); - foreach (var key in keysInModule) + public IReadOnlyList UnhandledContexts(QualifiedContext context) { - _unhandledContextsMap.Remove(key); + return _unhandledContextsMap.TryGetValue(context, out var unhandledContexts) + ? unhandledContexts + : new List(); } - base.ClearContexts(module); - } + public override void ClearContexts() + { + _unhandledContextsMap.Clear(); + base.ClearContexts(); + } - public override void ExitModuleBodyElement(VBAParser.ModuleBodyElementContext context) - { - if (_unhandledContexts.Any()) + public override void ClearContexts(QualifiedModuleName module) { - foreach (var errorContext in _unhandledContexts) + var keysInModule = _unhandledContextsMap.Keys + .Where(context => context.ModuleName.Equals(module)); + + foreach (var key in keysInModule) { - _unhandledContextsMap.Add(errorContext, new List(_unhandledContexts.Select(ctx => ctx.Context))); - SaveContext(errorContext.Context); + _unhandledContextsMap.Remove(key); } - _unhandledContexts.Clear(); + base.ClearContexts(module); } - } - public override void ExitOnErrorStmt(VBAParser.OnErrorStmtContext context) - { - if (context.RESUME() != null) + public override void ExitModuleBodyElement(VBAParser.ModuleBodyElementContext context) { - SaveUnhandledContext(context); + if (_unhandledContexts.Any()) + { + foreach (var errorContext in _unhandledContexts) + { + _unhandledContextsMap.Add(errorContext, new List(_unhandledContexts.Select(ctx => ctx.Context))); + SaveContext(errorContext.Context); + } + + _unhandledContexts.Clear(); + } } - else if (context.GOTO() != null) + + public override void ExitOnErrorStmt(VBAParser.OnErrorStmtContext context) { - _unhandledContexts.Clear(); + if (context.RESUME() != null) + { + SaveUnhandledContext(context); + } + else if (context.GOTO() != null) + { + _unhandledContexts.Clear(); + } } - } - private void SaveUnhandledContext(VBAParser.OnErrorStmtContext context) - { - var module = CurrentModuleName; - var qualifiedContext = new QualifiedContext(module, context); - _unhandledContexts.Add(qualifiedContext); + private void SaveUnhandledContext(VBAParser.OnErrorStmtContext context) + { + var module = CurrentModuleName; + var qualifiedContext = new QualifiedContext(module, context); + _unhandledContexts.Add(qualifiedContext); + } } } } From ecddd1e1eb66aa65814693f22037dc4eaca9d5a7 Mon Sep 17 00:00:00 2001 From: testingoutgith1 <58701179+testingoutgith1@users.noreply.github.com> Date: Fri, 6 Mar 2020 22:04:02 -0800 Subject: [PATCH 280/461] Update EnumeratorMemberAnnotation.cs replaced magical number with a variable reference to that magical number --- .../Annotations/Concrete/EnumeratorMemberAnnotation.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Rubberduck.Parsing/Annotations/Concrete/EnumeratorMemberAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/EnumeratorMemberAnnotation.cs index ada28d3157..a12df035b5 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/EnumeratorMemberAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/EnumeratorMemberAnnotation.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using Rubberduck.Parsing.Grammar; using Rubberduck.VBEditor; +using Rubberduck.Resources.Registration; namespace Rubberduck.Parsing.Annotations { @@ -10,7 +11,7 @@ namespace Rubberduck.Parsing.Annotations public sealed class EnumeratorMemberAnnotation : FixedAttributeValueAnnotationBase { public EnumeratorMemberAnnotation() - : base("Enumerator", AnnotationTarget.Member, "VB_UserMemId", new[] { "-4" }) + : base("Enumerator", AnnotationTarget.Member, "VB_UserMemId", new[] { WellKnownDispIds.NewEnum }) {} } -} \ No newline at end of file +} From 9f912dcf44166ab0af2fd263ab9e6dc3dca9c694 Mon Sep 17 00:00:00 2001 From: testingoutgith1 <58701179+testingoutgith1@users.noreply.github.com> Date: Fri, 6 Mar 2020 22:05:31 -0800 Subject: [PATCH 281/461] Update DefaultMemberAnnotation.cs as with enumerator annotation --- .../Annotations/Concrete/DefaultMemberAnnotation.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Rubberduck.Parsing/Annotations/Concrete/DefaultMemberAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/DefaultMemberAnnotation.cs index 32183fc0b6..4ca2966188 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/DefaultMemberAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/DefaultMemberAnnotation.cs @@ -2,6 +2,7 @@ using System.Linq; using Rubberduck.Parsing.Grammar; using Rubberduck.VBEditor; +using Rubberduck.Resources.Registration; namespace Rubberduck.Parsing.Annotations { @@ -11,8 +12,8 @@ namespace Rubberduck.Parsing.Annotations public sealed class DefaultMemberAnnotation : FixedAttributeValueAnnotationBase { public DefaultMemberAnnotation() - : base("DefaultMember", AnnotationTarget.Member, "VB_UserMemId", new[] { "0" }) + : base("DefaultMember", AnnotationTarget.Member, "VB_UserMemId", new[] { WellKnownDispIds.Value }) { } } -} \ No newline at end of file +} From 6dec0aa7fb93e46a50a92ea7a6fc39d4046c8ec6 Mon Sep 17 00:00:00 2001 From: testingoutgith1 <58701179+testingoutgith1@users.noreply.github.com> Date: Sat, 7 Mar 2020 00:02:38 -0800 Subject: [PATCH 282/461] Update DefaultMemberAnnotation.cs added `.ToString()` --- .../Annotations/Concrete/DefaultMemberAnnotation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rubberduck.Parsing/Annotations/Concrete/DefaultMemberAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/DefaultMemberAnnotation.cs index 4ca2966188..090ffa005e 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/DefaultMemberAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/DefaultMemberAnnotation.cs @@ -12,7 +12,7 @@ namespace Rubberduck.Parsing.Annotations public sealed class DefaultMemberAnnotation : FixedAttributeValueAnnotationBase { public DefaultMemberAnnotation() - : base("DefaultMember", AnnotationTarget.Member, "VB_UserMemId", new[] { WellKnownDispIds.Value }) + : base("DefaultMember", AnnotationTarget.Member, "VB_UserMemId", new[] { WellKnownDispIds.Value.ToString() }) { } } From a29be70331598f4dea232830e77e328d1dcec40b Mon Sep 17 00:00:00 2001 From: testingoutgith1 <58701179+testingoutgith1@users.noreply.github.com> Date: Sat, 7 Mar 2020 00:03:24 -0800 Subject: [PATCH 283/461] Update EnumeratorMemberAnnotation.cs --- .../Annotations/Concrete/EnumeratorMemberAnnotation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rubberduck.Parsing/Annotations/Concrete/EnumeratorMemberAnnotation.cs b/Rubberduck.Parsing/Annotations/Concrete/EnumeratorMemberAnnotation.cs index a12df035b5..22bfc8bca0 100644 --- a/Rubberduck.Parsing/Annotations/Concrete/EnumeratorMemberAnnotation.cs +++ b/Rubberduck.Parsing/Annotations/Concrete/EnumeratorMemberAnnotation.cs @@ -11,7 +11,7 @@ namespace Rubberduck.Parsing.Annotations public sealed class EnumeratorMemberAnnotation : FixedAttributeValueAnnotationBase { public EnumeratorMemberAnnotation() - : base("Enumerator", AnnotationTarget.Member, "VB_UserMemId", new[] { WellKnownDispIds.NewEnum }) + : base("Enumerator", AnnotationTarget.Member, "VB_UserMemId", new[] { WellKnownDispIds.NewEnum.ToString() }) {} } } From 0a517ae5b5d8f404cfc3869d4f02be3fa4b07873 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sat, 7 Mar 2020 15:59:45 +0100 Subject: [PATCH 284/461] Make empty block inspections derive from the same base providing the listener base --- .../Abstract/EmptyBlockInspectionBase.cs | 85 +++++++++++++++++++ .../EmptyCaseBlockInspection.cs | 4 +- .../EmptyDoWhileBlockInspection.cs | 4 +- .../EmptyElseBlockInspection.cs | 4 +- .../EmptyForEachBlockInspection.cs | 4 +- .../EmptyForLoopBlockInspection.cs | 4 +- .../EmptyIfBlockInspection.cs | 4 +- .../EmptyWhileWendBlockInspection.cs | 4 +- .../EmptyBlockInspectionListenerBase.cs | 78 ----------------- 9 files changed, 99 insertions(+), 92 deletions(-) create mode 100644 Rubberduck.CodeAnalysis/Inspections/Abstract/EmptyBlockInspectionBase.cs rename Rubberduck.CodeAnalysis/Inspections/Concrete/{ => EmptyBlock}/EmptyCaseBlockInspection.cs (93%) rename Rubberduck.CodeAnalysis/Inspections/Concrete/{ => EmptyBlock}/EmptyDoWhileBlockInspection.cs (92%) rename Rubberduck.CodeAnalysis/Inspections/Concrete/{ => EmptyBlock}/EmptyElseBlockInspection.cs (93%) rename Rubberduck.CodeAnalysis/Inspections/Concrete/{ => EmptyBlock}/EmptyForEachBlockInspection.cs (92%) rename Rubberduck.CodeAnalysis/Inspections/Concrete/{ => EmptyBlock}/EmptyForLoopBlockInspection.cs (92%) rename Rubberduck.CodeAnalysis/Inspections/Concrete/{ => EmptyBlock}/EmptyIfBlockInspection.cs (94%) rename Rubberduck.CodeAnalysis/Inspections/Concrete/{ => EmptyBlock}/EmptyWhileWendBlockInspection.cs (92%) delete mode 100644 Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlockInspectionListenerBase.cs diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/EmptyBlockInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/EmptyBlockInspectionBase.cs new file mode 100644 index 0000000000..2bf1700677 --- /dev/null +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/EmptyBlockInspectionBase.cs @@ -0,0 +1,85 @@ +using System.Collections.Generic; +using System.Diagnostics; +using Antlr4.Runtime; +using Antlr4.Runtime.Tree; +using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.VBA; + +namespace Rubberduck.Inspections.Abstract +{ + public abstract class EmptyBlockInspectionBase : ParseTreeInspectionBase + where TContext : ParserRuleContext + { + protected EmptyBlockInspectionBase(IDeclarationFinderProvider declarationFinderProvider) + : base(declarationFinderProvider) + {} + + protected class EmptyBlockInspectionListenerBase : InspectionListenerBase + { + public void InspectBlockForExecutableStatements(VBAParser.BlockContext block, T context) where T : TContext + { + if (!BlockContainsExecutableStatements(block)) + { + SaveContext(context); + } + } + + private bool BlockContainsExecutableStatements(VBAParser.BlockContext block) + { + return block?.children != null && ContainsExecutableStatements(block.children); + } + + private bool ContainsExecutableStatements(IList blockChildren) + { + foreach (var child in blockChildren) + { + if (child is VBAParser.BlockStmtContext blockStmt) + { + var mainBlockStmt = blockStmt.mainBlockStmt(); + + if (mainBlockStmt == null) + { + continue; //We have a lone line label, which is not executable. + } + + Debug.Assert(mainBlockStmt.ChildCount == 1); + + // exclude variables and consts because they are not executable statements + if (mainBlockStmt.GetChild(0) is VBAParser.VariableStmtContext || + mainBlockStmt.GetChild(0) is VBAParser.ConstStmtContext) + { + continue; + } + + return true; + } + + if (child is VBAParser.RemCommentContext || + child is VBAParser.CommentContext || + child is VBAParser.CommentOrAnnotationContext || + child is VBAParser.EndOfStatementContext) + { + continue; + } + + return true; + } + + return false; + } + + public void InspectBlockForExecutableStatements(VBAParser.UnterminatedBlockContext block, T context) where T : TContext + { + if (!BlockContainsExecutableStatements(block)) + { + SaveContext(context); + } + } + + private bool BlockContainsExecutableStatements(VBAParser.UnterminatedBlockContext block) + { + return block?.children != null && ContainsExecutableStatements(block.children); + } + } + } +} \ No newline at end of file diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyCaseBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyCaseBlockInspection.cs similarity index 93% rename from Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyCaseBlockInspection.cs rename to Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyCaseBlockInspection.cs index cb6dd07ccc..ff2dac9f50 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyCaseBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyCaseBlockInspection.cs @@ -40,7 +40,7 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [Experimental(nameof(ExperimentalNames.EmptyBlockInspections))] - internal sealed class EmptyCaseBlockInspection : ParseTreeInspectionBase + internal sealed class EmptyCaseBlockInspection : EmptyBlockInspectionBase { public EmptyCaseBlockInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) @@ -55,7 +55,7 @@ protected override string ResultDescription(QualifiedContext + private class EmptyCaseBlockListener : EmptyBlockInspectionListenerBase { public override void EnterCaseClause([NotNull] VBAParser.CaseClauseContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyDoWhileBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyDoWhileBlockInspection.cs similarity index 92% rename from Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyDoWhileBlockInspection.cs rename to Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyDoWhileBlockInspection.cs index e59fb3ca30..a82688b048 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyDoWhileBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyDoWhileBlockInspection.cs @@ -35,7 +35,7 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [Experimental(nameof(ExperimentalNames.EmptyBlockInspections))] - internal sealed class EmptyDoWhileBlockInspection : ParseTreeInspectionBase + internal sealed class EmptyDoWhileBlockInspection : EmptyBlockInspectionBase { public EmptyDoWhileBlockInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) @@ -50,7 +50,7 @@ protected override string ResultDescription(QualifiedContext + private class EmptyDoWhileBlockListener : EmptyBlockInspectionListenerBase { public override void EnterDoLoopStmt([NotNull] VBAParser.DoLoopStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyElseBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyElseBlockInspection.cs similarity index 93% rename from Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyElseBlockInspection.cs rename to Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyElseBlockInspection.cs index 7a7ebeb824..190a901c70 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyElseBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyElseBlockInspection.cs @@ -37,7 +37,7 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [Experimental(nameof(ExperimentalNames.EmptyBlockInspections))] - internal sealed class EmptyElseBlockInspection : ParseTreeInspectionBase + internal sealed class EmptyElseBlockInspection : EmptyBlockInspectionBase { public EmptyElseBlockInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) @@ -52,7 +52,7 @@ protected override string ResultDescription(QualifiedContext + private class EmptyElseBlockListener : EmptyBlockInspectionListenerBase { public override void EnterElseBlock([NotNull] VBAParser.ElseBlockContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForEachBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyForEachBlockInspection.cs similarity index 92% rename from Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForEachBlockInspection.cs rename to Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyForEachBlockInspection.cs index 87e29d7337..d1fd1f6e24 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForEachBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyForEachBlockInspection.cs @@ -37,7 +37,7 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [Experimental(nameof(ExperimentalNames.EmptyBlockInspections))] - internal sealed class EmptyForEachBlockInspection : ParseTreeInspectionBase + internal sealed class EmptyForEachBlockInspection : EmptyBlockInspectionBase { public EmptyForEachBlockInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) @@ -52,7 +52,7 @@ protected override string ResultDescription(QualifiedContext + private class EmptyForEachBlockListener : EmptyBlockInspectionListenerBase { public override void EnterForEachStmt([NotNull] VBAParser.ForEachStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForLoopBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyForLoopBlockInspection.cs similarity index 92% rename from Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForLoopBlockInspection.cs rename to Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyForLoopBlockInspection.cs index c14948a015..c31788959c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyForLoopBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyForLoopBlockInspection.cs @@ -37,7 +37,7 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [Experimental(nameof(ExperimentalNames.EmptyBlockInspections))] - internal sealed class EmptyForLoopBlockInspection : ParseTreeInspectionBase + internal sealed class EmptyForLoopBlockInspection : EmptyBlockInspectionBase { public EmptyForLoopBlockInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) @@ -52,7 +52,7 @@ protected override string ResultDescription(QualifiedContext + private class EmptyForLoopBlockListener : EmptyBlockInspectionListenerBase { public override void EnterForNextStmt([NotNull] VBAParser.ForNextStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyIfBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyIfBlockInspection.cs similarity index 94% rename from Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyIfBlockInspection.cs rename to Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyIfBlockInspection.cs index 1733320bb6..c8ec8307d0 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyIfBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyIfBlockInspection.cs @@ -34,7 +34,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - internal sealed class EmptyIfBlockInspection : ParseTreeInspectionBase + internal sealed class EmptyIfBlockInspection : EmptyBlockInspectionBase { public EmptyIfBlockInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) @@ -49,7 +49,7 @@ protected override string ResultDescription(QualifiedContext protected override IInspectionListener ContextListener { get; } - private class EmptyIfBlockListener : EmptyBlockInspectionListenerBase + private class EmptyIfBlockListener : EmptyBlockInspectionListenerBase { public override void EnterIfStmt([NotNull] VBAParser.IfStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyWhileWendBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyWhileWendBlockInspection.cs similarity index 92% rename from Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyWhileWendBlockInspection.cs rename to Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyWhileWendBlockInspection.cs index 19391e5ce5..d2edfed906 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyWhileWendBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyWhileWendBlockInspection.cs @@ -35,7 +35,7 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [Experimental(nameof(ExperimentalNames.EmptyBlockInspections))] - internal sealed class EmptyWhileWendBlockInspection : ParseTreeInspectionBase + internal sealed class EmptyWhileWendBlockInspection : EmptyBlockInspectionBase { public EmptyWhileWendBlockInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) @@ -50,7 +50,7 @@ protected override string ResultDescription(QualifiedContext + private class EmptyWhileWendBlockListener : EmptyBlockInspectionListenerBase { public override void EnterWhileWendStmt([NotNull] VBAParser.WhileWendStmtContext context) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlockInspectionListenerBase.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlockInspectionListenerBase.cs deleted file mode 100644 index d5d56a63ef..0000000000 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlockInspectionListenerBase.cs +++ /dev/null @@ -1,78 +0,0 @@ -using Antlr4.Runtime; -using Rubberduck.Parsing.Grammar; -using System.Collections.Generic; -using System.Diagnostics; -using Antlr4.Runtime.Tree; -using Rubberduck.Inspections.Abstract; - -namespace Rubberduck.Inspections.Concrete -{ - internal class EmptyBlockInspectionListenerBase : InspectionListenerBase - where TContext : ParserRuleContext - { - public void InspectBlockForExecutableStatements(VBAParser.BlockContext block, T context) where T : TContext - { - if (!BlockContainsExecutableStatements(block)) - { - SaveContext(context); - } - } - - private bool BlockContainsExecutableStatements(VBAParser.BlockContext block) - { - return block?.children != null && ContainsExecutableStatements(block.children); - } - - private bool ContainsExecutableStatements(IList blockChildren) - { - foreach (var child in blockChildren) - { - if (child is VBAParser.BlockStmtContext blockStmt) - { - var mainBlockStmt = blockStmt.mainBlockStmt(); - - if (mainBlockStmt == null) - { - continue; //We have a lone line lable, which is not executable. - } - - Debug.Assert(mainBlockStmt.ChildCount == 1); - - // exclude variables and consts because they are not executable statements - if (mainBlockStmt.GetChild(0) is VBAParser.VariableStmtContext || - mainBlockStmt.GetChild(0) is VBAParser.ConstStmtContext) - { - continue; - } - - return true; - } - - if (child is VBAParser.RemCommentContext || - child is VBAParser.CommentContext || - child is VBAParser.CommentOrAnnotationContext || - child is VBAParser.EndOfStatementContext) - { - continue; - } - - return true; - } - - return false; - } - - public void InspectBlockForExecutableStatements(VBAParser.UnterminatedBlockContext block, T context) where T : TContext - { - if (!BlockContainsExecutableStatements(block)) - { - SaveContext(context); - } - } - - private bool BlockContainsExecutableStatements(VBAParser.UnterminatedBlockContext block) - { - return block?.children != null && ContainsExecutableStatements(block.children); - } - } -} From 32e6201c9eaf5cbb4cf51a7ec5645f903550e530 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sat, 7 Mar 2020 18:13:45 +0100 Subject: [PATCH 285/461] Make inspection and quick fix implementation internal Also fixes wrong InternalsVisibleTo attributes. --- ...ReferenceInspectionFromDeclarationsBase.cs | 4 +- .../Abstract/DeclarationInspectionBase.cs | 4 +- .../Abstract/DeclarationInspectionBaseBase.cs | 2 +- .../DeclarationInspectionMultiResultBase.cs | 2 +- ...ionInspectionUsingGlobalInformationBase.cs | 4 +- ...nspectionUsingGlobalInformationBaseBase.cs | 2 +- .../Abstract/EmptyBlockInspectionBase.cs | 2 +- .../IdentifierReferenceInspectionBase.cs | 4 +- ...ReferenceInspectionFromDeclarationsBase.cs | 4 +- .../Abstract/ImplicitTypeInspectionBase.cs | 2 +- .../Inspections/Abstract/InspectionBase.cs | 2 +- .../Abstract/InspectionResultBase.cs | 2 +- .../Abstract/IsMissingInspectionBase.cs | 2 +- ...berAccessMayReturnNothingInspectionBase.cs | 2 +- .../Abstract/ParseTreeInspectionBase.cs | 6 +- ...entWithIncompatibleObjectTypeInspection.cs | 126 +++++++++--------- .../AssignedByValParameterInspection.cs | 2 +- .../Concrete/AssignmentNotUsedInspection.cs | 2 +- .../AttributeValueOutOfSyncInspection.cs | 2 +- .../BooleanAssignedInIfElseInspection.cs | 2 +- .../Concrete/ConstantNotUsedInspection.cs | 2 +- .../Concrete/DefTypeStatementInspection.cs | 2 +- .../DefaultMemberRequiredInspection.cs | 2 +- .../Concrete/DefaultProjectNameInspection.cs | 2 +- .../DuplicatedAnnotationInspection.cs | 2 +- .../Concrete/EmptyModuleInspection.cs | 2 +- .../Concrete/EmptyStringLiteralInspection.cs | 2 +- .../EncapsulatePublicFieldInspection.cs | 2 +- .../ApplicationWorksheetFunctionInspection.cs | 2 +- .../ExcelMemberMayReturnNothingInspection.cs | 2 +- ...elUdfNameIsValidCellReferenceInspection.cs | 2 +- .../ImplicitActiveSheetReferenceInspection.cs | 2 +- ...plicitActiveWorkbookReferenceInspection.cs | 2 +- .../SheetAccessedUsingStringInspection.cs | 2 +- ...ionReturnValueAlwaysDiscardedInspection.cs | 2 +- .../FunctionReturnValueDiscardedInspection.cs | 2 +- .../HostSpecificExpressionInspection.cs | 2 +- .../Concrete/HungarianNotationInspection.cs | 2 +- .../Concrete/IllegalAnnotationInspection.cs | 2 +- .../ImplementedInterfaceMemberInspection.cs | 2 +- .../ImplicitByRefModifierInspection.cs | 2 +- .../ImplicitDefaultMemberAccessInspection.cs | 2 +- .../ImplicitPublicMemberInspection.cs | 2 +- ...tRecursiveDefaultMemberAccessInspection.cs | 2 +- ...citUnboundDefaultMemberAccessInspection.cs | 2 +- .../ImplicitVariantReturnTypeInspection.cs | 2 +- .../ImplicitlyTypedConstInspection.cs | 2 +- .../IndexedDefaultMemberAccessInspection.cs | 2 +- ...dRecursiveDefaultMemberAccessInspection.cs | 2 +- ...xedUnboundDefaultMemberAccessInspection.cs | 2 +- .../Concrete/IntegerDataTypeInspection.cs | 2 +- ...issingOnInappropriateArgumentInspection.cs | 2 +- ...ssingWithNonArgumentParameterInspection.cs | 2 +- .../Concrete/LineLabelNotUsedInspection.cs | 2 +- .../MemberNotOnInterfaceInspection.cs | 2 +- .../MissingAnnotationArgumentInspection.cs | 2 +- .../Concrete/MissingAttributeInspection.cs | 2 +- .../MissingMemberAnnotationInspection.cs | 2 +- .../MissingModuleAnnotationInspection.cs | 2 +- .../ModuleScopeDimKeywordInspection.cs | 2 +- .../Concrete/ModuleWithoutFolderInspection.cs | 2 +- .../MoveFieldCloserToUsageInspection.cs | 2 +- .../Concrete/MultilineParameterInspection.cs | 2 +- .../MultipleDeclarationsInspection.cs | 2 +- .../NonReturningFunctionInspection.cs | 2 +- .../ObjectVariableNotSetInspection.cs | 2 +- ...bjectWhereProcedureIsRequiredInspection.cs | 2 +- .../ObsoleteCallStatementInspection.cs | 2 +- .../ObsoleteCallingConventionInspection.cs | 2 +- .../ObsoleteCommentSyntaxInspection.cs | 2 +- .../Concrete/ObsoleteErrorSyntaxInspection.cs | 2 +- .../Concrete/ObsoleteGlobalInspection.cs | 2 +- .../ObsoleteLetStatementInspection.cs | 2 +- .../Concrete/ObsoleteMemberUsageInspection.cs | 2 +- .../Concrete/ObsoleteTypeHintInspection.cs | 2 +- .../ObsoleteWhileWendStatementInspection.cs | 2 +- .../Concrete/OnLocalErrorInspection.cs | 2 +- .../Concrete/OptionBaseInspection.cs | 2 +- .../Concrete/OptionExplicitInspection.cs | 2 +- .../Concrete/ParameterCanBeByValInspection.cs | 2 +- .../Concrete/ParameterNotUsedInspection.cs | 2 +- ...ocedureCanBeWrittenAsFunctionInspection.cs | 2 +- .../Concrete/ProcedureNotUsedInspection.cs | 2 +- .../Concrete/ProcedureRequiredInspection.cs | 2 +- .../RedundantByRefModifierInspection.cs | 2 +- .../Concrete/RedundantOptionInspection.cs | 2 +- .../SelfAssignedDeclarationInspection.cs | 2 +- ...entWithIncompatibleObjectTypeInspection.cs | 122 ++++++++--------- .../Concrete/ShadowedDeclarationInspection.cs | 2 +- .../Concrete/StepIsNotSpecifiedInspection.cs | 2 +- .../Concrete/StepOneIsRedundantInspection.cs | 2 +- .../Concrete/StopKeywordInspection.cs | 2 +- ...SuperfluousAnnotationArgumentInspection.cs | 2 +- .../SuspiciousLetAssignmentInspection.cs | 2 +- .../KeywordsUsedAsMemberInspection.cs | 2 +- ...neContinuationBetweenKeywordsInspection.cs | 2 +- .../NegativeLineNumberInspection.cs | 2 +- .../NonBreakingSpaceIdentifierInspection.cs | 2 +- .../OnErrorGoToMinusOneInspection.cs | 2 +- .../ThunderCode/ThunderCodeFormatExtension.cs | 2 +- .../UnassignedVariableUsageInspection.cs | 2 +- .../Concrete/UndeclaredVariableInspection.cs | 2 +- ...coreInPublicClassModuleMemberInspection.cs | 2 +- .../UnhandledOnErrorResumeNextInspection.cs | 2 +- .../ComparableDateValue.cs | 2 +- .../ExpressionFilter.cs | 6 +- .../ExpressionFilterBoolean.cs | 33 +++-- .../ExpressionFilterDate.cs | 2 +- .../ExpressionFilterFactory.cs | 2 +- .../ExpressionFilterIntegral.cs | 2 +- .../UnreachableCaseInspection/FilterLimits.cs | 4 +- .../UnreachableCaseInspection/LetCoerce.cs | 4 +- .../OperatorTypesProvider.cs | 2 +- .../ParseTreeExpressionEvaluator.cs | 46 ++++--- .../ParseTreeValue.cs | 6 +- .../ParseTreeValueFactory.cs | 4 +- .../ParseTreeValueVisitor.cs | 6 +- .../ParseTreeVisitorResults.cs | 6 +- .../RangeClauseExpression.cs | 16 +-- .../TypeTokenPair.cs | 2 +- .../UnreachableCaseInspection.cs | 2 +- .../UnreachableCaseInspector.cs | 4 +- .../UntypedFunctionUsageInspection.cs | 2 +- .../Concrete/UseMeaningfulNameInspection.cs | 2 +- .../Concrete/UseOfBangNotationInspection.cs | 2 +- .../UseOfRecursiveBangNotationInspection.cs | 2 +- .../UseOfUnboundBangNotationInspection.cs | 2 +- .../Concrete/ValueRequiredInspection.cs | 2 +- .../Concrete/VariableNotAssignedInspection.cs | 2 +- .../Concrete/VariableNotUsedInspection.cs | 2 +- .../VariableRequiresSetAssignmentEvaluator.cs | 2 +- .../VariableTypeNotDeclaredInspection.cs | 2 +- .../Concrete/WriteOnlyPropertyInspection.cs | 2 +- .../Extensions/DeclarationTypeExtensions.cs | 2 +- .../Extensions/ExecutableBlocksExtensions.cs | 10 +- .../Extensions/IgnoreRelatedExtensions.cs | 2 +- .../{ => Logistics}/IInspectionProvider.cs | 0 .../{ => Logistics}/InspectionProvider.cs | 2 +- .../Inspections/{ => Logistics}/Inspector.cs | 2 +- .../Results/DeclarationInspectionResult.cs | 4 +- .../IdentifierReferenceInspectionResult.cs | 4 +- .../QualifiedContextInspectionResult.cs | 4 +- .../Properties/AssemblyInfo.cs | 6 +- .../Abstract/QuickFixBase.cs | 4 +- .../{ => Abstract}/RefactoringQuickFixBase.cs | 5 +- .../AccessSheetUsingCodeNameQuickFix.cs | 4 +- .../AddAttributeAnnotationQuickFix.cs | 7 +- .../AddIdentifierToWhiteListQuickFix.cs | 4 +- .../AddMissingAttributeQuickFix.cs | 4 +- .../{ => Concrete}/AddStepOneQuickFix.cs | 6 +- .../AdjustAttributeAnnotationQuickFix.cs | 4 +- .../AdjustAttributeValuesQuickFix.cs | 7 +- .../ApplicationWorksheetFunctionQuickFix.cs | 4 +- ...gnedByValParameterMakeLocalCopyQuickFix.cs | 4 +- .../ChangeDimToPrivateQuickFix.cs | 4 +- .../ChangeIntegerToLongQuickFix.cs | 5 +- .../ChangeProcedureToFunctionQuickFix.cs | 4 +- .../ConvertToProcedureQuickFix.cs | 4 +- .../DeclareAsExplicitVariantQuickFix.cs | 4 +- .../ExpandBangNotationQuickFix.cs | 4 +- .../ExpandDefaultMemberQuickFix.cs | 4 +- .../{ => Concrete}/IgnoreOnceQuickFix.cs | 4 +- .../IntroduceLocalVariableQuickFix.cs | 4 +- ...sMissingOnInappropriateArgumentQuickFix.cs | 4 +- .../MakeSingleLineParameterQuickFix.cs | 4 +- .../{ => Concrete}/OptionExplicitQuickFix.cs | 4 +- .../PassParameterByReferenceQuickFix.cs | 4 +- .../PassParameterByValueQuickFix.cs | 4 +- .../Refactoring}/EncapsulateFieldQuickFix.cs | 3 +- .../MoveFieldCloserToUsageQuickFix.cs | 3 +- .../RemoveUnusedParameterQuickFix.cs | 3 +- .../Refactoring}/RenameDeclarationQuickFix.cs | 3 +- .../RemoveAnnotationQuickFix.cs | 4 +- .../{ => Concrete}/RemoveAttributeQuickFix.cs | 5 +- .../{ => Concrete}/RemoveCommentQuickFix.cs | 4 +- .../RemoveDuplicatedAnnotationQuickFix.cs | 4 +- .../RemoveEmptyElseBlockQuickFix.cs | 4 +- .../RemoveEmptyIfBlockQuickFix.cs | 4 +- .../RemoveExplicitByRefModifierQuickFix.cs | 4 +- .../RemoveExplicitCallStatementQuickFix.cs | 4 +- .../RemoveExplicitLetStatementQuickFix.cs | 4 +- .../RemoveLocalErrorQuickFix.cs | 4 +- .../RemoveOptionBaseStatementQuickFix.cs | 4 +- .../{ => Concrete}/RemoveStepOneQuickFix.cs | 4 +- .../RemoveStopKeywordQuickFix.cs | 4 +- .../{ => Concrete}/RemoveTypeHintsQuickFix.cs | 4 +- .../RemoveUnassignedIdentifierQuickFix.cs | 4 +- .../RemoveUnassignedVariableUsageQuickFix.cs | 4 +- .../RemoveUnusedDeclarationQuickFix.cs | 4 +- ...laceEmptyStringLiteralStatementQuickFix.cs | 4 +- .../ReplaceGlobalModifierQuickFix.cs | 4 +- ...eIfElseWithConditionalStatementQuickFix.cs | 4 +- .../ReplaceObsoleteCommentMarkerQuickFix.cs | 4 +- .../ReplaceObsoleteErrorStatementQuickFix.cs | 4 +- ...ReplaceWhileWendWithDoWhileLoopQuickFix.cs | 4 +- .../RestoreErrorHandlingQuickFix.cs | 4 +- .../SetExplicitVariantReturnTypeQuickFix.cs | 4 +- .../SpecifyExplicitByRefModifierQuickFix.cs | 4 +- .../SpecifyExplicitPublicModifierQuickFix.cs | 4 +- .../SplitMultipleDeclarationsQuickFix.cs | 4 +- .../UntypedFunctionUsageQuickFix.cs | 4 +- ...seSetKeywordForObjectAssignmentQuickFix.cs | 4 +- .../WriteOnlyPropertyQuickFix.cs | 4 +- .../IQuickFixFailureNotifier.cs | 2 +- .../QuickFixFailureNotifier.cs | 2 +- .../{ => Logistics}/QuickFixProvider.cs | 2 +- Rubberduck.Core/Properties/AssemblyInfo.cs | 1 + .../Inspections/InspectionResultsViewModel.cs | 4 +- .../Properties/AssemblyInfo.cs | 4 +- .../Properties/AssemblyInfo.cs | 6 +- .../Properties/AssemblyInfo.cs | 5 +- Rubberduck.Main/Properties/AssemblyInfo.cs | 3 +- Rubberduck.Parsing/Properties/AssemblyInfo.cs | 6 +- .../Properties/AssemblyInfo.cs | 7 +- .../Properties/AssemblyInfo.cs | 6 +- .../Properties/AssemblyInfo.cs | 4 +- .../Properties/AssemblyInfo.cs | 6 +- .../Properties/AssemblyInfo.cs | 5 +- .../Properties/AssemblyInfo.cs | 6 +- .../Properties/AssemblyInfo.cs | 2 + .../Properties/AssemblyInfo.cs | 3 +- .../Properties/AssemblyInfo.cs | 4 +- 222 files changed, 513 insertions(+), 485 deletions(-) rename Rubberduck.CodeAnalysis/Inspections/{ => Logistics}/IInspectionProvider.cs (100%) rename Rubberduck.CodeAnalysis/Inspections/{ => Logistics}/InspectionProvider.cs (94%) rename Rubberduck.CodeAnalysis/Inspections/{ => Logistics}/Inspector.cs (99%) rename Rubberduck.CodeAnalysis/{Inspections => QuickFixes}/Abstract/QuickFixBase.cs (95%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Abstract}/RefactoringQuickFixBase.cs (90%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/AccessSheetUsingCodeNameQuickFix.cs (97%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/AddAttributeAnnotationQuickFix.cs (95%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/AddIdentifierToWhiteListQuickFix.cs (93%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/AddMissingAttributeQuickFix.cs (95%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/AddStepOneQuickFix.cs (93%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/AdjustAttributeAnnotationQuickFix.cs (97%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/AdjustAttributeValuesQuickFix.cs (95%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/ApplicationWorksheetFunctionQuickFix.cs (92%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/AssignedByValParameterMakeLocalCopyQuickFix.cs (98%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/ChangeDimToPrivateQuickFix.cs (93%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/ChangeIntegerToLongQuickFix.cs (98%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/ChangeProcedureToFunctionQuickFix.cs (97%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/ConvertToProcedureQuickFix.cs (98%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/DeclareAsExplicitVariantQuickFix.cs (94%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/ExpandBangNotationQuickFix.cs (98%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/ExpandDefaultMemberQuickFix.cs (98%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/IgnoreOnceQuickFix.cs (97%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/IntroduceLocalVariableQuickFix.cs (97%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/IsMissingOnInappropriateArgumentQuickFix.cs (97%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/MakeSingleLineParameterQuickFix.cs (93%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/OptionExplicitQuickFix.cs (93%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/PassParameterByReferenceQuickFix.cs (93%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/PassParameterByValueQuickFix.cs (97%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete/Refactoring}/EncapsulateFieldQuickFix.cs (92%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete/Refactoring}/MoveFieldCloserToUsageQuickFix.cs (91%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete/Refactoring}/RemoveUnusedParameterQuickFix.cs (92%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete/Refactoring}/RenameDeclarationQuickFix.cs (94%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/RemoveAnnotationQuickFix.cs (94%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/RemoveAttributeQuickFix.cs (95%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/RemoveCommentQuickFix.cs (92%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/RemoveDuplicatedAnnotationQuickFix.cs (94%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/RemoveEmptyElseBlockQuickFix.cs (94%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/RemoveEmptyIfBlockQuickFix.cs (98%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/RemoveExplicitByRefModifierQuickFix.cs (97%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/RemoveExplicitCallStatementQuickFix.cs (94%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/RemoveExplicitLetStatementQuickFix.cs (93%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/RemoveLocalErrorQuickFix.cs (94%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/RemoveOptionBaseStatementQuickFix.cs (93%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/RemoveStepOneQuickFix.cs (93%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/RemoveStopKeywordQuickFix.cs (92%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/RemoveTypeHintsQuickFix.cs (97%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/RemoveUnassignedIdentifierQuickFix.cs (92%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/RemoveUnassignedVariableUsageQuickFix.cs (95%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/RemoveUnusedDeclarationQuickFix.cs (94%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/ReplaceEmptyStringLiteralStatementQuickFix.cs (92%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/ReplaceGlobalModifierQuickFix.cs (92%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/ReplaceIfElseWithConditionalStatementQuickFix.cs (94%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/ReplaceObsoleteCommentMarkerQuickFix.cs (92%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/ReplaceObsoleteErrorStatementQuickFix.cs (92%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/ReplaceWhileWendWithDoWhileLoopQuickFix.cs (93%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/RestoreErrorHandlingQuickFix.cs (97%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/SetExplicitVariantReturnTypeQuickFix.cs (96%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/SpecifyExplicitByRefModifierQuickFix.cs (97%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/SpecifyExplicitPublicModifierQuickFix.cs (92%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/SplitMultipleDeclarationsQuickFix.cs (96%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/UntypedFunctionUsageQuickFix.cs (95%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/UseSetKeywordForObjectAssignmentQuickFix.cs (94%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Concrete}/WriteOnlyPropertyQuickFix.cs (96%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Logistics}/IQuickFixFailureNotifier.cs (78%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Logistics}/QuickFixFailureNotifier.cs (95%) rename Rubberduck.CodeAnalysis/QuickFixes/{ => Logistics}/QuickFixProvider.cs (99%) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/ArgumentReferenceInspectionFromDeclarationsBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/ArgumentReferenceInspectionFromDeclarationsBase.cs index 269e324470..99cbf2797f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/ArgumentReferenceInspectionFromDeclarationsBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/ArgumentReferenceInspectionFromDeclarationsBase.cs @@ -7,7 +7,7 @@ namespace Rubberduck.Inspections.Inspections.Abstract { - public abstract class ArgumentReferenceInspectionFromDeclarationsBase : IdentifierReferenceInspectionFromDeclarationsBase + internal abstract class ArgumentReferenceInspectionFromDeclarationsBase : IdentifierReferenceInspectionFromDeclarationsBase { protected ArgumentReferenceInspectionFromDeclarationsBase(RubberduckParserState state) : base(state) { } @@ -32,7 +32,7 @@ protected override bool IsResultReference(IdentifierReference reference, Declara } } - public abstract class ArgumentReferenceInspectionFromDeclarationsBase : IdentifierReferenceInspectionFromDeclarationsBase + internal abstract class ArgumentReferenceInspectionFromDeclarationsBase : IdentifierReferenceInspectionFromDeclarationsBase { protected ArgumentReferenceInspectionFromDeclarationsBase(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs index 99876d0438..4bef41918a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs @@ -9,7 +9,7 @@ namespace Rubberduck.Inspections.Abstract { - public abstract class DeclarationInspectionBase : DeclarationInspectionBaseBase + internal abstract class DeclarationInspectionBase : DeclarationInspectionBaseBase { protected DeclarationInspectionBase(IDeclarationFinderProvider declarationFinderProvider, params DeclarationType[] relevantDeclarationTypes) : base(declarationFinderProvider, relevantDeclarationTypes) @@ -44,7 +44,7 @@ protected virtual IInspectionResult InspectionResult(Declaration declaration) } } - public abstract class DeclarationInspectionBase : DeclarationInspectionBaseBase + internal abstract class DeclarationInspectionBase : DeclarationInspectionBaseBase { protected DeclarationInspectionBase(IDeclarationFinderProvider declarationFinderProvider, params DeclarationType[] relevantDeclarationTypes) : base(declarationFinderProvider, relevantDeclarationTypes) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs index a621ddb2e8..a368a7c0aa 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs @@ -11,7 +11,7 @@ namespace Rubberduck.Inspections.Abstract /// /// This is a base class for the other declaration inspection base classes. It should not be implemented directly by concrete inspections. /// - public abstract class DeclarationInspectionBaseBase : InspectionBase + internal abstract class DeclarationInspectionBaseBase : InspectionBase { private readonly DeclarationType[] _relevantDeclarationTypes; private readonly DeclarationType[] _excludeDeclarationTypes; diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionMultiResultBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionMultiResultBase.cs index c5863dcb83..1cef4eb833 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionMultiResultBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionMultiResultBase.cs @@ -9,7 +9,7 @@ namespace Rubberduck.Inspections.Abstract { - public abstract class DeclarationInspectionMultiResultBase : DeclarationInspectionBaseBase + internal abstract class DeclarationInspectionMultiResultBase : DeclarationInspectionBaseBase { protected DeclarationInspectionMultiResultBase(IDeclarationFinderProvider declarationFinderProvider, params DeclarationType[] relevantDeclarationTypes) : base(declarationFinderProvider, relevantDeclarationTypes) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBase.cs index 698f37bf47..5a4e313f8d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBase.cs @@ -9,7 +9,7 @@ namespace Rubberduck.Inspections.Abstract { - public abstract class DeclarationInspectionUsingGlobalInformationBase : DeclarationInspectionUsingGlobalInformationBaseBase + internal abstract class DeclarationInspectionUsingGlobalInformationBase : DeclarationInspectionUsingGlobalInformationBaseBase { protected DeclarationInspectionUsingGlobalInformationBase(IDeclarationFinderProvider declarationFinderProvider, params DeclarationType[] relevantDeclarationTypes) : base(declarationFinderProvider, relevantDeclarationTypes) @@ -44,7 +44,7 @@ protected virtual IInspectionResult InspectionResult(Declaration declaration) } } - public abstract class DeclarationInspectionUsingGlobalInformationBase : DeclarationInspectionUsingGlobalInformationBaseBase + internal abstract class DeclarationInspectionUsingGlobalInformationBase : DeclarationInspectionUsingGlobalInformationBaseBase { protected DeclarationInspectionUsingGlobalInformationBase(IDeclarationFinderProvider declarationFinderProvider, params DeclarationType[] relevantDeclarationTypes) : base(declarationFinderProvider, relevantDeclarationTypes) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs index 9848592caa..f85a0a2de8 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs @@ -8,7 +8,7 @@ namespace Rubberduck.Inspections.Abstract { - public abstract class DeclarationInspectionUsingGlobalInformationBaseBase : InspectionBase + internal abstract class DeclarationInspectionUsingGlobalInformationBaseBase : InspectionBase { protected readonly DeclarationType[] RelevantDeclarationTypes; protected readonly DeclarationType[] ExcludeDeclarationTypes; diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/EmptyBlockInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/EmptyBlockInspectionBase.cs index 2bf1700677..bfe98b69a4 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/EmptyBlockInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/EmptyBlockInspectionBase.cs @@ -7,7 +7,7 @@ namespace Rubberduck.Inspections.Abstract { - public abstract class EmptyBlockInspectionBase : ParseTreeInspectionBase + internal abstract class EmptyBlockInspectionBase : ParseTreeInspectionBase where TContext : ParserRuleContext { protected EmptyBlockInspectionBase(IDeclarationFinderProvider declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs index 5162e686f5..907e22386c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs @@ -9,7 +9,7 @@ namespace Rubberduck.Inspections.Abstract { - public abstract class IdentifierReferenceInspectionBase : InspectionBase + internal abstract class IdentifierReferenceInspectionBase : InspectionBase { protected IdentifierReferenceInspectionBase(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) @@ -54,7 +54,7 @@ protected virtual IInspectionResult InspectionResult(IdentifierReference referen } } - public abstract class IdentifierReferenceInspectionBase : InspectionBase + internal abstract class IdentifierReferenceInspectionBase : InspectionBase { protected IdentifierReferenceInspectionBase(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs index e18696a37f..361c073d81 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs @@ -9,7 +9,7 @@ namespace Rubberduck.Inspections.Abstract { - public abstract class IdentifierReferenceInspectionFromDeclarationsBase : InspectionBase + internal abstract class IdentifierReferenceInspectionFromDeclarationsBase : InspectionBase { protected IdentifierReferenceInspectionFromDeclarationsBase(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) @@ -65,7 +65,7 @@ protected virtual IInspectionResult InspectionResult(IdentifierReference referen } } - public abstract class IdentifierReferenceInspectionFromDeclarationsBase : InspectionBase + internal abstract class IdentifierReferenceInspectionFromDeclarationsBase : InspectionBase { protected IdentifierReferenceInspectionFromDeclarationsBase(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/ImplicitTypeInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/ImplicitTypeInspectionBase.cs index ab19772900..75ccef11e8 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/ImplicitTypeInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/ImplicitTypeInspectionBase.cs @@ -4,7 +4,7 @@ namespace Rubberduck.Inspections.Abstract { - public abstract class ImplicitTypeInspectionBase : DeclarationInspectionBase + internal abstract class ImplicitTypeInspectionBase : DeclarationInspectionBase { protected ImplicitTypeInspectionBase(IDeclarationFinderProvider declarationFinderProvider, params DeclarationType[] relevantDeclarationTypes) : base(declarationFinderProvider, relevantDeclarationTypes) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs index c0760a4f32..f7b844839a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs @@ -14,7 +14,7 @@ namespace Rubberduck.Inspections.Abstract { - public abstract class InspectionBase : IInspection + internal abstract class InspectionBase : IInspection { private readonly IDeclarationFinderProvider _declarationFinderProvider; diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionResultBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionResultBase.cs index 637723afff..96a66993e9 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionResultBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionResultBase.cs @@ -8,7 +8,7 @@ namespace Rubberduck.Inspections.Abstract { - public abstract class InspectionResultBase : IInspectionResult, INavigateSource + internal abstract class InspectionResultBase : IInspectionResult, INavigateSource { protected InspectionResultBase(IInspection inspection, string description, diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs index d1358ca671..a044ff0d19 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs @@ -8,7 +8,7 @@ namespace Rubberduck.Inspections.Inspections.Abstract { - public abstract class IsMissingInspectionBase : ArgumentReferenceInspectionFromDeclarationsBase + internal abstract class IsMissingInspectionBase : ArgumentReferenceInspectionFromDeclarationsBase { protected IsMissingInspectionBase(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/MemberAccessMayReturnNothingInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/MemberAccessMayReturnNothingInspectionBase.cs index 866ff85360..6f463406ab 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/MemberAccessMayReturnNothingInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/MemberAccessMayReturnNothingInspectionBase.cs @@ -13,7 +13,7 @@ namespace Rubberduck.Inspections.Abstract { - public abstract class MemberAccessMayReturnNothingInspectionBase : IdentifierReferenceInspectionFromDeclarationsBase + internal abstract class MemberAccessMayReturnNothingInspectionBase : IdentifierReferenceInspectionFromDeclarationsBase { protected MemberAccessMayReturnNothingInspectionBase(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs index e8f2fd3c49..2b26585299 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs @@ -13,7 +13,7 @@ namespace Rubberduck.Inspections.Abstract { - public abstract class ParseTreeInspectionBase : InspectionBase, IParseTreeInspection + internal abstract class ParseTreeInspectionBase : InspectionBase, IParseTreeInspection where TContext : ParserRuleContext { protected ParseTreeInspectionBase(IDeclarationFinderProvider declarationFinderProvider) @@ -62,7 +62,7 @@ protected virtual IInspectionResult InspectionResult(QualifiedContext } - public abstract class ParseTreeInspectionBase : InspectionBase, IParseTreeInspection + internal abstract class ParseTreeInspectionBase : InspectionBase, IParseTreeInspection where TContext : ParserRuleContext { protected ParseTreeInspectionBase(IDeclarationFinderProvider declarationFinderProvider) @@ -119,7 +119,7 @@ protected virtual IInspectionResult InspectionResult(QualifiedContext public virtual CodeKind TargetKindOfCode => CodeKind.CodePaneCode; } - public class InspectionListenerBase : VBAParserBaseListener, IInspectionListener + internal class InspectionListenerBase : VBAParserBaseListener, IInspectionListener where TContext : ParserRuleContext { private readonly IDictionary>> _contexts; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs index bda9fe6f21..498236d8d9 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs @@ -12,69 +12,69 @@ namespace Rubberduck.CodeAnalysis.Inspections.Concrete { - /// - /// Locates arguments passed to functions or procedures for object parameters which the do not have a compatible declared type. - /// - /// - /// The VBA compiler does not check whether different object types are compatible. Instead there is a runtime error whenever the types are incompatible. - /// - /// - /// - /// - /// - /// - /// - public class ArgumentWithIncompatibleObjectTypeInspection : ArgumentReferenceInspectionFromDeclarationsBase + /// + /// Locates arguments passed to functions or procedures for object parameters which the do not have a compatible declared type. + /// + /// + /// The VBA compiler does not check whether different object types are compatible. Instead there is a runtime error whenever the types are incompatible. + /// + /// + /// + /// + /// + /// + /// + internal class ArgumentWithIncompatibleObjectTypeInspection : ArgumentReferenceInspectionFromDeclarationsBase { private readonly ISetTypeResolver _setTypeResolver; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignedByValParameterInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignedByValParameterInspection.cs index 5b382e1df6..7af0cf672c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignedByValParameterInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignedByValParameterInspection.cs @@ -33,7 +33,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class AssignedByValParameterInspection : DeclarationInspectionBase + internal sealed class AssignedByValParameterInspection : DeclarationInspectionBase { public AssignedByValParameterInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, DeclarationType.Parameter) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs index 53f0882fd4..12cf13799c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs @@ -37,7 +37,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class AssignmentNotUsedInspection : IdentifierReferenceInspectionBase + internal sealed class AssignmentNotUsedInspection : IdentifierReferenceInspectionBase { private readonly Walker _walker; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/AttributeValueOutOfSyncInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/AttributeValueOutOfSyncInspection.cs index c917924c00..5fc79a18c2 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/AttributeValueOutOfSyncInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/AttributeValueOutOfSyncInspection.cs @@ -37,7 +37,7 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [CannotAnnotate] - public sealed class AttributeValueOutOfSyncInspection : DeclarationInspectionMultiResultBase<(IParseTreeAnnotation Annotation, string AttributeName, IReadOnlyList AttributeValues)> + internal sealed class AttributeValueOutOfSyncInspection : DeclarationInspectionMultiResultBase<(IParseTreeAnnotation Annotation, string AttributeName, IReadOnlyList AttributeValues)> { public AttributeValueOutOfSyncInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs index 34945abe34..71019835bb 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs @@ -36,7 +36,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class BooleanAssignedInIfElseInspection : ParseTreeInspectionBase + internal sealed class BooleanAssignedInIfElseInspection : ParseTreeInspectionBase { public BooleanAssignedInIfElseInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ConstantNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ConstantNotUsedInspection.cs index 109b22b4d8..5661913fe3 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ConstantNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ConstantNotUsedInspection.cs @@ -32,7 +32,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ConstantNotUsedInspection : DeclarationInspectionBase + internal sealed class ConstantNotUsedInspection : DeclarationInspectionBase { public ConstantNotUsedInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, DeclarationType.Constant) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs index 808838f200..28bf25ea4a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs @@ -26,7 +26,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class DefTypeStatementInspection : ParseTreeInspectionBase + internal sealed class DefTypeStatementInspection : ParseTreeInspectionBase { public DefTypeStatementInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs index ff84978636..6c698dfc3b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs @@ -53,7 +53,7 @@ namespace Rubberduck.CodeAnalysis.Inspections.Concrete /// End Sub /// ]]> /// - public class DefaultMemberRequiredInspection : IdentifierReferenceInspectionBase + internal class DefaultMemberRequiredInspection : IdentifierReferenceInspectionBase { public DefaultMemberRequiredInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultProjectNameInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultProjectNameInspection.cs index 6985072407..8d6de441ee 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultProjectNameInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultProjectNameInspection.cs @@ -13,7 +13,7 @@ namespace Rubberduck.Inspections.Concrete /// VBA projects should be meaningfully named, to avoid namespace clashes when referencing other VBA projects. /// [CannotAnnotate] - public sealed class DefaultProjectNameInspection : DeclarationInspectionBase + internal sealed class DefaultProjectNameInspection : DeclarationInspectionBase { public DefaultProjectNameInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, DeclarationType.Project) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DuplicatedAnnotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DuplicatedAnnotationInspection.cs index 5788ed56ac..754f7d6e4d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DuplicatedAnnotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DuplicatedAnnotationInspection.cs @@ -34,7 +34,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class DuplicatedAnnotationInspection : DeclarationInspectionMultiResultBase + internal sealed class DuplicatedAnnotationInspection : DeclarationInspectionMultiResultBase { public DuplicatedAnnotationInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyModuleInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyModuleInspection.cs index ea55537720..c25be03ab3 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyModuleInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyModuleInspection.cs @@ -15,7 +15,7 @@ namespace Rubberduck.Inspections.Concrete /// /// An empty module does not need to exist and can be safely removed. /// - public sealed class EmptyModuleInspection : DeclarationInspectionBase + internal sealed class EmptyModuleInspection : DeclarationInspectionBase { private readonly EmptyModuleVisitor _emptyModuleVisitor; private readonly IParseTreeProvider _parseTreeProvider; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs index 7fb2ad3d41..803da6db76 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs @@ -33,7 +33,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class EmptyStringLiteralInspection : ParseTreeInspectionBase + internal sealed class EmptyStringLiteralInspection : ParseTreeInspectionBase { public EmptyStringLiteralInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EncapsulatePublicFieldInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EncapsulatePublicFieldInspection.cs index ced2df11d2..f63c7958d6 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EncapsulatePublicFieldInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EncapsulatePublicFieldInspection.cs @@ -27,7 +27,7 @@ namespace Rubberduck.Inspections.Concrete /// End Property /// ]]> /// - public sealed class EncapsulatePublicFieldInspection : DeclarationInspectionBase + internal sealed class EncapsulatePublicFieldInspection : DeclarationInspectionBase { public EncapsulatePublicFieldInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, DeclarationType.Variable) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs index 27eec2d91c..c724efab23 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs @@ -52,7 +52,7 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [RequiredLibrary("Excel")] - public class ApplicationWorksheetFunctionInspection : IdentifierReferenceInspectionFromDeclarationsBase + internal class ApplicationWorksheetFunctionInspection : IdentifierReferenceInspectionFromDeclarationsBase { public ApplicationWorksheetFunctionInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelMemberMayReturnNothingInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelMemberMayReturnNothingInspection.cs index 6b6febced8..b0df79d56a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelMemberMayReturnNothingInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelMemberMayReturnNothingInspection.cs @@ -39,7 +39,7 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [RequiredLibrary("Excel")] - public class ExcelMemberMayReturnNothingInspection : MemberAccessMayReturnNothingInspectionBase + internal class ExcelMemberMayReturnNothingInspection : MemberAccessMayReturnNothingInspectionBase { public ExcelMemberMayReturnNothingInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs index 0da3951c6f..74e1321a23 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs @@ -35,7 +35,7 @@ namespace Rubberduck.Inspections.Inspections.Concrete /// ]]> /// [RequiredLibrary("Excel")] - public class ExcelUdfNameIsValidCellReferenceInspection : DeclarationInspectionUsingGlobalInformationBase + internal class ExcelUdfNameIsValidCellReferenceInspection : DeclarationInspectionUsingGlobalInformationBase { public ExcelUdfNameIsValidCellReferenceInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, new []{DeclarationType.Function}, new []{DeclarationType.PropertyGet, DeclarationType.LibraryFunction}) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs index 62fdcb30ff..5f8a07b478 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs @@ -38,7 +38,7 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [RequiredLibrary("Excel")] - public sealed class ImplicitActiveSheetReferenceInspection : IdentifierReferenceInspectionFromDeclarationsBase + internal sealed class ImplicitActiveSheetReferenceInspection : IdentifierReferenceInspectionFromDeclarationsBase { public ImplicitActiveSheetReferenceInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveWorkbookReferenceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveWorkbookReferenceInspection.cs index be4b6db073..4302bc4272 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveWorkbookReferenceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveWorkbookReferenceInspection.cs @@ -36,7 +36,7 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [RequiredLibrary("Excel")] - public sealed class ImplicitActiveWorkbookReferenceInspection : IdentifierReferenceInspectionFromDeclarationsBase + internal sealed class ImplicitActiveWorkbookReferenceInspection : IdentifierReferenceInspectionFromDeclarationsBase { public ImplicitActiveWorkbookReferenceInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs index c8b8340064..049f9215e1 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs @@ -45,7 +45,7 @@ namespace Rubberduck.Inspections.Concrete /// [RequiredHost("EXCEL.EXE")] [RequiredLibrary("Excel")] - public class SheetAccessedUsingStringInspection : IdentifierReferenceInspectionFromDeclarationsBase + internal class SheetAccessedUsingStringInspection : IdentifierReferenceInspectionFromDeclarationsBase { private readonly IProjectsProvider _projectsProvider; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueAlwaysDiscardedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueAlwaysDiscardedInspection.cs index f0464e1b96..4a3c7dbee5 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueAlwaysDiscardedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueAlwaysDiscardedInspection.cs @@ -47,7 +47,7 @@ namespace Rubberduck.Inspections.Concrete /// End Function /// ]]> /// - public sealed class FunctionReturnValueAlwaysDiscardedInspection : DeclarationInspectionBase + internal sealed class FunctionReturnValueAlwaysDiscardedInspection : DeclarationInspectionBase { public FunctionReturnValueAlwaysDiscardedInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, DeclarationType.Function) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueDiscardedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueDiscardedInspection.cs index 7f0ea6e2f0..e407a4d858 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueDiscardedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueDiscardedInspection.cs @@ -39,7 +39,7 @@ namespace Rubberduck.Inspections.Concrete /// End Function /// ]]> /// - public sealed class FunctionReturnValueDiscardedInspection : IdentifierReferenceInspectionBase + internal sealed class FunctionReturnValueDiscardedInspection : IdentifierReferenceInspectionBase { public FunctionReturnValueDiscardedInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/HostSpecificExpressionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/HostSpecificExpressionInspection.cs index 7b4c30247c..83fd3f07f0 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/HostSpecificExpressionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/HostSpecificExpressionInspection.cs @@ -27,7 +27,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class HostSpecificExpressionInspection : DeclarationInspectionBase + internal sealed class HostSpecificExpressionInspection : DeclarationInspectionBase { public HostSpecificExpressionInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, DeclarationType.BracketedExpression) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/HungarianNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/HungarianNotationInspection.cs index 521bd9f0d2..e8722cd3dd 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/HungarianNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/HungarianNotationInspection.cs @@ -43,7 +43,7 @@ namespace Rubberduck.Inspections.Concrete /// End Function /// ]]> /// - public sealed class HungarianNotationInspection : DeclarationInspectionUsingGlobalInformationBase> + internal sealed class HungarianNotationInspection : DeclarationInspectionUsingGlobalInformationBase> { private static readonly DeclarationType[] TargetDeclarationTypes = new [] { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs index 50c4a41f68..83070c64ea 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs @@ -41,7 +41,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class IllegalAnnotationInspection : InspectionBase + internal sealed class IllegalAnnotationInspection : InspectionBase { public IllegalAnnotationInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplementedInterfaceMemberInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplementedInterfaceMemberInspection.cs index 82a9590012..f20307598d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplementedInterfaceMemberInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplementedInterfaceMemberInspection.cs @@ -36,7 +36,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - internal class ImplementedInterfaceMemberInspection : DeclarationInspectionBase + internal sealed class ImplementedInterfaceMemberInspection : DeclarationInspectionBase { public ImplementedInterfaceMemberInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, DeclarationType.ClassModule) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitByRefModifierInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitByRefModifierInspection.cs index 25e4fd46a8..a55df0168d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitByRefModifierInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitByRefModifierInspection.cs @@ -27,7 +27,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ImplicitByRefModifierInspection : DeclarationInspectionBase + internal sealed class ImplicitByRefModifierInspection : DeclarationInspectionBase { public ImplicitByRefModifierInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, DeclarationType.Parameter) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs index 8a5029ebb6..d66217a75e 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs @@ -47,7 +47,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ImplicitDefaultMemberAccessInspection : IdentifierReferenceInspectionBase + internal sealed class ImplicitDefaultMemberAccessInspection : IdentifierReferenceInspectionBase { public ImplicitDefaultMemberAccessInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitPublicMemberInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitPublicMemberInspection.cs index 8d513ca519..d88fd064e9 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitPublicMemberInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitPublicMemberInspection.cs @@ -27,7 +27,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ImplicitPublicMemberInspection : DeclarationInspectionBase + internal sealed class ImplicitPublicMemberInspection : DeclarationInspectionBase { public ImplicitPublicMemberInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, ProcedureTypes) { } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs index 4cd940d458..2bb9907dad 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs @@ -67,7 +67,7 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// /// - public sealed class ImplicitRecursiveDefaultMemberAccessInspection : IdentifierReferenceInspectionBase + internal sealed class ImplicitRecursiveDefaultMemberAccessInspection : IdentifierReferenceInspectionBase { public ImplicitRecursiveDefaultMemberAccessInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs index df8f98abe1..04489437da 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs @@ -50,7 +50,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ImplicitUnboundDefaultMemberAccessInspection : IdentifierReferenceInspectionBase + internal sealed class ImplicitUnboundDefaultMemberAccessInspection : IdentifierReferenceInspectionBase { public ImplicitUnboundDefaultMemberAccessInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitVariantReturnTypeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitVariantReturnTypeInspection.cs index d2892ebec7..a5f59e87a9 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitVariantReturnTypeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitVariantReturnTypeInspection.cs @@ -25,7 +25,7 @@ namespace Rubberduck.Inspections.Concrete /// End Function /// ]]> /// - public sealed class ImplicitVariantReturnTypeInspection : ImplicitTypeInspectionBase + internal sealed class ImplicitVariantReturnTypeInspection : ImplicitTypeInspectionBase { public ImplicitVariantReturnTypeInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, DeclarationType.Function) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs index a54da4f18b..8c1f956392 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs @@ -26,7 +26,7 @@ namespace Rubberduck.Inspections.Concrete /// Const myInteger% = 12345 /// ]]> /// - public sealed class ImplicitlyTypedConstInspection : ImplicitTypeInspectionBase + internal sealed class ImplicitlyTypedConstInspection : ImplicitTypeInspectionBase { public ImplicitlyTypedConstInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, DeclarationType.Constant) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs index 32331e845f..7ea1385be5 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs @@ -31,7 +31,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class IndexedDefaultMemberAccessInspection : IdentifierReferenceInspectionBase + internal sealed class IndexedDefaultMemberAccessInspection : IdentifierReferenceInspectionBase { public IndexedDefaultMemberAccessInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs index 15e9d41f97..b702aeea69 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs @@ -31,7 +31,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class IndexedRecursiveDefaultMemberAccessInspection : IdentifierReferenceInspectionBase + internal sealed class IndexedRecursiveDefaultMemberAccessInspection : IdentifierReferenceInspectionBase { public IndexedRecursiveDefaultMemberAccessInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs index 4acdd7553e..06619a07fd 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs @@ -34,7 +34,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class IndexedUnboundDefaultMemberAccessInspection : IdentifierReferenceInspectionBase + internal sealed class IndexedUnboundDefaultMemberAccessInspection : IdentifierReferenceInspectionBase { public IndexedUnboundDefaultMemberAccessInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IntegerDataTypeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IntegerDataTypeInspection.cs index 2b09a43ea9..7fe4053901 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IntegerDataTypeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IntegerDataTypeInspection.cs @@ -30,7 +30,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class IntegerDataTypeInspection : DeclarationInspectionBase + internal sealed class IntegerDataTypeInspection : DeclarationInspectionBase { public IntegerDataTypeInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs index b53201a9dc..cfa4973ba9 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs @@ -30,7 +30,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public class IsMissingOnInappropriateArgumentInspection : IsMissingInspectionBase + internal class IsMissingOnInappropriateArgumentInspection : IsMissingInspectionBase { public IsMissingOnInappropriateArgumentInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs index 0847e0762f..44e63c57ef 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs @@ -30,7 +30,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public class IsMissingWithNonArgumentParameterInspection : IsMissingInspectionBase + internal class IsMissingWithNonArgumentParameterInspection : IsMissingInspectionBase { public IsMissingWithNonArgumentParameterInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/LineLabelNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/LineLabelNotUsedInspection.cs index c7553c2d71..f8a2300a7f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/LineLabelNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/LineLabelNotUsedInspection.cs @@ -38,7 +38,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class LineLabelNotUsedInspection : DeclarationInspectionBase + internal sealed class LineLabelNotUsedInspection : DeclarationInspectionBase { public LineLabelNotUsedInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, DeclarationType.LineLabel) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MemberNotOnInterfaceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MemberNotOnInterfaceInspection.cs index 5804105ae6..1f9f0cd853 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MemberNotOnInterfaceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MemberNotOnInterfaceInspection.cs @@ -37,7 +37,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class MemberNotOnInterfaceInspection : DeclarationInspectionBase + internal sealed class MemberNotOnInterfaceInspection : DeclarationInspectionBase { public MemberNotOnInterfaceInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs index e6eb5aba0a..509aa82245 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs @@ -35,7 +35,7 @@ namespace Rubberduck.Inspections.Concrete /// ' ... /// ]]> /// - public sealed class MissingAnnotationArgumentInspection : InspectionBase + internal sealed class MissingAnnotationArgumentInspection : InspectionBase { public MissingAnnotationArgumentInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAttributeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAttributeInspection.cs index 054b31cb19..31e49f1e4c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAttributeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAttributeInspection.cs @@ -36,7 +36,7 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [CannotAnnotate] - public sealed class MissingAttributeInspection : DeclarationInspectionMultiResultBase + internal sealed class MissingAttributeInspection : DeclarationInspectionMultiResultBase { public MissingAttributeInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingMemberAnnotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingMemberAnnotationInspection.cs index 677020302c..d8e0b44899 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingMemberAnnotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingMemberAnnotationInspection.cs @@ -34,7 +34,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class MissingMemberAnnotationInspection : DeclarationInspectionMultiResultBase<(string AttributeName, IReadOnlyList AttriguteValues)> + internal sealed class MissingMemberAnnotationInspection : DeclarationInspectionMultiResultBase<(string AttributeName, IReadOnlyList AttriguteValues)> { public MissingMemberAnnotationInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, new DeclarationType[0], new []{DeclarationType.Module }) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingModuleAnnotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingModuleAnnotationInspection.cs index 263f984c90..bcb493dd22 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingModuleAnnotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingModuleAnnotationInspection.cs @@ -31,7 +31,7 @@ namespace Rubberduck.Inspections.Concrete /// ' ... /// ]]> /// - public sealed class MissingModuleAnnotationInspection : DeclarationInspectionMultiResultBase<(string AttributeName, IReadOnlyList AttributeValues)> + internal sealed class MissingModuleAnnotationInspection : DeclarationInspectionMultiResultBase<(string AttributeName, IReadOnlyList AttributeValues)> { public MissingModuleAnnotationInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, new []{DeclarationType.Module}, new []{DeclarationType.Document}) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs index 3e8f0c2888..734f39484d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs @@ -29,7 +29,7 @@ namespace Rubberduck.Inspections.Concrete /// ' ... /// ]]> /// - public sealed class ModuleScopeDimKeywordInspection : ParseTreeInspectionBase + internal sealed class ModuleScopeDimKeywordInspection : ParseTreeInspectionBase { public ModuleScopeDimKeywordInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleWithoutFolderInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleWithoutFolderInspection.cs index d7adcf6aed..8eaa0ae81c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleWithoutFolderInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleWithoutFolderInspection.cs @@ -28,7 +28,7 @@ namespace Rubberduck.Inspections.Concrete /// ' ... /// ]]> /// - public sealed class ModuleWithoutFolderInspection : DeclarationInspectionBase + internal sealed class ModuleWithoutFolderInspection : DeclarationInspectionBase { public ModuleWithoutFolderInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, DeclarationType.Module) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MoveFieldCloserToUsageInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MoveFieldCloserToUsageInspection.cs index d238424760..4224993d5d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MoveFieldCloserToUsageInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MoveFieldCloserToUsageInspection.cs @@ -36,7 +36,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class MoveFieldCloserToUsageInspection : DeclarationInspectionBase + internal sealed class MoveFieldCloserToUsageInspection : DeclarationInspectionBase { public MoveFieldCloserToUsageInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, DeclarationType.Variable) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs index daf865cb8f..033ee97122 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs @@ -30,7 +30,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class MultilineParameterInspection : ParseTreeInspectionBase + internal sealed class MultilineParameterInspection : ParseTreeInspectionBase { public MultilineParameterInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs index cf9f7fb34d..a1789bbc96 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs @@ -26,7 +26,7 @@ namespace Rubberduck.Inspections.Concrete /// Dim bar As Long /// ]]> /// - public sealed class MultipleDeclarationsInspection : ParseTreeInspectionBase + internal sealed class MultipleDeclarationsInspection : ParseTreeInspectionBase { public MultipleDeclarationsInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/NonReturningFunctionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/NonReturningFunctionInspection.cs index 61806cdfef..ec3b85c950 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/NonReturningFunctionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/NonReturningFunctionInspection.cs @@ -33,7 +33,7 @@ namespace Rubberduck.Inspections.Concrete /// End Function /// ]]> /// - public sealed class NonReturningFunctionInspection : DeclarationInspectionBase + internal sealed class NonReturningFunctionInspection : DeclarationInspectionBase { public NonReturningFunctionInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, DeclarationType.Function) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs index 54ca0f318b..64ce6d3644 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs @@ -38,7 +38,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ObjectVariableNotSetInspection : IdentifierReferenceInspectionBase + internal sealed class ObjectVariableNotSetInspection : IdentifierReferenceInspectionBase { public ObjectVariableNotSetInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs index 518ad1f241..50b433e564 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs @@ -53,7 +53,7 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// /// - public sealed class ObjectWhereProcedureIsRequiredInspection : InspectionBase + internal sealed class ObjectWhereProcedureIsRequiredInspection : InspectionBase { public ObjectWhereProcedureIsRequiredInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs index 92f406e7a3..50b01771c9 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs @@ -36,7 +36,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ObsoleteCallStatementInspection : ParseTreeInspectionBase + internal sealed class ObsoleteCallStatementInspection : ParseTreeInspectionBase { public ObsoleteCallStatementInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs index 12b9adfa3b..c4d37bb3e2 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs @@ -25,7 +25,7 @@ namespace Rubberduck.Inspections.Inspections.Concrete /// Private Declare Sub Beep Lib "kernel32" (dwFreq As Any, dwDuration As Any) /// ]]> /// - public sealed class ObsoleteCallingConventionInspection : ParseTreeInspectionBase + internal sealed class ObsoleteCallingConventionInspection : ParseTreeInspectionBase { public ObsoleteCallingConventionInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs index cb63e95d53..09cb4f3b35 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs @@ -27,7 +27,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ObsoleteCommentSyntaxInspection : ParseTreeInspectionBase + internal sealed class ObsoleteCommentSyntaxInspection : ParseTreeInspectionBase { public ObsoleteCommentSyntaxInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs index 21f13d8637..1c3b9af6ec 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs @@ -27,7 +27,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ObsoleteErrorSyntaxInspection : ParseTreeInspectionBase + internal sealed class ObsoleteErrorSyntaxInspection : ParseTreeInspectionBase { public ObsoleteErrorSyntaxInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteGlobalInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteGlobalInspection.cs index 65149ac67e..3ed3963886 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteGlobalInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteGlobalInspection.cs @@ -25,7 +25,7 @@ namespace Rubberduck.Inspections.Concrete /// Public Foo As Long /// ]]> /// - public sealed class ObsoleteGlobalInspection : DeclarationInspectionBase + internal sealed class ObsoleteGlobalInspection : DeclarationInspectionBase { public ObsoleteGlobalInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs index 4ca5292265..596ba76ff1 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs @@ -29,7 +29,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ObsoleteLetStatementInspection : ParseTreeInspectionBase + internal sealed class ObsoleteLetStatementInspection : ParseTreeInspectionBase { public ObsoleteLetStatementInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs index 4929affd1a..b1ef32794f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs @@ -46,7 +46,7 @@ namespace Rubberduck.Inspections.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ObsoleteMemberUsageInspection : IdentifierReferenceInspectionBase + internal sealed class ObsoleteMemberUsageInspection : IdentifierReferenceInspectionBase { public ObsoleteMemberUsageInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs index dc954e775d..25f44c6fdd 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs @@ -33,7 +33,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ObsoleteTypeHintInspection : InspectionBase + internal sealed class ObsoleteTypeHintInspection : InspectionBase { public ObsoleteTypeHintInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs index 518d1e33f3..2203e98b82 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs @@ -32,7 +32,7 @@ namespace Rubberduck.CodeAnalysis.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ObsoleteWhileWendStatementInspection : ParseTreeInspectionBase + internal sealed class ObsoleteWhileWendStatementInspection : ParseTreeInspectionBase { public ObsoleteWhileWendStatementInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs index 21ba603b8d..548d5e061c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs @@ -36,7 +36,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class OnLocalErrorInspection : ParseTreeInspectionBase + internal sealed class OnLocalErrorInspection : ParseTreeInspectionBase { public OnLocalErrorInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs index 9362f21989..c276bc726e 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs @@ -36,7 +36,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class OptionBaseInspection : ParseTreeInspectionBase + internal sealed class OptionBaseInspection : ParseTreeInspectionBase { public OptionBaseInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs index 4724806eb7..7c0dd31f8a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs @@ -36,7 +36,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class OptionExplicitInspection : ParseTreeInspectionBase + internal sealed class OptionExplicitInspection : ParseTreeInspectionBase { public OptionExplicitInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterCanBeByValInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterCanBeByValInspection.cs index f70dbe005f..35a298489d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterCanBeByValInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterCanBeByValInspection.cs @@ -35,7 +35,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ParameterCanBeByValInspection : DeclarationInspectionBase + internal sealed class ParameterCanBeByValInspection : DeclarationInspectionBase { public ParameterCanBeByValInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, DeclarationType.Parameter) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterNotUsedInspection.cs index fa1f9df638..8532c77866 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterNotUsedInspection.cs @@ -36,7 +36,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ParameterNotUsedInspection : DeclarationInspectionBase + internal sealed class ParameterNotUsedInspection : DeclarationInspectionBase { public ParameterNotUsedInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, DeclarationType.Parameter) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureCanBeWrittenAsFunctionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureCanBeWrittenAsFunctionInspection.cs index f4bb134eeb..6e7314c4f0 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureCanBeWrittenAsFunctionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureCanBeWrittenAsFunctionInspection.cs @@ -44,7 +44,7 @@ namespace Rubberduck.Inspections.Concrete /// End Function /// ]]> /// - public sealed class ProcedureCanBeWrittenAsFunctionInspection : DeclarationInspectionBase + internal sealed class ProcedureCanBeWrittenAsFunctionInspection : DeclarationInspectionBase { public ProcedureCanBeWrittenAsFunctionInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, new []{DeclarationType.Procedure}, new []{DeclarationType.LibraryProcedure, DeclarationType.PropertyLet, DeclarationType.PropertySet}) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs index d1a291ea6f..f2e72f1fa1 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs @@ -40,7 +40,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ProcedureNotUsedInspection : DeclarationInspectionBase + internal sealed class ProcedureNotUsedInspection : DeclarationInspectionBase { public ProcedureNotUsedInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, ProcedureTypes) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs index 6c8599be27..8e0165e28b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs @@ -51,7 +51,7 @@ namespace Rubberduck.CodeAnalysis.Inspections.Concrete /// End Sub /// ]]> /// - public class ProcedureRequiredInspection : IdentifierReferenceInspectionBase + internal class ProcedureRequiredInspection : IdentifierReferenceInspectionBase { public ProcedureRequiredInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantByRefModifierInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantByRefModifierInspection.cs index fca99f3439..1afdc52aea 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantByRefModifierInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantByRefModifierInspection.cs @@ -32,7 +32,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class RedundantByRefModifierInspection : DeclarationInspectionBase + internal sealed class RedundantByRefModifierInspection : DeclarationInspectionBase { public RedundantByRefModifierInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, DeclarationType.Parameter) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs index a981a59ede..df71f002fd 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs @@ -33,7 +33,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class RedundantOptionInspection : ParseTreeInspectionBase + internal sealed class RedundantOptionInspection : ParseTreeInspectionBase { public RedundantOptionInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SelfAssignedDeclarationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SelfAssignedDeclarationInspection.cs index a5175d1de7..e864cc4b02 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SelfAssignedDeclarationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SelfAssignedDeclarationInspection.cs @@ -40,7 +40,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class SelfAssignedDeclarationInspection : DeclarationInspectionBase + internal sealed class SelfAssignedDeclarationInspection : DeclarationInspectionBase { public SelfAssignedDeclarationInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, DeclarationType.Variable) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs index 46ccbdaa5c..696278c40c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs @@ -12,67 +12,67 @@ namespace Rubberduck.CodeAnalysis.Inspections.Concrete { - /// - /// Locates assignments to object variables for which the RHS does not have a compatible declared type. - /// - /// - /// The VBA compiler does not check whether different object types are compatible. Instead there is a runtime error whenever the types are incompatible. - /// - /// - /// - /// - /// - /// - /// - public class SetAssignmentWithIncompatibleObjectTypeInspection : IdentifierReferenceInspectionBase + /// + /// Locates assignments to object variables for which the RHS does not have a compatible declared type. + /// + /// + /// The VBA compiler does not check whether different object types are compatible. Instead there is a runtime error whenever the types are incompatible. + /// + /// + /// + /// + /// + /// + /// + internal class SetAssignmentWithIncompatibleObjectTypeInspection : IdentifierReferenceInspectionBase { private readonly ISetTypeResolver _setTypeResolver; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ShadowedDeclarationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ShadowedDeclarationInspection.cs index d6551e659d..188aa8cdfa 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ShadowedDeclarationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ShadowedDeclarationInspection.cs @@ -39,7 +39,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class ShadowedDeclarationInspection : DeclarationInspectionUsingGlobalInformationBase>, Declaration> + internal sealed class ShadowedDeclarationInspection : DeclarationInspectionUsingGlobalInformationBase>, Declaration> { private enum DeclarationSite { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs index 351a5f9090..22bfd5b075 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs @@ -35,7 +35,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class StepIsNotSpecifiedInspection : ParseTreeInspectionBase + internal sealed class StepIsNotSpecifiedInspection : ParseTreeInspectionBase { public StepIsNotSpecifiedInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs index a5d16d7457..7c50d002f5 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs @@ -35,7 +35,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class StepOneIsRedundantInspection : ParseTreeInspectionBase + internal sealed class StepOneIsRedundantInspection : ParseTreeInspectionBase { public StepOneIsRedundantInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs index e7c5eb6a36..add6051547 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs @@ -32,7 +32,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class StopKeywordInspection : ParseTreeInspectionBase + internal sealed class StopKeywordInspection : ParseTreeInspectionBase { public StopKeywordInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuperfluousAnnotationArgumentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuperfluousAnnotationArgumentInspection.cs index fc298ea15d..526bef21ca 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuperfluousAnnotationArgumentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuperfluousAnnotationArgumentInspection.cs @@ -36,7 +36,7 @@ namespace Rubberduck.Inspections.Concrete /// ' ... /// ]]> /// - public sealed class SuperfluousAnnotationArgumentInspection : InspectionBase + internal sealed class SuperfluousAnnotationArgumentInspection : InspectionBase { public SuperfluousAnnotationArgumentInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs index 551cdd196a..a10970e155 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs @@ -43,7 +43,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class SuspiciousLetAssignmentInspection : InspectionBase + internal sealed class SuspiciousLetAssignmentInspection : InspectionBase { public SuspiciousLetAssignmentInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/KeywordsUsedAsMemberInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/KeywordsUsedAsMemberInspection.cs index 5ff7a5e7c0..a74dff78ee 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/KeywordsUsedAsMemberInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/KeywordsUsedAsMemberInspection.cs @@ -19,7 +19,7 @@ namespace Rubberduck.Inspections.Inspections.Concrete.ThunderCode /// While perfectly legal as Type or Enum member names, these identifiers should be avoided: /// they need to be square-bracketed everywhere they are used. /// - public class KeywordsUsedAsMemberInspection : DeclarationInspectionBase + internal class KeywordsUsedAsMemberInspection : DeclarationInspectionBase { public KeywordsUsedAsMemberInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, DeclarationType.EnumerationMember, DeclarationType.UserDefinedTypeMember) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/LineContinuationBetweenKeywordsInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/LineContinuationBetweenKeywordsInspection.cs index 8c447da2a1..456405e96d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/LineContinuationBetweenKeywordsInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/LineContinuationBetweenKeywordsInspection.cs @@ -21,7 +21,7 @@ namespace Rubberduck.Inspections.Inspections.Concrete.ThunderCode /// Note that the inspection only checks a subset of possible "evil" line continatuions /// for both simplicity and performance reasons. Exhaustive inspection would likely take too much effort. /// - public sealed class LineContinuationBetweenKeywordsInspection : ParseTreeInspectionBase + internal sealed class LineContinuationBetweenKeywordsInspection : ParseTreeInspectionBase { public LineContinuationBetweenKeywordsInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NegativeLineNumberInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NegativeLineNumberInspection.cs index ebcc48793f..cc214e373c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NegativeLineNumberInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NegativeLineNumberInspection.cs @@ -17,7 +17,7 @@ namespace Rubberduck.Inspections.Inspections.Concrete.ThunderCode /// code our friend Andrew Jackson would have written to confuse Rubberduck's parser and/or resolver. /// The VBE does allow rather strange and unbelievable things to happen. /// - public sealed class NegativeLineNumberInspection : ParseTreeInspectionBase + internal sealed class NegativeLineNumberInspection : ParseTreeInspectionBase { public NegativeLineNumberInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NonBreakingSpaceIdentifierInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NonBreakingSpaceIdentifierInspection.cs index c6056217b0..4187da22dd 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NonBreakingSpaceIdentifierInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NonBreakingSpaceIdentifierInspection.cs @@ -14,7 +14,7 @@ namespace Rubberduck.Inspections.Inspections.Concrete.ThunderCode /// code our friend Andrew Jackson would have written to confuse Rubberduck's parser and/or resolver. /// This inspection may accidentally reveal non-breaking spaces in code copied and pasted from a website. /// - public class NonBreakingSpaceIdentifierInspection : DeclarationInspectionBase + internal class NonBreakingSpaceIdentifierInspection : DeclarationInspectionBase { private const string Nbsp = "\u00A0"; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs index a5fcff9c07..1a8aa0592f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs @@ -16,7 +16,7 @@ namespace Rubberduck.Inspections.Inspections.Concrete.ThunderCode /// code our friend Andrew Jackson would have written to confuse Rubberduck's parser and/or resolver. /// 'On Error GoTo -1' is poorly documented and uselessly complicates error handling. /// - public sealed class OnErrorGoToMinusOneInspection : ParseTreeInspectionBase + internal sealed class OnErrorGoToMinusOneInspection : ParseTreeInspectionBase { public OnErrorGoToMinusOneInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/ThunderCodeFormatExtension.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/ThunderCodeFormatExtension.cs index ee9581268b..2ee9ecd92e 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/ThunderCodeFormatExtension.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/ThunderCodeFormatExtension.cs @@ -2,7 +2,7 @@ namespace Rubberduck.Inspections.Inspections.Concrete.ThunderCode { - public static class ThunderCodeFormatExtension + internal static class ThunderCodeFormatExtension { public static string ThunderCodeFormat(this string inspectionBase, params object[] args) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs index 9e0e1964ee..468c5d23c0 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnassignedVariableUsageInspection.cs @@ -41,7 +41,7 @@ namespace Rubberduck.Inspections.Concrete /// ]]> /// [SuppressMessage("ReSharper", "LoopCanBeConvertedToQuery")] - public sealed class UnassignedVariableUsageInspection : IdentifierReferenceInspectionFromDeclarationsBase + internal sealed class UnassignedVariableUsageInspection : IdentifierReferenceInspectionFromDeclarationsBase { public UnassignedVariableUsageInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UndeclaredVariableInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UndeclaredVariableInspection.cs index d6103d4bf6..8e9caecf99 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UndeclaredVariableInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UndeclaredVariableInspection.cs @@ -29,7 +29,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class UndeclaredVariableInspection : DeclarationInspectionBase + internal sealed class UndeclaredVariableInspection : DeclarationInspectionBase { public UndeclaredVariableInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, DeclarationType.Variable) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnderscoreInPublicClassModuleMemberInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnderscoreInPublicClassModuleMemberInspection.cs index 7d7fb88106..012d54328a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnderscoreInPublicClassModuleMemberInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnderscoreInPublicClassModuleMemberInspection.cs @@ -29,7 +29,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class UnderscoreInPublicClassModuleMemberInspection : DeclarationInspectionBase + internal sealed class UnderscoreInPublicClassModuleMemberInspection : DeclarationInspectionBase { public UnderscoreInPublicClassModuleMemberInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, DeclarationType.Member) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs index 625dce6b4e..c58a977acb 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs @@ -36,7 +36,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class UnhandledOnErrorResumeNextInspection : ParseTreeInspectionBase> + internal sealed class UnhandledOnErrorResumeNextInspection : ParseTreeInspectionBase> { private readonly OnErrorStatementListener _listener = new OnErrorStatementListener(); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ComparableDateValue.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ComparableDateValue.cs index db85d8e6d8..6f86956fcc 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ComparableDateValue.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ComparableDateValue.cs @@ -7,7 +7,7 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { - public class ComparableDateValue : IValue, IComparable + internal class ComparableDateValue : IValue, IComparable { private readonly DateValue _dateValue; private readonly int _hashCode; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilter.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilter.cs index 5b73fe5396..c0525134a7 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilter.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilter.cs @@ -7,7 +7,7 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { - public enum VariableClauseTypes + internal enum VariableClauseTypes { Predicate, Value, @@ -15,7 +15,7 @@ public enum VariableClauseTypes Is }; - public interface IExpressionFilter + internal interface IExpressionFilter { void CheckAndAddExpression(IRangeClauseExpression expression); void AddComparablePredicateFilter(string variable, string variableTypeName); @@ -24,7 +24,7 @@ public interface IExpressionFilter IParseTreeValue SelectExpressionValue { set; get; } } - public class ExpressionFilter : IExpressionFilter where T : IComparable + internal class ExpressionFilter : IExpressionFilter where T : IComparable { private struct PredicateValueExpression { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilterBoolean.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilterBoolean.cs index 4fe5c58d51..6a80932f6d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilterBoolean.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilterBoolean.cs @@ -2,7 +2,7 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { - public class ExpressionFilterBoolean : ExpressionFilter + internal class ExpressionFilterBoolean : ExpressionFilter { public ExpressionFilterBoolean() : base(Tokens.Boolean, (a) => { return a.Equals(Tokens.True); }) { } @@ -73,26 +73,31 @@ private bool AddIsClause(bool isValue, IRangeClauseExpression expression) { return AddSingleValue(!isValue); } - else if (opSymbol.Equals(RelationalOperators.EQ)) + + if (opSymbol.Equals(RelationalOperators.EQ)) { return AddSingleValue(isValue); } - else if (opSymbol.Equals(RelationalOperators.GT)) + + if (opSymbol.Equals(RelationalOperators.GT)) { expression.IsInherentlyUnreachable = !isValue; return isValue ? AddComparablePredicate(Tokens.Is, expression) : false; } - else if (opSymbol.Equals(RelationalOperators.GTE) || opSymbol.Equals(RelationalOperators.GTE2)) + + if (opSymbol.Equals(RelationalOperators.GTE) || opSymbol.Equals(RelationalOperators.GTE2)) { return isValue ? AddTrueAndFalse() //True for selectExpr value of True or False : AddComparablePredicate(Tokens.Is, expression); } - else if (opSymbol.Equals(RelationalOperators.LT)) + + if (opSymbol.Equals(RelationalOperators.LT)) { expression.IsInherentlyUnreachable = isValue; return isValue ? false : AddComparablePredicate(Tokens.Is, expression); } - else if (opSymbol.Equals(RelationalOperators.LTE) || opSymbol.Equals(RelationalOperators.LTE2)) + + if (opSymbol.Equals(RelationalOperators.LTE) || opSymbol.Equals(RelationalOperators.LTE2)) { return isValue ? AddComparablePredicate(Tokens.Is, expression) : AddTrueAndFalse(); //True for selectExpr value of True or False @@ -105,18 +110,21 @@ private bool AddIsClause(bool isValue, IRangeClauseExpression expression) { return AddSingleValue(selectExpr != isValue); } - else if (opSymbol.Equals(RelationalOperators.EQ)) + + if (opSymbol.Equals(RelationalOperators.EQ)) { return AddSingleValue(selectExpr == isValue); } - else if (opSymbol.Equals(RelationalOperators.GT)) + + if (opSymbol.Equals(RelationalOperators.GT)) { //if Is > True and the selectExpr is False => True //If Is > True and the selectExpr is True => False expression.IsInherentlyUnreachable = !isValue; return isValue ? AddSingleValue(!selectExpr) : false; } - else if (opSymbol.Equals(RelationalOperators.GTE) || opSymbol.Equals(RelationalOperators.GTE2)) + + if (opSymbol.Equals(RelationalOperators.GTE) || opSymbol.Equals(RelationalOperators.GTE2)) { //if Is >= True and the selectExpr is False => True //If Is >= True and the selectExpr is True => True @@ -124,12 +132,14 @@ private bool AddIsClause(bool isValue, IRangeClauseExpression expression) //If Is >= False and the selectExpr is True => False return AddSingleValue(!(!isValue && selectExpr)); } - else if (opSymbol.Equals(RelationalOperators.LT)) + + if (opSymbol.Equals(RelationalOperators.LT)) { expression.IsInherentlyUnreachable = isValue; return isValue ? false : AddSingleValue(selectExpr); } - else if (opSymbol.Equals(RelationalOperators.LTE) || opSymbol.Equals(RelationalOperators.LTE2)) + + if (opSymbol.Equals(RelationalOperators.LTE) || opSymbol.Equals(RelationalOperators.LTE2)) { //if Is <= True and the selectExpr is False => False //If Is <= True and the selectExpr is True => True @@ -138,6 +148,7 @@ private bool AddIsClause(bool isValue, IRangeClauseExpression expression) return AddSingleValue(!(isValue && !selectExpr)); } } + return false; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilterDate.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilterDate.cs index 55714c3301..7ead448cd7 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilterDate.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilterDate.cs @@ -4,7 +4,7 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { - public class ExpressionFilterDate : ExpressionFilter + internal class ExpressionFilterDate : ExpressionFilter { public ExpressionFilterDate() : base(Tokens.Date, ComparableDateValue.Parse) { } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilterFactory.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilterFactory.cs index af1447dd65..391f1705f1 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilterFactory.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilterFactory.cs @@ -7,7 +7,7 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection{ - public static class ExpressionFilterFactory + internal static class ExpressionFilterFactory { private static readonly Dictionary IntegralNumberExtents = new Dictionary() { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilterIntegral.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilterIntegral.cs index 4d751a85d2..074722a756 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilterIntegral.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilterIntegral.cs @@ -4,7 +4,7 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { - public class ExpressionFilterIntegral : ExpressionFilter + internal class ExpressionFilterIntegral : ExpressionFilter { public ExpressionFilterIntegral(string valueType, Func parser) : base(valueType, parser) { } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/FilterLimits.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/FilterLimits.cs index a2ec8ed867..ba6de7df0c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/FilterLimits.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/FilterLimits.cs @@ -2,7 +2,7 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { - public struct Limit where T : IComparable + internal struct Limit where T : IComparable { public bool HasValue; public T Value; @@ -61,7 +61,7 @@ public override string ToString() } } - public class FilterLimits where T : IComparable + internal class FilterLimits where T : IComparable { private Limit _min; private Limit _max; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/LetCoerce.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/LetCoerce.cs index e65bab587c..560b00a428 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/LetCoerce.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/LetCoerce.cs @@ -6,7 +6,7 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { - public struct VBACurrency + internal struct VBACurrency { public static decimal MinValue = -922337203685477.5808M; public static decimal MaxValue = 922337203685477.5807M; @@ -36,7 +36,7 @@ public static bool TryParse(string valueText, out decimal value) } } - public struct LetCoerce + internal struct LetCoerce { //Content: Dictionary private static Dictionary>> _coercions = new Dictionary>> diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/OperatorTypesProvider.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/OperatorTypesProvider.cs index bb7d238f59..ea43ab7758 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/OperatorTypesProvider.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/OperatorTypesProvider.cs @@ -5,7 +5,7 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { - public class OperatorTypesProvider + internal class OperatorTypesProvider { private readonly (string lhs, string rhs) _operandTypeNames; private readonly string _opSymbol; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeExpressionEvaluator.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeExpressionEvaluator.cs index 0b03c46d84..49fdbc8d75 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeExpressionEvaluator.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeExpressionEvaluator.cs @@ -8,13 +8,13 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { - public interface IParseTreeExpressionEvaluator + internal interface IParseTreeExpressionEvaluator { IParseTreeValue Evaluate(IParseTreeValue LHS, IParseTreeValue RHS, string opSymbol); IParseTreeValue Evaluate(IParseTreeValue LHS, string opSymbol); } - public class ParseTreeExpressionEvaluator : IParseTreeExpressionEvaluator + internal class ParseTreeExpressionEvaluator : IParseTreeExpressionEvaluator { private readonly IParseTreeValueFactory _valueFactory; private readonly bool _isOptionCompareBinary; @@ -105,7 +105,8 @@ private IParseTreeValue EvaluateRelationalOp(string opSymbol, IParseTreeValue LH : Compare(LHS, RHS, (decimal a, decimal b) => { return a == b; }, (double a, double b) => { return a == b; }); return _valueFactory.Create(result.Equals(Tokens.True)); } - else if (opSymbol.Equals(RelationalOperators.NEQ)) + + if (opSymbol.Equals(RelationalOperators.NEQ)) { if (opProvider.OperatorEffectiveType.Equals(Tokens.Boolean)) { @@ -116,7 +117,8 @@ private IParseTreeValue EvaluateRelationalOp(string opSymbol, IParseTreeValue LH : Compare(LHS, RHS, (decimal a, decimal b) => { return a != b; }, (double a, double b) => { return a != b; }); return _valueFactory.Create(result.Equals(Tokens.True)); } - else if (opSymbol.Equals(RelationalOperators.LT)) + + if (opSymbol.Equals(RelationalOperators.LT)) { if (opProvider.OperatorEffectiveType.Equals(Tokens.Boolean)) { @@ -127,7 +129,8 @@ private IParseTreeValue EvaluateRelationalOp(string opSymbol, IParseTreeValue LH : Compare(LHS, RHS, (decimal a, decimal b) => { return a < b; }, (double a, double b) => { return a < b; }); return _valueFactory.Create(result.Equals(Tokens.True)); } - else if (opSymbol.Equals(RelationalOperators.LTE) || opSymbol.Equals(RelationalOperators.LTE2)) + + if (opSymbol.Equals(RelationalOperators.LTE) || opSymbol.Equals(RelationalOperators.LTE2)) { if (opProvider.OperatorEffectiveType.Equals(Tokens.Boolean)) { @@ -138,7 +141,8 @@ private IParseTreeValue EvaluateRelationalOp(string opSymbol, IParseTreeValue LH : Compare(LHS, RHS, (decimal a, decimal b) => { return a <= b; }, (double a, double b) => { return a <= b; }); return _valueFactory.Create(result.Equals(Tokens.True)); } - else if (opSymbol.Equals(RelationalOperators.GT)) + + if (opSymbol.Equals(RelationalOperators.GT)) { if (opProvider.OperatorEffectiveType.Equals(Tokens.Boolean)) { @@ -149,7 +153,8 @@ private IParseTreeValue EvaluateRelationalOp(string opSymbol, IParseTreeValue LH : Compare(LHS, RHS, (decimal a, decimal b) => { return a > b; }, (double a, double b) => { return a > b; }); return _valueFactory.Create(result.Equals(Tokens.True)); } - else if (opSymbol.Equals(RelationalOperators.GTE) || opSymbol.Equals(RelationalOperators.GTE2)) + + if (opSymbol.Equals(RelationalOperators.GTE) || opSymbol.Equals(RelationalOperators.GTE2)) { if (opProvider.OperatorEffectiveType.Equals(Tokens.Boolean)) { @@ -160,7 +165,8 @@ private IParseTreeValue EvaluateRelationalOp(string opSymbol, IParseTreeValue LH : Compare(LHS, RHS, (decimal a, decimal b) => { return a >= b; }, (double a, double b) => { return a >= b; }); return _valueFactory.Create(result.Equals(Tokens.True)); } - else if (opSymbol.Equals(RelationalOperators.LIKE)) + + if (opSymbol.Equals(RelationalOperators.LIKE)) { if (RHS.Token.Equals("*")) { @@ -214,28 +220,32 @@ private IParseTreeValue EvaluateLogicalOperator(string opSymbol, IParseTreeValue : Calculate(LHS, RHS, (long a, long b) => { return a & b; }); return _valueFactory.CreateDeclaredType(result, opProvider.OperatorDeclaredType); } - else if (opSymbol.Equals(LogicalOperators.OR)) + + if (opSymbol.Equals(LogicalOperators.OR)) { var result = opProvider.OperatorDeclaredType.Equals(Tokens.Boolean) ? Calculate(LHS, RHS, (bool a, bool b) => { return a || b; }) : Calculate(LHS, RHS, (long a, long b) => { return a | b; }); return _valueFactory.CreateDeclaredType(result, opProvider.OperatorDeclaredType); } - else if (opSymbol.Equals(LogicalOperators.XOR)) + + if (opSymbol.Equals(LogicalOperators.XOR)) { var result = opProvider.OperatorDeclaredType.Equals(Tokens.Boolean) ? Calculate(LHS, RHS, (bool a, bool b) => { return a ^ b; }) : Calculate(LHS, RHS, (long a, long b) => { return a ^ b; }); return _valueFactory.CreateDeclaredType(result, opProvider.OperatorDeclaredType); } - else if (opSymbol.Equals(LogicalOperators.EQV)) + + if (opSymbol.Equals(LogicalOperators.EQV)) { var result = opProvider.OperatorDeclaredType.Equals(Tokens.Boolean) ? Calculate(LHS, RHS, (bool a, bool b) => { return Eqv(a, b); }) : Calculate(LHS, RHS, (long a, long b) => { return Eqv(a, b); }); return _valueFactory.CreateDeclaredType(result, opProvider.OperatorDeclaredType); } - else if (opSymbol.Equals(LogicalOperators.IMP)) + + if (opSymbol.Equals(LogicalOperators.IMP)) { var result = opProvider.OperatorDeclaredType.Equals(Tokens.Boolean) ? Calculate(LHS, RHS, (bool a, bool b) => { return Imp(a, b); }) @@ -301,14 +311,17 @@ private IParseTreeValue EvaluateArithmeticOp(string opSymbol, IParseTreeValue LH { return _valueFactory.CreateValueType(Calculate(effLHS, effRHS, (decimal a, decimal b) => a * b, (double a, double b) => a * b), opProvider.OperatorDeclaredType); } + if (opSymbol.Equals(ArithmeticOperators.DIVIDE)) { return _valueFactory.CreateValueType(Calculate(effLHS, effRHS, (decimal a, decimal b) => a / b, (double a, double b) => a / b), opProvider.OperatorDeclaredType); } + if (opSymbol.Equals(ArithmeticOperators.INTEGER_DIVIDE)) { return _valueFactory.CreateValueType(Calculate(effLHS, effRHS, IntDivision, IntDivision), opProvider.OperatorDeclaredType); } + if (opSymbol.Equals(ArithmeticOperators.PLUS)) { if (opProvider.OperatorEffectiveType.Equals(Tokens.String)) @@ -322,6 +335,7 @@ private IParseTreeValue EvaluateArithmeticOp(string opSymbol, IParseTreeValue LH } return _valueFactory.CreateValueType(Calculate(effLHS, effRHS, (decimal a, decimal b) => a + b, (double a, double b) => a + b), opProvider.OperatorDeclaredType); } + if (opSymbol.Equals(ArithmeticOperators.MINUS)) { if (LHS.ValueType.Equals(Tokens.Date) && RHS.ValueType.Equals(Tokens.Date)) @@ -330,11 +344,13 @@ private IParseTreeValue EvaluateArithmeticOp(string opSymbol, IParseTreeValue LH } return _valueFactory.CreateValueType(Calculate(effLHS, effRHS, (decimal a, decimal b) => a - b, (double a, double b) => a - b), opProvider.OperatorDeclaredType); } + if (opSymbol.Equals(ArithmeticOperators.EXPONENT)) { //Math.Pow only takes doubles, so the decimal conversion option is null return _valueFactory.CreateValueType(Calculate(effLHS, effRHS, null, Math.Pow), opProvider.OperatorDeclaredType); } + if (opSymbol.Equals(ArithmeticOperators.MODULO)) { return _valueFactory.CreateValueType(Calculate(effLHS, effRHS, (decimal a, decimal b) => a % b, (double a, double b) => a % b), opProvider.OperatorDeclaredType); @@ -517,7 +533,7 @@ public static string ConvertLikePatternToRegexPattern(string likePattern) } } - public class ArithmeticOperators + internal class ArithmeticOperators { private static string _multiply; private static string _divide; @@ -565,7 +581,7 @@ private static string LoadSymbols(int target) } } - public class RelationalOperators + internal class RelationalOperators { private static string _lessThan; private static string _greaterThan; @@ -605,7 +621,7 @@ private static string LoadSymbols(int target) } } - public class LogicalOperators + internal class LogicalOperators { public static string AND => Tokens.And; public static string OR => Tokens.Or; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValue.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValue.cs index 70aae8595e..3a635f5ed8 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValue.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValue.cs @@ -6,7 +6,7 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { - public interface IParseTreeValue + internal interface IParseTreeValue { string Token { get; } string ValueType { get; } @@ -15,7 +15,7 @@ public interface IParseTreeValue bool IsMismatchExpression { get; } } - public struct ParseTreeValue : IParseTreeValue + internal struct ParseTreeValue : IParseTreeValue { private readonly int _hashCode; private TypeTokenPair _typeTokenPair; @@ -180,7 +180,7 @@ public override int GetHashCode() private static bool IsStringConstant(string candidate) => candidate.StartsWith("\"") && candidate.EndsWith("\""); } - public static class ParseTreeValueExtensions + internal static class ParseTreeValueExtensions { public static bool TryLetCoerce(this IParseTreeValue parseTreeValue, string destinationType, out IParseTreeValue newValue) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueFactory.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueFactory.cs index 3277138930..cd9bb4b88c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueFactory.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueFactory.cs @@ -5,7 +5,7 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { - public interface IParseTreeValueFactory + internal interface IParseTreeValueFactory { IParseTreeValue CreateMismatchExpression(string expression, string typeName); IParseTreeValue CreateExpression(string expression, string typeName); @@ -23,7 +23,7 @@ public interface IParseTreeValueFactory IParseTreeValue CreateDate(double value); } - public class ParseTreeValueFactory : IParseTreeValueFactory + internal class ParseTreeValueFactory : IParseTreeValueFactory { public IParseTreeValue CreateValueType(string expression, string declaredTypeName) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs index bd46d9000c..fa3bc90ffa 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeValueVisitor.cs @@ -11,12 +11,12 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { - public interface IParseTreeValueVisitor + internal interface IParseTreeValueVisitor { IParseTreeVisitorResults VisitChildren(QualifiedModuleName module, IRuleNode node, DeclarationFinder finder); } - public class EnumMember + internal class EnumMember { public EnumMember(VBAParser.EnumerationStmt_ConstantContext constContext, long initValue) { @@ -29,7 +29,7 @@ public EnumMember(VBAParser.EnumerationStmt_ConstantContext constContext, long i public bool HasAssignment { get; } } - public class ParseTreeValueVisitor : IParseTreeValueVisitor + internal class ParseTreeValueVisitor : IParseTreeValueVisitor { private readonly IParseTreeValueFactory _valueFactory; private readonly Func _valueDeclarationEvaluator; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeVisitorResults.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeVisitorResults.cs index 9c150ba38e..cbd1808712 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeVisitorResults.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ParseTreeVisitorResults.cs @@ -6,7 +6,7 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { - public interface IParseTreeVisitorResults + internal interface IParseTreeVisitorResults { IParseTreeValue GetValue(ParserRuleContext context); List GetChildResults(ParserRuleContext parent); @@ -17,13 +17,13 @@ public interface IParseTreeVisitorResults bool TryGetEnumMembers(VBAParser.EnumerationStmtContext enumerationStmtContext, out IReadOnlyList enumMembers); } - public interface IMutableParseTreeVisitorResults : IParseTreeVisitorResults + internal interface IMutableParseTreeVisitorResults : IParseTreeVisitorResults { void AddIfNotPresent(ParserRuleContext context, IParseTreeValue value); void AddEnumMember(VBAParser.EnumerationStmtContext enumerationStmtContext, EnumMember enumMember); } - public class ParseTreeVisitorResults : IMutableParseTreeVisitorResults + internal class ParseTreeVisitorResults : IMutableParseTreeVisitorResults { private readonly Dictionary _parseTreeValues = new Dictionary(); private readonly Dictionary> _enumMembers = new Dictionary>(); diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/RangeClauseExpression.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/RangeClauseExpression.cs index 98c0e45f91..92c1eb5436 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/RangeClauseExpression.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/RangeClauseExpression.cs @@ -3,7 +3,7 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { - public interface IRangeClauseExpression + internal interface IRangeClauseExpression { IParseTreeValue RHS { get; } IParseTreeValue LHS { get; } @@ -14,13 +14,13 @@ public interface IRangeClauseExpression bool IsInherentlyUnreachable { set; get; } } - public class RangeOfValuesExpression : RangeClauseExpression + internal class RangeOfValuesExpression : RangeClauseExpression { public RangeOfValuesExpression((IParseTreeValue lhs, IParseTreeValue rhs) rangeOfValues) : base(rangeOfValues.lhs, rangeOfValues.rhs, Tokens.To) { } } - public class BinaryExpression : RangeClauseExpression + internal class BinaryExpression : RangeClauseExpression { public BinaryExpression(IParseTreeValue lhs, IParseTreeValue rhs, string opSymbol) : base(lhs, rhs, opSymbol, true) @@ -29,7 +29,7 @@ public BinaryExpression(IParseTreeValue lhs, IParseTreeValue rhs, string opSymbo } } - public class LikeExpression : RangeClauseExpression + internal class LikeExpression : RangeClauseExpression { public LikeExpression(IParseTreeValue lhs, IParseTreeValue rhs) : base(lhs, rhs, Tokens.Like, false) @@ -65,7 +65,7 @@ private static string AnnotateAsStringConstant(string input) } } - public class IsClauseExpression : RangeClauseExpression + internal class IsClauseExpression : RangeClauseExpression { public IsClauseExpression(IParseTreeValue value, string opSymbol) : base(value, null, opSymbol) @@ -79,7 +79,7 @@ public override string ToString() } } - public class UnaryExpression : RangeClauseExpression + internal class UnaryExpression : RangeClauseExpression { public UnaryExpression(IParseTreeValue value, string opSymbol) : base(value, null, opSymbol) @@ -93,7 +93,7 @@ public override string ToString() } } - public class ValueExpression : RangeClauseExpression + internal class ValueExpression : RangeClauseExpression { public ValueExpression(IParseTreeValue value) : base(value, null, string.Empty) @@ -104,7 +104,7 @@ public ValueExpression(IParseTreeValue value) public override string ToString() => LHS.Token; } - public abstract class RangeClauseExpression : IRangeClauseExpression + internal abstract class RangeClauseExpression : IRangeClauseExpression { private ClauseExpressionData _data; protected int _hashCode; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/TypeTokenPair.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/TypeTokenPair.cs index 8ec9a2d1d3..4e27260568 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/TypeTokenPair.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/TypeTokenPair.cs @@ -6,7 +6,7 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { - public struct TypeTokenPair + internal struct TypeTokenPair { public string ValueType { get; } public string Token { get; } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs index 87086ed004..7adb40bbdc 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs @@ -113,7 +113,7 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection /// End Sub /// ]]> /// - public sealed class UnreachableCaseInspection : InspectionBase, IParseTreeInspection + internal sealed class UnreachableCaseInspection : InspectionBase, IParseTreeInspection { private readonly IUnreachableCaseInspector _inspector; private readonly IParseTreeValueVisitor _parseTreeValueVisitor; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs index 951de0c174..963b725393 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspector.cs @@ -10,7 +10,7 @@ namespace Rubberduck.Inspections.Concrete.UnreachableCaseInspection { - public interface IUnreachableCaseInspector + internal interface IUnreachableCaseInspector { ICollection<(UnreachableCaseInspection.CaseInspectionResultType resultType, ParserRuleContext context)> InspectForUnreachableCases( QualifiedModuleName module, @@ -22,7 +22,7 @@ string SelectExpressionTypeName( IParseTreeVisitorResults parseTreeValues); } - public class UnreachableCaseInspector : IUnreachableCaseInspector + internal class UnreachableCaseInspector : IUnreachableCaseInspector { private readonly IParseTreeValueFactory _valueFactory; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UntypedFunctionUsageInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UntypedFunctionUsageInspection.cs index 242b09ea57..5047dd06ce 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UntypedFunctionUsageInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UntypedFunctionUsageInspection.cs @@ -30,7 +30,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class UntypedFunctionUsageInspection : IdentifierReferenceInspectionFromDeclarationsBase + internal sealed class UntypedFunctionUsageInspection : IdentifierReferenceInspectionFromDeclarationsBase { public UntypedFunctionUsageInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseMeaningfulNameInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseMeaningfulNameInspection.cs index f3bdd2916a..3b4c6a86c7 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseMeaningfulNameInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseMeaningfulNameInspection.cs @@ -33,7 +33,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class UseMeaningfulNameInspection : DeclarationInspectionUsingGlobalInformationBase + internal sealed class UseMeaningfulNameInspection : DeclarationInspectionUsingGlobalInformationBase { private readonly IConfigurationService _settings; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfBangNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfBangNotationInspection.cs index aa027a9063..74e2dd38be 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfBangNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfBangNotationInspection.cs @@ -53,7 +53,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class UseOfBangNotationInspection : IdentifierReferenceInspectionBase + internal sealed class UseOfBangNotationInspection : IdentifierReferenceInspectionBase { public UseOfBangNotationInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs index dbd47fe466..4128de45fb 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs @@ -61,7 +61,7 @@ namespace Rubberduck.Inspections.Concrete /// End Function /// ]]> /// - public sealed class UseOfRecursiveBangNotationInspection : IdentifierReferenceInspectionBase + internal sealed class UseOfRecursiveBangNotationInspection : IdentifierReferenceInspectionBase { public UseOfRecursiveBangNotationInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs index 6b0fa27db2..a291cbe464 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs @@ -56,7 +56,7 @@ namespace Rubberduck.Inspections.Concrete /// End Function /// ]]> /// - public sealed class UseOfUnboundBangNotationInspection : IdentifierReferenceInspectionBase + internal sealed class UseOfUnboundBangNotationInspection : IdentifierReferenceInspectionBase { public UseOfUnboundBangNotationInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs index 28b5742400..028611e3b4 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs @@ -55,7 +55,7 @@ namespace Rubberduck.CodeAnalysis.Inspections.Concrete /// End Sub /// ]]> /// - public class ValueRequiredInspection : IdentifierReferenceInspectionBase + internal class ValueRequiredInspection : IdentifierReferenceInspectionBase { public ValueRequiredInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotAssignedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotAssignedInspection.cs index 961b4ecbaf..efa2abd874 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotAssignedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotAssignedInspection.cs @@ -34,7 +34,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class VariableNotAssignedInspection : DeclarationInspectionBase + internal sealed class VariableNotAssignedInspection : DeclarationInspectionBase { public VariableNotAssignedInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, DeclarationType.Variable) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotUsedInspection.cs index 59e5e41a6a..514ed24a4a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotUsedInspection.cs @@ -37,7 +37,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class VariableNotUsedInspection : DeclarationInspectionBase + internal sealed class VariableNotUsedInspection : DeclarationInspectionBase { /// /// Inspection results for variables that are never referenced. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableRequiresSetAssignmentEvaluator.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableRequiresSetAssignmentEvaluator.cs index e4c1d28379..52097fe5fe 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableRequiresSetAssignmentEvaluator.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableRequiresSetAssignmentEvaluator.cs @@ -8,7 +8,7 @@ namespace Rubberduck.Inspections { - public static class VariableRequiresSetAssignmentEvaluator + internal static class VariableRequiresSetAssignmentEvaluator { /// /// Determines whether the 'Set' keyword is required (whether it's present or not) for the specified identifier reference. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableTypeNotDeclaredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableTypeNotDeclaredInspection.cs index 3f9786aad4..aa1067d155 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableTypeNotDeclaredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableTypeNotDeclaredInspection.cs @@ -31,7 +31,7 @@ namespace Rubberduck.Inspections.Concrete /// End Sub /// ]]> /// - public sealed class VariableTypeNotDeclaredInspection : ImplicitTypeInspectionBase + internal sealed class VariableTypeNotDeclaredInspection : ImplicitTypeInspectionBase { public VariableTypeNotDeclaredInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, new []{DeclarationType.Parameter, DeclarationType.Variable}, new[]{DeclarationType.Control}) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/WriteOnlyPropertyInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/WriteOnlyPropertyInspection.cs index d40134e3ac..fbb48dbf49 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/WriteOnlyPropertyInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/WriteOnlyPropertyInspection.cs @@ -39,7 +39,7 @@ namespace Rubberduck.Inspections.Concrete /// End Property /// ]]> /// - public sealed class WriteOnlyPropertyInspection : DeclarationInspectionBase + internal sealed class WriteOnlyPropertyInspection : DeclarationInspectionBase { public WriteOnlyPropertyInspection(IDeclarationFinderProvider declarationFinderProvider) : base(declarationFinderProvider, DeclarationType.PropertyLet, DeclarationType.PropertySet) { } diff --git a/Rubberduck.CodeAnalysis/Inspections/Extensions/DeclarationTypeExtensions.cs b/Rubberduck.CodeAnalysis/Inspections/Extensions/DeclarationTypeExtensions.cs index f4e89b872a..62917525d2 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Extensions/DeclarationTypeExtensions.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Extensions/DeclarationTypeExtensions.cs @@ -4,7 +4,7 @@ namespace Rubberduck.Inspections.Inspections.Extensions { - public static class DeclarationTypeExtensions + internal static class DeclarationTypeExtensions { public static string ToLocalizedString(this DeclarationType type) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Extensions/ExecutableBlocksExtensions.cs b/Rubberduck.CodeAnalysis/Inspections/Extensions/ExecutableBlocksExtensions.cs index 66ae596323..feede7ae54 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Extensions/ExecutableBlocksExtensions.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Extensions/ExecutableBlocksExtensions.cs @@ -1,9 +1,10 @@ -using Antlr4.Runtime.Tree; +using System.Collections.Generic; +using Antlr4.Runtime.Tree; using static Rubberduck.Parsing.Grammar.VBAParser; namespace Rubberduck.Inspections.Inspections.Extensions { - public static class ExecutableBlocksExtensions + internal static class ExecutableBlocksExtensions { /// /// Checks a block of code for executable statments and returns true if are present. @@ -16,8 +17,9 @@ public static bool ContainsExecutableStatements(this BlockContext block, bool co return block?.children != null && ContainsExecutableStatements(block.children, considerAllocations); } - private static bool ContainsExecutableStatements(System.Collections.Generic.IList blockChildren, - bool considerAllocations = false) + private static bool ContainsExecutableStatements( + IList blockChildren, + bool considerAllocations = false) { foreach (var child in blockChildren) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Extensions/IgnoreRelatedExtensions.cs b/Rubberduck.CodeAnalysis/Inspections/Extensions/IgnoreRelatedExtensions.cs index e23b68ce98..a023e46a5b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Extensions/IgnoreRelatedExtensions.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Extensions/IgnoreRelatedExtensions.cs @@ -9,7 +9,7 @@ namespace Rubberduck.Inspections.Inspections.Extensions { - static class IgnoreRelatedExtensions + internal static class IgnoreRelatedExtensions { public static bool IsIgnoringInspectionResultFor(this IdentifierReference reference, string inspectionName) { diff --git a/Rubberduck.CodeAnalysis/Inspections/IInspectionProvider.cs b/Rubberduck.CodeAnalysis/Inspections/Logistics/IInspectionProvider.cs similarity index 100% rename from Rubberduck.CodeAnalysis/Inspections/IInspectionProvider.cs rename to Rubberduck.CodeAnalysis/Inspections/Logistics/IInspectionProvider.cs diff --git a/Rubberduck.CodeAnalysis/Inspections/InspectionProvider.cs b/Rubberduck.CodeAnalysis/Inspections/Logistics/InspectionProvider.cs similarity index 94% rename from Rubberduck.CodeAnalysis/Inspections/InspectionProvider.cs rename to Rubberduck.CodeAnalysis/Inspections/Logistics/InspectionProvider.cs index 473cb7e846..68cda2c3d0 100644 --- a/Rubberduck.CodeAnalysis/Inspections/InspectionProvider.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Logistics/InspectionProvider.cs @@ -6,7 +6,7 @@ namespace Rubberduck.CodeAnalysis.Inspections { - public class InspectionProvider : IInspectionProvider + internal class InspectionProvider : IInspectionProvider { public InspectionProvider(IEnumerable inspections) { diff --git a/Rubberduck.CodeAnalysis/Inspections/Inspector.cs b/Rubberduck.CodeAnalysis/Inspections/Logistics/Inspector.cs similarity index 99% rename from Rubberduck.CodeAnalysis/Inspections/Inspector.cs rename to Rubberduck.CodeAnalysis/Inspections/Logistics/Inspector.cs index e2892762bc..71acea1df6 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Inspector.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Logistics/Inspector.cs @@ -24,7 +24,7 @@ namespace Rubberduck.Inspections { namespace Rubberduck.Inspections { - public class Inspector : IInspector + internal class Inspector : IInspector { private const int _maxDegreeOfInspectionParallelism = -1; private readonly IConfigurationService _configService; diff --git a/Rubberduck.CodeAnalysis/Inspections/Results/DeclarationInspectionResult.cs b/Rubberduck.CodeAnalysis/Inspections/Results/DeclarationInspectionResult.cs index 42dcf0a04d..536e21da99 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Results/DeclarationInspectionResult.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Results/DeclarationInspectionResult.cs @@ -7,7 +7,7 @@ namespace Rubberduck.Inspections.Results { - public class DeclarationInspectionResult : InspectionResultBase + internal class DeclarationInspectionResult : InspectionResultBase { public DeclarationInspectionResult( IInspection inspection, @@ -44,7 +44,7 @@ public override bool ChangesInvalidateResult(ICollection mo } } - public class DeclarationInspectionResult : DeclarationInspectionResult, IWithInspectionResultProperties + internal class DeclarationInspectionResult : DeclarationInspectionResult, IWithInspectionResultProperties { public DeclarationInspectionResult( IInspection inspection, diff --git a/Rubberduck.CodeAnalysis/Inspections/Results/IdentifierReferenceInspectionResult.cs b/Rubberduck.CodeAnalysis/Inspections/Results/IdentifierReferenceInspectionResult.cs index c3cdeef75a..209800b7dd 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Results/IdentifierReferenceInspectionResult.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Results/IdentifierReferenceInspectionResult.cs @@ -9,7 +9,7 @@ namespace Rubberduck.Inspections.Results { - public class IdentifierReferenceInspectionResult : InspectionResultBase + internal class IdentifierReferenceInspectionResult : InspectionResultBase { public IdentifierReference Reference { get; } @@ -44,7 +44,7 @@ public override bool ChangesInvalidateResult(ICollection mo } } - public class IdentifierReferenceInspectionResult : IdentifierReferenceInspectionResult, IWithInspectionResultProperties + internal class IdentifierReferenceInspectionResult : IdentifierReferenceInspectionResult, IWithInspectionResultProperties { public IdentifierReferenceInspectionResult( IInspection inspection, diff --git a/Rubberduck.CodeAnalysis/Inspections/Results/QualifiedContextInspectionResult.cs b/Rubberduck.CodeAnalysis/Inspections/Results/QualifiedContextInspectionResult.cs index bdd871bf9f..ba3a7f018e 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Results/QualifiedContextInspectionResult.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Results/QualifiedContextInspectionResult.cs @@ -6,7 +6,7 @@ namespace Rubberduck.Inspections.Results { - public class QualifiedContextInspectionResult : InspectionResultBase + internal class QualifiedContextInspectionResult : InspectionResultBase { public QualifiedContextInspectionResult( IInspection inspection, @@ -24,7 +24,7 @@ public QualifiedContextInspectionResult( {} } - public class QualifiedContextInspectionResult : QualifiedContextInspectionResult, IWithInspectionResultProperties + internal class QualifiedContextInspectionResult : QualifiedContextInspectionResult, IWithInspectionResultProperties { public QualifiedContextInspectionResult( IInspection inspection, diff --git a/Rubberduck.CodeAnalysis/Properties/AssemblyInfo.cs b/Rubberduck.CodeAnalysis/Properties/AssemblyInfo.cs index fffd87a21c..636860a9b9 100644 --- a/Rubberduck.CodeAnalysis/Properties/AssemblyInfo.cs +++ b/Rubberduck.CodeAnalysis/Properties/AssemblyInfo.cs @@ -1,8 +1,8 @@ -using System.Reflection; -using System.Runtime.CompilerServices; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -[assembly: InternalsVisibleTo("Rubberduck.Main")] +//This is the assembly name of the project Rubberduck.Main. +[assembly: InternalsVisibleTo("Rubberduck")] [assembly: InternalsVisibleTo("RubberduckTests")] // Setting ComVisible to false makes the types in this assembly not visible diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/QuickFixBase.cs b/Rubberduck.CodeAnalysis/QuickFixes/Abstract/QuickFixBase.cs similarity index 95% rename from Rubberduck.CodeAnalysis/Inspections/Abstract/QuickFixBase.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Abstract/QuickFixBase.cs index f8c246b357..ac69eab02b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/QuickFixBase.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Abstract/QuickFixBase.cs @@ -8,9 +8,9 @@ using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.VBA.Parsing; -namespace Rubberduck.Inspections.Abstract +namespace Rubberduck.CodeAnalysis.QuickFixes.Abstract { - public abstract class QuickFixBase : IQuickFix + internal abstract class QuickFixBase : IQuickFix { protected readonly ILogger Logger = LogManager.GetCurrentClassLogger(); private HashSet _supportedInspections; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RefactoringQuickFixBase.cs b/Rubberduck.CodeAnalysis/QuickFixes/Abstract/RefactoringQuickFixBase.cs similarity index 90% rename from Rubberduck.CodeAnalysis/QuickFixes/RefactoringQuickFixBase.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Abstract/RefactoringQuickFixBase.cs index f6c4433e2f..0539534a15 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RefactoringQuickFixBase.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Abstract/RefactoringQuickFixBase.cs @@ -1,13 +1,12 @@ using System; -using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Refactorings; using Rubberduck.Refactorings.Exceptions; -namespace Rubberduck.Inspections.QuickFixes +namespace Rubberduck.CodeAnalysis.QuickFixes.Abstract { - public abstract class RefactoringQuickFixBase : QuickFixBase + internal abstract class RefactoringQuickFixBase : QuickFixBase { protected readonly IRefactoring Refactoring; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AccessSheetUsingCodeNameQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AccessSheetUsingCodeNameQuickFix.cs similarity index 97% rename from Rubberduck.CodeAnalysis/QuickFixes/AccessSheetUsingCodeNameQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/AccessSheetUsingCodeNameQuickFix.cs index 54656657bc..6a42043c5e 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AccessSheetUsingCodeNameQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AccessSheetUsingCodeNameQuickFix.cs @@ -1,6 +1,6 @@ using System.Linq; using Antlr4.Runtime; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.Results; using Rubberduck.Parsing; @@ -36,7 +36,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class AccessSheetUsingCodeNameQuickFix : QuickFixBase + internal sealed class AccessSheetUsingCodeNameQuickFix : QuickFixBase { private readonly IDeclarationFinderProvider _declarationFinderProvider; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AddAttributeAnnotationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddAttributeAnnotationQuickFix.cs similarity index 95% rename from Rubberduck.CodeAnalysis/QuickFixes/AddAttributeAnnotationQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddAttributeAnnotationQuickFix.cs index 1a6c6cf813..1250e1ca38 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AddAttributeAnnotationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddAttributeAnnotationQuickFix.cs @@ -1,6 +1,5 @@ -using System; -using System.Collections.Generic; -using Rubberduck.Inspections.Abstract; +using System.Collections.Generic; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Inspections.Abstract; @@ -46,7 +45,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public class AddAttributeAnnotationQuickFix : QuickFixBase + internal class AddAttributeAnnotationQuickFix : QuickFixBase { private readonly IAnnotationUpdater _annotationUpdater; private readonly IAttributeAnnotationProvider _attributeAnnotationProvider; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AddIdentifierToWhiteListQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddIdentifierToWhiteListQuickFix.cs similarity index 93% rename from Rubberduck.CodeAnalysis/QuickFixes/AddIdentifierToWhiteListQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddIdentifierToWhiteListQuickFix.cs index 6d8795bb38..206e781554 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AddIdentifierToWhiteListQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddIdentifierToWhiteListQuickFix.cs @@ -1,5 +1,5 @@ using System.Linq; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; @@ -16,7 +16,7 @@ namespace Rubberduck.Inspections.QuickFixes /// /// /// - public sealed class AddIdentifierToWhiteListQuickFix : QuickFixBase + internal sealed class AddIdentifierToWhiteListQuickFix : QuickFixBase { private readonly IConfigurationService _settings; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AddMissingAttributeQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddMissingAttributeQuickFix.cs similarity index 95% rename from Rubberduck.CodeAnalysis/QuickFixes/AddMissingAttributeQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddMissingAttributeQuickFix.cs index 6fb4270878..92ccbc9438 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AddMissingAttributeQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddMissingAttributeQuickFix.cs @@ -1,4 +1,4 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Inspections.Abstract; @@ -42,7 +42,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class AddMissingAttributeQuickFix : QuickFixBase + internal sealed class AddMissingAttributeQuickFix : QuickFixBase { private readonly IAttributesUpdater _attributesUpdater; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AddStepOneQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddStepOneQuickFix.cs similarity index 93% rename from Rubberduck.CodeAnalysis/QuickFixes/AddStepOneQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddStepOneQuickFix.cs index b67f062aef..1948da1198 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AddStepOneQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddStepOneQuickFix.cs @@ -1,8 +1,8 @@ -using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Concrete; +using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using System; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using static Rubberduck.Parsing.Grammar.VBAParser; namespace Rubberduck.Inspections.QuickFixes @@ -36,7 +36,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class AddStepOneQuickFix : QuickFixBase + internal sealed class AddStepOneQuickFix : QuickFixBase { public AddStepOneQuickFix() : base(typeof(StepIsNotSpecifiedInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeAnnotationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AdjustAttributeAnnotationQuickFix.cs similarity index 97% rename from Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeAnnotationQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/AdjustAttributeAnnotationQuickFix.cs index 89e234bfdc..9e68d8ea6d 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeAnnotationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AdjustAttributeAnnotationQuickFix.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Inspections.Abstract; @@ -45,7 +45,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public class AdjustAttributeAnnotationQuickFix : QuickFixBase + internal class AdjustAttributeAnnotationQuickFix : QuickFixBase { private readonly IAnnotationUpdater _annotationUpdater; private readonly IAttributeAnnotationProvider _attributeAnnotationProvider; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeValuesQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AdjustAttributeValuesQuickFix.cs similarity index 95% rename from Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeValuesQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/AdjustAttributeValuesQuickFix.cs index 6fe3076fff..1838523157 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AdjustAttributeValuesQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AdjustAttributeValuesQuickFix.cs @@ -1,7 +1,6 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Diagnostics; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Inspections.Abstract; @@ -49,7 +48,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public class AdjustAttributeValuesQuickFix : QuickFixBase + internal class AdjustAttributeValuesQuickFix : QuickFixBase { private readonly IAttributesUpdater _attributesUpdater; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ApplicationWorksheetFunctionQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ApplicationWorksheetFunctionQuickFix.cs similarity index 92% rename from Rubberduck.CodeAnalysis/QuickFixes/ApplicationWorksheetFunctionQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/ApplicationWorksheetFunctionQuickFix.cs index 9a493032f6..385af89e08 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ApplicationWorksheetFunctionQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ApplicationWorksheetFunctionQuickFix.cs @@ -1,4 +1,4 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; @@ -28,7 +28,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class ApplicationWorksheetFunctionQuickFix : QuickFixBase + internal sealed class ApplicationWorksheetFunctionQuickFix : QuickFixBase { public ApplicationWorksheetFunctionQuickFix() : base(typeof(ApplicationWorksheetFunctionInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/AssignedByValParameterMakeLocalCopyQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AssignedByValParameterMakeLocalCopyQuickFix.cs similarity index 98% rename from Rubberduck.CodeAnalysis/QuickFixes/AssignedByValParameterMakeLocalCopyQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/AssignedByValParameterMakeLocalCopyQuickFix.cs index c15115a2ef..b85a91e5a5 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/AssignedByValParameterMakeLocalCopyQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AssignedByValParameterMakeLocalCopyQuickFix.cs @@ -7,12 +7,12 @@ using Rubberduck.Common; using System.Windows.Forms; using Antlr4.Runtime; -using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.VBA; using System.Diagnostics; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Refactorings.Common; namespace Rubberduck.Inspections.QuickFixes @@ -46,7 +46,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class AssignedByValParameterMakeLocalCopyQuickFix : QuickFixBase + internal sealed class AssignedByValParameterMakeLocalCopyQuickFix : QuickFixBase { private readonly IAssignedByValParameterQuickFixDialogFactory _dialogFactory; private readonly IDeclarationFinderProvider _declarationFinderProvider; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ChangeDimToPrivateQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ChangeDimToPrivateQuickFix.cs similarity index 93% rename from Rubberduck.CodeAnalysis/QuickFixes/ChangeDimToPrivateQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/ChangeDimToPrivateQuickFix.cs index b24aad949e..3dd45b2f08 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ChangeDimToPrivateQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ChangeDimToPrivateQuickFix.cs @@ -1,4 +1,4 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -33,7 +33,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class ChangeDimToPrivateQuickFix : QuickFixBase + internal sealed class ChangeDimToPrivateQuickFix : QuickFixBase { public ChangeDimToPrivateQuickFix() : base(typeof(ModuleScopeDimKeywordInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ChangeIntegerToLongQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ChangeIntegerToLongQuickFix.cs similarity index 98% rename from Rubberduck.CodeAnalysis/QuickFixes/ChangeIntegerToLongQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/ChangeIntegerToLongQuickFix.cs index 89f0819dd1..d6bac5f867 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ChangeIntegerToLongQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ChangeIntegerToLongQuickFix.cs @@ -2,7 +2,7 @@ using Rubberduck.Parsing.Grammar; using System.Linq; using Antlr4.Runtime; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing; @@ -10,7 +10,6 @@ using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.VBA.Extensions; namespace Rubberduck.Inspections.QuickFixes { @@ -41,7 +40,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class ChangeIntegerToLongQuickFix : QuickFixBase + internal sealed class ChangeIntegerToLongQuickFix : QuickFixBase { private readonly IDeclarationFinderProvider _declarationFinderProvider; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ChangeProcedureToFunctionQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ChangeProcedureToFunctionQuickFix.cs similarity index 97% rename from Rubberduck.CodeAnalysis/QuickFixes/ChangeProcedureToFunctionQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/ChangeProcedureToFunctionQuickFix.cs index bc929993e7..f3770473f3 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ChangeProcedureToFunctionQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ChangeProcedureToFunctionQuickFix.cs @@ -1,6 +1,6 @@ using System; using System.Linq; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing; @@ -47,7 +47,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class ChangeProcedureToFunctionQuickFix : QuickFixBase + internal sealed class ChangeProcedureToFunctionQuickFix : QuickFixBase { public ChangeProcedureToFunctionQuickFix() : base(typeof(ProcedureCanBeWrittenAsFunctionInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ConvertToProcedureQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ConvertToProcedureQuickFix.cs similarity index 98% rename from Rubberduck.CodeAnalysis/QuickFixes/ConvertToProcedureQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/ConvertToProcedureQuickFix.cs index 1634cf401a..568051c9e6 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ConvertToProcedureQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ConvertToProcedureQuickFix.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; using Antlr4.Runtime; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; @@ -48,7 +48,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class ConvertToProcedureQuickFix : QuickFixBase + internal sealed class ConvertToProcedureQuickFix : QuickFixBase { private readonly IDeclarationFinderProvider _declarationFinderProvider; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/DeclareAsExplicitVariantQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/DeclareAsExplicitVariantQuickFix.cs similarity index 94% rename from Rubberduck.CodeAnalysis/QuickFixes/DeclareAsExplicitVariantQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/DeclareAsExplicitVariantQuickFix.cs index 6862004fae..4c94d08f16 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/DeclareAsExplicitVariantQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/DeclareAsExplicitVariantQuickFix.cs @@ -1,5 +1,5 @@ using Antlr4.Runtime; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -34,7 +34,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class DeclareAsExplicitVariantQuickFix : QuickFixBase + internal sealed class DeclareAsExplicitVariantQuickFix : QuickFixBase { public DeclareAsExplicitVariantQuickFix() : base(typeof(VariableTypeNotDeclaredInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ExpandBangNotationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ExpandBangNotationQuickFix.cs similarity index 98% rename from Rubberduck.CodeAnalysis/QuickFixes/ExpandBangNotationQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/ExpandBangNotationQuickFix.cs index 69a89eb637..42fd28c0c8 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ExpandBangNotationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ExpandBangNotationQuickFix.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; using Antlr4.Runtime; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -45,7 +45,7 @@ namespace Rubberduck.CodeAnalysis.QuickFixes /// ]]> /// /// - public class ExpandBangNotationQuickFix : QuickFixBase + internal class ExpandBangNotationQuickFix : QuickFixBase { private readonly IDeclarationFinderProvider _declarationFinderProvider; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ExpandDefaultMemberQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ExpandDefaultMemberQuickFix.cs similarity index 98% rename from Rubberduck.CodeAnalysis/QuickFixes/ExpandDefaultMemberQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/ExpandDefaultMemberQuickFix.cs index c823a5ac55..7c7ae85124 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ExpandDefaultMemberQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ExpandDefaultMemberQuickFix.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; using Antlr4.Runtime; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -49,7 +49,7 @@ namespace Rubberduck.CodeAnalysis.QuickFixes /// ]]> /// /// - public class ExpandDefaultMemberQuickFix : QuickFixBase + internal class ExpandDefaultMemberQuickFix : QuickFixBase { private readonly IDeclarationFinderProvider _declarationFinderProvider; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/IgnoreOnceQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/IgnoreOnceQuickFix.cs similarity index 97% rename from Rubberduck.CodeAnalysis/QuickFixes/IgnoreOnceQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/IgnoreOnceQuickFix.cs index f066084850..860b0f583b 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/IgnoreOnceQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/IgnoreOnceQuickFix.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Inspections; @@ -36,7 +36,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class IgnoreOnceQuickFix : QuickFixBase + internal sealed class IgnoreOnceQuickFix : QuickFixBase { private readonly RubberduckParserState _state; private readonly IAnnotationUpdater _annotationUpdater; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/IntroduceLocalVariableQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/IntroduceLocalVariableQuickFix.cs similarity index 97% rename from Rubberduck.CodeAnalysis/QuickFixes/IntroduceLocalVariableQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/IntroduceLocalVariableQuickFix.cs index b02f03ba0c..801b19824a 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/IntroduceLocalVariableQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/IntroduceLocalVariableQuickFix.cs @@ -1,6 +1,6 @@ using System; using System.Text.RegularExpressions; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; @@ -35,7 +35,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class IntroduceLocalVariableQuickFix : QuickFixBase + internal sealed class IntroduceLocalVariableQuickFix : QuickFixBase { public IntroduceLocalVariableQuickFix() : base(typeof(UndeclaredVariableInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/IsMissingOnInappropriateArgumentQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/IsMissingOnInappropriateArgumentQuickFix.cs similarity index 97% rename from Rubberduck.CodeAnalysis/QuickFixes/IsMissingOnInappropriateArgumentQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/IsMissingOnInappropriateArgumentQuickFix.cs index 53c22f974b..473a8af474 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/IsMissingOnInappropriateArgumentQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/IsMissingOnInappropriateArgumentQuickFix.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; @@ -39,7 +39,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class IsMissingOnInappropriateArgumentQuickFix : QuickFixBase + internal sealed class IsMissingOnInappropriateArgumentQuickFix : QuickFixBase { private readonly IDeclarationFinderProvider _declarationFinderProvider; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/MakeSingleLineParameterQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/MakeSingleLineParameterQuickFix.cs similarity index 93% rename from Rubberduck.CodeAnalysis/QuickFixes/MakeSingleLineParameterQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/MakeSingleLineParameterQuickFix.cs index e5a5ac1890..b3009f0df1 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/MakeSingleLineParameterQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/MakeSingleLineParameterQuickFix.cs @@ -1,4 +1,4 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; @@ -28,7 +28,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class MakeSingleLineParameterQuickFix : QuickFixBase + internal sealed class MakeSingleLineParameterQuickFix : QuickFixBase { public MakeSingleLineParameterQuickFix() : base(typeof(MultilineParameterInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/OptionExplicitQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/OptionExplicitQuickFix.cs similarity index 93% rename from Rubberduck.CodeAnalysis/QuickFixes/OptionExplicitQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/OptionExplicitQuickFix.cs index d7a7666a4e..f2a8c8293a 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/OptionExplicitQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/OptionExplicitQuickFix.cs @@ -1,5 +1,5 @@ using System; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -33,7 +33,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class OptionExplicitQuickFix : QuickFixBase + internal sealed class OptionExplicitQuickFix : QuickFixBase { public OptionExplicitQuickFix() : base(typeof(OptionExplicitInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/PassParameterByReferenceQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/PassParameterByReferenceQuickFix.cs similarity index 93% rename from Rubberduck.CodeAnalysis/QuickFixes/PassParameterByReferenceQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/PassParameterByReferenceQuickFix.cs index 4d565ab77b..1f23b5112b 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/PassParameterByReferenceQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/PassParameterByReferenceQuickFix.cs @@ -1,4 +1,4 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -31,7 +31,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class PassParameterByReferenceQuickFix : QuickFixBase + internal sealed class PassParameterByReferenceQuickFix : QuickFixBase { public PassParameterByReferenceQuickFix() : base(typeof(AssignedByValParameterInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/PassParameterByValueQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/PassParameterByValueQuickFix.cs similarity index 97% rename from Rubberduck.CodeAnalysis/QuickFixes/PassParameterByValueQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/PassParameterByValueQuickFix.cs index 1222777721..82763a63f2 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/PassParameterByValueQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/PassParameterByValueQuickFix.cs @@ -1,5 +1,5 @@ using System.Linq; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -33,7 +33,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class PassParameterByValueQuickFix : QuickFixBase + internal sealed class PassParameterByValueQuickFix : QuickFixBase { private readonly IDeclarationFinderProvider _declarationFinderProvider; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/EncapsulateFieldQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/EncapsulateFieldQuickFix.cs similarity index 92% rename from Rubberduck.CodeAnalysis/QuickFixes/EncapsulateFieldQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/EncapsulateFieldQuickFix.cs index cab501754d..d4c0b22167 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/EncapsulateFieldQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/EncapsulateFieldQuickFix.cs @@ -1,3 +1,4 @@ +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Refactorings.EncapsulateField; @@ -33,7 +34,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class EncapsulateFieldQuickFix : RefactoringQuickFixBase + internal sealed class EncapsulateFieldQuickFix : RefactoringQuickFixBase { public EncapsulateFieldQuickFix(EncapsulateFieldRefactoring refactoring) : base(refactoring, typeof(EncapsulatePublicFieldInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/MoveFieldCloserToUsageQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/MoveFieldCloserToUsageQuickFix.cs similarity index 91% rename from Rubberduck.CodeAnalysis/QuickFixes/MoveFieldCloserToUsageQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/MoveFieldCloserToUsageQuickFix.cs index 042f67f9e7..e5c2d5f5c8 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/MoveFieldCloserToUsageQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/MoveFieldCloserToUsageQuickFix.cs @@ -1,3 +1,4 @@ +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Refactorings.MoveCloserToUsage; @@ -36,7 +37,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class MoveFieldCloserToUsageQuickFix : RefactoringQuickFixBase + internal sealed class MoveFieldCloserToUsageQuickFix : RefactoringQuickFixBase { public MoveFieldCloserToUsageQuickFix(MoveCloserToUsageRefactoring refactoring) : base(refactoring, typeof(MoveFieldCloserToUsageInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveUnusedParameterQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/RemoveUnusedParameterQuickFix.cs similarity index 92% rename from Rubberduck.CodeAnalysis/QuickFixes/RemoveUnusedParameterQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/RemoveUnusedParameterQuickFix.cs index b37b6e22c8..c00909d4b9 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveUnusedParameterQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/RemoveUnusedParameterQuickFix.cs @@ -1,3 +1,4 @@ +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Refactorings.RemoveParameters; @@ -39,7 +40,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class RemoveUnusedParameterQuickFix : RefactoringQuickFixBase + internal sealed class RemoveUnusedParameterQuickFix : RefactoringQuickFixBase { public RemoveUnusedParameterQuickFix(RemoveParametersRefactoring refactoring) : base(refactoring, typeof(ParameterNotUsedInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RenameDeclarationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/RenameDeclarationQuickFix.cs similarity index 94% rename from Rubberduck.CodeAnalysis/QuickFixes/RenameDeclarationQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/RenameDeclarationQuickFix.cs index d636607b5b..65645cdfb0 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RenameDeclarationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/RenameDeclarationQuickFix.cs @@ -1,4 +1,5 @@ using System.Globalization; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.Inspections.Concrete; using Rubberduck.Parsing.Inspections.Abstract; @@ -46,7 +47,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class RenameDeclarationQuickFix : RefactoringQuickFixBase + internal sealed class RenameDeclarationQuickFix : RefactoringQuickFixBase { public RenameDeclarationQuickFix(RenameRefactoring refactoring) : base(refactoring, diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveAnnotationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveAnnotationQuickFix.cs similarity index 94% rename from Rubberduck.CodeAnalysis/QuickFixes/RemoveAnnotationQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveAnnotationQuickFix.cs index b05980df1f..f94ca46477 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveAnnotationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveAnnotationQuickFix.cs @@ -1,4 +1,4 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Inspections.Abstract; @@ -37,7 +37,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class RemoveAnnotationQuickFix : QuickFixBase + internal sealed class RemoveAnnotationQuickFix : QuickFixBase { private readonly IAnnotationUpdater _annotationUpdater; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveAttributeQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveAttributeQuickFix.cs similarity index 95% rename from Rubberduck.CodeAnalysis/QuickFixes/RemoveAttributeQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveAttributeQuickFix.cs index 7783c17f3d..01bb94b938 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveAttributeQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveAttributeQuickFix.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; @@ -39,7 +38,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public class RemoveAttributeQuickFix : QuickFixBase + internal class RemoveAttributeQuickFix : QuickFixBase { private readonly IAttributesUpdater _attributesUpdater; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveCommentQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveCommentQuickFix.cs similarity index 92% rename from Rubberduck.CodeAnalysis/QuickFixes/RemoveCommentQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveCommentQuickFix.cs index 982109d35c..777a0f214b 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveCommentQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveCommentQuickFix.cs @@ -1,4 +1,4 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; @@ -32,7 +32,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class RemoveCommentQuickFix : QuickFixBase + internal sealed class RemoveCommentQuickFix : QuickFixBase { public RemoveCommentQuickFix() : base(typeof(ObsoleteCommentSyntaxInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveDuplicatedAnnotationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveDuplicatedAnnotationQuickFix.cs similarity index 94% rename from Rubberduck.CodeAnalysis/QuickFixes/RemoveDuplicatedAnnotationQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveDuplicatedAnnotationQuickFix.cs index 8d7cf1f468..b492999068 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveDuplicatedAnnotationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveDuplicatedAnnotationQuickFix.cs @@ -1,5 +1,5 @@ using System.Linq; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Inspections.Abstract; @@ -36,7 +36,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class RemoveDuplicatedAnnotationQuickFix : QuickFixBase + internal sealed class RemoveDuplicatedAnnotationQuickFix : QuickFixBase { private readonly IAnnotationUpdater _annotationUpdater; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveEmptyElseBlockQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveEmptyElseBlockQuickFix.cs similarity index 94% rename from Rubberduck.CodeAnalysis/QuickFixes/RemoveEmptyElseBlockQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveEmptyElseBlockQuickFix.cs index 201a322ef0..289b58c9a5 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveEmptyElseBlockQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveEmptyElseBlockQuickFix.cs @@ -1,4 +1,4 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Grammar; @@ -38,7 +38,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class RemoveEmptyElseBlockQuickFix : QuickFixBase + internal sealed class RemoveEmptyElseBlockQuickFix : QuickFixBase { public RemoveEmptyElseBlockQuickFix() : base(typeof(EmptyElseBlockInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveEmptyIfBlockQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveEmptyIfBlockQuickFix.cs similarity index 98% rename from Rubberduck.CodeAnalysis/QuickFixes/RemoveEmptyIfBlockQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveEmptyIfBlockQuickFix.cs index 92f04c8f91..03a78c04a9 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveEmptyIfBlockQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveEmptyIfBlockQuickFix.cs @@ -2,7 +2,7 @@ using System.Diagnostics; using System.Linq; using Antlr4.Runtime; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -45,7 +45,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class RemoveEmptyIfBlockQuickFix : QuickFixBase + internal sealed class RemoveEmptyIfBlockQuickFix : QuickFixBase { public RemoveEmptyIfBlockQuickFix() : base(typeof(EmptyIfBlockInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitByRefModifierQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveExplicitByRefModifierQuickFix.cs similarity index 97% rename from Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitByRefModifierQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveExplicitByRefModifierQuickFix.cs index 43e9737d10..46d1b4dd8d 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitByRefModifierQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveExplicitByRefModifierQuickFix.cs @@ -1,6 +1,6 @@ using Rubberduck.Parsing.Grammar; using System.Linq; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing.Inspections.Abstract; @@ -38,7 +38,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class RemoveExplicitByRefModifierQuickFix : QuickFixBase + internal sealed class RemoveExplicitByRefModifierQuickFix : QuickFixBase { private readonly IDeclarationFinderProvider _declarationFinderProvider; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitCallStatementQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveExplicitCallStatementQuickFix.cs similarity index 94% rename from Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitCallStatementQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveExplicitCallStatementQuickFix.cs index afd0d6e984..0e0d1bcca6 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitCallStatementQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveExplicitCallStatementQuickFix.cs @@ -1,4 +1,4 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -41,7 +41,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class RemoveExplicitCallStatementQuickFix : QuickFixBase + internal sealed class RemoveExplicitCallStatementQuickFix : QuickFixBase { public RemoveExplicitCallStatementQuickFix() : base(typeof(ObsoleteCallStatementInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitLetStatementQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveExplicitLetStatementQuickFix.cs similarity index 93% rename from Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitLetStatementQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveExplicitLetStatementQuickFix.cs index 264a975765..78ddda5bc7 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveExplicitLetStatementQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveExplicitLetStatementQuickFix.cs @@ -1,5 +1,5 @@ using System.Linq; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -38,7 +38,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class RemoveExplicitLetStatementQuickFix : QuickFixBase + internal sealed class RemoveExplicitLetStatementQuickFix : QuickFixBase { public RemoveExplicitLetStatementQuickFix() : base(typeof(ObsoleteLetStatementInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveLocalErrorQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveLocalErrorQuickFix.cs similarity index 94% rename from Rubberduck.CodeAnalysis/QuickFixes/RemoveLocalErrorQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveLocalErrorQuickFix.cs index 10150baad3..443e604f55 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveLocalErrorQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveLocalErrorQuickFix.cs @@ -1,4 +1,4 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -45,7 +45,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class RemoveLocalErrorQuickFix : QuickFixBase + internal sealed class RemoveLocalErrorQuickFix : QuickFixBase { public RemoveLocalErrorQuickFix() : base(typeof(OnLocalErrorInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveOptionBaseStatementQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveOptionBaseStatementQuickFix.cs similarity index 93% rename from Rubberduck.CodeAnalysis/QuickFixes/RemoveOptionBaseStatementQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveOptionBaseStatementQuickFix.cs index 7cb1ef5510..a2b682a826 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveOptionBaseStatementQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveOptionBaseStatementQuickFix.cs @@ -1,4 +1,4 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; @@ -35,7 +35,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class RemoveOptionBaseStatementQuickFix : QuickFixBase + internal sealed class RemoveOptionBaseStatementQuickFix : QuickFixBase { public RemoveOptionBaseStatementQuickFix() : base(typeof(RedundantOptionInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveStepOneQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveStepOneQuickFix.cs similarity index 93% rename from Rubberduck.CodeAnalysis/QuickFixes/RemoveStepOneQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveStepOneQuickFix.cs index 08c68e529e..d1081b77bf 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveStepOneQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveStepOneQuickFix.cs @@ -1,4 +1,4 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; @@ -38,7 +38,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class RemoveStepOneQuickFix : QuickFixBase + internal sealed class RemoveStepOneQuickFix : QuickFixBase { public RemoveStepOneQuickFix() : base(typeof(StepOneIsRedundantInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveStopKeywordQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveStopKeywordQuickFix.cs similarity index 92% rename from Rubberduck.CodeAnalysis/QuickFixes/RemoveStopKeywordQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveStopKeywordQuickFix.cs index 7dbc04151c..10ede263e7 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveStopKeywordQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveStopKeywordQuickFix.cs @@ -1,4 +1,4 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; @@ -34,7 +34,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class RemoveStopKeywordQuickFix : QuickFixBase + internal sealed class RemoveStopKeywordQuickFix : QuickFixBase { public RemoveStopKeywordQuickFix() : base(typeof(StopKeywordInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveTypeHintsQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveTypeHintsQuickFix.cs similarity index 97% rename from Rubberduck.CodeAnalysis/QuickFixes/RemoveTypeHintsQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveTypeHintsQuickFix.cs index 2336f9818a..1039fbae3a 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveTypeHintsQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveTypeHintsQuickFix.cs @@ -1,4 +1,4 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; @@ -39,7 +39,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class RemoveTypeHintsQuickFix : QuickFixBase + internal sealed class RemoveTypeHintsQuickFix : QuickFixBase { public RemoveTypeHintsQuickFix() : base(typeof(ObsoleteTypeHintInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveUnassignedIdentifierQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveUnassignedIdentifierQuickFix.cs similarity index 92% rename from Rubberduck.CodeAnalysis/QuickFixes/RemoveUnassignedIdentifierQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveUnassignedIdentifierQuickFix.cs index da3054fa59..5917631ba7 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveUnassignedIdentifierQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveUnassignedIdentifierQuickFix.cs @@ -1,4 +1,4 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; @@ -33,7 +33,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class RemoveUnassignedIdentifierQuickFix : QuickFixBase + internal sealed class RemoveUnassignedIdentifierQuickFix : QuickFixBase { public RemoveUnassignedIdentifierQuickFix() : base(typeof(VariableNotAssignedInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveUnassignedVariableUsageQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveUnassignedVariableUsageQuickFix.cs similarity index 95% rename from Rubberduck.CodeAnalysis/QuickFixes/RemoveUnassignedVariableUsageQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveUnassignedVariableUsageQuickFix.cs index bd7f5282d1..e3a2d32e4d 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveUnassignedVariableUsageQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveUnassignedVariableUsageQuickFix.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; using Antlr4.Runtime; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; @@ -40,7 +40,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class RemoveUnassignedVariableUsageQuickFix : QuickFixBase + internal sealed class RemoveUnassignedVariableUsageQuickFix : QuickFixBase { public RemoveUnassignedVariableUsageQuickFix() : base(typeof(UnassignedVariableUsageInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RemoveUnusedDeclarationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveUnusedDeclarationQuickFix.cs similarity index 94% rename from Rubberduck.CodeAnalysis/QuickFixes/RemoveUnusedDeclarationQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveUnusedDeclarationQuickFix.cs index 6aa169ee60..57773cb284 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RemoveUnusedDeclarationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveUnusedDeclarationQuickFix.cs @@ -1,4 +1,4 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; @@ -37,7 +37,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class RemoveUnusedDeclarationQuickFix : QuickFixBase + internal sealed class RemoveUnusedDeclarationQuickFix : QuickFixBase { public RemoveUnusedDeclarationQuickFix() : base(typeof(ConstantNotUsedInspection), diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ReplaceEmptyStringLiteralStatementQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceEmptyStringLiteralStatementQuickFix.cs similarity index 92% rename from Rubberduck.CodeAnalysis/QuickFixes/ReplaceEmptyStringLiteralStatementQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceEmptyStringLiteralStatementQuickFix.cs index 36127b53fd..fe80ad5b2b 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ReplaceEmptyStringLiteralStatementQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceEmptyStringLiteralStatementQuickFix.cs @@ -1,4 +1,4 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; @@ -36,7 +36,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class ReplaceEmptyStringLiteralStatementQuickFix : QuickFixBase + internal sealed class ReplaceEmptyStringLiteralStatementQuickFix : QuickFixBase { public ReplaceEmptyStringLiteralStatementQuickFix() : base(typeof(EmptyStringLiteralInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ReplaceGlobalModifierQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceGlobalModifierQuickFix.cs similarity index 92% rename from Rubberduck.CodeAnalysis/QuickFixes/ReplaceGlobalModifierQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceGlobalModifierQuickFix.cs index f707c277a3..4ff1446fdd 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ReplaceGlobalModifierQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceGlobalModifierQuickFix.cs @@ -1,5 +1,5 @@ using Antlr4.Runtime; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; @@ -29,7 +29,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class ReplaceGlobalModifierQuickFix : QuickFixBase + internal sealed class ReplaceGlobalModifierQuickFix : QuickFixBase { public ReplaceGlobalModifierQuickFix() : base(typeof(ObsoleteGlobalInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ReplaceIfElseWithConditionalStatementQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceIfElseWithConditionalStatementQuickFix.cs similarity index 94% rename from Rubberduck.CodeAnalysis/QuickFixes/ReplaceIfElseWithConditionalStatementQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceIfElseWithConditionalStatementQuickFix.cs index db6683e9ff..369f96aa94 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ReplaceIfElseWithConditionalStatementQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceIfElseWithConditionalStatementQuickFix.cs @@ -1,4 +1,4 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; @@ -42,7 +42,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class ReplaceIfElseWithConditionalStatementQuickFix : QuickFixBase + internal sealed class ReplaceIfElseWithConditionalStatementQuickFix : QuickFixBase { public ReplaceIfElseWithConditionalStatementQuickFix() : base(typeof(BooleanAssignedInIfElseInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ReplaceObsoleteCommentMarkerQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceObsoleteCommentMarkerQuickFix.cs similarity index 92% rename from Rubberduck.CodeAnalysis/QuickFixes/ReplaceObsoleteCommentMarkerQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceObsoleteCommentMarkerQuickFix.cs index b78e787c44..48d4508f5c 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ReplaceObsoleteCommentMarkerQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceObsoleteCommentMarkerQuickFix.cs @@ -1,4 +1,4 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -33,7 +33,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class ReplaceObsoleteCommentMarkerQuickFix : QuickFixBase + internal sealed class ReplaceObsoleteCommentMarkerQuickFix : QuickFixBase { public ReplaceObsoleteCommentMarkerQuickFix() : base(typeof(ObsoleteCommentSyntaxInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ReplaceObsoleteErrorStatementQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceObsoleteErrorStatementQuickFix.cs similarity index 92% rename from Rubberduck.CodeAnalysis/QuickFixes/ReplaceObsoleteErrorStatementQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceObsoleteErrorStatementQuickFix.cs index 8852366442..2476a8afbd 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ReplaceObsoleteErrorStatementQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceObsoleteErrorStatementQuickFix.cs @@ -1,4 +1,4 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -33,7 +33,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class ReplaceObsoleteErrorStatementQuickFix : QuickFixBase + internal sealed class ReplaceObsoleteErrorStatementQuickFix : QuickFixBase { public ReplaceObsoleteErrorStatementQuickFix() : base(typeof(ObsoleteErrorSyntaxInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/ReplaceWhileWendWithDoWhileLoopQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceWhileWendWithDoWhileLoopQuickFix.cs similarity index 93% rename from Rubberduck.CodeAnalysis/QuickFixes/ReplaceWhileWendWithDoWhileLoopQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceWhileWendWithDoWhileLoopQuickFix.cs index 3df609b4c9..bf8ff2ae17 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/ReplaceWhileWendWithDoWhileLoopQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceWhileWendWithDoWhileLoopQuickFix.cs @@ -1,5 +1,5 @@ using Rubberduck.CodeAnalysis.Inspections.Concrete; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; @@ -39,7 +39,7 @@ namespace Rubberduck.CodeAnalysis.QuickFixes /// ]]> /// /// - public sealed class ReplaceWhileWendWithDoWhileLoopQuickFix : QuickFixBase + internal sealed class ReplaceWhileWendWithDoWhileLoopQuickFix : QuickFixBase { public ReplaceWhileWendWithDoWhileLoopQuickFix() : base(typeof(ObsoleteWhileWendStatementInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RestoreErrorHandlingQuickFix.cs similarity index 97% rename from Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/RestoreErrorHandlingQuickFix.cs index 225c2088f4..2f3132f222 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/RestoreErrorHandlingQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RestoreErrorHandlingQuickFix.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing; @@ -45,7 +45,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class RestoreErrorHandlingQuickFix : QuickFixBase + internal sealed class RestoreErrorHandlingQuickFix : QuickFixBase { private const string LabelPrefix = "ErrorHandler"; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/SetExplicitVariantReturnTypeQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/SetExplicitVariantReturnTypeQuickFix.cs similarity index 96% rename from Rubberduck.CodeAnalysis/QuickFixes/SetExplicitVariantReturnTypeQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/SetExplicitVariantReturnTypeQuickFix.cs index b9baa96ace..7ca9bb8394 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/SetExplicitVariantReturnTypeQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/SetExplicitVariantReturnTypeQuickFix.cs @@ -1,4 +1,4 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -34,7 +34,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class SetExplicitVariantReturnTypeQuickFix : QuickFixBase + internal sealed class SetExplicitVariantReturnTypeQuickFix : QuickFixBase { public SetExplicitVariantReturnTypeQuickFix() :base(typeof(ImplicitVariantReturnTypeInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/SpecifyExplicitByRefModifierQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/SpecifyExplicitByRefModifierQuickFix.cs similarity index 97% rename from Rubberduck.CodeAnalysis/QuickFixes/SpecifyExplicitByRefModifierQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/SpecifyExplicitByRefModifierQuickFix.cs index b562dccaa6..10b738b4a1 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/SpecifyExplicitByRefModifierQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/SpecifyExplicitByRefModifierQuickFix.cs @@ -1,6 +1,6 @@ using Rubberduck.Parsing.Grammar; using System.Linq; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing.Inspections.Abstract; @@ -38,7 +38,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class SpecifyExplicitByRefModifierQuickFix : QuickFixBase + internal sealed class SpecifyExplicitByRefModifierQuickFix : QuickFixBase { private readonly IDeclarationFinderProvider _declarationFinderProvider; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/SpecifyExplicitPublicModifierQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/SpecifyExplicitPublicModifierQuickFix.cs similarity index 92% rename from Rubberduck.CodeAnalysis/QuickFixes/SpecifyExplicitPublicModifierQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/SpecifyExplicitPublicModifierQuickFix.cs index e870757ef9..656590db4e 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/SpecifyExplicitPublicModifierQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/SpecifyExplicitPublicModifierQuickFix.cs @@ -1,4 +1,4 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; @@ -32,7 +32,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class SpecifyExplicitPublicModifierQuickFix : QuickFixBase + internal sealed class SpecifyExplicitPublicModifierQuickFix : QuickFixBase { public SpecifyExplicitPublicModifierQuickFix() : base(typeof(ImplicitPublicMemberInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/SplitMultipleDeclarationsQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/SplitMultipleDeclarationsQuickFix.cs similarity index 96% rename from Rubberduck.CodeAnalysis/QuickFixes/SplitMultipleDeclarationsQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/SplitMultipleDeclarationsQuickFix.cs index 8b990ccebb..fc32964450 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/SplitMultipleDeclarationsQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/SplitMultipleDeclarationsQuickFix.cs @@ -1,7 +1,7 @@ using System; using System.Text; using Antlr4.Runtime; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -39,7 +39,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class SplitMultipleDeclarationsQuickFix : QuickFixBase + internal sealed class SplitMultipleDeclarationsQuickFix : QuickFixBase { public SplitMultipleDeclarationsQuickFix() : base(typeof(MultipleDeclarationsInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/UntypedFunctionUsageQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/UntypedFunctionUsageQuickFix.cs similarity index 95% rename from Rubberduck.CodeAnalysis/QuickFixes/UntypedFunctionUsageQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/UntypedFunctionUsageQuickFix.cs index 3bf068293d..300936a004 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/UntypedFunctionUsageQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/UntypedFunctionUsageQuickFix.cs @@ -1,7 +1,7 @@ using System.Diagnostics; using System.Linq; using Antlr4.Runtime; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -36,7 +36,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class UntypedFunctionUsageQuickFix : QuickFixBase + internal sealed class UntypedFunctionUsageQuickFix : QuickFixBase { public UntypedFunctionUsageQuickFix() : base(typeof(UntypedFunctionUsageInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/UseSetKeywordForObjectAssignmentQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/UseSetKeywordForObjectAssignmentQuickFix.cs similarity index 94% rename from Rubberduck.CodeAnalysis/QuickFixes/UseSetKeywordForObjectAssignmentQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/UseSetKeywordForObjectAssignmentQuickFix.cs index 6fa9e08652..fb52a460d3 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/UseSetKeywordForObjectAssignmentQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/UseSetKeywordForObjectAssignmentQuickFix.cs @@ -1,4 +1,4 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; @@ -37,7 +37,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class UseSetKeywordForObjectAssignmentQuickFix : QuickFixBase + internal sealed class UseSetKeywordForObjectAssignmentQuickFix : QuickFixBase { public UseSetKeywordForObjectAssignmentQuickFix() : base(typeof(ObjectVariableNotSetInspection), typeof(SuspiciousLetAssignmentInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/WriteOnlyPropertyQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/WriteOnlyPropertyQuickFix.cs similarity index 96% rename from Rubberduck.CodeAnalysis/QuickFixes/WriteOnlyPropertyQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Concrete/WriteOnlyPropertyQuickFix.cs index 3ee1aa718a..1693a3ae31 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/WriteOnlyPropertyQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/WriteOnlyPropertyQuickFix.cs @@ -1,6 +1,6 @@ using System; using System.Linq; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; @@ -41,7 +41,7 @@ namespace Rubberduck.Inspections.QuickFixes /// ]]> /// /// - public sealed class WriteOnlyPropertyQuickFix : QuickFixBase + internal sealed class WriteOnlyPropertyQuickFix : QuickFixBase { public WriteOnlyPropertyQuickFix() : base(typeof(WriteOnlyPropertyInspection)) diff --git a/Rubberduck.CodeAnalysis/QuickFixes/IQuickFixFailureNotifier.cs b/Rubberduck.CodeAnalysis/QuickFixes/Logistics/IQuickFixFailureNotifier.cs similarity index 78% rename from Rubberduck.CodeAnalysis/QuickFixes/IQuickFixFailureNotifier.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Logistics/IQuickFixFailureNotifier.cs index ddfc74125e..a1fdf75981 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/IQuickFixFailureNotifier.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Logistics/IQuickFixFailureNotifier.cs @@ -2,7 +2,7 @@ namespace Rubberduck.Inspections.QuickFixes { - public interface IQuickFixFailureNotifier + internal interface IQuickFixFailureNotifier { void NotifyQuickFixExecutionFailure(RewriteSessionState sessionState); } diff --git a/Rubberduck.CodeAnalysis/QuickFixes/QuickFixFailureNotifier.cs b/Rubberduck.CodeAnalysis/QuickFixes/Logistics/QuickFixFailureNotifier.cs similarity index 95% rename from Rubberduck.CodeAnalysis/QuickFixes/QuickFixFailureNotifier.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Logistics/QuickFixFailureNotifier.cs index 5877be4f50..3d11dd211c 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/QuickFixFailureNotifier.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Logistics/QuickFixFailureNotifier.cs @@ -4,7 +4,7 @@ namespace Rubberduck.Inspections.QuickFixes { - public class QuickFixFailureNotifier : IQuickFixFailureNotifier + internal class QuickFixFailureNotifier : IQuickFixFailureNotifier { private readonly IMessageBox _messageBox; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/QuickFixProvider.cs b/Rubberduck.CodeAnalysis/QuickFixes/Logistics/QuickFixProvider.cs similarity index 99% rename from Rubberduck.CodeAnalysis/QuickFixes/QuickFixProvider.cs rename to Rubberduck.CodeAnalysis/QuickFixes/Logistics/QuickFixProvider.cs index 9db5bcd29c..c2682a35b6 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/QuickFixProvider.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Logistics/QuickFixProvider.cs @@ -10,7 +10,7 @@ namespace Rubberduck.Inspections.QuickFixes { - public class QuickFixProvider : IQuickFixProvider + internal class QuickFixProvider : IQuickFixProvider { private readonly IRewritingManager _rewritingManager; private readonly IQuickFixFailureNotifier _failureNotifier; diff --git a/Rubberduck.Core/Properties/AssemblyInfo.cs b/Rubberduck.Core/Properties/AssemblyInfo.cs index f69f5b5c7b..6b3ce1131c 100644 --- a/Rubberduck.Core/Properties/AssemblyInfo.cs +++ b/Rubberduck.Core/Properties/AssemblyInfo.cs @@ -1,6 +1,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +//This is the assembly name of the project Rubberduck.Main. [assembly: InternalsVisibleTo("Rubberduck")] // internals visible for testing and mocking [assembly: InternalsVisibleTo("RubberduckTests")] diff --git a/Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs b/Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs index edfa29fd58..e02bcfb5a2 100644 --- a/Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs +++ b/Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs @@ -281,9 +281,9 @@ public string InspectionDescriptionFilter private bool FilterResults(object inspectionResult) { - var inspectionResultBase = inspectionResult as InspectionResultBase; + var inspectionResultBase = inspectionResult as IInspectionResult; - return inspectionResultBase.Description.ToUpper().Contains(InspectionDescriptionFilter.ToUpper()); ; + return inspectionResultBase?.Description.ToUpper().Contains(InspectionDescriptionFilter.ToUpper()) ?? false; } private bool InspectionFilter(IInspectionResult result) diff --git a/Rubberduck.Deployment/Properties/AssemblyInfo.cs b/Rubberduck.Deployment/Properties/AssemblyInfo.cs index 940508a13d..9213ccf3c2 100644 --- a/Rubberduck.Deployment/Properties/AssemblyInfo.cs +++ b/Rubberduck.Deployment/Properties/AssemblyInfo.cs @@ -1,6 +1,4 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from diff --git a/Rubberduck.Interaction/Properties/AssemblyInfo.cs b/Rubberduck.Interaction/Properties/AssemblyInfo.cs index 3fbbcdf59e..552b666982 100644 --- a/Rubberduck.Interaction/Properties/AssemblyInfo.cs +++ b/Rubberduck.Interaction/Properties/AssemblyInfo.cs @@ -1,9 +1,9 @@ -using System.Reflection; -using System.Runtime.CompilerServices; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; [assembly: InternalsVisibleTo("RubberduckTests")] -[assembly: InternalsVisibleTo("Rubberduck.Main")] +//This is the assembly name of the project Rubberduck.Main. +[assembly: InternalsVisibleTo("Rubberduck")] [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM diff --git a/Rubberduck.JunkDrawer/Properties/AssemblyInfo.cs b/Rubberduck.JunkDrawer/Properties/AssemblyInfo.cs index 0d9df4ec3a..ab6df6d990 100644 --- a/Rubberduck.JunkDrawer/Properties/AssemblyInfo.cs +++ b/Rubberduck.JunkDrawer/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ -using System.Reflection; -using System.Runtime.CompilerServices; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // Setting ComVisible to false makes the types in this assembly not visible @@ -9,5 +8,7 @@ // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("d7a3f7a3-bd90-4845-b098-ac3afbf0e16f")] + [assembly: InternalsVisibleTo("RubberduckTests")] +//This is the assembly name of the project Rubberduck.Main. [assembly: InternalsVisibleTo("Rubberduck")] \ No newline at end of file diff --git a/Rubberduck.Main/Properties/AssemblyInfo.cs b/Rubberduck.Main/Properties/AssemblyInfo.cs index 684a087eb4..dc2ef11c13 100644 --- a/Rubberduck.Main/Properties/AssemblyInfo.cs +++ b/Rubberduck.Main/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ -using System.Reflection; -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; using System.Runtime.CompilerServices; using Rubberduck.Resources.Registration; diff --git a/Rubberduck.Parsing/Properties/AssemblyInfo.cs b/Rubberduck.Parsing/Properties/AssemblyInfo.cs index 7d724fd7bc..bba390252c 100644 --- a/Rubberduck.Parsing/Properties/AssemblyInfo.cs +++ b/Rubberduck.Parsing/Properties/AssemblyInfo.cs @@ -1,8 +1,8 @@ -using System; -using System.Reflection; -using System.Runtime.CompilerServices; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +//This is the assembly name of the project Rubberduck.Main. +[assembly: InternalsVisibleTo("Rubberduck")] [assembly: InternalsVisibleTo("RubberduckTests")] [assembly: ComVisible(false)] diff --git a/Rubberduck.Refactorings/Properties/AssemblyInfo.cs b/Rubberduck.Refactorings/Properties/AssemblyInfo.cs index ccfe2b7dc1..19f015b0cf 100644 --- a/Rubberduck.Refactorings/Properties/AssemblyInfo.cs +++ b/Rubberduck.Refactorings/Properties/AssemblyInfo.cs @@ -1,7 +1,10 @@ -using System.Reflection; -using System.Runtime.CompilerServices; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +//This is the assembly name of the project Rubberduck.Main. +[assembly: InternalsVisibleTo("Rubberduck")] +[assembly: InternalsVisibleTo("RubberduckTests")] + [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("d4b6a510-14e1-420a-a8d5-6a09890fd7d8")] \ No newline at end of file diff --git a/Rubberduck.RegexAssistant/Properties/AssemblyInfo.cs b/Rubberduck.RegexAssistant/Properties/AssemblyInfo.cs index 0402f52543..ca111f136a 100644 --- a/Rubberduck.RegexAssistant/Properties/AssemblyInfo.cs +++ b/Rubberduck.RegexAssistant/Properties/AssemblyInfo.cs @@ -1,8 +1,8 @@ -using System.Reflection; -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; using System.Runtime.CompilerServices; -// Make internals visible to test project +//This is the assembly name of the project Rubberduck.Main. +[assembly: InternalsVisibleTo("Rubberduck")] [assembly: InternalsVisibleTo("RubberduckTests")] [assembly: ComVisible(false)] diff --git a/Rubberduck.Resources/Properties/AssemblyInfo.cs b/Rubberduck.Resources/Properties/AssemblyInfo.cs index 4161080b7d..02b2069c3c 100644 --- a/Rubberduck.Resources/Properties/AssemblyInfo.cs +++ b/Rubberduck.Resources/Properties/AssemblyInfo.cs @@ -1,6 +1,4 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM diff --git a/Rubberduck.SettingsProvider/Properties/AssemblyInfo.cs b/Rubberduck.SettingsProvider/Properties/AssemblyInfo.cs index ac1ad8ea83..17c25c253e 100644 --- a/Rubberduck.SettingsProvider/Properties/AssemblyInfo.cs +++ b/Rubberduck.SettingsProvider/Properties/AssemblyInfo.cs @@ -1,9 +1,9 @@ -using System.Reflection; -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; using System.Runtime.CompilerServices; -[assembly: InternalsVisibleTo("RubberduckTests")] +//This is the assembly name of the project Rubberduck.Main. [assembly: InternalsVisibleTo("Rubberduck")] +[assembly: InternalsVisibleTo("RubberduckTests")] // Moq needs this to access the types [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] diff --git a/Rubberduck.SmartIndenter/Properties/AssemblyInfo.cs b/Rubberduck.SmartIndenter/Properties/AssemblyInfo.cs index 0967228bfd..5144ead171 100644 --- a/Rubberduck.SmartIndenter/Properties/AssemblyInfo.cs +++ b/Rubberduck.SmartIndenter/Properties/AssemblyInfo.cs @@ -1,7 +1,8 @@ -using System.Reflection; -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; using System.Runtime.CompilerServices; +//This is the assembly name of the project Rubberduck.Main. +[assembly: InternalsVisibleTo("Rubberduck")] [assembly: InternalsVisibleTo("RubberduckTests")] [assembly: ComVisible(false)] diff --git a/Rubberduck.UnitTesting/Properties/AssemblyInfo.cs b/Rubberduck.UnitTesting/Properties/AssemblyInfo.cs index 809cb704b8..194d913dbb 100644 --- a/Rubberduck.UnitTesting/Properties/AssemblyInfo.cs +++ b/Rubberduck.UnitTesting/Properties/AssemblyInfo.cs @@ -1,9 +1,9 @@ -using System.Reflection; -using System.Runtime.CompilerServices; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -[assembly: InternalsVisibleTo("RubberduckTests")] +//This is the assembly name of the project Rubberduck.Main. [assembly: InternalsVisibleTo("Rubberduck")] +[assembly: InternalsVisibleTo("RubberduckTests")] [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM diff --git a/Rubberduck.VBEEditor/Properties/AssemblyInfo.cs b/Rubberduck.VBEEditor/Properties/AssemblyInfo.cs index 149c390a70..d87e267923 100644 --- a/Rubberduck.VBEEditor/Properties/AssemblyInfo.cs +++ b/Rubberduck.VBEEditor/Properties/AssemblyInfo.cs @@ -1,6 +1,8 @@ using System.Runtime.InteropServices; using System.Runtime.CompilerServices; +//This is the assembly name of the project Rubberduck.Main. +[assembly: InternalsVisibleTo("Rubberduck")] [assembly: InternalsVisibleTo("RubberduckTests")] //Allow Rubberduck.VBEditor.* projects to use internal class diff --git a/Rubberduck.VBEditor.VB6/Properties/AssemblyInfo.cs b/Rubberduck.VBEditor.VB6/Properties/AssemblyInfo.cs index 79f0171086..23ecb7c401 100644 --- a/Rubberduck.VBEditor.VB6/Properties/AssemblyInfo.cs +++ b/Rubberduck.VBEditor.VB6/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ -using System.Reflection; -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM diff --git a/Rubberduck.VBEditor.VBA/Properties/AssemblyInfo.cs b/Rubberduck.VBEditor.VBA/Properties/AssemblyInfo.cs index 11e5372835..987b6b758b 100644 --- a/Rubberduck.VBEditor.VBA/Properties/AssemblyInfo.cs +++ b/Rubberduck.VBEditor.VBA/Properties/AssemblyInfo.cs @@ -1,6 +1,4 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; +using System.Runtime.InteropServices; [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM From 932ac85b06026ace5bbf80f011047e0d34d332c7 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sat, 7 Mar 2020 18:35:07 +0100 Subject: [PATCH 286/461] Move inspection and quick fix interfaces into CodeAnalysis --- .../Inspections/Abstract/DeclarationInspectionBase.cs | 2 +- .../Inspections/Abstract/DeclarationInspectionBaseBase.cs | 2 +- .../Abstract/DeclarationInspectionMultiResultBase.cs | 2 +- .../DeclarationInspectionUsingGlobalInformationBase.cs | 2 +- .../DeclarationInspectionUsingGlobalInformationBaseBase.cs | 2 +- .../Inspections/Abstract/IdentifierReferenceInspectionBase.cs | 2 +- .../IdentifierReferenceInspectionFromDeclarationsBase.cs | 2 +- .../Inspections/Abstract/InspectionBase.cs | 2 +- .../Inspections/Abstract/InspectionResultBase.cs | 2 +- .../Inspections/Abstract/ParseTreeInspectionBase.cs | 2 +- .../Inspections/Concrete/BooleanAssignedInIfElseInspection.cs | 2 +- .../Inspections/Concrete/DefTypeStatementInspection.cs | 2 +- .../Concrete/EmptyBlock/EmptyCaseBlockInspection.cs | 2 +- .../Concrete/EmptyBlock/EmptyDoWhileBlockInspection.cs | 2 +- .../Concrete/EmptyBlock/EmptyElseBlockInspection.cs | 2 +- .../Concrete/EmptyBlock/EmptyForEachBlockInspection.cs | 2 +- .../Concrete/EmptyBlock/EmptyForLoopBlockInspection.cs | 2 +- .../Inspections/Concrete/EmptyBlock/EmptyIfBlockInspection.cs | 2 +- .../Concrete/EmptyBlock/EmptyWhileWendBlockInspection.cs | 2 +- .../Inspections/Concrete/EmptyStringLiteralInspection.cs | 4 ++-- .../Excel/ExcelUdfNameIsValidCellReferenceInspection.cs | 2 +- .../Inspections/Concrete/IllegalAnnotationInspection.cs | 2 +- .../Concrete/MissingAnnotationArgumentInspection.cs | 2 +- .../Inspections/Concrete/ModuleScopeDimKeywordInspection.cs | 2 +- .../Inspections/Concrete/MultilineParameterInspection.cs | 2 +- .../Inspections/Concrete/MultipleDeclarationsInspection.cs | 2 +- .../Concrete/ObjectWhereProcedureIsRequiredInspection.cs | 2 +- .../Inspections/Concrete/ObsoleteCallStatementInspection.cs | 2 +- .../Concrete/ObsoleteCallingConventionInspection.cs | 4 ++-- .../Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs | 4 ++-- .../Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs | 4 ++-- .../Inspections/Concrete/ObsoleteLetStatementInspection.cs | 2 +- .../Inspections/Concrete/ObsoleteTypeHintInspection.cs | 2 +- .../Concrete/ObsoleteWhileWendStatementInspection.cs | 1 - .../Inspections/Concrete/OnLocalErrorInspection.cs | 2 +- .../Inspections/Concrete/OptionBaseInspection.cs | 2 +- .../Inspections/Concrete/OptionExplicitInspection.cs | 2 +- .../Inspections/Concrete/RedundantOptionInspection.cs | 2 +- .../Inspections/Concrete/StepIsNotSpecifiedInspection.cs | 2 +- .../Inspections/Concrete/StepOneIsRedundantInspection.cs | 2 +- .../Inspections/Concrete/StopKeywordInspection.cs | 2 +- .../Concrete/SuperfluousAnnotationArgumentInspection.cs | 2 +- .../Inspections/Concrete/SuspiciousLetAssignmentInspection.cs | 2 +- .../ThunderCode/LineContinuationBetweenKeywordsInspection.cs | 2 +- .../Concrete/ThunderCode/NegativeLineNumberInspection.cs | 2 +- .../Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs | 2 +- .../Concrete/UnhandledOnErrorResumeNextInspection.cs | 2 +- .../UnreachableCaseInspection/UnreachableCaseInspection.cs | 2 +- .../Inspections/Concrete/VariableNotUsedInspection.cs | 2 +- .../Inspections/Concrete/WriteOnlyPropertyInspection.cs | 2 +- .../Inspections/Extensions/IgnoreRelatedExtensions.cs | 2 +- .../Inspections}/IInpsectionListener.cs | 3 ++- .../Inspections}/IInspection.cs | 2 +- .../Inspections}/IInspectionModel.cs | 2 +- .../Inspections}/IInspectionResult.cs | 2 +- .../Inspections}/IInspector.cs | 2 +- .../Inspections}/IParseTreeInspection.cs | 2 +- .../Inspections/Logistics/IInspectionProvider.cs | 1 - .../Inspections/Logistics/InspectionProvider.cs | 1 - Rubberduck.CodeAnalysis/Inspections/Logistics/Inspector.cs | 1 - .../Inspections/Results/DeclarationInspectionResult.cs | 2 +- .../Results/IdentifierReferenceInspectionResult.cs | 2 +- .../Inspections/Results/QualifiedContextInspectionResult.cs | 2 +- Rubberduck.CodeAnalysis/Properties/AssemblyInfo.cs | 2 ++ Rubberduck.CodeAnalysis/QuickFixes/Abstract/QuickFixBase.cs | 2 +- .../QuickFixes/Abstract/RefactoringQuickFixBase.cs | 2 +- .../QuickFixes/Concrete/AccessSheetUsingCodeNameQuickFix.cs | 2 +- .../QuickFixes/Concrete/AddAttributeAnnotationQuickFix.cs | 2 +- .../QuickFixes/Concrete/AddIdentifierToWhiteListQuickFix.cs | 2 +- .../QuickFixes/Concrete/AddMissingAttributeQuickFix.cs | 4 ++-- .../QuickFixes/Concrete/AddStepOneQuickFix.cs | 2 +- .../QuickFixes/Concrete/AdjustAttributeAnnotationQuickFix.cs | 2 +- .../QuickFixes/Concrete/AdjustAttributeValuesQuickFix.cs | 2 +- .../Concrete/ApplicationWorksheetFunctionQuickFix.cs | 2 +- .../Concrete/AssignedByValParameterMakeLocalCopyQuickFix.cs | 2 +- .../QuickFixes/Concrete/ChangeDimToPrivateQuickFix.cs | 2 +- .../QuickFixes/Concrete/ChangeIntegerToLongQuickFix.cs | 2 +- .../QuickFixes/Concrete/ChangeProcedureToFunctionQuickFix.cs | 2 +- .../QuickFixes/Concrete/ConvertToProcedureQuickFix.cs | 2 +- .../QuickFixes/Concrete/DeclareAsExplicitVariantQuickFix.cs | 2 +- .../QuickFixes/Concrete/ExpandBangNotationQuickFix.cs | 2 +- .../QuickFixes/Concrete/ExpandDefaultMemberQuickFix.cs | 2 +- .../QuickFixes/Concrete/IgnoreOnceQuickFix.cs | 2 +- .../QuickFixes/Concrete/IntroduceLocalVariableQuickFix.cs | 2 +- .../Concrete/IsMissingOnInappropriateArgumentQuickFix.cs | 2 +- .../QuickFixes/Concrete/MakeSingleLineParameterQuickFix.cs | 2 +- .../QuickFixes/Concrete/OptionExplicitQuickFix.cs | 2 +- .../QuickFixes/Concrete/PassParameterByReferenceQuickFix.cs | 2 +- .../QuickFixes/Concrete/PassParameterByValueQuickFix.cs | 2 +- .../Concrete/Refactoring/EncapsulateFieldQuickFix.cs | 2 +- .../Concrete/Refactoring/MoveFieldCloserToUsageQuickFix.cs | 2 +- .../Concrete/Refactoring/RemoveUnusedParameterQuickFix.cs | 2 +- .../Concrete/Refactoring/RenameDeclarationQuickFix.cs | 2 +- .../QuickFixes/Concrete/RemoveAnnotationQuickFix.cs | 4 ++-- .../QuickFixes/Concrete/RemoveAttributeQuickFix.cs | 2 +- .../QuickFixes/Concrete/RemoveCommentQuickFix.cs | 2 +- .../QuickFixes/Concrete/RemoveDuplicatedAnnotationQuickFix.cs | 2 +- .../QuickFixes/Concrete/RemoveEmptyElseBlockQuickFix.cs | 4 ++-- .../QuickFixes/Concrete/RemoveEmptyIfBlockQuickFix.cs | 2 +- .../Concrete/RemoveExplicitByRefModifierQuickFix.cs | 2 +- .../Concrete/RemoveExplicitCallStatementQuickFix.cs | 2 +- .../QuickFixes/Concrete/RemoveExplicitLetStatementQuickFix.cs | 2 +- .../QuickFixes/Concrete/RemoveLocalErrorQuickFix.cs | 2 +- .../QuickFixes/Concrete/RemoveOptionBaseStatementQuickFix.cs | 2 +- .../QuickFixes/Concrete/RemoveStepOneQuickFix.cs | 4 ++-- .../QuickFixes/Concrete/RemoveStopKeywordQuickFix.cs | 2 +- .../QuickFixes/Concrete/RemoveTypeHintsQuickFix.cs | 2 +- .../QuickFixes/Concrete/RemoveUnassignedIdentifierQuickFix.cs | 2 +- .../Concrete/RemoveUnassignedVariableUsageQuickFix.cs | 2 +- .../QuickFixes/Concrete/RemoveUnusedDeclarationQuickFix.cs | 2 +- .../Concrete/ReplaceEmptyStringLiteralStatementQuickFix.cs | 2 +- .../QuickFixes/Concrete/ReplaceGlobalModifierQuickFix.cs | 2 +- .../Concrete/ReplaceIfElseWithConditionalStatementQuickFix.cs | 2 +- .../Concrete/ReplaceObsoleteCommentMarkerQuickFix.cs | 2 +- .../Concrete/ReplaceObsoleteErrorStatementQuickFix.cs | 2 +- .../Concrete/ReplaceWhileWendWithDoWhileLoopQuickFix.cs | 4 ++-- .../QuickFixes/Concrete/RestoreErrorHandlingQuickFix.cs | 2 +- .../Concrete/SetExplicitVariantReturnTypeQuickFix.cs | 2 +- .../Concrete/SpecifyExplicitByRefModifierQuickFix.cs | 2 +- .../Concrete/SpecifyExplicitPublicModifierQuickFix.cs | 2 +- .../QuickFixes/Concrete/SplitMultipleDeclarationsQuickFix.cs | 2 +- .../QuickFixes/Concrete/UntypedFunctionUsageQuickFix.cs | 2 +- .../Concrete/UseSetKeywordForObjectAssignmentQuickFix.cs | 2 +- .../QuickFixes/Concrete/WriteOnlyPropertyQuickFix.cs | 2 +- .../QuickFixes}/IQuickFix.cs | 3 ++- .../QuickFixes}/IQuickFixProvider.cs | 3 ++- .../QuickFixes/Logistics/QuickFixProvider.cs | 3 ++- Rubberduck.CodeAnalysis/Settings/CodeInspectionSettings.cs | 2 +- Rubberduck.Core/Formatters/InspectionResultFormatter.cs | 4 ++-- .../UI/Inspections/InspectionImageSourceConverter.cs | 2 +- Rubberduck.Core/UI/Inspections/InspectionResultComparer.cs | 4 ++-- Rubberduck.Core/UI/Inspections/InspectionResultsControl.xaml | 4 ++-- Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs | 3 ++- Rubberduck.Core/UI/Inspections/InspectionTypeConverter.cs | 2 +- Rubberduck.Main/Root/RubberduckIoCInstaller.cs | 3 ++- RubberduckTests/ConfigurationTests.cs | 2 +- .../ApplicationWorksheetFunctionInspectionTests.cs | 2 +- .../ArgumentWithIncompatibleObjectTypeInspectionTests.cs | 2 +- .../Inspections/AssignedByValParameterInspectionTests.cs | 2 +- .../Inspections/AssignmentNotUsedInspectionTests.cs | 2 +- .../Inspections/AttributeValueOutOfSyncInspectionTests.cs | 2 +- .../Inspections/BooleanAssignedInIfElseInspectionTests.cs | 2 +- RubberduckTests/Inspections/ConstantNotUsedInspectionTests.cs | 2 +- .../Inspections/DefTypeStatementInspectionTests.cs | 2 +- .../Inspections/DefaultMemberRequiredInspectionTests.cs | 2 +- .../Inspections/DefaultProjectNameInspectionTests.cs | 2 +- .../Inspections/DuplicatedAnnotationInspectionTests.cs | 2 +- RubberduckTests/Inspections/EmptyCaseBlockInspectionTests.cs | 2 +- .../Inspections/EmptyDoWhileBlockInspectionTests.cs | 2 +- RubberduckTests/Inspections/EmptyElseBlockInspectionTests.cs | 2 +- .../Inspections/EmptyForEachBlockInspectionTests.cs | 2 +- .../Inspections/EmptyForLoopBlockInspectionTests.cs | 2 +- RubberduckTests/Inspections/EmptyIfBlockInspectionTests.cs | 2 +- RubberduckTests/Inspections/EmptyMethodInspectionTests.cs | 2 +- RubberduckTests/Inspections/EmptyModuleInspectionTests.cs | 2 +- .../Inspections/EmptyStringLiteralInspectionTests.cs | 2 +- .../Inspections/EmptyWhileWendBlockInspectionTests.cs | 2 +- .../Inspections/EncapsulatePublicFieldInspectionTests.cs | 2 +- .../Inspections/ExcelMemberMayReturnNothingInspectionTests.cs | 2 +- .../ExcelUdfNameIsValidCellReferenceInspectionTests.cs | 2 +- .../FunctionReturnValueAlwaysDiscardedInspectionTests.cs | 2 +- .../FunctionReturnValueDiscardedInspectionTests.cs | 2 +- .../Inspections/HostSpecificExpressionInspectionTests.cs | 2 +- .../Inspections/HungarianNotationInspectionTests.cs | 2 +- .../Inspections/IllegalAnnotationsInspectionTests.cs | 2 +- .../Inspections/ImplementedInterfaceMemberInspectionTests.cs | 2 +- .../ImplicitActiveSheetReferenceInspectionTests.cs | 2 +- .../ImplicitActiveWorkbookReferenceInspectionTests.cs | 2 +- .../Inspections/ImplicitByRefModifierInspectionTests.cs | 2 +- .../Inspections/ImplicitDefaultMemberAccessInspectionTests.cs | 2 +- .../Inspections/ImplicitPublicMemberInspectionTests.cs | 2 +- .../ImplicitRecursiveDefaultMemberAccessInspectionTests.cs | 2 +- .../ImplicitUnboundDefaultMemberAccessInspectionTests.cs | 2 +- .../Inspections/ImplicitVariantReturnTypeInspectionTests.cs | 2 +- .../Inspections/ImplicitlyTypedConstInspectionTests.cs | 2 +- .../Inspections/IndexedDefaultMemberAccessInspectionTests.cs | 2 +- .../IndexedRecursiveDefaultMemberAccessInspectionTests.cs | 2 +- .../IndexedUnboundDefaultMemberAccessInspectionTests.cs | 2 +- RubberduckTests/Inspections/InspectionProviderTests.cs | 1 - RubberduckTests/Inspections/InspectionResultTests.cs | 2 +- RubberduckTests/Inspections/InspectionTestsBase.cs | 2 +- RubberduckTests/Inspections/InspectionsHelper.cs | 1 - RubberduckTests/Inspections/IntegerDataTypeInspectionTests.cs | 2 +- .../IsMissingOnInappropriateArgumentInspectionTests.cs | 2 +- .../IsMissingWithNonArgumentParameterInspectionTests.cs | 2 +- .../Inspections/LineLabelNotUsedInspectionTests.cs | 2 +- .../Inspections/MalformedAnnotationInspectionTests.cs | 2 +- .../Inspections/MemberNotOnInterfaceInspectionTests.cs | 2 +- .../Inspections/MissingAnnotationArgumentInspectionTests.cs | 2 +- .../Inspections/MissingAttributeInspectionTests.cs | 2 +- .../Inspections/MissingMemberAnnotationInspectionTests.cs | 2 +- .../Inspections/MissingModuleAnnotationInspectionTests.cs | 2 +- .../Inspections/ModuleScopeDimKeywordInspectionTests.cs | 2 +- .../Inspections/ModuleWithoutFolderInspectionTests.cs | 2 +- .../Inspections/MoveFieldCloserToUsageInspectionTests.cs | 2 +- .../Inspections/MultilineParameterInspectionTests.cs | 2 +- .../Inspections/MultipleDeclarationsInspectionTests.cs | 2 +- .../Inspections/NonReturningFunctionInspectionTests.cs | 2 +- .../Inspections/ObjectVariableNotSetInspectionTests.cs | 2 +- .../ObjectWhereProcedureIsRequiredInspectionTests.cs | 2 +- .../Inspections/ObsoleteCallStatementInspectionTests.cs | 2 +- .../Inspections/ObsoleteCallingConventionInspectionTests.cs | 2 +- .../Inspections/ObsoleteCommentSyntaxInspectionTests.cs | 2 +- .../Inspections/ObsoleteErrorSyntaxInspectionTests.cs | 2 +- RubberduckTests/Inspections/ObsoleteGlobalInspectionTests.cs | 2 +- .../Inspections/ObsoleteLetStatementInspectionTests.cs | 2 +- .../Inspections/ObsoleteMemberUsageInspectionTests.cs | 2 +- .../Inspections/ObsoleteTypeHintInspectionTests.cs | 2 +- .../Inspections/ObsoleteWhileWendInspectionTests.cs | 2 +- RubberduckTests/Inspections/OnLocalErrorInspectionTests.cs | 2 +- RubberduckTests/Inspections/OptionBaseInspectionTests.cs | 2 +- RubberduckTests/Inspections/OptionExplicitInspectionTests.cs | 2 +- .../Inspections/ParameterCanBeByValInspectionTests.cs | 2 +- .../Inspections/ParameterNotUsedInspectionTests.cs | 2 +- .../Inspections/ProcedureNotUsedInspectionTests.cs | 2 +- .../Inspections/ProcedureRequiredInspectionTests.cs | 2 +- .../Inspections/ProcedureShouldBeFunctionInspectionTests.cs | 2 +- .../Inspections/RedundantByRefModifierInspectionTests.cs | 2 +- RubberduckTests/Inspections/RedundantOptionInspectionTests.cs | 2 +- .../Inspections/SelfAssignedDeclarationInspectionTests.cs | 2 +- .../SetAssignmentWithIncompatibleObjectTypeInspectionTests.cs | 2 +- .../Inspections/ShadowedDeclarationInspectionTests.cs | 2 +- .../Inspections/SheetAccessedUsingStringInspectionTests.cs | 2 +- .../Inspections/StepNotSpecifiedInspectionTests.cs | 2 +- .../Inspections/StepOneIsRedundantInspectionTests.cs | 2 +- RubberduckTests/Inspections/StopKeywordInspectionTests.cs | 2 +- .../SuperfluousAnnotationArgumentInspectionTests.cs | 2 +- .../Inspections/SuspiciousLetAssignmentInspectionTests.cs | 2 +- .../Inspections/ThunderCode/ThunderCodeInspectionTests.cs | 2 +- .../Inspections/UnassignedVariableUsageInspectionTests.cs | 2 +- .../Inspections/UndeclaredVariableInspectionTests.cs | 2 +- .../UnderscoreInPublicClassModuleMemberInspectionTests.cs | 2 +- .../Inspections/UnhandledOnErrorResumeNextInspectionTest.cs | 2 +- .../UnreachableCase/UnreachableCaseInspectionTests.cs | 2 +- .../Inspections/UntypedFunctionUsageInspectionTests.cs | 2 +- .../Inspections/UseMeaningfulNameInspectionTests.cs | 2 +- .../Inspections/UseOfBangNotationInspectionTests.cs | 2 +- .../Inspections/UseOfRecursiveBangNotationInspectionTests.cs | 2 +- .../Inspections/UseOfUnboundBangNotationInspectionTests.cs | 2 +- RubberduckTests/Inspections/ValueRequiredInspectionTests.cs | 2 +- .../Inspections/VariableNotAssignedInspectionTests.cs | 2 +- RubberduckTests/Inspections/VariableNotUsedInspectionTests.cs | 2 +- .../Inspections/VariableTypeNotDeclaredInspectionTests.cs | 2 +- .../Inspections/WriteOnlyPropertyInspectionTests.cs | 2 +- RubberduckTests/IoCContainer/IoCResolvingTests.cs | 2 +- .../QuickFixes/AccessSheetUsingCodeNameQuickFixTests.cs | 2 +- .../QuickFixes/AddAttributeAnnotationQuickFixTests.cs | 2 +- .../QuickFixes/AddMissingAttributeQuickFixTests.cs | 2 +- RubberduckTests/QuickFixes/AddStepOneQuickFixTests.cs | 2 +- .../QuickFixes/AdjustAttributeAnnotationQuickFixTests.cs | 2 +- .../QuickFixes/AdjustAttributeValuesQuickFixTests.cs | 2 +- .../QuickFixes/ApplicationWorksheetFunctionQuickFixTests.cs | 2 +- RubberduckTests/QuickFixes/ChangeDimToPrivateQuickFixTests.cs | 2 +- .../QuickFixes/ChangeIntegerToLongQuickFixTests.cs | 3 ++- .../QuickFixes/ChangeProcedureToFunctionQuickFixTests.cs | 2 +- RubberduckTests/QuickFixes/ConvertToProcedureQuickFixTests.cs | 2 +- .../QuickFixes/DeclareAsExplicitVariantQuickFixTests.cs | 2 +- RubberduckTests/QuickFixes/ExpandBangNotationQuickFixTests.cs | 1 - .../QuickFixes/ExpandDefaultMemberQuickFixTests.cs | 1 - RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs | 2 +- .../QuickFixes/IntroduceLocalVariableQuickFixTests.cs | 2 +- .../IsMissingOnInappropriateArgumentQuickFixTests.cs | 2 +- .../QuickFixes/MakeSingleLineParamegerQuickFixTests.cs | 2 +- RubberduckTests/QuickFixes/OptionExplicitQuickFixTests.cs | 2 +- .../QuickFixes/PassParameterByReferenceQuickFixTests.cs | 2 +- .../QuickFixes/PassParameterByValueQuickFixTests.cs | 2 +- RubberduckTests/QuickFixes/QuickFixProviderTests.cs | 2 +- RubberduckTests/QuickFixes/QuickFixTestBase.cs | 3 ++- RubberduckTests/QuickFixes/RemoveAnnotationQuickFixTests.cs | 2 +- RubberduckTests/QuickFixes/RemoveAttributeQuickFixTests.cs | 2 +- RubberduckTests/QuickFixes/RemoveCommentQuickFixTests.cs | 2 +- .../QuickFixes/RemoveDuplicatedAnnotationQuickFixTests.cs | 3 ++- .../QuickFixes/RemoveEmptyElseBlockQuickFixTests.cs | 2 +- RubberduckTests/QuickFixes/RemoveEmptyIfBlockQuickFixTests.cs | 2 +- .../QuickFixes/RemoveExplicitByRefModifierQuickFixTests.cs | 3 ++- .../QuickFixes/RemoveExplicitCallStatementQuickFixTests.cs | 2 +- .../QuickFixes/RemoveExplicitLetStatementQuickFixTests.cs | 2 +- RubberduckTests/QuickFixes/RemoveLocalErrorQuickFixTests.cs | 2 +- .../QuickFixes/RemoveOptionBaseStatementQuickFixTests.cs | 2 +- RubberduckTests/QuickFixes/RemoveStepOneQuickFixTests.cs | 2 +- RubberduckTests/QuickFixes/RemoveStopKeywordQuickFixTests.cs | 2 +- RubberduckTests/QuickFixes/RemoveTypeHintsQuickFixTests.cs | 2 +- .../QuickFixes/RemoveUnassignedIdentifierQuickFixTests.cs | 3 ++- .../QuickFixes/RemoveUnassignedVariableUsageQuickFixTests.cs | 3 ++- .../QuickFixes/RemoveUnusedDeclarationQuickFixTests.cs | 2 +- .../ReplaceEmptyStringLiteralStatementQuickFixTests.cs | 2 +- .../QuickFixes/ReplaceGlobalModifierQuickFixTests.cs | 2 +- .../ReplaceIfElseWithConditionalStatementQuickFixTests.cs | 2 +- .../QuickFixes/ReplaceObsoleteCommentMarkerQuickFixTests.cs | 2 +- .../QuickFixes/ReplaceObsoleteErrorStatementQuickFixTests.cs | 2 +- .../ReplaceWhileWendWithDoWhileLoopQuickFixTests.cs | 1 - .../QuickFixes/RestoreErrorHandlingQuickFixTests.cs | 2 +- .../QuickFixes/SetExplicitVariantReturnTypeQuickFixTests.cs | 2 +- .../QuickFixes/SpecifyExplicitByRefModifierQuickFixTests.cs | 3 ++- .../QuickFixes/SpecifyExplicitPublicModifierQuickFixTests.cs | 2 +- .../QuickFixes/SplitMultipleDeclarationsQuickFixTests.cs | 2 +- .../UseSetKeywordForObjectAssignmentQuickFixTests.cs | 2 +- RubberduckTests/QuickFixes/WriteOnlyPropertyQuickFixTests.cs | 2 +- RubberduckTests/Settings/CodeInspectionConfigProviderTests.cs | 1 - 299 files changed, 315 insertions(+), 310 deletions(-) rename {Rubberduck.Parsing/Inspections/Abstract => Rubberduck.CodeAnalysis/Inspections}/IInpsectionListener.cs (89%) rename {Rubberduck.Parsing/Inspections/Abstract => Rubberduck.CodeAnalysis/Inspections}/IInspection.cs (96%) rename {Rubberduck.Parsing/Inspections/Abstract => Rubberduck.CodeAnalysis/Inspections}/IInspectionModel.cs (96%) rename {Rubberduck.Parsing/Inspections/Abstract => Rubberduck.CodeAnalysis/Inspections}/IInspectionResult.cs (93%) rename {Rubberduck.Parsing/Inspections/Abstract => Rubberduck.CodeAnalysis/Inspections}/IInspector.cs (86%) rename {Rubberduck.Parsing/Inspections/Abstract => Rubberduck.CodeAnalysis/Inspections}/IParseTreeInspection.cs (80%) rename {Rubberduck.Parsing/Inspections/Abstract => Rubberduck.CodeAnalysis/QuickFixes}/IQuickFix.cs (87%) rename {Rubberduck.Parsing/Inspections/Abstract => Rubberduck.CodeAnalysis/QuickFixes}/IQuickFixProvider.cs (92%) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs index 4bef41918a..8cb7ca65fe 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs index a368a7c0aa..7eb471f9b5 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionMultiResultBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionMultiResultBase.cs index 1cef4eb833..11f22db2c4 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionMultiResultBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionMultiResultBase.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBase.cs index 5a4e313f8d..726ef994c9 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBase.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs index f85a0a2de8..1de2ba7de6 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs index 907e22386c..8e171d6365 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs index 361c073d81..22e2218b1a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs index f7b844839a..ca0b99ba31 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs @@ -2,12 +2,12 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor; using System.Diagnostics; using System.Threading; using NLog; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Parsing.Inspections; using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionResultBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionResultBase.cs index 96a66993e9..9e3c0d3585 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionResultBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionResultBase.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using Antlr4.Runtime; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Common; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.VBEditor; using Rubberduck.Interaction.Navigation; diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs index 2b26585299..deba9858d6 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs @@ -1,11 +1,11 @@ using System.Collections.Generic; using System.Linq; using Antlr4.Runtime; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Results; using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Parsing.VBA.Parsing; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs index 71019835bb..c41b553f82 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs @@ -1,8 +1,8 @@ using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs index 28bf25ea4a..01e88a6ddf 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs @@ -2,10 +2,10 @@ using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Inspections; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing; using Antlr4.Runtime.Misc; +using Rubberduck.CodeAnalysis.Inspections; namespace Rubberduck.Inspections.Concrete { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyCaseBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyCaseBlockInspection.cs index ff2dac9f50..bf91c75e68 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyCaseBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyCaseBlockInspection.cs @@ -1,8 +1,8 @@ using Antlr4.Runtime.Misc; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Common; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Experimentals; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyDoWhileBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyDoWhileBlockInspection.cs index a82688b048..f07ba39905 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyDoWhileBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyDoWhileBlockInspection.cs @@ -1,8 +1,8 @@ using Antlr4.Runtime.Misc; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.Common; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Experimentals; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyElseBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyElseBlockInspection.cs index 190a901c70..dde85335cc 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyElseBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyElseBlockInspection.cs @@ -1,8 +1,8 @@ using Antlr4.Runtime.Misc; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.Common; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Experimentals; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyForEachBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyForEachBlockInspection.cs index d1fd1f6e24..d21eca5b77 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyForEachBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyForEachBlockInspection.cs @@ -1,8 +1,8 @@ using Antlr4.Runtime.Misc; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.Common; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Experimentals; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyForLoopBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyForLoopBlockInspection.cs index c31788959c..5f5d96a29c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyForLoopBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyForLoopBlockInspection.cs @@ -1,8 +1,8 @@ using Antlr4.Runtime.Misc; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.Common; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Experimentals; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyIfBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyIfBlockInspection.cs index c8ec8307d0..a6312f3764 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyIfBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyIfBlockInspection.cs @@ -1,9 +1,9 @@ using Antlr4.Runtime; using Antlr4.Runtime.Misc; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyWhileWendBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyWhileWendBlockInspection.cs index d2edfed906..021c449033 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyWhileWendBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyWhileWendBlockInspection.cs @@ -1,8 +1,8 @@ using Antlr4.Runtime.Misc; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.Common; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Experimentals; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs index 803da6db76..ea34ef3b30 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs @@ -1,7 +1,7 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs index 74e1321a23..02715f8282 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs @@ -2,9 +2,9 @@ using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.Inspections; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs index 83070c64ea..c92a9f35d5 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs @@ -1,11 +1,11 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Results; using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing; using Rubberduck.Parsing.Annotations; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs index 509aa82245..667c119634 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs @@ -1,10 +1,10 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Annotations; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs index 734f39484d..90c6f8bb4c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs @@ -1,8 +1,8 @@ using Antlr4.Runtime.Misc; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs index 033ee97122..ce6b2984a3 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs @@ -1,8 +1,8 @@ using Antlr4.Runtime.Misc; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Resources; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs index a1789bbc96..282d755b09 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs @@ -1,9 +1,9 @@ using Antlr4.Runtime; using Antlr4.Runtime.Misc; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs index 50b433e564..9b423e152b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs @@ -1,9 +1,9 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Results; using Rubberduck.Parsing.Inspections; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs index 50b01771c9..52bb2fd3e1 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs @@ -1,7 +1,7 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs index c4d37bb3e2..f8d3dbf7df 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs @@ -1,7 +1,7 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs index 09cb4f3b35..e40d6aef37 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs @@ -1,7 +1,7 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs index 1c3b9af6ec..4a1461e6da 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs @@ -1,7 +1,7 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs index 596ba76ff1..6cfb576e45 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs @@ -1,7 +1,7 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs index 25f44c6fdd..f5a7a65ff9 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs index 2203e98b82..89835e1523 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs @@ -1,7 +1,6 @@ using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Inspections; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs index 548d5e061c..ecdbe1f893 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs @@ -1,10 +1,10 @@ using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Antlr4.Runtime.Misc; +using Rubberduck.CodeAnalysis.Inspections; namespace Rubberduck.Inspections.Concrete { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs index c276bc726e..2c3fe8cc49 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs @@ -1,7 +1,7 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs index 7c0dd31f8a..7ccdb6ed5f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs @@ -1,9 +1,9 @@ using System.Collections.Generic; using Antlr4.Runtime.Misc; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs index df71f002fd..b8531f0022 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs @@ -1,8 +1,8 @@ using Antlr4.Runtime; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs index 22bfd5b075..94a8398e78 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs @@ -1,8 +1,8 @@ using Rubberduck.Inspections.Abstract; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Antlr4.Runtime.Misc; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs index 7c50d002f5..05a241a7a2 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs @@ -1,8 +1,8 @@ using Rubberduck.Inspections.Abstract; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Antlr4.Runtime.Misc; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs index add6051547..ae51bdd092 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs @@ -1,8 +1,8 @@ using Antlr4.Runtime.Misc; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuperfluousAnnotationArgumentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuperfluousAnnotationArgumentInspection.cs index 526bef21ca..306cda40ec 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuperfluousAnnotationArgumentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuperfluousAnnotationArgumentInspection.cs @@ -1,11 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Annotations; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs index a10970e155..cb14f0b694 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs @@ -1,12 +1,12 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/LineContinuationBetweenKeywordsInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/LineContinuationBetweenKeywordsInspection.cs index 456405e96d..59c06a609d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/LineContinuationBetweenKeywordsInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/LineContinuationBetweenKeywordsInspection.cs @@ -1,9 +1,9 @@ using Antlr4.Runtime; using Antlr4.Runtime.Tree; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Inspections; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NegativeLineNumberInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NegativeLineNumberInspection.cs index cc214e373c..76dcd0576f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NegativeLineNumberInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/NegativeLineNumberInspection.cs @@ -1,9 +1,9 @@ using Antlr4.Runtime; using Antlr4.Runtime.Tree; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Inspections; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs index 1a8aa0592f..b814116998 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/OnErrorGoToMinusOneInspection.cs @@ -1,8 +1,8 @@ using Antlr4.Runtime.Tree; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Inspections; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs index c58a977acb..1670358869 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnhandledOnErrorResumeNextInspection.cs @@ -1,9 +1,9 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs index 7adb40bbdc..4ea754cc8d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/UnreachableCaseInspection.cs @@ -4,7 +4,6 @@ using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor; @@ -12,6 +11,7 @@ using System.Linq; using Rubberduck.Parsing.Symbols; using System; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Parsing.VBA.Parsing; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotUsedInspection.cs index 514ed24a4a..a5b57c22a0 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/VariableNotUsedInspection.cs @@ -1,9 +1,9 @@ using System.Linq; using Antlr4.Runtime; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Results; using Rubberduck.Parsing; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/WriteOnlyPropertyInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/WriteOnlyPropertyInspection.cs index fbb48dbf49..50738349f0 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/WriteOnlyPropertyInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/WriteOnlyPropertyInspection.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Extensions/IgnoreRelatedExtensions.cs b/Rubberduck.CodeAnalysis/Inspections/Extensions/IgnoreRelatedExtensions.cs index a023e46a5b..576a22fd65 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Extensions/IgnoreRelatedExtensions.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Extensions/IgnoreRelatedExtensions.cs @@ -1,11 +1,11 @@ using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Annotations; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.VBEditor; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; namespace Rubberduck.Inspections.Inspections.Extensions { diff --git a/Rubberduck.Parsing/Inspections/Abstract/IInpsectionListener.cs b/Rubberduck.CodeAnalysis/Inspections/IInpsectionListener.cs similarity index 89% rename from Rubberduck.Parsing/Inspections/Abstract/IInpsectionListener.cs rename to Rubberduck.CodeAnalysis/Inspections/IInpsectionListener.cs index ff45d862a2..c8525f3c81 100644 --- a/Rubberduck.Parsing/Inspections/Abstract/IInpsectionListener.cs +++ b/Rubberduck.CodeAnalysis/Inspections/IInpsectionListener.cs @@ -1,9 +1,10 @@ using System.Collections.Generic; using Antlr4.Runtime; using Antlr4.Runtime.Tree; +using Rubberduck.Parsing; using Rubberduck.VBEditor; -namespace Rubberduck.Parsing.Inspections.Abstract +namespace Rubberduck.CodeAnalysis.Inspections { public interface IInspectionListener: IParseTreeListener { diff --git a/Rubberduck.Parsing/Inspections/Abstract/IInspection.cs b/Rubberduck.CodeAnalysis/Inspections/IInspection.cs similarity index 96% rename from Rubberduck.Parsing/Inspections/Abstract/IInspection.cs rename to Rubberduck.CodeAnalysis/Inspections/IInspection.cs index 519cca52b2..01019ffbee 100644 --- a/Rubberduck.Parsing/Inspections/Abstract/IInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/IInspection.cs @@ -3,7 +3,7 @@ using System.Threading; using Rubberduck.VBEditor; -namespace Rubberduck.Parsing.Inspections.Abstract +namespace Rubberduck.CodeAnalysis.Inspections { /// /// An interface that abstracts a runnable code inspection. diff --git a/Rubberduck.Parsing/Inspections/Abstract/IInspectionModel.cs b/Rubberduck.CodeAnalysis/Inspections/IInspectionModel.cs similarity index 96% rename from Rubberduck.Parsing/Inspections/Abstract/IInspectionModel.cs rename to Rubberduck.CodeAnalysis/Inspections/IInspectionModel.cs index 7f62f18a6d..bd1257f8e9 100644 --- a/Rubberduck.Parsing/Inspections/Abstract/IInspectionModel.cs +++ b/Rubberduck.CodeAnalysis/Inspections/IInspectionModel.cs @@ -1,6 +1,6 @@ using Rubberduck.Parsing.Inspections; -namespace Rubberduck.Parsing.Inspections.Abstract +namespace Rubberduck.CodeAnalysis.Inspections { /// /// An interface that abstracts the data structure for a code inspection diff --git a/Rubberduck.Parsing/Inspections/Abstract/IInspectionResult.cs b/Rubberduck.CodeAnalysis/Inspections/IInspectionResult.cs similarity index 93% rename from Rubberduck.Parsing/Inspections/Abstract/IInspectionResult.cs rename to Rubberduck.CodeAnalysis/Inspections/IInspectionResult.cs index 5df13602c7..ed1a69d591 100644 --- a/Rubberduck.Parsing/Inspections/Abstract/IInspectionResult.cs +++ b/Rubberduck.CodeAnalysis/Inspections/IInspectionResult.cs @@ -4,7 +4,7 @@ using Rubberduck.Parsing.Symbols; using Rubberduck.VBEditor; -namespace Rubberduck.Parsing.Inspections.Abstract +namespace Rubberduck.CodeAnalysis.Inspections { public interface IInspectionResult : IComparable, IComparable { diff --git a/Rubberduck.Parsing/Inspections/Abstract/IInspector.cs b/Rubberduck.CodeAnalysis/Inspections/IInspector.cs similarity index 86% rename from Rubberduck.Parsing/Inspections/Abstract/IInspector.cs rename to Rubberduck.CodeAnalysis/Inspections/IInspector.cs index f2287c97ec..a3c8e47309 100644 --- a/Rubberduck.Parsing/Inspections/Abstract/IInspector.cs +++ b/Rubberduck.CodeAnalysis/Inspections/IInspector.cs @@ -4,7 +4,7 @@ using System.Threading.Tasks; using Rubberduck.Parsing.VBA; -namespace Rubberduck.Parsing.Inspections.Abstract +namespace Rubberduck.CodeAnalysis.Inspections { public interface IInspector : IDisposable { diff --git a/Rubberduck.Parsing/Inspections/Abstract/IParseTreeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/IParseTreeInspection.cs similarity index 80% rename from Rubberduck.Parsing/Inspections/Abstract/IParseTreeInspection.cs rename to Rubberduck.CodeAnalysis/Inspections/IParseTreeInspection.cs index 8aa530a0d2..cc2211a232 100644 --- a/Rubberduck.Parsing/Inspections/Abstract/IParseTreeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/IParseTreeInspection.cs @@ -1,6 +1,6 @@ using Rubberduck.Parsing.VBA.Parsing; -namespace Rubberduck.Parsing.Inspections.Abstract +namespace Rubberduck.CodeAnalysis.Inspections { public interface IParseTreeInspection : IInspection { diff --git a/Rubberduck.CodeAnalysis/Inspections/Logistics/IInspectionProvider.cs b/Rubberduck.CodeAnalysis/Inspections/Logistics/IInspectionProvider.cs index d1501f63a6..48c66d6f5c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Logistics/IInspectionProvider.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Logistics/IInspectionProvider.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using Rubberduck.Parsing.Inspections.Abstract; namespace Rubberduck.CodeAnalysis.Inspections { diff --git a/Rubberduck.CodeAnalysis/Inspections/Logistics/InspectionProvider.cs b/Rubberduck.CodeAnalysis/Inspections/Logistics/InspectionProvider.cs index 68cda2c3d0..0e152c4fb8 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Logistics/InspectionProvider.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Logistics/InspectionProvider.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Settings; using Rubberduck.CodeAnalysis.Settings; diff --git a/Rubberduck.CodeAnalysis/Inspections/Logistics/Inspector.cs b/Rubberduck.CodeAnalysis/Inspections/Logistics/Inspector.cs index 71acea1df6..19a4ccc0cd 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Logistics/Inspector.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Logistics/Inspector.cs @@ -12,7 +12,6 @@ using NLog; using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Parsing.Inspections; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.Parsing; using Rubberduck.VBEditor; diff --git a/Rubberduck.CodeAnalysis/Inspections/Results/DeclarationInspectionResult.cs b/Rubberduck.CodeAnalysis/Inspections/Results/DeclarationInspectionResult.cs index 536e21da99..fe92c1d3b7 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Results/DeclarationInspectionResult.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Results/DeclarationInspectionResult.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.VBEditor; diff --git a/Rubberduck.CodeAnalysis/Inspections/Results/IdentifierReferenceInspectionResult.cs b/Rubberduck.CodeAnalysis/Inspections/Results/IdentifierReferenceInspectionResult.cs index 209800b7dd..c3c4c888f9 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Results/IdentifierReferenceInspectionResult.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Results/IdentifierReferenceInspectionResult.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.VBEditor; diff --git a/Rubberduck.CodeAnalysis/Inspections/Results/QualifiedContextInspectionResult.cs b/Rubberduck.CodeAnalysis/Inspections/Results/QualifiedContextInspectionResult.cs index ba3a7f018e..54e0fe5ceb 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Results/QualifiedContextInspectionResult.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Results/QualifiedContextInspectionResult.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.VBEditor; namespace Rubberduck.Inspections.Results diff --git a/Rubberduck.CodeAnalysis/Properties/AssemblyInfo.cs b/Rubberduck.CodeAnalysis/Properties/AssemblyInfo.cs index 636860a9b9..611db18814 100644 --- a/Rubberduck.CodeAnalysis/Properties/AssemblyInfo.cs +++ b/Rubberduck.CodeAnalysis/Properties/AssemblyInfo.cs @@ -3,7 +3,9 @@ //This is the assembly name of the project Rubberduck.Main. [assembly: InternalsVisibleTo("Rubberduck")] +// internals visible for testing and mocking [assembly: InternalsVisibleTo("RubberduckTests")] +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Abstract/QuickFixBase.cs b/Rubberduck.CodeAnalysis/QuickFixes/Abstract/QuickFixBase.cs index ac69eab02b..30657adbcf 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Abstract/QuickFixBase.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Abstract/QuickFixBase.cs @@ -3,8 +3,8 @@ using System.Diagnostics; using System.Linq; using NLog; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.JunkDrawer.Extensions; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.VBA.Parsing; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Abstract/RefactoringQuickFixBase.cs b/Rubberduck.CodeAnalysis/QuickFixes/Abstract/RefactoringQuickFixBase.cs index 0539534a15..3106e14dc5 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Abstract/RefactoringQuickFixBase.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Abstract/RefactoringQuickFixBase.cs @@ -1,5 +1,5 @@ using System; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Parsing.Rewriter; using Rubberduck.Refactorings; using Rubberduck.Refactorings.Exceptions; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AccessSheetUsingCodeNameQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AccessSheetUsingCodeNameQuickFix.cs index 6a42043c5e..2078e21658 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AccessSheetUsingCodeNameQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AccessSheetUsingCodeNameQuickFix.cs @@ -1,11 +1,11 @@ using System.Linq; using Antlr4.Runtime; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddAttributeAnnotationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddAttributeAnnotationQuickFix.cs index 1250e1ca38..47a6e432bb 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddAttributeAnnotationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddAttributeAnnotationQuickFix.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Annotations; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddIdentifierToWhiteListQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddIdentifierToWhiteListQuickFix.cs index 206e781554..d5205a83de 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddIdentifierToWhiteListQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddIdentifierToWhiteListQuickFix.cs @@ -1,7 +1,7 @@ using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.CodeAnalysis.Settings; using Rubberduck.SettingsProvider; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddMissingAttributeQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddMissingAttributeQuickFix.cs index 92ccbc9438..c7db80ffee 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddMissingAttributeQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddMissingAttributeQuickFix.cs @@ -1,7 +1,7 @@ -using Rubberduck.CodeAnalysis.QuickFixes.Abstract; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Annotations; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddStepOneQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddStepOneQuickFix.cs index 1948da1198..5e83c5615a 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddStepOneQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AddStepOneQuickFix.cs @@ -1,7 +1,7 @@ using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using System; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using static Rubberduck.Parsing.Grammar.VBAParser; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AdjustAttributeAnnotationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AdjustAttributeAnnotationQuickFix.cs index 9e68d8ea6d..18f6f06234 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AdjustAttributeAnnotationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AdjustAttributeAnnotationQuickFix.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Annotations; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AdjustAttributeValuesQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AdjustAttributeValuesQuickFix.cs index 1838523157..c242f6ba8b 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AdjustAttributeValuesQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AdjustAttributeValuesQuickFix.cs @@ -1,9 +1,9 @@ using System.Collections.Generic; using System.Diagnostics; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Annotations; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ApplicationWorksheetFunctionQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ApplicationWorksheetFunctionQuickFix.cs index 385af89e08..ccabc52334 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ApplicationWorksheetFunctionQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ApplicationWorksheetFunctionQuickFix.cs @@ -1,6 +1,6 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AssignedByValParameterMakeLocalCopyQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AssignedByValParameterMakeLocalCopyQuickFix.cs index b85a91e5a5..8ea46319fc 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AssignedByValParameterMakeLocalCopyQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/AssignedByValParameterMakeLocalCopyQuickFix.cs @@ -8,10 +8,10 @@ using System.Windows.Forms; using Antlr4.Runtime; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.VBA; using System.Diagnostics; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Refactorings.Common; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ChangeDimToPrivateQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ChangeDimToPrivateQuickFix.cs index 3dd45b2f08..8121b7dbc8 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ChangeDimToPrivateQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ChangeDimToPrivateQuickFix.cs @@ -1,7 +1,7 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ChangeIntegerToLongQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ChangeIntegerToLongQuickFix.cs index d6bac5f867..7f4d36c420 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ChangeIntegerToLongQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ChangeIntegerToLongQuickFix.cs @@ -2,11 +2,11 @@ using Rubberduck.Parsing.Grammar; using System.Linq; using Antlr4.Runtime; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ChangeProcedureToFunctionQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ChangeProcedureToFunctionQuickFix.cs index f3770473f3..bf9ca1c45c 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ChangeProcedureToFunctionQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ChangeProcedureToFunctionQuickFix.cs @@ -1,11 +1,11 @@ using System; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ConvertToProcedureQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ConvertToProcedureQuickFix.cs index 568051c9e6..22a4d2c2c6 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ConvertToProcedureQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ConvertToProcedureQuickFix.cs @@ -1,11 +1,11 @@ using System.Collections.Generic; using System.Linq; using Antlr4.Runtime; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/DeclareAsExplicitVariantQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/DeclareAsExplicitVariantQuickFix.cs index 4c94d08f16..7506f42fb2 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/DeclareAsExplicitVariantQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/DeclareAsExplicitVariantQuickFix.cs @@ -1,8 +1,8 @@ using Antlr4.Runtime; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ExpandBangNotationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ExpandBangNotationQuickFix.cs index 42fd28c0c8..e5701248e9 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ExpandBangNotationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ExpandBangNotationQuickFix.cs @@ -1,10 +1,10 @@ using System.Collections.Generic; using System.Linq; using Antlr4.Runtime; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ExpandDefaultMemberQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ExpandDefaultMemberQuickFix.cs index 7c7ae85124..f14972612e 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ExpandDefaultMemberQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ExpandDefaultMemberQuickFix.cs @@ -1,10 +1,10 @@ using System.Collections.Generic; using System.Linq; using Antlr4.Runtime; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/IgnoreOnceQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/IgnoreOnceQuickFix.cs index 860b0f583b..0222a2f511 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/IgnoreOnceQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/IgnoreOnceQuickFix.cs @@ -1,10 +1,10 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Inspections; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/IntroduceLocalVariableQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/IntroduceLocalVariableQuickFix.cs index 801b19824a..62ad2e7529 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/IntroduceLocalVariableQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/IntroduceLocalVariableQuickFix.cs @@ -1,10 +1,10 @@ using System; using System.Text.RegularExpressions; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/IsMissingOnInappropriateArgumentQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/IsMissingOnInappropriateArgumentQuickFix.cs index 473a8af474..e096c46553 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/IsMissingOnInappropriateArgumentQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/IsMissingOnInappropriateArgumentQuickFix.cs @@ -1,11 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/MakeSingleLineParameterQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/MakeSingleLineParameterQuickFix.cs index b3009f0df1..e15f0efb12 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/MakeSingleLineParameterQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/MakeSingleLineParameterQuickFix.cs @@ -1,6 +1,6 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.VBA.Extensions; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/OptionExplicitQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/OptionExplicitQuickFix.cs index f2a8c8293a..0e9c761d96 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/OptionExplicitQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/OptionExplicitQuickFix.cs @@ -1,8 +1,8 @@ using System; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/PassParameterByReferenceQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/PassParameterByReferenceQuickFix.cs index 1f23b5112b..0129fd12e0 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/PassParameterByReferenceQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/PassParameterByReferenceQuickFix.cs @@ -1,7 +1,7 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/PassParameterByValueQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/PassParameterByValueQuickFix.cs index 82763a63f2..f951e767f3 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/PassParameterByValueQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/PassParameterByValueQuickFix.cs @@ -1,8 +1,8 @@ using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/EncapsulateFieldQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/EncapsulateFieldQuickFix.cs index d4c0b22167..8f28d1e34a 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/EncapsulateFieldQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/EncapsulateFieldQuickFix.cs @@ -1,6 +1,6 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Refactorings.EncapsulateField; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/MoveFieldCloserToUsageQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/MoveFieldCloserToUsageQuickFix.cs index e5c2d5f5c8..81579c1732 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/MoveFieldCloserToUsageQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/MoveFieldCloserToUsageQuickFix.cs @@ -1,6 +1,6 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Refactorings.MoveCloserToUsage; using Rubberduck.Resources.Inspections; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/RemoveUnusedParameterQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/RemoveUnusedParameterQuickFix.cs index c00909d4b9..ca9244c049 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/RemoveUnusedParameterQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/RemoveUnusedParameterQuickFix.cs @@ -1,6 +1,6 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Refactorings.RemoveParameters; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/RenameDeclarationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/RenameDeclarationQuickFix.cs index 65645cdfb0..372200bafa 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/RenameDeclarationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/Refactoring/RenameDeclarationQuickFix.cs @@ -1,8 +1,8 @@ using System.Globalization; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Refactorings.Rename; using Rubberduck.Resources; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveAnnotationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveAnnotationQuickFix.cs index f94ca46477..f62cbc198b 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveAnnotationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveAnnotationQuickFix.cs @@ -1,7 +1,7 @@ -using Rubberduck.CodeAnalysis.QuickFixes.Abstract; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Annotations; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveAttributeQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveAttributeQuickFix.cs index 01bb94b938..5e3574bb59 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveAttributeQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveAttributeQuickFix.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveCommentQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveCommentQuickFix.cs index 777a0f214b..a197590e0c 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveCommentQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveCommentQuickFix.cs @@ -1,6 +1,6 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveDuplicatedAnnotationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveDuplicatedAnnotationQuickFix.cs index b492999068..89426729e4 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveDuplicatedAnnotationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveDuplicatedAnnotationQuickFix.cs @@ -1,8 +1,8 @@ using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Annotations; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveEmptyElseBlockQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveEmptyElseBlockQuickFix.cs index 289b58c9a5..7066e09edd 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveEmptyElseBlockQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveEmptyElseBlockQuickFix.cs @@ -1,6 +1,6 @@ -using Rubberduck.CodeAnalysis.QuickFixes.Abstract; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Rewriter; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveEmptyIfBlockQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveEmptyIfBlockQuickFix.cs index 03a78c04a9..bb410aed6a 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveEmptyIfBlockQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveEmptyIfBlockQuickFix.cs @@ -2,10 +2,10 @@ using System.Diagnostics; using System.Linq; using Antlr4.Runtime; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveExplicitByRefModifierQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveExplicitByRefModifierQuickFix.cs index 46d1b4dd8d..74f9fb6e38 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveExplicitByRefModifierQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveExplicitByRefModifierQuickFix.cs @@ -1,9 +1,9 @@ using Rubberduck.Parsing.Grammar; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.JunkDrawer.Extensions; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveExplicitCallStatementQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveExplicitCallStatementQuickFix.cs index 0e0d1bcca6..7af905a61b 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveExplicitCallStatementQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveExplicitCallStatementQuickFix.cs @@ -1,7 +1,7 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveExplicitLetStatementQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveExplicitLetStatementQuickFix.cs index 78ddda5bc7..8357a20698 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveExplicitLetStatementQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveExplicitLetStatementQuickFix.cs @@ -1,8 +1,8 @@ using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveLocalErrorQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveLocalErrorQuickFix.cs index 443e604f55..b3c3be9c70 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveLocalErrorQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveLocalErrorQuickFix.cs @@ -1,7 +1,7 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveOptionBaseStatementQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveOptionBaseStatementQuickFix.cs index a2b682a826..69e23b5d75 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveOptionBaseStatementQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveOptionBaseStatementQuickFix.cs @@ -1,6 +1,6 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveStepOneQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveStepOneQuickFix.cs index d1081b77bf..ef2c12edbb 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveStepOneQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveStepOneQuickFix.cs @@ -1,6 +1,6 @@ -using Rubberduck.CodeAnalysis.QuickFixes.Abstract; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveStopKeywordQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveStopKeywordQuickFix.cs index 10ede263e7..9769205ecf 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveStopKeywordQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveStopKeywordQuickFix.cs @@ -1,6 +1,6 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveTypeHintsQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveTypeHintsQuickFix.cs index 1039fbae3a..ee6e23445e 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveTypeHintsQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveTypeHintsQuickFix.cs @@ -1,8 +1,8 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveUnassignedIdentifierQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveUnassignedIdentifierQuickFix.cs index 5917631ba7..046a7378b5 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveUnassignedIdentifierQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveUnassignedIdentifierQuickFix.cs @@ -1,6 +1,6 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveUnassignedVariableUsageQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveUnassignedVariableUsageQuickFix.cs index e3a2d32e4d..d6acd4bb5f 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveUnassignedVariableUsageQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveUnassignedVariableUsageQuickFix.cs @@ -2,11 +2,11 @@ using System.Collections.Generic; using System.Linq; using Antlr4.Runtime; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveUnusedDeclarationQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveUnusedDeclarationQuickFix.cs index 57773cb284..e8e10b3c77 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveUnusedDeclarationQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RemoveUnusedDeclarationQuickFix.cs @@ -1,6 +1,6 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceEmptyStringLiteralStatementQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceEmptyStringLiteralStatementQuickFix.cs index fe80ad5b2b..34d88cee02 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceEmptyStringLiteralStatementQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceEmptyStringLiteralStatementQuickFix.cs @@ -1,6 +1,6 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceGlobalModifierQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceGlobalModifierQuickFix.cs index 4ff1446fdd..516b3ae6d7 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceGlobalModifierQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceGlobalModifierQuickFix.cs @@ -1,9 +1,9 @@ using Antlr4.Runtime; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceIfElseWithConditionalStatementQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceIfElseWithConditionalStatementQuickFix.cs index 369f96aa94..f18efcf038 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceIfElseWithConditionalStatementQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceIfElseWithConditionalStatementQuickFix.cs @@ -1,8 +1,8 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceObsoleteCommentMarkerQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceObsoleteCommentMarkerQuickFix.cs index 48d4508f5c..bfc80b5d34 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceObsoleteCommentMarkerQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceObsoleteCommentMarkerQuickFix.cs @@ -1,7 +1,7 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceObsoleteErrorStatementQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceObsoleteErrorStatementQuickFix.cs index 2476a8afbd..6ecd88932b 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceObsoleteErrorStatementQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceObsoleteErrorStatementQuickFix.cs @@ -1,7 +1,7 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceWhileWendWithDoWhileLoopQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceWhileWendWithDoWhileLoopQuickFix.cs index bf8ff2ae17..974a45af56 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceWhileWendWithDoWhileLoopQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/ReplaceWhileWendWithDoWhileLoopQuickFix.cs @@ -1,7 +1,7 @@ -using Rubberduck.CodeAnalysis.Inspections.Concrete; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.CodeAnalysis.Inspections.Concrete; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.CodeAnalysis.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RestoreErrorHandlingQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RestoreErrorHandlingQuickFix.cs index 2f3132f222..a3ecc1c681 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RestoreErrorHandlingQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/RestoreErrorHandlingQuickFix.cs @@ -1,11 +1,11 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/SetExplicitVariantReturnTypeQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/SetExplicitVariantReturnTypeQuickFix.cs index 7ca9bb8394..d44245f4bc 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/SetExplicitVariantReturnTypeQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/SetExplicitVariantReturnTypeQuickFix.cs @@ -1,7 +1,7 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/SpecifyExplicitByRefModifierQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/SpecifyExplicitByRefModifierQuickFix.cs index 10b738b4a1..2c2a273373 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/SpecifyExplicitByRefModifierQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/SpecifyExplicitByRefModifierQuickFix.cs @@ -1,9 +1,9 @@ using Rubberduck.Parsing.Grammar; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.JunkDrawer.Extensions; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/SpecifyExplicitPublicModifierQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/SpecifyExplicitPublicModifierQuickFix.cs index 656590db4e..c6135e432b 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/SpecifyExplicitPublicModifierQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/SpecifyExplicitPublicModifierQuickFix.cs @@ -1,6 +1,6 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/SplitMultipleDeclarationsQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/SplitMultipleDeclarationsQuickFix.cs index fc32964450..3d34344312 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/SplitMultipleDeclarationsQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/SplitMultipleDeclarationsQuickFix.cs @@ -1,10 +1,10 @@ using System; using System.Text; using Antlr4.Runtime; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/UntypedFunctionUsageQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/UntypedFunctionUsageQuickFix.cs index 300936a004..c165a48a6e 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/UntypedFunctionUsageQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/UntypedFunctionUsageQuickFix.cs @@ -1,10 +1,10 @@ using System.Diagnostics; using System.Linq; using Antlr4.Runtime; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/UseSetKeywordForObjectAssignmentQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/UseSetKeywordForObjectAssignmentQuickFix.cs index fb52a460d3..3d2487d800 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/UseSetKeywordForObjectAssignmentQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/UseSetKeywordForObjectAssignmentQuickFix.cs @@ -1,8 +1,8 @@ +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; namespace Rubberduck.Inspections.QuickFixes diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/WriteOnlyPropertyQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/WriteOnlyPropertyQuickFix.cs index 1693a3ae31..565292dc2c 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/WriteOnlyPropertyQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/WriteOnlyPropertyQuickFix.cs @@ -1,9 +1,9 @@ using System; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; diff --git a/Rubberduck.Parsing/Inspections/Abstract/IQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/IQuickFix.cs similarity index 87% rename from Rubberduck.Parsing/Inspections/Abstract/IQuickFix.cs rename to Rubberduck.CodeAnalysis/QuickFixes/IQuickFix.cs index f84cc8c814..ef08b66b3a 100644 --- a/Rubberduck.Parsing/Inspections/Abstract/IQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/IQuickFix.cs @@ -1,9 +1,10 @@ using System; using System.Collections.Generic; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.VBA.Parsing; -namespace Rubberduck.Parsing.Inspections.Abstract +namespace Rubberduck.CodeAnalysis.QuickFixes { public interface IQuickFix { diff --git a/Rubberduck.Parsing/Inspections/Abstract/IQuickFixProvider.cs b/Rubberduck.CodeAnalysis/QuickFixes/IQuickFixProvider.cs similarity index 92% rename from Rubberduck.Parsing/Inspections/Abstract/IQuickFixProvider.cs rename to Rubberduck.CodeAnalysis/QuickFixes/IQuickFixProvider.cs index 75d2cf8149..a45a2b114c 100644 --- a/Rubberduck.Parsing/Inspections/Abstract/IQuickFixProvider.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/IQuickFixProvider.cs @@ -1,8 +1,9 @@ using System; using System.Collections.Generic; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.VBEditor; -namespace Rubberduck.Parsing.Inspections.Abstract +namespace Rubberduck.CodeAnalysis.QuickFixes { /// /// An interface that abstracts a runnable code inspection. diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Logistics/QuickFixProvider.cs b/Rubberduck.CodeAnalysis/QuickFixes/Logistics/QuickFixProvider.cs index c2682a35b6..f1ddbafa47 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Logistics/QuickFixProvider.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Logistics/QuickFixProvider.cs @@ -2,7 +2,8 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.VBA.Parsing; using Rubberduck.Refactorings.Exceptions; diff --git a/Rubberduck.CodeAnalysis/Settings/CodeInspectionSettings.cs b/Rubberduck.CodeAnalysis/Settings/CodeInspectionSettings.cs index 4d8dc15467..1a133ad979 100644 --- a/Rubberduck.CodeAnalysis/Settings/CodeInspectionSettings.cs +++ b/Rubberduck.CodeAnalysis/Settings/CodeInspectionSettings.cs @@ -4,7 +4,7 @@ using System.Globalization; using System.Linq; using System.Xml.Serialization; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Parsing.Inspections; namespace Rubberduck.CodeAnalysis.Settings diff --git a/Rubberduck.Core/Formatters/InspectionResultFormatter.cs b/Rubberduck.Core/Formatters/InspectionResultFormatter.cs index d98a739442..0ca9a243a4 100644 --- a/Rubberduck.Core/Formatters/InspectionResultFormatter.cs +++ b/Rubberduck.Core/Formatters/InspectionResultFormatter.cs @@ -1,5 +1,5 @@ -using Rubberduck.Common; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.Common; using Rubberduck.Resources.Inspections; namespace Rubberduck.Formatters diff --git a/Rubberduck.Core/UI/Inspections/InspectionImageSourceConverter.cs b/Rubberduck.Core/UI/Inspections/InspectionImageSourceConverter.cs index 4fd6f0cdb4..be6a35dc73 100644 --- a/Rubberduck.Core/UI/Inspections/InspectionImageSourceConverter.cs +++ b/Rubberduck.Core/UI/Inspections/InspectionImageSourceConverter.cs @@ -1,7 +1,7 @@ using System; using System.Globalization; using System.Windows.Data; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; namespace Rubberduck.UI.Inspections { diff --git a/Rubberduck.Core/UI/Inspections/InspectionResultComparer.cs b/Rubberduck.Core/UI/Inspections/InspectionResultComparer.cs index 7495e69020..d1e554aa4e 100644 --- a/Rubberduck.Core/UI/Inspections/InspectionResultComparer.cs +++ b/Rubberduck.Core/UI/Inspections/InspectionResultComparer.cs @@ -1,5 +1,5 @@ -using Rubberduck.Parsing.Inspections.Abstract; -using System.Collections.Generic; +using System.Collections.Generic; +using Rubberduck.CodeAnalysis.Inspections; namespace Rubberduck.UI.Inspections { diff --git a/Rubberduck.Core/UI/Inspections/InspectionResultsControl.xaml b/Rubberduck.Core/UI/Inspections/InspectionResultsControl.xaml index 8256fc209b..53fd28924f 100644 --- a/Rubberduck.Core/UI/Inspections/InspectionResultsControl.xaml +++ b/Rubberduck.Core/UI/Inspections/InspectionResultsControl.xaml @@ -5,8 +5,8 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:codeInspections="clr-namespace:Rubberduck.UI.Inspections" xmlns:controls="clr-namespace:Rubberduck.UI.Controls" - xmlns:abstract1="clr-namespace:Rubberduck.Parsing.Inspections.Abstract;assembly=Rubberduck.Parsing" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" + xmlns:inspections="clr-namespace:Rubberduck.CodeAnalysis.Inspections;assembly=Rubberduck.CodeAnalysis" ResxExtension.DefaultResxName="Rubberduck.Resources.RubberduckUI" Language="{UICulture}" mc:Ignorable="d" @@ -216,7 +216,7 @@ - + diff --git a/Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs b/Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs index e02bcfb5a2..04602e67e0 100644 --- a/Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs +++ b/Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs @@ -13,13 +13,14 @@ using System.Windows.Data; using System.Windows.Input; using NLog; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Common; using Rubberduck.Formatters; using Rubberduck.Inspections.Abstract; using Rubberduck.Interaction.Navigation; using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing.Inspections; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.UIContext; using Rubberduck.Parsing.VBA; using Rubberduck.Settings; diff --git a/Rubberduck.Core/UI/Inspections/InspectionTypeConverter.cs b/Rubberduck.Core/UI/Inspections/InspectionTypeConverter.cs index 016444e347..c0b667cd32 100644 --- a/Rubberduck.Core/UI/Inspections/InspectionTypeConverter.cs +++ b/Rubberduck.Core/UI/Inspections/InspectionTypeConverter.cs @@ -1,7 +1,7 @@ using System; using System.Globalization; using System.Windows.Data; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Resources.Inspections; namespace Rubberduck.UI.Inspections diff --git a/Rubberduck.Main/Root/RubberduckIoCInstaller.cs b/Rubberduck.Main/Root/RubberduckIoCInstaller.cs index 45ec8c401c..e9f6a610b5 100644 --- a/Rubberduck.Main/Root/RubberduckIoCInstaller.cs +++ b/Rubberduck.Main/Root/RubberduckIoCInstaller.cs @@ -13,6 +13,8 @@ using Castle.Windsor; using Rubberduck.AutoComplete; using Rubberduck.CodeAnalysis.CodeMetrics; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.ComClientLibrary.UnitTesting; using Rubberduck.Common; using Rubberduck.Common.Hotkeys; @@ -21,7 +23,6 @@ using Rubberduck.Parsing; using Rubberduck.Parsing.Common; using Rubberduck.Parsing.ComReflection; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.PreProcessing; using Rubberduck.Parsing.Symbols.DeclarationLoaders; using Rubberduck.Parsing.Rewriter; diff --git a/RubberduckTests/ConfigurationTests.cs b/RubberduckTests/ConfigurationTests.cs index 105915b628..5ed6f32d42 100644 --- a/RubberduckTests/ConfigurationTests.cs +++ b/RubberduckTests/ConfigurationTests.cs @@ -2,7 +2,7 @@ using System.Linq; using NUnit.Framework; using Moq; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Settings; using Rubberduck.Parsing.Inspections; using Rubberduck.CodeAnalysis.Settings; diff --git a/RubberduckTests/Inspections/ApplicationWorksheetFunctionInspectionTests.cs b/RubberduckTests/Inspections/ApplicationWorksheetFunctionInspectionTests.cs index b49b2ddf57..9f43882159 100644 --- a/RubberduckTests/Inspections/ApplicationWorksheetFunctionInspectionTests.cs +++ b/RubberduckTests/Inspections/ApplicationWorksheetFunctionInspectionTests.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; diff --git a/RubberduckTests/Inspections/ArgumentWithIncompatibleObjectTypeInspectionTests.cs b/RubberduckTests/Inspections/ArgumentWithIncompatibleObjectTypeInspectionTests.cs index 60b3b103c4..dc6b856f79 100644 --- a/RubberduckTests/Inspections/ArgumentWithIncompatibleObjectTypeInspectionTests.cs +++ b/RubberduckTests/Inspections/ArgumentWithIncompatibleObjectTypeInspectionTests.cs @@ -3,9 +3,9 @@ using System.Threading; using Moq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.Inspections.Concrete; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.TypeResolvers; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor; diff --git a/RubberduckTests/Inspections/AssignedByValParameterInspectionTests.cs b/RubberduckTests/Inspections/AssignedByValParameterInspectionTests.cs index 865a78670e..1837c55266 100644 --- a/RubberduckTests/Inspections/AssignedByValParameterInspectionTests.cs +++ b/RubberduckTests/Inspections/AssignedByValParameterInspectionTests.cs @@ -1,8 +1,8 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; using Rubberduck.VBEditor.SafeComWrappers; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/AssignmentNotUsedInspectionTests.cs b/RubberduckTests/Inspections/AssignmentNotUsedInspectionTests.cs index fda1718be0..a45968f717 100644 --- a/RubberduckTests/Inspections/AssignmentNotUsedInspectionTests.cs +++ b/RubberduckTests/Inspections/AssignmentNotUsedInspectionTests.cs @@ -4,7 +4,7 @@ using Rubberduck.Inspections.Concrete; using RubberduckTests.Mocks; using System.Linq; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/AttributeValueOutOfSyncInspectionTests.cs b/RubberduckTests/Inspections/AttributeValueOutOfSyncInspectionTests.cs index cfe2cda9fb..bda5c02034 100644 --- a/RubberduckTests/Inspections/AttributeValueOutOfSyncInspectionTests.cs +++ b/RubberduckTests/Inspections/AttributeValueOutOfSyncInspectionTests.cs @@ -1,9 +1,9 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Annotations; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/Inspections/BooleanAssignedInIfElseInspectionTests.cs b/RubberduckTests/Inspections/BooleanAssignedInIfElseInspectionTests.cs index bd6950cf7a..75227f7527 100644 --- a/RubberduckTests/Inspections/BooleanAssignedInIfElseInspectionTests.cs +++ b/RubberduckTests/Inspections/BooleanAssignedInIfElseInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/ConstantNotUsedInspectionTests.cs b/RubberduckTests/Inspections/ConstantNotUsedInspectionTests.cs index c068c26e8e..666ce4e592 100644 --- a/RubberduckTests/Inspections/ConstantNotUsedInspectionTests.cs +++ b/RubberduckTests/Inspections/ConstantNotUsedInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/DefTypeStatementInspectionTests.cs b/RubberduckTests/Inspections/DefTypeStatementInspectionTests.cs index ddf385c42c..3258303e2f 100644 --- a/RubberduckTests/Inspections/DefTypeStatementInspectionTests.cs +++ b/RubberduckTests/Inspections/DefTypeStatementInspectionTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; using Rubberduck.Inspections.Concrete; using System.Linq; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/DefaultMemberRequiredInspectionTests.cs b/RubberduckTests/Inspections/DefaultMemberRequiredInspectionTests.cs index a57a9b9f0d..69205e9b13 100644 --- a/RubberduckTests/Inspections/DefaultMemberRequiredInspectionTests.cs +++ b/RubberduckTests/Inspections/DefaultMemberRequiredInspectionTests.cs @@ -1,8 +1,8 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.Inspections.Concrete; using Rubberduck.Parsing; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/Inspections/DefaultProjectNameInspectionTests.cs b/RubberduckTests/Inspections/DefaultProjectNameInspectionTests.cs index ad9e65d23d..a50d06b4dc 100644 --- a/RubberduckTests/Inspections/DefaultProjectNameInspectionTests.cs +++ b/RubberduckTests/Inspections/DefaultProjectNameInspectionTests.cs @@ -1,8 +1,8 @@ using System.Linq; using System.Threading; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; diff --git a/RubberduckTests/Inspections/DuplicatedAnnotationInspectionTests.cs b/RubberduckTests/Inspections/DuplicatedAnnotationInspectionTests.cs index 2d0931231c..968d846842 100644 --- a/RubberduckTests/Inspections/DuplicatedAnnotationInspectionTests.cs +++ b/RubberduckTests/Inspections/DuplicatedAnnotationInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/EmptyCaseBlockInspectionTests.cs b/RubberduckTests/Inspections/EmptyCaseBlockInspectionTests.cs index 7352bf3033..30653f77f0 100644 --- a/RubberduckTests/Inspections/EmptyCaseBlockInspectionTests.cs +++ b/RubberduckTests/Inspections/EmptyCaseBlockInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/EmptyDoWhileBlockInspectionTests.cs b/RubberduckTests/Inspections/EmptyDoWhileBlockInspectionTests.cs index d1ab1ac65e..a5c449a4b7 100644 --- a/RubberduckTests/Inspections/EmptyDoWhileBlockInspectionTests.cs +++ b/RubberduckTests/Inspections/EmptyDoWhileBlockInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/EmptyElseBlockInspectionTests.cs b/RubberduckTests/Inspections/EmptyElseBlockInspectionTests.cs index 18bc3a0c4c..d8300681b8 100644 --- a/RubberduckTests/Inspections/EmptyElseBlockInspectionTests.cs +++ b/RubberduckTests/Inspections/EmptyElseBlockInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/EmptyForEachBlockInspectionTests.cs b/RubberduckTests/Inspections/EmptyForEachBlockInspectionTests.cs index 272998c506..5cb46b8995 100644 --- a/RubberduckTests/Inspections/EmptyForEachBlockInspectionTests.cs +++ b/RubberduckTests/Inspections/EmptyForEachBlockInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/EmptyForLoopBlockInspectionTests.cs b/RubberduckTests/Inspections/EmptyForLoopBlockInspectionTests.cs index c733122afc..94e599dc96 100644 --- a/RubberduckTests/Inspections/EmptyForLoopBlockInspectionTests.cs +++ b/RubberduckTests/Inspections/EmptyForLoopBlockInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/EmptyIfBlockInspectionTests.cs b/RubberduckTests/Inspections/EmptyIfBlockInspectionTests.cs index 11db5a30a1..ff77db8357 100644 --- a/RubberduckTests/Inspections/EmptyIfBlockInspectionTests.cs +++ b/RubberduckTests/Inspections/EmptyIfBlockInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/EmptyMethodInspectionTests.cs b/RubberduckTests/Inspections/EmptyMethodInspectionTests.cs index 7b29251523..518fd4e559 100644 --- a/RubberduckTests/Inspections/EmptyMethodInspectionTests.cs +++ b/RubberduckTests/Inspections/EmptyMethodInspectionTests.cs @@ -1,8 +1,8 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; using Rubberduck.VBEditor.SafeComWrappers; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/EmptyModuleInspectionTests.cs b/RubberduckTests/Inspections/EmptyModuleInspectionTests.cs index 308a10b150..0439e01545 100644 --- a/RubberduckTests/Inspections/EmptyModuleInspectionTests.cs +++ b/RubberduckTests/Inspections/EmptyModuleInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/Inspections/EmptyStringLiteralInspectionTests.cs b/RubberduckTests/Inspections/EmptyStringLiteralInspectionTests.cs index d2ac893e2a..5e876e71e1 100644 --- a/RubberduckTests/Inspections/EmptyStringLiteralInspectionTests.cs +++ b/RubberduckTests/Inspections/EmptyStringLiteralInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/EmptyWhileWendBlockInspectionTests.cs b/RubberduckTests/Inspections/EmptyWhileWendBlockInspectionTests.cs index bbeac7cdd1..4a1d0c47b3 100644 --- a/RubberduckTests/Inspections/EmptyWhileWendBlockInspectionTests.cs +++ b/RubberduckTests/Inspections/EmptyWhileWendBlockInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/EncapsulatePublicFieldInspectionTests.cs b/RubberduckTests/Inspections/EncapsulatePublicFieldInspectionTests.cs index c40d232d05..f2768d0829 100644 --- a/RubberduckTests/Inspections/EncapsulatePublicFieldInspectionTests.cs +++ b/RubberduckTests/Inspections/EncapsulatePublicFieldInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/ExcelMemberMayReturnNothingInspectionTests.cs b/RubberduckTests/Inspections/ExcelMemberMayReturnNothingInspectionTests.cs index eb38da4a52..a7cf78972e 100644 --- a/RubberduckTests/Inspections/ExcelMemberMayReturnNothingInspectionTests.cs +++ b/RubberduckTests/Inspections/ExcelMemberMayReturnNothingInspectionTests.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; diff --git a/RubberduckTests/Inspections/ExcelUdfNameIsValidCellReferenceInspectionTests.cs b/RubberduckTests/Inspections/ExcelUdfNameIsValidCellReferenceInspectionTests.cs index 474a55cc79..680e015351 100644 --- a/RubberduckTests/Inspections/ExcelUdfNameIsValidCellReferenceInspectionTests.cs +++ b/RubberduckTests/Inspections/ExcelUdfNameIsValidCellReferenceInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; diff --git a/RubberduckTests/Inspections/FunctionReturnValueAlwaysDiscardedInspectionTests.cs b/RubberduckTests/Inspections/FunctionReturnValueAlwaysDiscardedInspectionTests.cs index 63b0ecfeb9..c7ade0bfdb 100644 --- a/RubberduckTests/Inspections/FunctionReturnValueAlwaysDiscardedInspectionTests.cs +++ b/RubberduckTests/Inspections/FunctionReturnValueAlwaysDiscardedInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/Inspections/FunctionReturnValueDiscardedInspectionTests.cs b/RubberduckTests/Inspections/FunctionReturnValueDiscardedInspectionTests.cs index e4add27931..09f30294d5 100644 --- a/RubberduckTests/Inspections/FunctionReturnValueDiscardedInspectionTests.cs +++ b/RubberduckTests/Inspections/FunctionReturnValueDiscardedInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/Inspections/HostSpecificExpressionInspectionTests.cs b/RubberduckTests/Inspections/HostSpecificExpressionInspectionTests.cs index 12b8085f11..14bfa5aaa2 100644 --- a/RubberduckTests/Inspections/HostSpecificExpressionInspectionTests.cs +++ b/RubberduckTests/Inspections/HostSpecificExpressionInspectionTests.cs @@ -1,11 +1,11 @@ using System.Linq; using NUnit.Framework; using Moq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; using RubberduckTests.Mocks; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/HungarianNotationInspectionTests.cs b/RubberduckTests/Inspections/HungarianNotationInspectionTests.cs index a7274762e7..b556369d16 100644 --- a/RubberduckTests/Inspections/HungarianNotationInspectionTests.cs +++ b/RubberduckTests/Inspections/HungarianNotationInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/Inspections/IllegalAnnotationsInspectionTests.cs b/RubberduckTests/Inspections/IllegalAnnotationsInspectionTests.cs index f54c3e2d0c..cf5a382ac2 100644 --- a/RubberduckTests/Inspections/IllegalAnnotationsInspectionTests.cs +++ b/RubberduckTests/Inspections/IllegalAnnotationsInspectionTests.cs @@ -1,8 +1,8 @@ using System.Linq; using System.Threading; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; diff --git a/RubberduckTests/Inspections/ImplementedInterfaceMemberInspectionTests.cs b/RubberduckTests/Inspections/ImplementedInterfaceMemberInspectionTests.cs index abfd68dbc5..c0e346a637 100644 --- a/RubberduckTests/Inspections/ImplementedInterfaceMemberInspectionTests.cs +++ b/RubberduckTests/Inspections/ImplementedInterfaceMemberInspectionTests.cs @@ -1,8 +1,8 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; using Rubberduck.VBEditor.SafeComWrappers; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/ImplicitActiveSheetReferenceInspectionTests.cs b/RubberduckTests/Inspections/ImplicitActiveSheetReferenceInspectionTests.cs index acc57a05df..0e7b43bca5 100644 --- a/RubberduckTests/Inspections/ImplicitActiveSheetReferenceInspectionTests.cs +++ b/RubberduckTests/Inspections/ImplicitActiveSheetReferenceInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; diff --git a/RubberduckTests/Inspections/ImplicitActiveWorkbookReferenceInspectionTests.cs b/RubberduckTests/Inspections/ImplicitActiveWorkbookReferenceInspectionTests.cs index 12fca8fe76..efe9ba8433 100644 --- a/RubberduckTests/Inspections/ImplicitActiveWorkbookReferenceInspectionTests.cs +++ b/RubberduckTests/Inspections/ImplicitActiveWorkbookReferenceInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; diff --git a/RubberduckTests/Inspections/ImplicitByRefModifierInspectionTests.cs b/RubberduckTests/Inspections/ImplicitByRefModifierInspectionTests.cs index bf92456f49..b89ed95518 100644 --- a/RubberduckTests/Inspections/ImplicitByRefModifierInspectionTests.cs +++ b/RubberduckTests/Inspections/ImplicitByRefModifierInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/Inspections/ImplicitDefaultMemberAccessInspectionTests.cs b/RubberduckTests/Inspections/ImplicitDefaultMemberAccessInspectionTests.cs index 786ed55196..73de82e5e2 100644 --- a/RubberduckTests/Inspections/ImplicitDefaultMemberAccessInspectionTests.cs +++ b/RubberduckTests/Inspections/ImplicitDefaultMemberAccessInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; diff --git a/RubberduckTests/Inspections/ImplicitPublicMemberInspectionTests.cs b/RubberduckTests/Inspections/ImplicitPublicMemberInspectionTests.cs index 642a3d416a..6dfdc7e5dd 100644 --- a/RubberduckTests/Inspections/ImplicitPublicMemberInspectionTests.cs +++ b/RubberduckTests/Inspections/ImplicitPublicMemberInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/ImplicitRecursiveDefaultMemberAccessInspectionTests.cs b/RubberduckTests/Inspections/ImplicitRecursiveDefaultMemberAccessInspectionTests.cs index f31a8b2b1b..a130603710 100644 --- a/RubberduckTests/Inspections/ImplicitRecursiveDefaultMemberAccessInspectionTests.cs +++ b/RubberduckTests/Inspections/ImplicitRecursiveDefaultMemberAccessInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; diff --git a/RubberduckTests/Inspections/ImplicitUnboundDefaultMemberAccessInspectionTests.cs b/RubberduckTests/Inspections/ImplicitUnboundDefaultMemberAccessInspectionTests.cs index 07f83b72df..8243c9aa14 100644 --- a/RubberduckTests/Inspections/ImplicitUnboundDefaultMemberAccessInspectionTests.cs +++ b/RubberduckTests/Inspections/ImplicitUnboundDefaultMemberAccessInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; diff --git a/RubberduckTests/Inspections/ImplicitVariantReturnTypeInspectionTests.cs b/RubberduckTests/Inspections/ImplicitVariantReturnTypeInspectionTests.cs index 73443a2f74..8604cc5eb1 100644 --- a/RubberduckTests/Inspections/ImplicitVariantReturnTypeInspectionTests.cs +++ b/RubberduckTests/Inspections/ImplicitVariantReturnTypeInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs b/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs index c76b9cbede..6e916b5ef3 100644 --- a/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs +++ b/RubberduckTests/Inspections/ImplicitlyTypedConstInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/Inspections/IndexedDefaultMemberAccessInspectionTests.cs b/RubberduckTests/Inspections/IndexedDefaultMemberAccessInspectionTests.cs index e3183dc107..d92a6b4d1c 100644 --- a/RubberduckTests/Inspections/IndexedDefaultMemberAccessInspectionTests.cs +++ b/RubberduckTests/Inspections/IndexedDefaultMemberAccessInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; diff --git a/RubberduckTests/Inspections/IndexedRecursiveDefaultMemberAccessInspectionTests.cs b/RubberduckTests/Inspections/IndexedRecursiveDefaultMemberAccessInspectionTests.cs index 71acc6362f..8b1f425980 100644 --- a/RubberduckTests/Inspections/IndexedRecursiveDefaultMemberAccessInspectionTests.cs +++ b/RubberduckTests/Inspections/IndexedRecursiveDefaultMemberAccessInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; diff --git a/RubberduckTests/Inspections/IndexedUnboundDefaultMemberAccessInspectionTests.cs b/RubberduckTests/Inspections/IndexedUnboundDefaultMemberAccessInspectionTests.cs index 1818e50d81..2df849b730 100644 --- a/RubberduckTests/Inspections/IndexedUnboundDefaultMemberAccessInspectionTests.cs +++ b/RubberduckTests/Inspections/IndexedUnboundDefaultMemberAccessInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; diff --git a/RubberduckTests/Inspections/InspectionProviderTests.cs b/RubberduckTests/Inspections/InspectionProviderTests.cs index 20b3723d3e..38dd1935bf 100644 --- a/RubberduckTests/Inspections/InspectionProviderTests.cs +++ b/RubberduckTests/Inspections/InspectionProviderTests.cs @@ -2,7 +2,6 @@ using Moq; using NUnit.Framework; using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Inspections; using Rubberduck.Settings; using Rubberduck.CodeAnalysis.Settings; diff --git a/RubberduckTests/Inspections/InspectionResultTests.cs b/RubberduckTests/Inspections/InspectionResultTests.cs index 8511e18072..784f777c50 100644 --- a/RubberduckTests/Inspections/InspectionResultTests.cs +++ b/RubberduckTests/Inspections/InspectionResultTests.cs @@ -1,10 +1,10 @@ using System.Collections.Generic; using Moq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Annotations; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/RubberduckTests/Inspections/InspectionTestsBase.cs b/RubberduckTests/Inspections/InspectionTestsBase.cs index 9d39e059bd..2b4fc058e8 100644 --- a/RubberduckTests/Inspections/InspectionTestsBase.cs +++ b/RubberduckTests/Inspections/InspectionTestsBase.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Threading; using Antlr4.Runtime.Tree; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.Parsing; using Rubberduck.VBEditor; diff --git a/RubberduckTests/Inspections/InspectionsHelper.cs b/RubberduckTests/Inspections/InspectionsHelper.cs index bb932b03c4..289a1bf106 100644 --- a/RubberduckTests/Inspections/InspectionsHelper.cs +++ b/RubberduckTests/Inspections/InspectionsHelper.cs @@ -1,5 +1,4 @@ using Moq; -using Rubberduck.Parsing.Inspections.Abstract; using System.Linq; using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Rubberduck.Inspections; diff --git a/RubberduckTests/Inspections/IntegerDataTypeInspectionTests.cs b/RubberduckTests/Inspections/IntegerDataTypeInspectionTests.cs index 3879213ecc..83f248fa7b 100644 --- a/RubberduckTests/Inspections/IntegerDataTypeInspectionTests.cs +++ b/RubberduckTests/Inspections/IntegerDataTypeInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/Inspections/IsMissingOnInappropriateArgumentInspectionTests.cs b/RubberduckTests/Inspections/IsMissingOnInappropriateArgumentInspectionTests.cs index cb597699cf..5dda55ed8d 100644 --- a/RubberduckTests/Inspections/IsMissingOnInappropriateArgumentInspectionTests.cs +++ b/RubberduckTests/Inspections/IsMissingOnInappropriateArgumentInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; diff --git a/RubberduckTests/Inspections/IsMissingWithNonArgumentParameterInspectionTests.cs b/RubberduckTests/Inspections/IsMissingWithNonArgumentParameterInspectionTests.cs index eceaa31520..2bb8e84d81 100644 --- a/RubberduckTests/Inspections/IsMissingWithNonArgumentParameterInspectionTests.cs +++ b/RubberduckTests/Inspections/IsMissingWithNonArgumentParameterInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; diff --git a/RubberduckTests/Inspections/LineLabelNotUsedInspectionTests.cs b/RubberduckTests/Inspections/LineLabelNotUsedInspectionTests.cs index 36ae2baf3d..5d6aafdfa6 100644 --- a/RubberduckTests/Inspections/LineLabelNotUsedInspectionTests.cs +++ b/RubberduckTests/Inspections/LineLabelNotUsedInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/MalformedAnnotationInspectionTests.cs b/RubberduckTests/Inspections/MalformedAnnotationInspectionTests.cs index 983ccc9bd7..2451f8570b 100644 --- a/RubberduckTests/Inspections/MalformedAnnotationInspectionTests.cs +++ b/RubberduckTests/Inspections/MalformedAnnotationInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/MemberNotOnInterfaceInspectionTests.cs b/RubberduckTests/Inspections/MemberNotOnInterfaceInspectionTests.cs index b65d589321..06c58d7fb8 100644 --- a/RubberduckTests/Inspections/MemberNotOnInterfaceInspectionTests.cs +++ b/RubberduckTests/Inspections/MemberNotOnInterfaceInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; diff --git a/RubberduckTests/Inspections/MissingAnnotationArgumentInspectionTests.cs b/RubberduckTests/Inspections/MissingAnnotationArgumentInspectionTests.cs index 7c58e48734..615870763a 100644 --- a/RubberduckTests/Inspections/MissingAnnotationArgumentInspectionTests.cs +++ b/RubberduckTests/Inspections/MissingAnnotationArgumentInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/Inspections/MissingAttributeInspectionTests.cs b/RubberduckTests/Inspections/MissingAttributeInspectionTests.cs index 0375de21e3..7924116129 100644 --- a/RubberduckTests/Inspections/MissingAttributeInspectionTests.cs +++ b/RubberduckTests/Inspections/MissingAttributeInspectionTests.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/Inspections/MissingMemberAnnotationInspectionTests.cs b/RubberduckTests/Inspections/MissingMemberAnnotationInspectionTests.cs index 84df636c79..48b150e3ab 100644 --- a/RubberduckTests/Inspections/MissingMemberAnnotationInspectionTests.cs +++ b/RubberduckTests/Inspections/MissingMemberAnnotationInspectionTests.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/Inspections/MissingModuleAnnotationInspectionTests.cs b/RubberduckTests/Inspections/MissingModuleAnnotationInspectionTests.cs index 6752a7da31..9a458c2a4d 100644 --- a/RubberduckTests/Inspections/MissingModuleAnnotationInspectionTests.cs +++ b/RubberduckTests/Inspections/MissingModuleAnnotationInspectionTests.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/Inspections/ModuleScopeDimKeywordInspectionTests.cs b/RubberduckTests/Inspections/ModuleScopeDimKeywordInspectionTests.cs index ed5c225c49..34c792ed62 100644 --- a/RubberduckTests/Inspections/ModuleScopeDimKeywordInspectionTests.cs +++ b/RubberduckTests/Inspections/ModuleScopeDimKeywordInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/ModuleWithoutFolderInspectionTests.cs b/RubberduckTests/Inspections/ModuleWithoutFolderInspectionTests.cs index cda214c6c6..6ce4988c1c 100644 --- a/RubberduckTests/Inspections/ModuleWithoutFolderInspectionTests.cs +++ b/RubberduckTests/Inspections/ModuleWithoutFolderInspectionTests.cs @@ -1,8 +1,8 @@ using NUnit.Framework; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; namespace RubberduckTests.Inspections { diff --git a/RubberduckTests/Inspections/MoveFieldCloserToUsageInspectionTests.cs b/RubberduckTests/Inspections/MoveFieldCloserToUsageInspectionTests.cs index 84d969a2b2..a3b885c1b9 100644 --- a/RubberduckTests/Inspections/MoveFieldCloserToUsageInspectionTests.cs +++ b/RubberduckTests/Inspections/MoveFieldCloserToUsageInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/MultilineParameterInspectionTests.cs b/RubberduckTests/Inspections/MultilineParameterInspectionTests.cs index 3dc112f9cb..f071c63537 100644 --- a/RubberduckTests/Inspections/MultilineParameterInspectionTests.cs +++ b/RubberduckTests/Inspections/MultilineParameterInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/MultipleDeclarationsInspectionTests.cs b/RubberduckTests/Inspections/MultipleDeclarationsInspectionTests.cs index 4b72cd9a08..0770a9d585 100644 --- a/RubberduckTests/Inspections/MultipleDeclarationsInspectionTests.cs +++ b/RubberduckTests/Inspections/MultipleDeclarationsInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/NonReturningFunctionInspectionTests.cs b/RubberduckTests/Inspections/NonReturningFunctionInspectionTests.cs index c615e47f27..db9d7ad14c 100644 --- a/RubberduckTests/Inspections/NonReturningFunctionInspectionTests.cs +++ b/RubberduckTests/Inspections/NonReturningFunctionInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; diff --git a/RubberduckTests/Inspections/ObjectVariableNotSetInspectionTests.cs b/RubberduckTests/Inspections/ObjectVariableNotSetInspectionTests.cs index 5bc572eea7..ccdf2ea99a 100644 --- a/RubberduckTests/Inspections/ObjectVariableNotSetInspectionTests.cs +++ b/RubberduckTests/Inspections/ObjectVariableNotSetInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/Inspections/ObjectWhereProcedureIsRequiredInspectionTests.cs b/RubberduckTests/Inspections/ObjectWhereProcedureIsRequiredInspectionTests.cs index 8528b16263..4beea58f0e 100644 --- a/RubberduckTests/Inspections/ObjectWhereProcedureIsRequiredInspectionTests.cs +++ b/RubberduckTests/Inspections/ObjectWhereProcedureIsRequiredInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/Inspections/ObsoleteCallStatementInspectionTests.cs b/RubberduckTests/Inspections/ObsoleteCallStatementInspectionTests.cs index 79949ab47d..b8b57b8368 100644 --- a/RubberduckTests/Inspections/ObsoleteCallStatementInspectionTests.cs +++ b/RubberduckTests/Inspections/ObsoleteCallStatementInspectionTests.cs @@ -1,8 +1,8 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.Inspections.Abstract; namespace RubberduckTests.Inspections { diff --git a/RubberduckTests/Inspections/ObsoleteCallingConventionInspectionTests.cs b/RubberduckTests/Inspections/ObsoleteCallingConventionInspectionTests.cs index fff3807463..d7afe57b72 100644 --- a/RubberduckTests/Inspections/ObsoleteCallingConventionInspectionTests.cs +++ b/RubberduckTests/Inspections/ObsoleteCallingConventionInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/ObsoleteCommentSyntaxInspectionTests.cs b/RubberduckTests/Inspections/ObsoleteCommentSyntaxInspectionTests.cs index e22dd3e063..f7445aba1a 100644 --- a/RubberduckTests/Inspections/ObsoleteCommentSyntaxInspectionTests.cs +++ b/RubberduckTests/Inspections/ObsoleteCommentSyntaxInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/ObsoleteErrorSyntaxInspectionTests.cs b/RubberduckTests/Inspections/ObsoleteErrorSyntaxInspectionTests.cs index f568742a25..8020984b69 100644 --- a/RubberduckTests/Inspections/ObsoleteErrorSyntaxInspectionTests.cs +++ b/RubberduckTests/Inspections/ObsoleteErrorSyntaxInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/ObsoleteGlobalInspectionTests.cs b/RubberduckTests/Inspections/ObsoleteGlobalInspectionTests.cs index 82ee599ae3..cde28fc37e 100644 --- a/RubberduckTests/Inspections/ObsoleteGlobalInspectionTests.cs +++ b/RubberduckTests/Inspections/ObsoleteGlobalInspectionTests.cs @@ -1,8 +1,8 @@ using System.Linq; using Moq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; diff --git a/RubberduckTests/Inspections/ObsoleteLetStatementInspectionTests.cs b/RubberduckTests/Inspections/ObsoleteLetStatementInspectionTests.cs index 315ce9ff55..190f8c6fc8 100644 --- a/RubberduckTests/Inspections/ObsoleteLetStatementInspectionTests.cs +++ b/RubberduckTests/Inspections/ObsoleteLetStatementInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/ObsoleteMemberUsageInspectionTests.cs b/RubberduckTests/Inspections/ObsoleteMemberUsageInspectionTests.cs index 3a6ab970a9..984cdde500 100644 --- a/RubberduckTests/Inspections/ObsoleteMemberUsageInspectionTests.cs +++ b/RubberduckTests/Inspections/ObsoleteMemberUsageInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/ObsoleteTypeHintInspectionTests.cs b/RubberduckTests/Inspections/ObsoleteTypeHintInspectionTests.cs index 59d774ecbc..b3630b922a 100644 --- a/RubberduckTests/Inspections/ObsoleteTypeHintInspectionTests.cs +++ b/RubberduckTests/Inspections/ObsoleteTypeHintInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/ObsoleteWhileWendInspectionTests.cs b/RubberduckTests/Inspections/ObsoleteWhileWendInspectionTests.cs index 0a20bf9c88..94ee96430e 100644 --- a/RubberduckTests/Inspections/ObsoleteWhileWendInspectionTests.cs +++ b/RubberduckTests/Inspections/ObsoleteWhileWendInspectionTests.cs @@ -1,6 +1,6 @@ using NUnit.Framework; -using Rubberduck.Parsing.Inspections.Abstract; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.Inspections.Concrete; using Rubberduck.Parsing.VBA; diff --git a/RubberduckTests/Inspections/OnLocalErrorInspectionTests.cs b/RubberduckTests/Inspections/OnLocalErrorInspectionTests.cs index 00f8aaaeaf..4080c6a11f 100644 --- a/RubberduckTests/Inspections/OnLocalErrorInspectionTests.cs +++ b/RubberduckTests/Inspections/OnLocalErrorInspectionTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; using Rubberduck.Inspections.Concrete; using System.Linq; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/OptionBaseInspectionTests.cs b/RubberduckTests/Inspections/OptionBaseInspectionTests.cs index cd6dcd7409..4002964b0d 100644 --- a/RubberduckTests/Inspections/OptionBaseInspectionTests.cs +++ b/RubberduckTests/Inspections/OptionBaseInspectionTests.cs @@ -1,8 +1,8 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; using Rubberduck.VBEditor.SafeComWrappers; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/OptionExplicitInspectionTests.cs b/RubberduckTests/Inspections/OptionExplicitInspectionTests.cs index 4ffd830f0b..0500fa4ae7 100644 --- a/RubberduckTests/Inspections/OptionExplicitInspectionTests.cs +++ b/RubberduckTests/Inspections/OptionExplicitInspectionTests.cs @@ -1,8 +1,8 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; using Rubberduck.VBEditor.SafeComWrappers; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/ParameterCanBeByValInspectionTests.cs b/RubberduckTests/Inspections/ParameterCanBeByValInspectionTests.cs index 819f591b6e..c0cf205a28 100644 --- a/RubberduckTests/Inspections/ParameterCanBeByValInspectionTests.cs +++ b/RubberduckTests/Inspections/ParameterCanBeByValInspectionTests.cs @@ -1,8 +1,8 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; using Rubberduck.VBEditor.SafeComWrappers; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/ParameterNotUsedInspectionTests.cs b/RubberduckTests/Inspections/ParameterNotUsedInspectionTests.cs index 88cf8fabe3..bec1c2f2e1 100644 --- a/RubberduckTests/Inspections/ParameterNotUsedInspectionTests.cs +++ b/RubberduckTests/Inspections/ParameterNotUsedInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; diff --git a/RubberduckTests/Inspections/ProcedureNotUsedInspectionTests.cs b/RubberduckTests/Inspections/ProcedureNotUsedInspectionTests.cs index 80e85ca6ee..bcf8bebe0b 100644 --- a/RubberduckTests/Inspections/ProcedureNotUsedInspectionTests.cs +++ b/RubberduckTests/Inspections/ProcedureNotUsedInspectionTests.cs @@ -1,12 +1,12 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Symbols; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; using RubberduckTests.Mocks; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.Inspections.Abstract; namespace RubberduckTests.Inspections { diff --git a/RubberduckTests/Inspections/ProcedureRequiredInspectionTests.cs b/RubberduckTests/Inspections/ProcedureRequiredInspectionTests.cs index 80240f81da..c17870f5ed 100644 --- a/RubberduckTests/Inspections/ProcedureRequiredInspectionTests.cs +++ b/RubberduckTests/Inspections/ProcedureRequiredInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/Inspections/ProcedureShouldBeFunctionInspectionTests.cs b/RubberduckTests/Inspections/ProcedureShouldBeFunctionInspectionTests.cs index 70ad2e8c27..66b754a3ed 100644 --- a/RubberduckTests/Inspections/ProcedureShouldBeFunctionInspectionTests.cs +++ b/RubberduckTests/Inspections/ProcedureShouldBeFunctionInspectionTests.cs @@ -1,9 +1,9 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.Inspections.Abstract; namespace RubberduckTests.Inspections { diff --git a/RubberduckTests/Inspections/RedundantByRefModifierInspectionTests.cs b/RubberduckTests/Inspections/RedundantByRefModifierInspectionTests.cs index f363a6e205..6d2050e972 100644 --- a/RubberduckTests/Inspections/RedundantByRefModifierInspectionTests.cs +++ b/RubberduckTests/Inspections/RedundantByRefModifierInspectionTests.cs @@ -1,9 +1,9 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.Inspections.Abstract; namespace RubberduckTests.Inspections { diff --git a/RubberduckTests/Inspections/RedundantOptionInspectionTests.cs b/RubberduckTests/Inspections/RedundantOptionInspectionTests.cs index 946eb48495..cd31410870 100644 --- a/RubberduckTests/Inspections/RedundantOptionInspectionTests.cs +++ b/RubberduckTests/Inspections/RedundantOptionInspectionTests.cs @@ -1,8 +1,8 @@ using System.Linq; using System.Threading; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using RubberduckTests.Mocks; diff --git a/RubberduckTests/Inspections/SelfAssignedDeclarationInspectionTests.cs b/RubberduckTests/Inspections/SelfAssignedDeclarationInspectionTests.cs index 09d8e6eefb..d51b6d9352 100644 --- a/RubberduckTests/Inspections/SelfAssignedDeclarationInspectionTests.cs +++ b/RubberduckTests/Inspections/SelfAssignedDeclarationInspectionTests.cs @@ -1,8 +1,8 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.Inspections.Abstract; namespace RubberduckTests.Inspections { diff --git a/RubberduckTests/Inspections/SetAssignmentWithIncompatibleObjectTypeInspectionTests.cs b/RubberduckTests/Inspections/SetAssignmentWithIncompatibleObjectTypeInspectionTests.cs index 1d2b5a65c1..d1b261142a 100644 --- a/RubberduckTests/Inspections/SetAssignmentWithIncompatibleObjectTypeInspectionTests.cs +++ b/RubberduckTests/Inspections/SetAssignmentWithIncompatibleObjectTypeInspectionTests.cs @@ -3,9 +3,9 @@ using System.Threading; using Moq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.Inspections.Concrete; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.TypeResolvers; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor; diff --git a/RubberduckTests/Inspections/ShadowedDeclarationInspectionTests.cs b/RubberduckTests/Inspections/ShadowedDeclarationInspectionTests.cs index 17182c2568..cd7a4c255d 100644 --- a/RubberduckTests/Inspections/ShadowedDeclarationInspectionTests.cs +++ b/RubberduckTests/Inspections/ShadowedDeclarationInspectionTests.cs @@ -4,8 +4,8 @@ using System.Text; using System.Threading; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; diff --git a/RubberduckTests/Inspections/SheetAccessedUsingStringInspectionTests.cs b/RubberduckTests/Inspections/SheetAccessedUsingStringInspectionTests.cs index 4b26ae6b41..fbf6524342 100644 --- a/RubberduckTests/Inspections/SheetAccessedUsingStringInspectionTests.cs +++ b/RubberduckTests/Inspections/SheetAccessedUsingStringInspectionTests.cs @@ -2,8 +2,8 @@ using System.Linq; using Moq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; diff --git a/RubberduckTests/Inspections/StepNotSpecifiedInspectionTests.cs b/RubberduckTests/Inspections/StepNotSpecifiedInspectionTests.cs index 4719dc7f9c..813864151c 100644 --- a/RubberduckTests/Inspections/StepNotSpecifiedInspectionTests.cs +++ b/RubberduckTests/Inspections/StepNotSpecifiedInspectionTests.cs @@ -2,7 +2,7 @@ using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections; using System.Linq; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/StepOneIsRedundantInspectionTests.cs b/RubberduckTests/Inspections/StepOneIsRedundantInspectionTests.cs index 9b1a858cb4..f399c539f1 100644 --- a/RubberduckTests/Inspections/StepOneIsRedundantInspectionTests.cs +++ b/RubberduckTests/Inspections/StepOneIsRedundantInspectionTests.cs @@ -2,7 +2,7 @@ using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.Inspections; using System.Linq; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/StopKeywordInspectionTests.cs b/RubberduckTests/Inspections/StopKeywordInspectionTests.cs index 4ccb84a092..9f797b2cc0 100644 --- a/RubberduckTests/Inspections/StopKeywordInspectionTests.cs +++ b/RubberduckTests/Inspections/StopKeywordInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/SuperfluousAnnotationArgumentInspectionTests.cs b/RubberduckTests/Inspections/SuperfluousAnnotationArgumentInspectionTests.cs index 75cd2e2344..675f4ec9a7 100644 --- a/RubberduckTests/Inspections/SuperfluousAnnotationArgumentInspectionTests.cs +++ b/RubberduckTests/Inspections/SuperfluousAnnotationArgumentInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/Inspections/SuspiciousLetAssignmentInspectionTests.cs b/RubberduckTests/Inspections/SuspiciousLetAssignmentInspectionTests.cs index 17e96f0d2b..5206f692c7 100644 --- a/RubberduckTests/Inspections/SuspiciousLetAssignmentInspectionTests.cs +++ b/RubberduckTests/Inspections/SuspiciousLetAssignmentInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/Inspections/ThunderCode/ThunderCodeInspectionTests.cs b/RubberduckTests/Inspections/ThunderCode/ThunderCodeInspectionTests.cs index 6ce5db6fad..4399be64f9 100644 --- a/RubberduckTests/Inspections/ThunderCode/ThunderCodeInspectionTests.cs +++ b/RubberduckTests/Inspections/ThunderCode/ThunderCodeInspectionTests.cs @@ -4,8 +4,8 @@ using System.Threading; using Antlr4.Runtime.Tree; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Inspections.Concrete.ThunderCode; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.Parsing; using Rubberduck.Resources.Inspections; diff --git a/RubberduckTests/Inspections/UnassignedVariableUsageInspectionTests.cs b/RubberduckTests/Inspections/UnassignedVariableUsageInspectionTests.cs index 097beca9b0..62bff98552 100644 --- a/RubberduckTests/Inspections/UnassignedVariableUsageInspectionTests.cs +++ b/RubberduckTests/Inspections/UnassignedVariableUsageInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; diff --git a/RubberduckTests/Inspections/UndeclaredVariableInspectionTests.cs b/RubberduckTests/Inspections/UndeclaredVariableInspectionTests.cs index 5ddcab68d2..3f3ca411b9 100644 --- a/RubberduckTests/Inspections/UndeclaredVariableInspectionTests.cs +++ b/RubberduckTests/Inspections/UndeclaredVariableInspectionTests.cs @@ -1,8 +1,8 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; using Rubberduck.VBEditor.SafeComWrappers; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using RubberduckTests.Mocks; diff --git a/RubberduckTests/Inspections/UnderscoreInPublicClassModuleMemberInspectionTests.cs b/RubberduckTests/Inspections/UnderscoreInPublicClassModuleMemberInspectionTests.cs index 8d6401d297..73fd8d5ccb 100644 --- a/RubberduckTests/Inspections/UnderscoreInPublicClassModuleMemberInspectionTests.cs +++ b/RubberduckTests/Inspections/UnderscoreInPublicClassModuleMemberInspectionTests.cs @@ -2,7 +2,7 @@ using Rubberduck.Inspections.Concrete; using Rubberduck.VBEditor.SafeComWrappers; using System.Linq; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/UnhandledOnErrorResumeNextInspectionTest.cs b/RubberduckTests/Inspections/UnhandledOnErrorResumeNextInspectionTest.cs index 730f08680e..bd9d712872 100644 --- a/RubberduckTests/Inspections/UnhandledOnErrorResumeNextInspectionTest.cs +++ b/RubberduckTests/Inspections/UnhandledOnErrorResumeNextInspectionTest.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs b/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs index 13adaa416d..1c79cf31e2 100644 --- a/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs +++ b/RubberduckTests/Inspections/UnreachableCase/UnreachableCaseInspectionTests.cs @@ -4,7 +4,6 @@ using Rubberduck.Inspections.Concrete.UnreachableCaseInspection; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; @@ -14,6 +13,7 @@ using System.Linq; using System.Threading; using Moq; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.VBEditor; using Rubberduck.VBEditor.Extensions; diff --git a/RubberduckTests/Inspections/UntypedFunctionUsageInspectionTests.cs b/RubberduckTests/Inspections/UntypedFunctionUsageInspectionTests.cs index 472525837e..f2442148a8 100644 --- a/RubberduckTests/Inspections/UntypedFunctionUsageInspectionTests.cs +++ b/RubberduckTests/Inspections/UntypedFunctionUsageInspectionTests.cs @@ -1,9 +1,9 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; -using Rubberduck.Parsing.Inspections.Abstract; using RubberduckTests.Mocks; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/UseMeaningfulNameInspectionTests.cs b/RubberduckTests/Inspections/UseMeaningfulNameInspectionTests.cs index d495db90c0..f0a21481b2 100644 --- a/RubberduckTests/Inspections/UseMeaningfulNameInspectionTests.cs +++ b/RubberduckTests/Inspections/UseMeaningfulNameInspectionTests.cs @@ -7,8 +7,8 @@ using RubberduckTests.Mocks; using Rubberduck.CodeAnalysis.Settings; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing.Inspections.Abstract; using System.Collections.Generic; +using Rubberduck.CodeAnalysis.Inspections; namespace RubberduckTests.Inspections { diff --git a/RubberduckTests/Inspections/UseOfBangNotationInspectionTests.cs b/RubberduckTests/Inspections/UseOfBangNotationInspectionTests.cs index 1dad1e8bef..56c772e729 100644 --- a/RubberduckTests/Inspections/UseOfBangNotationInspectionTests.cs +++ b/RubberduckTests/Inspections/UseOfBangNotationInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/Inspections/UseOfRecursiveBangNotationInspectionTests.cs b/RubberduckTests/Inspections/UseOfRecursiveBangNotationInspectionTests.cs index 552e4b18b2..cee7745110 100644 --- a/RubberduckTests/Inspections/UseOfRecursiveBangNotationInspectionTests.cs +++ b/RubberduckTests/Inspections/UseOfRecursiveBangNotationInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/Inspections/UseOfUnboundBangNotationInspectionTests.cs b/RubberduckTests/Inspections/UseOfUnboundBangNotationInspectionTests.cs index d3b2fe11e8..ed37dbdb8e 100644 --- a/RubberduckTests/Inspections/UseOfUnboundBangNotationInspectionTests.cs +++ b/RubberduckTests/Inspections/UseOfUnboundBangNotationInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/Inspections/ValueRequiredInspectionTests.cs b/RubberduckTests/Inspections/ValueRequiredInspectionTests.cs index 92134ccf4f..651bfef9be 100644 --- a/RubberduckTests/Inspections/ValueRequiredInspectionTests.cs +++ b/RubberduckTests/Inspections/ValueRequiredInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; diff --git a/RubberduckTests/Inspections/VariableNotAssignedInspectionTests.cs b/RubberduckTests/Inspections/VariableNotAssignedInspectionTests.cs index f24e33e2e4..68f7694652 100644 --- a/RubberduckTests/Inspections/VariableNotAssignedInspectionTests.cs +++ b/RubberduckTests/Inspections/VariableNotAssignedInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/Inspections/VariableNotUsedInspectionTests.cs b/RubberduckTests/Inspections/VariableNotUsedInspectionTests.cs index 7893fd1314..49b5b9ff2e 100644 --- a/RubberduckTests/Inspections/VariableNotUsedInspectionTests.cs +++ b/RubberduckTests/Inspections/VariableNotUsedInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/VariableTypeNotDeclaredInspectionTests.cs b/RubberduckTests/Inspections/VariableTypeNotDeclaredInspectionTests.cs index e112735c9c..e459127052 100644 --- a/RubberduckTests/Inspections/VariableTypeNotDeclaredInspectionTests.cs +++ b/RubberduckTests/Inspections/VariableTypeNotDeclaredInspectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/WriteOnlyPropertyInspectionTests.cs b/RubberduckTests/Inspections/WriteOnlyPropertyInspectionTests.cs index 6e168f1abf..3a1a8c5f14 100644 --- a/RubberduckTests/Inspections/WriteOnlyPropertyInspectionTests.cs +++ b/RubberduckTests/Inspections/WriteOnlyPropertyInspectionTests.cs @@ -1,8 +1,8 @@ using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; using Rubberduck.VBEditor.SafeComWrappers; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/IoCContainer/IoCResolvingTests.cs b/RubberduckTests/IoCContainer/IoCResolvingTests.cs index 1c7c9387b5..5478554a17 100644 --- a/RubberduckTests/IoCContainer/IoCResolvingTests.cs +++ b/RubberduckTests/IoCContainer/IoCResolvingTests.cs @@ -3,7 +3,7 @@ using Castle.Windsor; using NUnit.Framework; using Moq; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Settings; using Rubberduck.Root; diff --git a/RubberduckTests/QuickFixes/AccessSheetUsingCodeNameQuickFixTests.cs b/RubberduckTests/QuickFixes/AccessSheetUsingCodeNameQuickFixTests.cs index 00edeb3f5f..ee7b6ee4c4 100644 --- a/RubberduckTests/QuickFixes/AccessSheetUsingCodeNameQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/AccessSheetUsingCodeNameQuickFixTests.cs @@ -1,8 +1,8 @@ using Moq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; diff --git a/RubberduckTests/QuickFixes/AddAttributeAnnotationQuickFixTests.cs b/RubberduckTests/QuickFixes/AddAttributeAnnotationQuickFixTests.cs index e69a0b2b8f..19deab0010 100644 --- a/RubberduckTests/QuickFixes/AddAttributeAnnotationQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/AddAttributeAnnotationQuickFixTests.cs @@ -2,11 +2,11 @@ using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; using Rubberduck.Parsing.Annotations; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using RubberduckTests.Mocks; using System; using System.Linq; +using Rubberduck.CodeAnalysis.QuickFixes; namespace RubberduckTests.QuickFixes { diff --git a/RubberduckTests/QuickFixes/AddMissingAttributeQuickFixTests.cs b/RubberduckTests/QuickFixes/AddMissingAttributeQuickFixTests.cs index 580a41490a..8a2485ab3e 100644 --- a/RubberduckTests/QuickFixes/AddMissingAttributeQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/AddMissingAttributeQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.Parsing; diff --git a/RubberduckTests/QuickFixes/AddStepOneQuickFixTests.cs b/RubberduckTests/QuickFixes/AddStepOneQuickFixTests.cs index 2fcb80b433..d03f1c6c79 100644 --- a/RubberduckTests/QuickFixes/AddStepOneQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/AddStepOneQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/AdjustAttributeAnnotationQuickFixTests.cs b/RubberduckTests/QuickFixes/AdjustAttributeAnnotationQuickFixTests.cs index 363b0621dd..9b3a5d60fd 100644 --- a/RubberduckTests/QuickFixes/AdjustAttributeAnnotationQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/AdjustAttributeAnnotationQuickFixTests.cs @@ -2,13 +2,13 @@ using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; using Rubberduck.Parsing.Annotations; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; using RubberduckTests.Mocks; using System; using System.Linq; +using Rubberduck.CodeAnalysis.QuickFixes; namespace RubberduckTests.QuickFixes { diff --git a/RubberduckTests/QuickFixes/AdjustAttributeValuesQuickFixTests.cs b/RubberduckTests/QuickFixes/AdjustAttributeValuesQuickFixTests.cs index 0578fcf2e7..49285326d6 100644 --- a/RubberduckTests/QuickFixes/AdjustAttributeValuesQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/AdjustAttributeValuesQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.Parsing; diff --git a/RubberduckTests/QuickFixes/ApplicationWorksheetFunctionQuickFixTests.cs b/RubberduckTests/QuickFixes/ApplicationWorksheetFunctionQuickFixTests.cs index f7ff8c175d..6711501147 100644 --- a/RubberduckTests/QuickFixes/ApplicationWorksheetFunctionQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ApplicationWorksheetFunctionQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; diff --git a/RubberduckTests/QuickFixes/ChangeDimToPrivateQuickFixTests.cs b/RubberduckTests/QuickFixes/ChangeDimToPrivateQuickFixTests.cs index 96b4676842..2ce0234914 100644 --- a/RubberduckTests/QuickFixes/ChangeDimToPrivateQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ChangeDimToPrivateQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/ChangeIntegerToLongQuickFixTests.cs b/RubberduckTests/QuickFixes/ChangeIntegerToLongQuickFixTests.cs index d3f181af86..227aad510a 100644 --- a/RubberduckTests/QuickFixes/ChangeIntegerToLongQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ChangeIntegerToLongQuickFixTests.cs @@ -1,9 +1,10 @@ using System; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/ChangeProcedureToFunctionQuickFixTests.cs b/RubberduckTests/QuickFixes/ChangeProcedureToFunctionQuickFixTests.cs index a34f1cf6f2..4ea48f2370 100644 --- a/RubberduckTests/QuickFixes/ChangeProcedureToFunctionQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ChangeProcedureToFunctionQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/ConvertToProcedureQuickFixTests.cs b/RubberduckTests/QuickFixes/ConvertToProcedureQuickFixTests.cs index a3958c7ff8..eee6e5bda1 100644 --- a/RubberduckTests/QuickFixes/ConvertToProcedureQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ConvertToProcedureQuickFixTests.cs @@ -1,9 +1,9 @@ using System.Linq; using System.Threading; using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; diff --git a/RubberduckTests/QuickFixes/DeclareAsExplicitVariantQuickFixTests.cs b/RubberduckTests/QuickFixes/DeclareAsExplicitVariantQuickFixTests.cs index 90d4a2cd79..84d8f616e3 100644 --- a/RubberduckTests/QuickFixes/DeclareAsExplicitVariantQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/DeclareAsExplicitVariantQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/ExpandBangNotationQuickFixTests.cs b/RubberduckTests/QuickFixes/ExpandBangNotationQuickFixTests.cs index 25103f5f24..3ef01dd4b7 100644 --- a/RubberduckTests/QuickFixes/ExpandBangNotationQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ExpandBangNotationQuickFixTests.cs @@ -1,7 +1,6 @@ using NUnit.Framework; using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; diff --git a/RubberduckTests/QuickFixes/ExpandDefaultMemberQuickFixTests.cs b/RubberduckTests/QuickFixes/ExpandDefaultMemberQuickFixTests.cs index 4668bebe40..eec4ee8b1d 100644 --- a/RubberduckTests/QuickFixes/ExpandDefaultMemberQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ExpandDefaultMemberQuickFixTests.cs @@ -1,7 +1,6 @@ using NUnit.Framework; using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.Parsing; using Rubberduck.VBEditor.SafeComWrappers; diff --git a/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs b/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs index e488536a04..2936bfdd20 100644 --- a/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/IgnoreOnceQuickFixTests.cs @@ -3,13 +3,13 @@ using System.Linq; using System.Threading; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; using RubberduckTests.Inspections; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.VBEditor; using Rubberduck.VBEditor.SafeComWrappers.Abstract; using Rubberduck.CodeAnalysis.Inspections.Concrete; diff --git a/RubberduckTests/QuickFixes/IntroduceLocalVariableQuickFixTests.cs b/RubberduckTests/QuickFixes/IntroduceLocalVariableQuickFixTests.cs index 86e48ecc89..83874c2b72 100644 --- a/RubberduckTests/QuickFixes/IntroduceLocalVariableQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/IntroduceLocalVariableQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/IsMissingOnInappropriateArgumentQuickFixTests.cs b/RubberduckTests/QuickFixes/IsMissingOnInappropriateArgumentQuickFixTests.cs index c0fd3ad76d..38412640ee 100644 --- a/RubberduckTests/QuickFixes/IsMissingOnInappropriateArgumentQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/IsMissingOnInappropriateArgumentQuickFixTests.cs @@ -1,9 +1,9 @@ using System.Linq; using System.Threading; using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; diff --git a/RubberduckTests/QuickFixes/MakeSingleLineParamegerQuickFixTests.cs b/RubberduckTests/QuickFixes/MakeSingleLineParamegerQuickFixTests.cs index 49d59d0d3e..5f0a28a096 100644 --- a/RubberduckTests/QuickFixes/MakeSingleLineParamegerQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/MakeSingleLineParamegerQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/OptionExplicitQuickFixTests.cs b/RubberduckTests/QuickFixes/OptionExplicitQuickFixTests.cs index 9734d85c5d..8d650a0862 100644 --- a/RubberduckTests/QuickFixes/OptionExplicitQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/OptionExplicitQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/PassParameterByReferenceQuickFixTests.cs b/RubberduckTests/QuickFixes/PassParameterByReferenceQuickFixTests.cs index 58f2bc0a90..fc9bde7dbe 100644 --- a/RubberduckTests/QuickFixes/PassParameterByReferenceQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/PassParameterByReferenceQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/PassParameterByValueQuickFixTests.cs b/RubberduckTests/QuickFixes/PassParameterByValueQuickFixTests.cs index 5b4ab08207..eb45074998 100644 --- a/RubberduckTests/QuickFixes/PassParameterByValueQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/PassParameterByValueQuickFixTests.cs @@ -1,9 +1,9 @@ using System.Linq; using System.Threading; using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using RubberduckTests.Mocks; diff --git a/RubberduckTests/QuickFixes/QuickFixProviderTests.cs b/RubberduckTests/QuickFixes/QuickFixProviderTests.cs index 23827a6cc1..c5bd8116a1 100644 --- a/RubberduckTests/QuickFixes/QuickFixProviderTests.cs +++ b/RubberduckTests/QuickFixes/QuickFixProviderTests.cs @@ -2,9 +2,9 @@ using System.Threading; using Moq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.Rewriter; using RubberduckTests.Mocks; using RubberduckTests.Inspections; diff --git a/RubberduckTests/QuickFixes/QuickFixTestBase.cs b/RubberduckTests/QuickFixes/QuickFixTestBase.cs index 163d3c6c5b..5a0ac8167b 100644 --- a/RubberduckTests/QuickFixes/QuickFixTestBase.cs +++ b/RubberduckTests/QuickFixes/QuickFixTestBase.cs @@ -3,7 +3,8 @@ using System.Linq; using System.Threading; using Antlr4.Runtime.Tree; -using Rubberduck.Parsing.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.Parsing; diff --git a/RubberduckTests/QuickFixes/RemoveAnnotationQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveAnnotationQuickFixTests.cs index fa76838cd0..6d44b5081d 100644 --- a/RubberduckTests/QuickFixes/RemoveAnnotationQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveAnnotationQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/RemoveAttributeQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveAttributeQuickFixTests.cs index d7a8a91240..386856f222 100644 --- a/RubberduckTests/QuickFixes/RemoveAttributeQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveAttributeQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.Parsing; diff --git a/RubberduckTests/QuickFixes/RemoveCommentQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveCommentQuickFixTests.cs index 9d5481e0df..427e491afe 100644 --- a/RubberduckTests/QuickFixes/RemoveCommentQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveCommentQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/RemoveDuplicatedAnnotationQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveDuplicatedAnnotationQuickFixTests.cs index 50065d7396..93f375ebbe 100644 --- a/RubberduckTests/QuickFixes/RemoveDuplicatedAnnotationQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveDuplicatedAnnotationQuickFixTests.cs @@ -1,9 +1,10 @@ using System; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; using Rubberduck.Parsing.Annotations; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/RemoveEmptyElseBlockQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveEmptyElseBlockQuickFixTests.cs index 6f74ae03b4..70152bdbdc 100644 --- a/RubberduckTests/QuickFixes/RemoveEmptyElseBlockQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveEmptyElseBlockQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/RemoveEmptyIfBlockQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveEmptyIfBlockQuickFixTests.cs index dce1c00c4f..9db9df606e 100644 --- a/RubberduckTests/QuickFixes/RemoveEmptyIfBlockQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveEmptyIfBlockQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/RemoveExplicitByRefModifierQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveExplicitByRefModifierQuickFixTests.cs index d14c9df093..742f93444a 100644 --- a/RubberduckTests/QuickFixes/RemoveExplicitByRefModifierQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveExplicitByRefModifierQuickFixTests.cs @@ -1,9 +1,10 @@ using System; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/RemoveExplicitCallStatementQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveExplicitCallStatementQuickFixTests.cs index b50d2ba040..3309330b2a 100644 --- a/RubberduckTests/QuickFixes/RemoveExplicitCallStatementQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveExplicitCallStatementQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/RemoveExplicitLetStatementQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveExplicitLetStatementQuickFixTests.cs index c90fe12f6e..45f149e9a2 100644 --- a/RubberduckTests/QuickFixes/RemoveExplicitLetStatementQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveExplicitLetStatementQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/RemoveLocalErrorQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveLocalErrorQuickFixTests.cs index d5529316df..4769e106e7 100644 --- a/RubberduckTests/QuickFixes/RemoveLocalErrorQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveLocalErrorQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/RemoveOptionBaseStatementQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveOptionBaseStatementQuickFixTests.cs index 7e0082f69e..6304c631a0 100644 --- a/RubberduckTests/QuickFixes/RemoveOptionBaseStatementQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveOptionBaseStatementQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/RemoveStepOneQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveStepOneQuickFixTests.cs index b91c78038c..c6607c3fd0 100644 --- a/RubberduckTests/QuickFixes/RemoveStepOneQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveStepOneQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/RemoveStopKeywordQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveStopKeywordQuickFixTests.cs index 6b6a14b434..2a0d7cff24 100644 --- a/RubberduckTests/QuickFixes/RemoveStopKeywordQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveStopKeywordQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/RemoveTypeHintsQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveTypeHintsQuickFixTests.cs index ba47d4dce1..3ae6589072 100644 --- a/RubberduckTests/QuickFixes/RemoveTypeHintsQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveTypeHintsQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using RubberduckTests.Mocks; diff --git a/RubberduckTests/QuickFixes/RemoveUnassignedIdentifierQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveUnassignedIdentifierQuickFixTests.cs index 30279f6190..41e07483e2 100644 --- a/RubberduckTests/QuickFixes/RemoveUnassignedIdentifierQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveUnassignedIdentifierQuickFixTests.cs @@ -1,8 +1,9 @@ using System; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/RemoveUnassignedVariableUsageQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveUnassignedVariableUsageQuickFixTests.cs index aef8e8cd05..ad4cfb63eb 100644 --- a/RubberduckTests/QuickFixes/RemoveUnassignedVariableUsageQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveUnassignedVariableUsageQuickFixTests.cs @@ -2,9 +2,10 @@ using System.Linq; using System.Threading; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using RubberduckTests.Mocks; diff --git a/RubberduckTests/QuickFixes/RemoveUnusedDeclarationQuickFixTests.cs b/RubberduckTests/QuickFixes/RemoveUnusedDeclarationQuickFixTests.cs index 5638bee38d..7850b3daeb 100644 --- a/RubberduckTests/QuickFixes/RemoveUnusedDeclarationQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RemoveUnusedDeclarationQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/ReplaceEmptyStringLiteralStatementQuickFixTests.cs b/RubberduckTests/QuickFixes/ReplaceEmptyStringLiteralStatementQuickFixTests.cs index 05fb6f3c73..40926b58d8 100644 --- a/RubberduckTests/QuickFixes/ReplaceEmptyStringLiteralStatementQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ReplaceEmptyStringLiteralStatementQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/ReplaceGlobalModifierQuickFixTests.cs b/RubberduckTests/QuickFixes/ReplaceGlobalModifierQuickFixTests.cs index 3918ff935e..47a16c65e0 100644 --- a/RubberduckTests/QuickFixes/ReplaceGlobalModifierQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ReplaceGlobalModifierQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; diff --git a/RubberduckTests/QuickFixes/ReplaceIfElseWithConditionalStatementQuickFixTests.cs b/RubberduckTests/QuickFixes/ReplaceIfElseWithConditionalStatementQuickFixTests.cs index 24e21709b4..0f132d0e65 100644 --- a/RubberduckTests/QuickFixes/ReplaceIfElseWithConditionalStatementQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ReplaceIfElseWithConditionalStatementQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/ReplaceObsoleteCommentMarkerQuickFixTests.cs b/RubberduckTests/QuickFixes/ReplaceObsoleteCommentMarkerQuickFixTests.cs index 262fff29a1..d0b4671ea8 100644 --- a/RubberduckTests/QuickFixes/ReplaceObsoleteCommentMarkerQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ReplaceObsoleteCommentMarkerQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/ReplaceObsoleteErrorStatementQuickFixTests.cs b/RubberduckTests/QuickFixes/ReplaceObsoleteErrorStatementQuickFixTests.cs index c6e7acf058..756704ea6c 100644 --- a/RubberduckTests/QuickFixes/ReplaceObsoleteErrorStatementQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ReplaceObsoleteErrorStatementQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/ReplaceWhileWendWithDoWhileLoopQuickFixTests.cs b/RubberduckTests/QuickFixes/ReplaceWhileWendWithDoWhileLoopQuickFixTests.cs index fc298e5a05..f99d9ffae8 100644 --- a/RubberduckTests/QuickFixes/ReplaceWhileWendWithDoWhileLoopQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/ReplaceWhileWendWithDoWhileLoopQuickFixTests.cs @@ -1,7 +1,6 @@ using NUnit.Framework; using Rubberduck.CodeAnalysis.Inspections.Concrete; using Rubberduck.CodeAnalysis.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/RestoreErrorHandlingQuickFixTests.cs b/RubberduckTests/QuickFixes/RestoreErrorHandlingQuickFixTests.cs index d61a032ddc..c8a736ad7e 100644 --- a/RubberduckTests/QuickFixes/RestoreErrorHandlingQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/RestoreErrorHandlingQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/SetExplicitVariantReturnTypeQuickFixTests.cs b/RubberduckTests/QuickFixes/SetExplicitVariantReturnTypeQuickFixTests.cs index dad7d8ebf4..a06957b178 100644 --- a/RubberduckTests/QuickFixes/SetExplicitVariantReturnTypeQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/SetExplicitVariantReturnTypeQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/SpecifyExplicitByRefModifierQuickFixTests.cs b/RubberduckTests/QuickFixes/SpecifyExplicitByRefModifierQuickFixTests.cs index 86e06cb435..480936da67 100644 --- a/RubberduckTests/QuickFixes/SpecifyExplicitByRefModifierQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/SpecifyExplicitByRefModifierQuickFixTests.cs @@ -1,9 +1,10 @@ using System; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/SpecifyExplicitPublicModifierQuickFixTests.cs b/RubberduckTests/QuickFixes/SpecifyExplicitPublicModifierQuickFixTests.cs index 9a3f6c7c97..ae025cbaac 100644 --- a/RubberduckTests/QuickFixes/SpecifyExplicitPublicModifierQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/SpecifyExplicitPublicModifierQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; diff --git a/RubberduckTests/QuickFixes/SplitMultipleDeclarationsQuickFixTests.cs b/RubberduckTests/QuickFixes/SplitMultipleDeclarationsQuickFixTests.cs index 19e9f103be..2e27d29fc2 100644 --- a/RubberduckTests/QuickFixes/SplitMultipleDeclarationsQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/SplitMultipleDeclarationsQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; namespace RubberduckTests.QuickFixes diff --git a/RubberduckTests/QuickFixes/UseSetKeywordForObjectAssignmentQuickFixTests.cs b/RubberduckTests/QuickFixes/UseSetKeywordForObjectAssignmentQuickFixTests.cs index 82568fad75..301f93ab13 100644 --- a/RubberduckTests/QuickFixes/UseSetKeywordForObjectAssignmentQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/UseSetKeywordForObjectAssignmentQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; diff --git a/RubberduckTests/QuickFixes/WriteOnlyPropertyQuickFixTests.cs b/RubberduckTests/QuickFixes/WriteOnlyPropertyQuickFixTests.cs index d07b1d1f6d..b78e50d414 100644 --- a/RubberduckTests/QuickFixes/WriteOnlyPropertyQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/WriteOnlyPropertyQuickFixTests.cs @@ -1,7 +1,7 @@ using NUnit.Framework; +using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; using Rubberduck.VBEditor.SafeComWrappers.Abstract; diff --git a/RubberduckTests/Settings/CodeInspectionConfigProviderTests.cs b/RubberduckTests/Settings/CodeInspectionConfigProviderTests.cs index 4fa35972aa..71c3709680 100644 --- a/RubberduckTests/Settings/CodeInspectionConfigProviderTests.cs +++ b/RubberduckTests/Settings/CodeInspectionConfigProviderTests.cs @@ -4,7 +4,6 @@ using NUnit.Framework; using Rubberduck.Parsing.Inspections; using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Settings; using Rubberduck.SettingsProvider; using Rubberduck.CodeAnalysis.Settings; From 3cdd860b49f162fb5f9f045448bacc3f086f18e1 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sat, 7 Mar 2020 19:00:51 +0100 Subject: [PATCH 287/461] Move remainder of inspections API to CodeAnalysis --- .../Inspections/Abstract/InspectionBase.cs | 1 - .../Attributes/CannotAnnotateAttribute.cs | 11 ++++++++ .../Attributes}/RequiredHostAttribute.cs | 4 +-- .../Attributes}/RequiredLibraryAttribute.cs | 4 +-- .../Inspections/CodeInspectionSeverity.cs | 2 +- .../Inspections/CodeInspectionType.cs | 2 +- ...entWithIncompatibleObjectTypeInspection.cs | 1 - .../AttributeValueOutOfSyncInspection.cs | 2 +- .../DefaultMemberRequiredInspection.cs | 1 - .../Concrete/DefaultProjectNameInspection.cs | 4 +-- .../ApplicationWorksheetFunctionInspection.cs | 2 +- .../ExcelMemberMayReturnNothingInspection.cs | 2 +- ...elUdfNameIsValidCellReferenceInspection.cs | 2 +- .../ImplicitActiveSheetReferenceInspection.cs | 2 +- ...plicitActiveWorkbookReferenceInspection.cs | 2 +- .../SheetAccessedUsingStringInspection.cs | 2 +- .../FunctionReturnValueDiscardedInspection.cs | 2 +- .../ImplicitDefaultMemberAccessInspection.cs | 4 +-- ...tRecursiveDefaultMemberAccessInspection.cs | 4 +-- ...citUnboundDefaultMemberAccessInspection.cs | 2 +- .../IndexedDefaultMemberAccessInspection.cs | 4 +-- ...dRecursiveDefaultMemberAccessInspection.cs | 4 +-- ...xedUnboundDefaultMemberAccessInspection.cs | 2 +- .../Concrete/MissingAttributeInspection.cs | 2 +- ...bjectWhereProcedureIsRequiredInspection.cs | 1 - .../Concrete/ProcedureRequiredInspection.cs | 1 - ...entWithIncompatibleObjectTypeInspection.cs | 1 - ...SuperfluousAnnotationArgumentInspection.cs | 1 - .../SuspiciousLetAssignmentInspection.cs | 1 - .../ExpressionFilterFactory.cs | 4 +-- .../Concrete/UseOfBangNotationInspection.cs | 4 +-- .../UseOfRecursiveBangNotationInspection.cs | 4 +-- .../UseOfUnboundBangNotationInspection.cs | 2 +- .../Concrete/ValueRequiredInspection.cs | 1 - .../Inspections/IInspectionModel.cs | 4 +-- .../Inspections/Logistics/Inspector.cs | 2 +- .../QuickFixes/Concrete/IgnoreOnceQuickFix.cs | 2 +- .../Settings/CodeInspectionConfigProvider.cs | 1 - .../Settings/CodeInspectionSettings.cs | 1 - .../Inspections/InspectionResultsViewModel.cs | 2 -- .../InspectionSeverityImageSourceConverter.cs | 2 +- .../AddRemoveReferencesUserSettings.xaml.cs | 4 +-- .../UI/Settings/AutoCompleteSettings.xaml.cs | 15 +---------- ...deInspectionSeverityEnumToTextConverter.cs | 2 +- .../UI/Settings/GeneralSettingsViewModel.cs | 1 - .../UI/Settings/InspectionSettings.xaml | 5 ++-- .../UI/Settings/InspectionSettings.xaml.cs | 2 +- .../Settings/InspectionSettingsViewModel.cs | 2 +- .../UI/Settings/SettingsViewModelBase.cs | 3 +-- .../Inspections/CannotAnnotateAttribute.cs | 23 ---------------- Rubberduck.Parsing/Inspections/PropertyBag.cs | 26 ------------------- RubberduckTests/ConfigurationTests.cs | 1 - .../DefaultProjectNameInspectionTests.cs | 1 - .../IllegalAnnotationsInspectionTests.cs | 2 -- .../Inspections/InspectionProviderTests.cs | 1 - .../Inspections/InspectionResultTests.cs | 2 -- .../StepNotSpecifiedInspectionTests.cs | 1 - .../StepOneIsRedundantInspectionTests.cs | 1 - .../ThunderCode/ThunderCodeInspectionTests.cs | 1 - .../Settings/AutoCompleteSettingsTests.cs | 4 +-- .../CodeInspectionConfigProviderTests.cs | 2 -- .../Settings/GeneralSettingsTests.cs | 1 - .../Settings/InspectionSettingsTests.cs | 2 +- 63 files changed, 59 insertions(+), 145 deletions(-) create mode 100644 Rubberduck.CodeAnalysis/Inspections/Attributes/CannotAnnotateAttribute.cs rename {Rubberduck.Parsing/Inspections => Rubberduck.CodeAnalysis/Inspections/Attributes}/RequiredHostAttribute.cs (82%) rename {Rubberduck.Parsing/Inspections => Rubberduck.CodeAnalysis/Inspections/Attributes}/RequiredLibraryAttribute.cs (76%) rename {Rubberduck.Parsing => Rubberduck.CodeAnalysis}/Inspections/CodeInspectionSeverity.cs (91%) rename {Rubberduck.Parsing => Rubberduck.CodeAnalysis}/Inspections/CodeInspectionType.cs (80%) delete mode 100644 Rubberduck.Parsing/Inspections/CannotAnnotateAttribute.cs delete mode 100644 Rubberduck.Parsing/Inspections/PropertyBag.cs diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs index ca0b99ba31..bae480aeb2 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs @@ -8,7 +8,6 @@ using System.Threading; using NLog; using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Parsing.Inspections; using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Attributes/CannotAnnotateAttribute.cs b/Rubberduck.CodeAnalysis/Inspections/Attributes/CannotAnnotateAttribute.cs new file mode 100644 index 0000000000..d366c5dca8 --- /dev/null +++ b/Rubberduck.CodeAnalysis/Inspections/Attributes/CannotAnnotateAttribute.cs @@ -0,0 +1,11 @@ +using System; + +namespace Rubberduck.CodeAnalysis.Inspections.Attributes +{ + /// + /// This inspection isn't looking at code from the CodePane pass, and cannot be annotated. + /// + [AttributeUsage(AttributeTargets.Class)] + internal class CannotAnnotateAttribute : Attribute + {} +} \ No newline at end of file diff --git a/Rubberduck.Parsing/Inspections/RequiredHostAttribute.cs b/Rubberduck.CodeAnalysis/Inspections/Attributes/RequiredHostAttribute.cs similarity index 82% rename from Rubberduck.Parsing/Inspections/RequiredHostAttribute.cs rename to Rubberduck.CodeAnalysis/Inspections/Attributes/RequiredHostAttribute.cs index 63d2fd929f..a6918d3a0e 100644 --- a/Rubberduck.Parsing/Inspections/RequiredHostAttribute.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Attributes/RequiredHostAttribute.cs @@ -2,13 +2,13 @@ using System.Collections.Generic; using System.Linq; -namespace Rubberduck.Parsing.Inspections +namespace Rubberduck.CodeAnalysis.Inspections.Attributes { /// /// This inspection requires a specific host application in order to run. /// [AttributeUsage(AttributeTargets.Class)] - public class RequiredHostAttribute : Attribute + internal class RequiredHostAttribute : Attribute { public IEnumerable HostNames { get; } diff --git a/Rubberduck.Parsing/Inspections/RequiredLibraryAttribute.cs b/Rubberduck.CodeAnalysis/Inspections/Attributes/RequiredLibraryAttribute.cs similarity index 76% rename from Rubberduck.Parsing/Inspections/RequiredLibraryAttribute.cs rename to Rubberduck.CodeAnalysis/Inspections/Attributes/RequiredLibraryAttribute.cs index fd0363c600..951434590e 100644 --- a/Rubberduck.Parsing/Inspections/RequiredLibraryAttribute.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Attributes/RequiredLibraryAttribute.cs @@ -1,12 +1,12 @@ using System; -namespace Rubberduck.Parsing.Inspections +namespace Rubberduck.CodeAnalysis.Inspections.Attributes { /// /// This inspection requires a specific type library to be referenced in order to run. /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] - public class RequiredLibraryAttribute : Attribute + internal class RequiredLibraryAttribute : Attribute { public RequiredLibraryAttribute(string name) { diff --git a/Rubberduck.Parsing/Inspections/CodeInspectionSeverity.cs b/Rubberduck.CodeAnalysis/Inspections/CodeInspectionSeverity.cs similarity index 91% rename from Rubberduck.Parsing/Inspections/CodeInspectionSeverity.cs rename to Rubberduck.CodeAnalysis/Inspections/CodeInspectionSeverity.cs index a532e6ea4a..c1e3c3593a 100644 --- a/Rubberduck.Parsing/Inspections/CodeInspectionSeverity.cs +++ b/Rubberduck.CodeAnalysis/Inspections/CodeInspectionSeverity.cs @@ -1,4 +1,4 @@ -namespace Rubberduck.Parsing.Inspections +namespace Rubberduck.CodeAnalysis.Inspections { public enum CodeInspectionSeverity { diff --git a/Rubberduck.Parsing/Inspections/CodeInspectionType.cs b/Rubberduck.CodeAnalysis/Inspections/CodeInspectionType.cs similarity index 80% rename from Rubberduck.Parsing/Inspections/CodeInspectionType.cs rename to Rubberduck.CodeAnalysis/Inspections/CodeInspectionType.cs index 5203ef6337..c5965218ad 100644 --- a/Rubberduck.Parsing/Inspections/CodeInspectionType.cs +++ b/Rubberduck.CodeAnalysis/Inspections/CodeInspectionType.cs @@ -1,4 +1,4 @@ -namespace Rubberduck.Parsing.Inspections +namespace Rubberduck.CodeAnalysis.Inspections { public enum CodeInspectionType { diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs index 498236d8d9..eb4fcc23ef 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs @@ -2,7 +2,6 @@ using System.Linq; using Rubberduck.Inspections.Inspections.Abstract; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.TypeResolvers; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/AttributeValueOutOfSyncInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/AttributeValueOutOfSyncInspection.cs index 5fc79a18c2..7039e7f781 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/AttributeValueOutOfSyncInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/AttributeValueOutOfSyncInspection.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections.Attributes; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.Annotations; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs index 6c698dfc3b..955d12afc4 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Rubberduck.Inspections.Abstract; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultProjectNameInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultProjectNameInspection.cs index 8d6de441ee..281e25be14 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultProjectNameInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultProjectNameInspection.cs @@ -1,5 +1,5 @@ -using Rubberduck.Inspections.Abstract; -using Rubberduck.Parsing.Inspections; +using Rubberduck.CodeAnalysis.Inspections.Attributes; +using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs index c724efab23..38fccd3ddf 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections.Attributes; using Rubberduck.Inspections.Abstract; -using Rubberduck.Parsing.Inspections; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelMemberMayReturnNothingInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelMemberMayReturnNothingInspection.cs index b0df79d56a..bdf49c3e7d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelMemberMayReturnNothingInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelMemberMayReturnNothingInspection.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections.Attributes; using Rubberduck.Inspections.Abstract; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs index 02715f8282..c0f1c69d4a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs @@ -3,8 +3,8 @@ using System.Linq; using System.Text.RegularExpressions; using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.CodeAnalysis.Inspections.Attributes; using Rubberduck.Inspections.Abstract; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs index 5f8a07b478..1c6aa9289e 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections.Attributes; using Rubberduck.Inspections.Abstract; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveWorkbookReferenceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveWorkbookReferenceInspection.cs index 4302bc4272..dbc9a4f7f7 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveWorkbookReferenceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveWorkbookReferenceInspection.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections.Attributes; using Rubberduck.Inspections.Abstract; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs index 049f9215e1..d1f64f0439 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs @@ -1,9 +1,9 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections.Attributes; using Rubberduck.Common; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueDiscardedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueDiscardedInspection.cs index e407a4d858..ea442ba3ef 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueDiscardedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueDiscardedInspection.cs @@ -1,8 +1,8 @@ using Antlr4.Runtime; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs index d66217a75e..c915a0baaa 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs @@ -1,9 +1,9 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs index 2bb9907dad..14850c79d8 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs @@ -1,9 +1,9 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs index 04489437da..8306056fc1 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs @@ -1,10 +1,10 @@ using System.Collections.Generic; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.VBEditor; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs index 7ea1385be5..0388d87c8f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs @@ -1,10 +1,10 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs index b702aeea69..395048993a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs @@ -1,10 +1,10 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs index 06619a07fd..d5d2edc7fa 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs @@ -1,11 +1,11 @@ using System.Collections.Generic; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.VBEditor; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAttributeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAttributeInspection.cs index 31e49f1e4c..49de3e1578 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAttributeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAttributeInspection.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections.Attributes; using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.Annotations; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs index 9b423e152b..0994e47f7b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs @@ -3,7 +3,6 @@ using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Results; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs index 8e0165e28b..bb7829930a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Rubberduck.Inspections.Abstract; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs index 696278c40c..d1acf1ae66 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs @@ -2,7 +2,6 @@ using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.TypeResolvers; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuperfluousAnnotationArgumentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuperfluousAnnotationArgumentInspection.cs index 306cda40ec..972109dc80 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuperfluousAnnotationArgumentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuperfluousAnnotationArgumentInspection.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using Rubberduck.CodeAnalysis.Inspections; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs index cb14f0b694..4bb14eab52 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs @@ -6,7 +6,6 @@ using Rubberduck.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilterFactory.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilterFactory.cs index 391f1705f1..78140dff8a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilterFactory.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UnreachableCaseInspection/ExpressionFilterFactory.cs @@ -1,6 +1,4 @@ -using Rubberduck.Parsing; -using Rubberduck.Parsing.Grammar; -using System; +using Rubberduck.Parsing.Grammar; using System.Collections.Generic; using System.Globalization; using System.Linq; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfBangNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfBangNotationInspection.cs index 74e2dd38be..b6bec10443 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfBangNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfBangNotationInspection.cs @@ -1,9 +1,9 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs index 4128de45fb..9547ca95a2 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfRecursiveBangNotationInspection.cs @@ -1,9 +1,9 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.VBA.DeclarationCaching; namespace Rubberduck.Inspections.Concrete diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs index a291cbe464..2a524e82ef 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/UseOfUnboundBangNotationInspection.cs @@ -1,10 +1,10 @@ using System.Collections.Generic; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.VBEditor; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs index 028611e3b4..e3e61a0bdc 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ValueRequiredInspection.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Rubberduck.Inspections.Abstract; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/IInspectionModel.cs b/Rubberduck.CodeAnalysis/Inspections/IInspectionModel.cs index bd1257f8e9..cb99a4263e 100644 --- a/Rubberduck.CodeAnalysis/Inspections/IInspectionModel.cs +++ b/Rubberduck.CodeAnalysis/Inspections/IInspectionModel.cs @@ -1,6 +1,4 @@ -using Rubberduck.Parsing.Inspections; - -namespace Rubberduck.CodeAnalysis.Inspections +namespace Rubberduck.CodeAnalysis.Inspections { /// /// An interface that abstracts the data structure for a code inspection diff --git a/Rubberduck.CodeAnalysis/Inspections/Logistics/Inspector.cs b/Rubberduck.CodeAnalysis/Inspections/Logistics/Inspector.cs index 19a4ccc0cd..68045223cb 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Logistics/Inspector.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Logistics/Inspector.cs @@ -11,7 +11,7 @@ using Antlr4.Runtime.Tree; using NLog; using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Parsing.Inspections; +using Rubberduck.CodeAnalysis.Inspections.Attributes; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.Parsing; using Rubberduck.VBEditor; diff --git a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/IgnoreOnceQuickFix.cs b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/IgnoreOnceQuickFix.cs index 0222a2f511..d693d25ed0 100644 --- a/Rubberduck.CodeAnalysis/QuickFixes/Concrete/IgnoreOnceQuickFix.cs +++ b/Rubberduck.CodeAnalysis/QuickFixes/Concrete/IgnoreOnceQuickFix.cs @@ -1,10 +1,10 @@ using System.Collections.Generic; using System.Linq; using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.CodeAnalysis.Inspections.Attributes; using Rubberduck.CodeAnalysis.QuickFixes.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Annotations; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.Rewriter; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Settings/CodeInspectionConfigProvider.cs b/Rubberduck.CodeAnalysis/Settings/CodeInspectionConfigProvider.cs index 0b42405804..09228bd715 100644 --- a/Rubberduck.CodeAnalysis/Settings/CodeInspectionConfigProvider.cs +++ b/Rubberduck.CodeAnalysis/Settings/CodeInspectionConfigProvider.cs @@ -3,7 +3,6 @@ using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.JunkDrawer.Extensions; using Rubberduck.SettingsProvider; -using Rubberduck.Parsing.VBA.Extensions; using Rubberduck.Settings; namespace Rubberduck.CodeAnalysis.Settings diff --git a/Rubberduck.CodeAnalysis/Settings/CodeInspectionSettings.cs b/Rubberduck.CodeAnalysis/Settings/CodeInspectionSettings.cs index 1a133ad979..e0e5b8f434 100644 --- a/Rubberduck.CodeAnalysis/Settings/CodeInspectionSettings.cs +++ b/Rubberduck.CodeAnalysis/Settings/CodeInspectionSettings.cs @@ -5,7 +5,6 @@ using System.Linq; using System.Xml.Serialization; using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Parsing.Inspections; namespace Rubberduck.CodeAnalysis.Settings { diff --git a/Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs b/Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs index 04602e67e0..21fb5c2499 100644 --- a/Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs +++ b/Rubberduck.Core/UI/Inspections/InspectionResultsViewModel.cs @@ -17,10 +17,8 @@ using Rubberduck.CodeAnalysis.QuickFixes; using Rubberduck.Common; using Rubberduck.Formatters; -using Rubberduck.Inspections.Abstract; using Rubberduck.Interaction.Navigation; using Rubberduck.JunkDrawer.Extensions; -using Rubberduck.Parsing.Inspections; using Rubberduck.Parsing.UIContext; using Rubberduck.Parsing.VBA; using Rubberduck.Settings; diff --git a/Rubberduck.Core/UI/Inspections/InspectionSeverityImageSourceConverter.cs b/Rubberduck.Core/UI/Inspections/InspectionSeverityImageSourceConverter.cs index 9325442b9b..61e83c9052 100644 --- a/Rubberduck.Core/UI/Inspections/InspectionSeverityImageSourceConverter.cs +++ b/Rubberduck.Core/UI/Inspections/InspectionSeverityImageSourceConverter.cs @@ -3,7 +3,7 @@ using System.Globalization; using System.Linq; using System.Windows.Media; -using Rubberduck.Parsing.Inspections; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Resources.Inspections; using ImageSourceConverter = Rubberduck.UI.Converters.ImageSourceConverter; diff --git a/Rubberduck.Core/UI/Settings/AddRemoveReferencesUserSettings.xaml.cs b/Rubberduck.Core/UI/Settings/AddRemoveReferencesUserSettings.xaml.cs index 3cf31559b4..ebaade8d71 100644 --- a/Rubberduck.Core/UI/Settings/AddRemoveReferencesUserSettings.xaml.cs +++ b/Rubberduck.Core/UI/Settings/AddRemoveReferencesUserSettings.xaml.cs @@ -1,6 +1,4 @@ -using System.Windows.Controls; - -namespace Rubberduck.UI.Settings +namespace Rubberduck.UI.Settings { /// /// Interaction logic for AddRemoveReferencesUserSettings.xaml diff --git a/Rubberduck.Core/UI/Settings/AutoCompleteSettings.xaml.cs b/Rubberduck.Core/UI/Settings/AutoCompleteSettings.xaml.cs index de1c79e9e9..fa7bfc1f5e 100644 --- a/Rubberduck.Core/UI/Settings/AutoCompleteSettings.xaml.cs +++ b/Rubberduck.Core/UI/Settings/AutoCompleteSettings.xaml.cs @@ -1,17 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; +using System.Windows.Controls; namespace Rubberduck.UI.Settings { diff --git a/Rubberduck.Core/UI/Settings/Converters/CodeInspectionSeverityEnumToTextConverter.cs b/Rubberduck.Core/UI/Settings/Converters/CodeInspectionSeverityEnumToTextConverter.cs index 705db003cf..5b0d0b21c7 100644 --- a/Rubberduck.Core/UI/Settings/Converters/CodeInspectionSeverityEnumToTextConverter.cs +++ b/Rubberduck.Core/UI/Settings/Converters/CodeInspectionSeverityEnumToTextConverter.cs @@ -3,7 +3,7 @@ using System.Globalization; using System.Linq; using System.Windows.Data; -using Rubberduck.Parsing.Inspections; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Resources.Inspections; namespace Rubberduck.UI.Settings.Converters diff --git a/Rubberduck.Core/UI/Settings/GeneralSettingsViewModel.cs b/Rubberduck.Core/UI/Settings/GeneralSettingsViewModel.cs index c1d53a5ea2..3f043e3bcc 100644 --- a/Rubberduck.Core/UI/Settings/GeneralSettingsViewModel.cs +++ b/Rubberduck.Core/UI/Settings/GeneralSettingsViewModel.cs @@ -12,7 +12,6 @@ using Rubberduck.Resources; using Rubberduck.Resources.Settings; using Rubberduck.Parsing.Common; -using System.Collections.Specialized; using Rubberduck.UI.WPF; namespace Rubberduck.UI.Settings diff --git a/Rubberduck.Core/UI/Settings/InspectionSettings.xaml b/Rubberduck.Core/UI/Settings/InspectionSettings.xaml index 26fe0aa908..a91363f8b6 100644 --- a/Rubberduck.Core/UI/Settings/InspectionSettings.xaml +++ b/Rubberduck.Core/UI/Settings/InspectionSettings.xaml @@ -4,11 +4,12 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:core="clr-namespace:System;assembly=mscorlib" - xmlns:inspections="clr-namespace:Rubberduck.Parsing.Inspections;assembly=Rubberduck.Parsing" + xmlns:inspections="clr-namespace:Rubberduck.CodeAnalysis.Inspections;assembly=Rubberduck.CodeAnalysis" xmlns:settings="clr-namespace:Rubberduck.UI.Settings" xmlns:converters="clr-namespace:Rubberduck.UI.Settings.Converters" xmlns:controls="clr-namespace:Rubberduck.UI.Controls" xmlns:themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" + xmlns:inspections1="clr-namespace:Rubberduck.CodeAnalysis.Inspections;assembly=Rubberduck.CodeAnalysis" mc:Ignorable="d" d:DesignWidth="700" d:DataContext="{d:DesignInstance {x:Type settings:InspectionSettingsViewModel}, IsDesignTimeCreatable=False}"> @@ -29,7 +30,7 @@ MethodName="GetValues" ObjectType="{x:Type core:Enum}"> - + diff --git a/Rubberduck.Core/UI/Settings/InspectionSettings.xaml.cs b/Rubberduck.Core/UI/Settings/InspectionSettings.xaml.cs index ef94d6aaab..4d68943186 100644 --- a/Rubberduck.Core/UI/Settings/InspectionSettings.xaml.cs +++ b/Rubberduck.Core/UI/Settings/InspectionSettings.xaml.cs @@ -2,7 +2,7 @@ using System.Linq; using System.Windows.Controls; using System.Collections.ObjectModel; -using Rubberduck.Parsing.Inspections; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.Settings; namespace Rubberduck.UI.Settings diff --git a/Rubberduck.Core/UI/Settings/InspectionSettingsViewModel.cs b/Rubberduck.Core/UI/Settings/InspectionSettingsViewModel.cs index 2e4fa3c52f..7b0050cfc9 100644 --- a/Rubberduck.Core/UI/Settings/InspectionSettingsViewModel.cs +++ b/Rubberduck.Core/UI/Settings/InspectionSettingsViewModel.cs @@ -3,13 +3,13 @@ using System.Linq; using System.Windows.Data; using NLog; -using Rubberduck.Parsing.Inspections; using Rubberduck.Settings; using Rubberduck.SettingsProvider; using Rubberduck.UI.Command; using Rubberduck.Resources.Inspections; using System.Globalization; using System; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Resources.Settings; using Rubberduck.CodeAnalysis.Settings; diff --git a/Rubberduck.Core/UI/Settings/SettingsViewModelBase.cs b/Rubberduck.Core/UI/Settings/SettingsViewModelBase.cs index cbb247b456..04aac8bf5e 100644 --- a/Rubberduck.Core/UI/Settings/SettingsViewModelBase.cs +++ b/Rubberduck.Core/UI/Settings/SettingsViewModelBase.cs @@ -1,5 +1,4 @@ -using System.ComponentModel; -using Rubberduck.Resources.Settings; +using Rubberduck.Resources.Settings; using Rubberduck.SettingsProvider; using Rubberduck.UI.Command; diff --git a/Rubberduck.Parsing/Inspections/CannotAnnotateAttribute.cs b/Rubberduck.Parsing/Inspections/CannotAnnotateAttribute.cs deleted file mode 100644 index 7fc45b77be..0000000000 --- a/Rubberduck.Parsing/Inspections/CannotAnnotateAttribute.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; - -namespace Rubberduck.Parsing.Inspections -{ - /// - /// This inspection isn't looking at code from the CodePane pass, and cannot be annotated. - /// - [AttributeUsage(AttributeTargets.Class)] - public class CannotAnnotateAttribute : Attribute - { - } - - [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] - public class QuickFixAttribute : Attribute - { - public QuickFixAttribute(Type quickFixType) - { - QuickFixType = quickFixType; - } - - public Type QuickFixType { get; } - } -} \ No newline at end of file diff --git a/Rubberduck.Parsing/Inspections/PropertyBag.cs b/Rubberduck.Parsing/Inspections/PropertyBag.cs deleted file mode 100644 index 1f3ee15092..0000000000 --- a/Rubberduck.Parsing/Inspections/PropertyBag.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; -using System.Dynamic; - -namespace Rubberduck.Parsing.Inspections -{ - public class PropertyBag : DynamicObject - { - private readonly Dictionary _properties = new Dictionary(); - - public override bool TryGetMember(GetMemberBinder binder, out object result) - { - return _properties.TryGetValue(binder.Name, out result); - } - - public override bool TrySetMember(SetMemberBinder binder, object value) - { - _properties[binder.Name] = value; - return true; - } - - public override IEnumerable GetDynamicMemberNames() - { - return _properties.Keys; - } - } -} diff --git a/RubberduckTests/ConfigurationTests.cs b/RubberduckTests/ConfigurationTests.cs index 5ed6f32d42..12f3392614 100644 --- a/RubberduckTests/ConfigurationTests.cs +++ b/RubberduckTests/ConfigurationTests.cs @@ -4,7 +4,6 @@ using Moq; using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Settings; -using Rubberduck.Parsing.Inspections; using Rubberduck.CodeAnalysis.Settings; namespace RubberduckTests diff --git a/RubberduckTests/Inspections/DefaultProjectNameInspectionTests.cs b/RubberduckTests/Inspections/DefaultProjectNameInspectionTests.cs index a50d06b4dc..401d7d3ade 100644 --- a/RubberduckTests/Inspections/DefaultProjectNameInspectionTests.cs +++ b/RubberduckTests/Inspections/DefaultProjectNameInspectionTests.cs @@ -1,5 +1,4 @@ using System.Linq; -using System.Threading; using NUnit.Framework; using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; diff --git a/RubberduckTests/Inspections/IllegalAnnotationsInspectionTests.cs b/RubberduckTests/Inspections/IllegalAnnotationsInspectionTests.cs index cf5a382ac2..fb2ee63669 100644 --- a/RubberduckTests/Inspections/IllegalAnnotationsInspectionTests.cs +++ b/RubberduckTests/Inspections/IllegalAnnotationsInspectionTests.cs @@ -1,11 +1,9 @@ using System.Linq; -using System.Threading; using NUnit.Framework; using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Inspections.Concrete; using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers; -using RubberduckTests.Mocks; namespace RubberduckTests.Inspections { diff --git a/RubberduckTests/Inspections/InspectionProviderTests.cs b/RubberduckTests/Inspections/InspectionProviderTests.cs index 38dd1935bf..4a93435837 100644 --- a/RubberduckTests/Inspections/InspectionProviderTests.cs +++ b/RubberduckTests/Inspections/InspectionProviderTests.cs @@ -2,7 +2,6 @@ using Moq; using NUnit.Framework; using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Parsing.Inspections; using Rubberduck.Settings; using Rubberduck.CodeAnalysis.Settings; diff --git a/RubberduckTests/Inspections/InspectionResultTests.cs b/RubberduckTests/Inspections/InspectionResultTests.cs index 784f777c50..65ff34486b 100644 --- a/RubberduckTests/Inspections/InspectionResultTests.cs +++ b/RubberduckTests/Inspections/InspectionResultTests.cs @@ -6,10 +6,8 @@ using Rubberduck.Parsing; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Symbols; -using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Parsing.VBA.ReferenceManagement; -using Rubberduck.UI.Inspections; using Rubberduck.VBEditor; namespace RubberduckTests.Inspections diff --git a/RubberduckTests/Inspections/StepNotSpecifiedInspectionTests.cs b/RubberduckTests/Inspections/StepNotSpecifiedInspectionTests.cs index 813864151c..9056fe7403 100644 --- a/RubberduckTests/Inspections/StepNotSpecifiedInspectionTests.cs +++ b/RubberduckTests/Inspections/StepNotSpecifiedInspectionTests.cs @@ -1,6 +1,5 @@ using NUnit.Framework; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections; using System.Linq; using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Parsing.VBA; diff --git a/RubberduckTests/Inspections/StepOneIsRedundantInspectionTests.cs b/RubberduckTests/Inspections/StepOneIsRedundantInspectionTests.cs index f399c539f1..c4d6bf17f0 100644 --- a/RubberduckTests/Inspections/StepOneIsRedundantInspectionTests.cs +++ b/RubberduckTests/Inspections/StepOneIsRedundantInspectionTests.cs @@ -1,6 +1,5 @@ using NUnit.Framework; using Rubberduck.Inspections.Concrete; -using Rubberduck.Parsing.Inspections; using System.Linq; using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Parsing.VBA; diff --git a/RubberduckTests/Inspections/ThunderCode/ThunderCodeInspectionTests.cs b/RubberduckTests/Inspections/ThunderCode/ThunderCodeInspectionTests.cs index 4399be64f9..3611d72019 100644 --- a/RubberduckTests/Inspections/ThunderCode/ThunderCodeInspectionTests.cs +++ b/RubberduckTests/Inspections/ThunderCode/ThunderCodeInspectionTests.cs @@ -8,7 +8,6 @@ using Rubberduck.Inspections.Inspections.Concrete.ThunderCode; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.Parsing; -using Rubberduck.Resources.Inspections; using Rubberduck.VBEditor; using Rubberduck.VBEditor.Extensions; using RubberduckTests.Mocks; diff --git a/RubberduckTests/Settings/AutoCompleteSettingsTests.cs b/RubberduckTests/Settings/AutoCompleteSettingsTests.cs index f7206dd854..bcdab0ff01 100644 --- a/RubberduckTests/Settings/AutoCompleteSettingsTests.cs +++ b/RubberduckTests/Settings/AutoCompleteSettingsTests.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; -using System.Linq; -using NUnit.Framework; +using NUnit.Framework; using Rubberduck.Settings; using Rubberduck.UI.Settings; using AutoCompleteSettings = Rubberduck.Settings.AutoCompleteSettings; diff --git a/RubberduckTests/Settings/CodeInspectionConfigProviderTests.cs b/RubberduckTests/Settings/CodeInspectionConfigProviderTests.cs index 71c3709680..6fc6ad2dde 100644 --- a/RubberduckTests/Settings/CodeInspectionConfigProviderTests.cs +++ b/RubberduckTests/Settings/CodeInspectionConfigProviderTests.cs @@ -2,9 +2,7 @@ using System.Linq; using Moq; using NUnit.Framework; -using Rubberduck.Parsing.Inspections; using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Settings; using Rubberduck.SettingsProvider; using Rubberduck.CodeAnalysis.Settings; diff --git a/RubberduckTests/Settings/GeneralSettingsTests.cs b/RubberduckTests/Settings/GeneralSettingsTests.cs index 7fe43dcff9..8de10ed8bf 100644 --- a/RubberduckTests/Settings/GeneralSettingsTests.cs +++ b/RubberduckTests/Settings/GeneralSettingsTests.cs @@ -8,7 +8,6 @@ using Moq; using Rubberduck.VBEditor.VbeRuntime.Settings; using System; -using System.Collections.ObjectModel; using Rubberduck.Interaction; using Rubberduck.SettingsProvider; diff --git a/RubberduckTests/Settings/InspectionSettingsTests.cs b/RubberduckTests/Settings/InspectionSettingsTests.cs index e17777050e..4f6fae5afa 100644 --- a/RubberduckTests/Settings/InspectionSettingsTests.cs +++ b/RubberduckTests/Settings/InspectionSettingsTests.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.Linq; using NUnit.Framework; +using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.CodeAnalysis.Settings; -using Rubberduck.Parsing.Inspections; using Rubberduck.Settings; using Rubberduck.UI.Settings; From e7c76e3d11fce3af69df5d590f2f085fb3d36193 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sat, 7 Mar 2020 19:31:41 +0100 Subject: [PATCH 288/461] Adjust inspection and quick fix namespaces --- ...ReferenceInspectionFromDeclarationsBase.cs | 3 +- .../Abstract/DeclarationInspectionBase.cs | 5 +- .../Abstract/DeclarationInspectionBaseBase.cs | 3 +- .../DeclarationInspectionMultiResultBase.cs | 5 +- ...ionInspectionUsingGlobalInformationBase.cs | 5 +- ...nspectionUsingGlobalInformationBaseBase.cs | 3 +- .../Abstract/EmptyBlockInspectionBase.cs | 2 +- .../IdentifierReferenceInspectionBase.cs | 5 +- ...ReferenceInspectionFromDeclarationsBase.cs | 5 +- .../Abstract/ImplicitTypeInspectionBase.cs | 2 +- .../Inspections/Abstract/InspectionBase.cs | 11 +- .../Abstract/InspectionResultBase.cs | 5 +- .../Abstract/IsMissingInspectionBase.cs | 2 +- ...berAccessMayReturnNothingInspectionBase.cs | 4 +- .../Abstract/ParseTreeInspectionBase.cs | 5 +- ...entWithIncompatibleObjectTypeInspection.cs | 2 +- .../AssignedByValParameterInspection.cs | 6 +- .../Concrete/AssignmentNotUsedInspection.cs | 12 +- .../AttributeValueOutOfSyncInspection.cs | 4 +- .../BooleanAssignedInIfElseInspection.cs | 7 +- .../Concrete/ConstantNotUsedInspection.cs | 8 +- .../Concrete/DefTypeStatementInspection.cs | 11 +- .../DefaultMemberRequiredInspection.cs | 2 +- .../Concrete/DefaultProjectNameInspection.cs | 6 +- .../DuplicatedAnnotationInspection.cs | 4 +- .../EmptyBlock/EmptyCaseBlockInspection.cs | 11 +- .../EmptyBlock/EmptyDoWhileBlockInspection.cs | 9 +- .../EmptyBlock/EmptyElseBlockInspection.cs | 9 +- .../EmptyBlock/EmptyForEachBlockInspection.cs | 9 +- .../EmptyBlock/EmptyForLoopBlockInspection.cs | 9 +- .../EmptyBlock/EmptyIfBlockInspection.cs | 7 +- .../EmptyWhileWendBlockInspection.cs | 9 +- .../Concrete/EmptyMethodInspection.cs | 10 +- .../Concrete/EmptyModuleInspection.cs | 6 +- .../Concrete/EmptyStringLiteralInspection.cs | 7 +- .../EncapsulatePublicFieldInspection.cs | 6 +- .../ApplicationWorksheetFunctionInspection.cs | 8 +- .../ExcelMemberMayReturnNothingInspection.cs | 4 +- ...elUdfNameIsValidCellReferenceInspection.cs | 5 +- .../ImplicitActiveSheetReferenceInspection.cs | 6 +- ...plicitActiveWorkbookReferenceInspection.cs | 6 +- .../SheetAccessedUsingStringInspection.cs | 10 +- ...ionReturnValueAlwaysDiscardedInspection.cs | 6 +- .../FunctionReturnValueDiscardedInspection.cs | 7 +- .../HostSpecificExpressionInspection.cs | 6 +- .../Concrete/HungarianNotationInspection.cs | 6 +- .../Concrete/IllegalAnnotationInspection.cs | 9 +- .../ImplementedInterfaceMemberInspection.cs | 12 +- .../ImplicitByRefModifierInspection.cs | 8 +- .../ImplicitDefaultMemberAccessInspection.cs | 9 +- .../ImplicitPublicMemberInspection.cs | 6 +- ...tRecursiveDefaultMemberAccessInspection.cs | 9 +- ...citUnboundDefaultMemberAccessInspection.cs | 9 +- .../ImplicitVariantReturnTypeInspection.cs | 6 +- .../ImplicitlyTypedConstInspection.cs | 6 +- .../IndexedDefaultMemberAccessInspection.cs | 11 +- ...dRecursiveDefaultMemberAccessInspection.cs | 11 +- ...xedUnboundDefaultMemberAccessInspection.cs | 11 +- .../Concrete/IntegerDataTypeInspection.cs | 6 +- ...issingOnInappropriateArgumentInspection.cs | 4 +- ...ssingWithNonArgumentParameterInspection.cs | 4 +- .../Concrete/LineLabelNotUsedInspection.cs | 10 +- .../MemberNotOnInterfaceInspection.cs | 8 +- .../MissingAnnotationArgumentInspection.cs | 9 +- .../Concrete/MissingAttributeInspection.cs | 4 +- .../MissingMemberAnnotationInspection.cs | 6 +- .../MissingModuleAnnotationInspection.cs | 6 +- .../ModuleScopeDimKeywordInspection.cs | 7 +- .../Concrete/ModuleWithoutFolderInspection.cs | 8 +- .../MoveFieldCloserToUsageInspection.cs | 6 +- .../Concrete/MultilineParameterInspection.cs | 5 +- .../MultipleDeclarationsInspection.cs | 7 +- .../NonReturningFunctionInspection.cs | 6 +- .../ObjectVariableNotSetInspection.cs | 10 +- ...bjectWhereProcedureIsRequiredInspection.cs | 7 +- .../ObsoleteCallStatementInspection.cs | 7 +- .../ObsoleteCallingConventionInspection.cs | 5 +- .../ObsoleteCommentSyntaxInspection.cs | 7 +- .../Concrete/ObsoleteErrorSyntaxInspection.cs | 7 +- .../Concrete/ObsoleteGlobalInspection.cs | 8 +- .../ObsoleteLetStatementInspection.cs | 7 +- .../Concrete/ObsoleteMemberUsageInspection.cs | 4 +- .../Concrete/ObsoleteTypeHintInspection.cs | 9 +- .../ObsoleteWhileWendStatementInspection.cs | 2 +- .../Concrete/OnLocalErrorInspection.cs | 9 +- .../Concrete/OptionBaseInspection.cs | 7 +- .../Concrete/OptionExplicitInspection.cs | 7 +- .../Concrete/ParameterCanBeByValInspection.cs | 6 +- .../Concrete/ParameterNotUsedInspection.cs | 6 +- ...ocedureCanBeWrittenAsFunctionInspection.cs | 6 +- .../Concrete/ProcedureNotUsedInspection.cs | 8 +- .../Concrete/ProcedureRequiredInspection.cs | 2 +- .../RedundantByRefModifierInspection.cs | 8 +- .../Concrete/RedundantOptionInspection.cs | 7 +- .../SelfAssignedDeclarationInspection.cs | 6 +- ...entWithIncompatibleObjectTypeInspection.cs | 2 +- .../Concrete/ShadowedDeclarationInspection.cs | 6 +- .../Concrete/StepIsNotSpecifiedInspection.cs | 11 +- .../Concrete/StepOneIsRedundantInspection.cs | 11 +- .../Concrete/StopKeywordInspection.cs | 7 +- ...SuperfluousAnnotationArgumentInspection.cs | 9 +- .../SuspiciousLetAssignmentInspection.cs | 9 +- .../KeywordsUsedAsMemberInspection.cs | 4 +- ...neContinuationBetweenKeywordsInspection.cs | 5 +- .../NegativeLineNumberInspection.cs | 5 +- .../NonBreakingSpaceIdentifierInspection.cs | 4 +- .../OnErrorGoToMinusOneInspection.cs | 5 +- .../ThunderCode/ThunderCodeFormatExtension.cs | 2 +- .../UnassignedVariableUsageInspection.cs | 6 +- .../Concrete/UndeclaredVariableInspection.cs | 6 +- ...coreInPublicClassModuleMemberInspection.cs | 8 +- .../UnhandledOnErrorResumeNextInspection.cs | 7 +- .../ComparableDateValue.cs | 8 +- .../ExpressionFilter.cs | 6 +- .../ExpressionFilterBoolean.cs | 2 +- .../ExpressionFilterDate.cs | 6 +- .../ExpressionFilterFactory.cs | 6 +- .../ExpressionFilterIntegral.cs | 2 +- .../UnreachableCaseInspection/FilterLimits.cs | 2 +- .../UnreachableCaseInspection/LetCoerce.cs | 8 +- .../OperatorTypesProvider.cs | 6 +- .../ParseTreeExpressionEvaluator.cs | 8 +- .../ParseTreeValue.cs | 8 +- .../ParseTreeValueFactory.cs | 8 +- .../ParseTreeValueVisitor.cs | 10 +- .../ParseTreeVisitorResults.cs | 6 +- .../RangeClauseExpression.cs | 6 +- .../TypeTokenPair.cs | 6 +- .../UnreachableCaseInspection.cs | 23 +- .../UnreachableCaseInspector.cs | 10 +- .../UntypedFunctionUsageInspection.cs | 8 +- .../Concrete/UseMeaningfulNameInspection.cs | 6 +- .../Concrete/UseOfBangNotationInspection.cs | 9 +- .../UseOfRecursiveBangNotationInspection.cs | 9 +- .../UseOfUnboundBangNotationInspection.cs | 9 +- .../Concrete/ValueRequiredInspection.cs | 2 +- .../Concrete/VariableNotAssignedInspection.cs | 6 +- .../Concrete/VariableNotUsedInspection.cs | 13 +- .../VariableRequiresSetAssignmentEvaluator.cs | 8 +- .../VariableTypeNotDeclaredInspection.cs | 8 +- .../Concrete/WriteOnlyPropertyInspection.cs | 7 +- .../Extensions/DeclarationTypeExtensions.cs | 2 +- .../Extensions/ExecutableBlocksExtensions.cs | 2 +- .../Extensions/IgnoreRelatedExtensions.cs | 7 +- .../Logistics/IInspectionProvider.cs | 4 +- .../Logistics/InspectionProvider.cs | 4 +- .../Inspections/Logistics/Inspector.cs | 364 +++++++++--------- .../Results/DeclarationInspectionResult.cs | 5 +- .../IdentifierReferenceInspectionResult.cs | 5 +- .../QualifiedContextInspectionResult.cs | 5 +- .../AccessSheetUsingCodeNameQuickFix.cs | 6 +- .../AddAttributeAnnotationQuickFix.cs | 4 +- .../AddIdentifierToWhiteListQuickFix.cs | 6 +- .../Concrete/AddMissingAttributeQuickFix.cs | 4 +- .../QuickFixes/Concrete/AddStepOneQuickFix.cs | 8 +- .../AdjustAttributeAnnotationQuickFix.cs | 4 +- .../Concrete/AdjustAttributeValuesQuickFix.cs | 4 +- .../ApplicationWorksheetFunctionQuickFix.cs | 4 +- ...gnedByValParameterMakeLocalCopyQuickFix.cs | 20 +- .../Concrete/ChangeDimToPrivateQuickFix.cs | 4 +- .../Concrete/ChangeIntegerToLongQuickFix.cs | 6 +- .../ChangeProcedureToFunctionQuickFix.cs | 4 +- .../Concrete/ConvertToProcedureQuickFix.cs | 4 +- .../DeclareAsExplicitVariantQuickFix.cs | 4 +- .../Concrete/ExpandBangNotationQuickFix.cs | 4 +- .../Concrete/ExpandDefaultMemberQuickFix.cs | 4 +- .../QuickFixes/Concrete/IgnoreOnceQuickFix.cs | 2 +- .../IntroduceLocalVariableQuickFix.cs | 4 +- ...sMissingOnInappropriateArgumentQuickFix.cs | 4 +- .../MakeSingleLineParameterQuickFix.cs | 4 +- .../Concrete/OptionExplicitQuickFix.cs | 4 +- .../PassParameterByReferenceQuickFix.cs | 4 +- .../Concrete/PassParameterByValueQuickFix.cs | 4 +- .../Refactoring/EncapsulateFieldQuickFix.cs | 4 +- .../MoveFieldCloserToUsageQuickFix.cs | 4 +- .../RemoveUnusedParameterQuickFix.cs | 4 +- .../Refactoring/RenameDeclarationQuickFix.cs | 6 +- .../Concrete/RemoveAnnotationQuickFix.cs | 4 +- .../Concrete/RemoveAttributeQuickFix.cs | 4 +- .../Concrete/RemoveCommentQuickFix.cs | 4 +- .../RemoveDuplicatedAnnotationQuickFix.cs | 4 +- .../Concrete/RemoveEmptyElseBlockQuickFix.cs | 4 +- .../Concrete/RemoveEmptyIfBlockQuickFix.cs | 4 +- .../RemoveExplicitByRefModifierQuickFix.cs | 8 +- .../RemoveExplicitCallStatementQuickFix.cs | 4 +- .../RemoveExplicitLetStatementQuickFix.cs | 4 +- .../Concrete/RemoveLocalErrorQuickFix.cs | 4 +- .../RemoveOptionBaseStatementQuickFix.cs | 4 +- .../Concrete/RemoveStepOneQuickFix.cs | 4 +- .../Concrete/RemoveStopKeywordQuickFix.cs | 4 +- .../Concrete/RemoveTypeHintsQuickFix.cs | 4 +- .../RemoveUnassignedIdentifierQuickFix.cs | 4 +- .../RemoveUnassignedVariableUsageQuickFix.cs | 4 +- .../RemoveUnusedDeclarationQuickFix.cs | 4 +- ...laceEmptyStringLiteralStatementQuickFix.cs | 4 +- .../Concrete/ReplaceGlobalModifierQuickFix.cs | 4 +- ...eIfElseWithConditionalStatementQuickFix.cs | 4 +- .../ReplaceObsoleteCommentMarkerQuickFix.cs | 4 +- .../ReplaceObsoleteErrorStatementQuickFix.cs | 4 +- ...ReplaceWhileWendWithDoWhileLoopQuickFix.cs | 2 +- .../Concrete/RestoreErrorHandlingQuickFix.cs | 4 +- .../SetExplicitVariantReturnTypeQuickFix.cs | 4 +- .../SpecifyExplicitByRefModifierQuickFix.cs | 6 +- .../SpecifyExplicitPublicModifierQuickFix.cs | 4 +- .../SplitMultipleDeclarationsQuickFix.cs | 4 +- .../Concrete/UntypedFunctionUsageQuickFix.cs | 4 +- ...seSetKeywordForObjectAssignmentQuickFix.cs | 4 +- .../Concrete/WriteOnlyPropertyQuickFix.cs | 4 +- .../Logistics/IQuickFixFailureNotifier.cs | 2 +- .../Logistics/QuickFixFailureNotifier.cs | 2 +- .../QuickFixes/Logistics/QuickFixProvider.cs | 3 +- .../Settings/CodeInspectionConfigProvider.cs | 4 +- .../Root/RubberduckIoCInstaller.cs | 5 +- RubberduckTests/Grammar/AttributesTests.cs | 1 - ...icationWorksheetFunctionInspectionTests.cs | 2 +- .../AssignedByValParameterInspectionTests.cs | 2 +- .../AssignmentNotUsedInspectionTests.cs | 2 +- .../AttributeValueOutOfSyncInspectionTests.cs | 2 +- .../BooleanAssignedInIfElseInspectionTests.cs | 2 +- .../ConstantNotUsedInspectionTests.cs | 2 +- .../DefTypeStatementInspectionTests.cs | 2 +- .../DefaultProjectNameInspectionTests.cs | 2 +- .../DuplicatedAnnotationInspectionTests.cs | 2 +- .../EmptyCaseBlockInspectionTests.cs | 2 +- .../EmptyDoWhileBlockInspectionTests.cs | 2 +- .../EmptyElseBlockInspectionTests.cs | 2 +- .../EmptyForEachBlockInspectionTests.cs | 2 +- .../EmptyForLoopBlockInspectionTests.cs | 2 +- .../EmptyIfBlockInspectionTests.cs | 2 +- .../Inspections/EmptyMethodInspectionTests.cs | 2 +- .../Inspections/EmptyModuleInspectionTests.cs | 2 +- .../EmptyStringLiteralInspectionTests.cs | 2 +- .../EmptyWhileWendBlockInspectionTests.cs | 2 +- .../EncapsulatePublicFieldInspectionTests.cs | 2 +- ...elMemberMayReturnNothingInspectionTests.cs | 2 +- ...NameIsValidCellReferenceInspectionTests.cs | 2 +- ...turnValueAlwaysDiscardedInspectionTests.cs | 2 +- ...tionReturnValueDiscardedInspectionTests.cs | 2 +- .../Inspections/GeneralInspectionTests.cs | 4 +- .../HostSpecificExpressionInspectionTests.cs | 2 +- .../HungarianNotationInspectionTests.cs | 2 +- .../IllegalAnnotationsInspectionTests.cs | 2 +- ...plementedInterfaceMemberInspectionTests.cs | 2 +- ...icitActiveSheetReferenceInspectionTests.cs | 2 +- ...tActiveWorkbookReferenceInspectionTests.cs | 2 +- .../ImplicitByRefModifierInspectionTests.cs | 2 +- ...licitDefaultMemberAccessInspectionTests.cs | 2 +- .../ImplicitPublicMemberInspectionTests.cs | 2 +- ...rsiveDefaultMemberAccessInspectionTests.cs | 2 +- ...boundDefaultMemberAccessInspectionTests.cs | 2 +- ...mplicitVariantReturnTypeInspectionTests.cs | 2 +- .../ImplicitlyTypedConstInspectionTests.cs | 2 +- ...dexedDefaultMemberAccessInspectionTests.cs | 2 +- ...rsiveDefaultMemberAccessInspectionTests.cs | 2 +- ...boundDefaultMemberAccessInspectionTests.cs | 2 +- .../Inspections/InspectionProviderTests.cs | 1 + .../Inspections/InspectionResultTests.cs | 2 +- .../Inspections/InspectionsHelper.cs | 2 +- .../IntegerDataTypeInspectionTests.cs | 2 +- ...gOnInappropriateArgumentInspectionTests.cs | 2 +- ...WithNonArgumentParameterInspectionTests.cs | 2 +- .../LineLabelNotUsedInspectionTests.cs | 2 +- .../MalformedAnnotationInspectionTests.cs | 2 +- .../MemberNotOnInterfaceInspectionTests.cs | 2 +- ...issingAnnotationArgumentInspectionTests.cs | 2 +- .../MissingAttributeInspectionTests.cs | 2 +- .../MissingMemberAnnotationInspectionTests.cs | 2 +- .../MissingModuleAnnotationInspectionTests.cs | 2 +- .../ModuleScopeDimKeywordInspectionTests.cs | 2 +- .../ModuleWithoutFolderInspectionTests.cs | 2 +- .../MoveFieldCloserToUsageInspectionTests.cs | 2 +- .../MultilineParameterInspectionTests.cs | 2 +- .../MultipleDeclarationsInspectionTests.cs | 2 +- .../NonReturningFunctionInspectionTests.cs | 2 +- .../ObjectVariableNotSetInspectionTests.cs | 2 +- ...WhereProcedureIsRequiredInspectionTests.cs | 2 +- .../ObsoleteCallStatementInspectionTests.cs | 2 +- ...bsoleteCallingConventionInspectionTests.cs | 2 +- .../ObsoleteCommentSyntaxInspectionTests.cs | 2 +- .../ObsoleteErrorSyntaxInspectionTests.cs | 2 +- .../ObsoleteGlobalInspectionTests.cs | 2 +- .../ObsoleteLetStatementInspectionTests.cs | 2 +- .../ObsoleteMemberUsageInspectionTests.cs | 2 +- .../ObsoleteTypeHintInspectionTests.cs | 2 +- .../OnLocalErrorInspectionTests.cs | 2 +- .../Inspections/OptionBaseInspectionTests.cs | 2 +- .../OptionExplicitInspectionTests.cs | 2 +- .../ParameterCanBeByValInspectionTests.cs | 2 +- .../ParameterNotUsedInspectionTests.cs | 2 +- .../ProcedureNotUsedInspectionTests.cs | 2 +- ...rocedureShouldBeFunctionInspectionTests.cs | 2 +- .../RedundantByRefModifierInspectionTests.cs | 2 +- .../RedundantOptionInspectionTests.cs | 2 +- .../SelfAssignedDeclarationInspectionTests.cs | 2 +- .../ShadowedDeclarationInspectionTests.cs | 2 +- ...SheetAccessedUsingStringInspectionTests.cs | 2 +- .../StepNotSpecifiedInspectionTests.cs | 2 +- .../StepOneIsRedundantInspectionTests.cs | 2 +- .../Inspections/StopKeywordInspectionTests.cs | 2 +- ...fluousAnnotationArgumentInspectionTests.cs | 2 +- .../SuspiciousLetAssignmentInspectionTests.cs | 2 +- .../ThunderCode/ThunderCodeInspectionTests.cs | 2 +- .../UnassignedVariableUsageInspectionTests.cs | 2 +- .../UndeclaredVariableInspectionTests.cs | 2 +- ...nPublicClassModuleMemberInspectionTests.cs | 2 +- ...nhandledOnErrorResumeNextInspectionTest.cs | 2 +- .../ExpressionFilterUnitTests.cs | 2 +- .../ParseTreeExpressionEvaluatorUnitTests.cs | 2 +- .../ParseTreeValueUnitTests.cs | 2 +- .../UnreachableCaseInspectionTests.cs | 2 +- .../UntypedFunctionUsageInspectionTests.cs | 2 +- .../UseMeaningfulNameInspectionTests.cs | 2 +- .../UseOfBangNotationInspectionTests.cs | 2 +- ...eOfRecursiveBangNotationInspectionTests.cs | 2 +- ...UseOfUnboundBangNotationInspectionTests.cs | 2 +- .../VariableNotAssignedInspectionTests.cs | 2 +- .../VariableNotUsedInspectionTests.cs | 2 +- .../VariableTypeNotDeclaredInspectionTests.cs | 2 +- .../WriteOnlyPropertyInspectionTests.cs | 2 +- .../AccessSheetUsingCodeNameQuickFixTests.cs | 4 +- .../AddAttributeAnnotationQuickFixTests.cs | 4 +- .../AddMissingAttributeQuickFixTests.cs | 4 +- .../QuickFixes/AddStepOneQuickFixTests.cs | 4 +- .../AdjustAttributeAnnotationQuickFixTests.cs | 4 +- .../AdjustAttributeValuesQuickFixTests.cs | 4 +- ...plicationWorksheetFunctionQuickFixTests.cs | 4 +- ...yValParameterMakeLocalCopyQuickFixTests.cs | 4 +- .../ChangeDimToPrivateQuickFixTests.cs | 4 +- .../ChangeIntegerToLongQuickFixTests.cs | 4 +- .../ChangeProcedureToFunctionQuickFixTests.cs | 4 +- .../ConvertToProcedureQuickFixTests.cs | 4 +- .../DeclareAsExplicitVariantQuickFixTests.cs | 4 +- .../ExpandBangNotationQuickFixTests.cs | 3 +- .../ExpandDefaultMemberQuickFixTests.cs | 3 +- .../QuickFixes/IgnoreOnceQuickFixTests.cs | 4 +- .../IntroduceLocalVariableQuickFixTests.cs | 4 +- ...ingOnInappropriateArgumentQuickFixTests.cs | 4 +- .../MakeSingleLineParamegerQuickFixTests.cs | 4 +- .../MoveFieldCloserToUsageQuickFixTests.cs | 4 +- .../QuickFixes/OptionExplicitQuickFixTests.cs | 4 +- .../PassParameterByReferenceQuickFixTests.cs | 4 +- .../PassParameterByValueQuickFixTests.cs | 4 +- .../QuickFixes/QuickFixBaseTests.cs | 4 +- .../QuickFixes/QuickFixProviderTests.cs | 5 +- .../RemoveAnnotationQuickFixTests.cs | 4 +- .../RemoveAttributeQuickFixTests.cs | 4 +- .../QuickFixes/RemoveCommentQuickFixTests.cs | 4 +- ...RemoveDuplicatedAnnotationQuickFixTests.cs | 4 +- .../RemoveEmptyElseBlockQuickFixTests.cs | 4 +- .../RemoveEmptyIfBlockQuickFixTests.cs | 4 +- ...emoveExplicitByRefModifierQuickFixTests.cs | 4 +- ...emoveExplicitCallStatementQuickFixTests.cs | 4 +- ...RemoveExplicitLetStatementQuickFixTests.cs | 4 +- .../RemoveLocalErrorQuickFixTests.cs | 4 +- .../RemoveOptionBaseStatementQuickFixTests.cs | 4 +- .../QuickFixes/RemoveStepOneQuickFixTests.cs | 4 +- .../RemoveStopKeywordQuickFixTests.cs | 4 +- .../RemoveTypeHintsQuickFixTests.cs | 4 +- ...RemoveUnassignedIdentifierQuickFixTests.cs | 4 +- ...oveUnassignedVariableUsageQuickFixTests.cs | 4 +- .../RemoveUnusedDeclarationQuickFixTests.cs | 4 +- .../RemoveUnusedParameterQuickFixTests.cs | 4 +- ...mptyStringLiteralStatementQuickFixTests.cs | 4 +- .../ReplaceGlobalModifierQuickFixTests.cs | 4 +- ...seWithConditionalStatementQuickFixTests.cs | 4 +- ...placeObsoleteCommentMarkerQuickFixTests.cs | 4 +- ...laceObsoleteErrorStatementQuickFixTests.cs | 4 +- ...ceWhileWendWithDoWhileLoopQuickFixTests.cs | 1 + .../RestoreErrorHandlingQuickFixTests.cs | 4 +- ...tExplicitVariantReturnTypeQuickFixTests.cs | 4 +- ...ecifyExplicitByRefModifierQuickFixTests.cs | 4 +- ...cifyExplicitPublicModifierQuickFixTests.cs | 4 +- .../SplitMultipleDeclarationsQuickFixTests.cs | 4 +- .../UntypedFunctionUsageQuickFixTests.cs | 4 +- ...KeywordForObjectAssignmentQuickFixTests.cs | 4 +- .../WriteOnlyPropertyQuickFixTests.cs | 4 +- .../CodeInspectionConfigProviderTests.cs | 1 + 377 files changed, 1002 insertions(+), 1065 deletions(-) diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/ArgumentReferenceInspectionFromDeclarationsBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/ArgumentReferenceInspectionFromDeclarationsBase.cs index 99cbf2797f..79fc533007 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/ArgumentReferenceInspectionFromDeclarationsBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/ArgumentReferenceInspectionFromDeclarationsBase.cs @@ -1,11 +1,10 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; -namespace Rubberduck.Inspections.Inspections.Abstract +namespace Rubberduck.CodeAnalysis.Inspections.Abstract { internal abstract class ArgumentReferenceInspectionFromDeclarationsBase : IdentifierReferenceInspectionFromDeclarationsBase { diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs index 8cb7ca65fe..f90711db0b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBase.cs @@ -1,13 +1,12 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Results; +using Rubberduck.CodeAnalysis.Inspections.Results; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.VBEditor; -namespace Rubberduck.Inspections.Abstract +namespace Rubberduck.CodeAnalysis.Inspections.Abstract { internal abstract class DeclarationInspectionBase : DeclarationInspectionBaseBase { diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs index 7eb471f9b5..e766e7fe8a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionBaseBase.cs @@ -1,12 +1,11 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.VBEditor; -namespace Rubberduck.Inspections.Abstract +namespace Rubberduck.CodeAnalysis.Inspections.Abstract { /// /// This is a base class for the other declaration inspection base classes. It should not be implemented directly by concrete inspections. diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionMultiResultBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionMultiResultBase.cs index 11f22db2c4..0dbf4f7ca5 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionMultiResultBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionMultiResultBase.cs @@ -1,13 +1,12 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Results; +using Rubberduck.CodeAnalysis.Inspections.Results; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.VBEditor; -namespace Rubberduck.Inspections.Abstract +namespace Rubberduck.CodeAnalysis.Inspections.Abstract { internal abstract class DeclarationInspectionMultiResultBase : DeclarationInspectionBaseBase { diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBase.cs index 726ef994c9..fa2f3e2b24 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBase.cs @@ -1,13 +1,12 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Results; +using Rubberduck.CodeAnalysis.Inspections.Results; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.VBEditor; -namespace Rubberduck.Inspections.Abstract +namespace Rubberduck.CodeAnalysis.Inspections.Abstract { internal abstract class DeclarationInspectionUsingGlobalInformationBase : DeclarationInspectionUsingGlobalInformationBaseBase { diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs index 1de2ba7de6..217a7a77ef 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/DeclarationInspectionUsingGlobalInformationBaseBase.cs @@ -1,12 +1,11 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.VBEditor; -namespace Rubberduck.Inspections.Abstract +namespace Rubberduck.CodeAnalysis.Inspections.Abstract { internal abstract class DeclarationInspectionUsingGlobalInformationBaseBase : InspectionBase { diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/EmptyBlockInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/EmptyBlockInspectionBase.cs index bfe98b69a4..9672930fcd 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/EmptyBlockInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/EmptyBlockInspectionBase.cs @@ -5,7 +5,7 @@ using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.VBA; -namespace Rubberduck.Inspections.Abstract +namespace Rubberduck.CodeAnalysis.Inspections.Abstract { internal abstract class EmptyBlockInspectionBase : ParseTreeInspectionBase where TContext : ParserRuleContext diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs index 8e171d6365..2844e5c692 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionBase.cs @@ -1,13 +1,12 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Results; +using Rubberduck.CodeAnalysis.Inspections.Results; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.VBEditor; -namespace Rubberduck.Inspections.Abstract +namespace Rubberduck.CodeAnalysis.Inspections.Abstract { internal abstract class IdentifierReferenceInspectionBase : InspectionBase { diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs index 22e2218b1a..bd41dbd43d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IdentifierReferenceInspectionFromDeclarationsBase.cs @@ -1,13 +1,12 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Results; +using Rubberduck.CodeAnalysis.Inspections.Results; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.VBEditor; -namespace Rubberduck.Inspections.Abstract +namespace Rubberduck.CodeAnalysis.Inspections.Abstract { internal abstract class IdentifierReferenceInspectionFromDeclarationsBase : InspectionBase { diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/ImplicitTypeInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/ImplicitTypeInspectionBase.cs index 75ccef11e8..45a973e9c5 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/ImplicitTypeInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/ImplicitTypeInspectionBase.cs @@ -2,7 +2,7 @@ using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; -namespace Rubberduck.Inspections.Abstract +namespace Rubberduck.CodeAnalysis.Inspections.Abstract { internal abstract class ImplicitTypeInspectionBase : DeclarationInspectionBase { diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs index bae480aeb2..23b94c9a92 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs @@ -1,17 +1,16 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Globalization; using System.Linq; -using Rubberduck.Parsing.VBA; -using Rubberduck.VBEditor; -using System.Diagnostics; using System.Threading; using NLog; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.CodeAnalysis.Inspections.Extensions; +using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.VBEditor; -namespace Rubberduck.Inspections.Abstract +namespace Rubberduck.CodeAnalysis.Inspections.Abstract { internal abstract class InspectionBase : IInspection { diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionResultBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionResultBase.cs index 9e3c0d3585..75b5ad791a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionResultBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionResultBase.cs @@ -1,12 +1,11 @@ using System.Collections.Generic; using Antlr4.Runtime; -using Rubberduck.CodeAnalysis.Inspections; using Rubberduck.Common; +using Rubberduck.Interaction.Navigation; using Rubberduck.Parsing.Symbols; using Rubberduck.VBEditor; -using Rubberduck.Interaction.Navigation; -namespace Rubberduck.Inspections.Abstract +namespace Rubberduck.CodeAnalysis.Inspections.Abstract { internal abstract class InspectionResultBase : IInspectionResult, INavigateSource { diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs index a044ff0d19..c32af59c4f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/IsMissingInspectionBase.cs @@ -6,7 +6,7 @@ using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; -namespace Rubberduck.Inspections.Inspections.Abstract +namespace Rubberduck.CodeAnalysis.Inspections.Abstract { internal abstract class IsMissingInspectionBase : ArgumentReferenceInspectionFromDeclarationsBase { diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/MemberAccessMayReturnNothingInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/MemberAccessMayReturnNothingInspectionBase.cs index 6f463406ab..b0defd534a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/MemberAccessMayReturnNothingInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/MemberAccessMayReturnNothingInspectionBase.cs @@ -2,16 +2,16 @@ using System.Linq; using Antlr4.Runtime; using Antlr4.Runtime.Tree; +using Rubberduck.CodeAnalysis.Inspections.Extensions; using Rubberduck.Inspections.CodePathAnalysis; using Rubberduck.Inspections.CodePathAnalysis.Nodes; -using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; -namespace Rubberduck.Inspections.Abstract +namespace Rubberduck.CodeAnalysis.Inspections.Abstract { internal abstract class MemberAccessMayReturnNothingInspectionBase : IdentifierReferenceInspectionFromDeclarationsBase { diff --git a/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs b/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs index deba9858d6..71ea3782c5 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Abstract/ParseTreeInspectionBase.cs @@ -1,8 +1,7 @@ using System.Collections.Generic; using System.Linq; using Antlr4.Runtime; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Results; +using Rubberduck.CodeAnalysis.Inspections.Results; using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; @@ -11,7 +10,7 @@ using Rubberduck.Parsing.VBA.Parsing; using Rubberduck.VBEditor; -namespace Rubberduck.Inspections.Abstract +namespace Rubberduck.CodeAnalysis.Inspections.Abstract { internal abstract class ParseTreeInspectionBase : InspectionBase, IParseTreeInspection where TContext : ParserRuleContext diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs index eb4fcc23ef..57698e878c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ArgumentWithIncompatibleObjectTypeInspection.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.Inspections.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.TypeResolvers; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignedByValParameterInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignedByValParameterInspection.cs index 7af0cf672c..86f0a0b910 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignedByValParameterInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignedByValParameterInspection.cs @@ -1,11 +1,11 @@ using System.Linq; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Resources.Inspections; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Warns about parameters passed by value being assigned a new value in the body of a procedure. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs index 12cf13799c..de266ea53d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/AssignmentNotUsedInspection.cs @@ -1,17 +1,17 @@ using System.Collections.Generic; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Parsing.VBA; +using System.Linq; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Extensions; using Rubberduck.Inspections.CodePathAnalysis; -using Rubberduck.Parsing.Symbols; using Rubberduck.Inspections.CodePathAnalysis.Extensions; -using System.Linq; using Rubberduck.Inspections.CodePathAnalysis.Nodes; -using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.VBEditor; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Warns about a variable that is assigned, and then re-assigned before the first assignment is read. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/AttributeValueOutOfSyncInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/AttributeValueOutOfSyncInspection.cs index 7039e7f781..19dd6c63a8 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/AttributeValueOutOfSyncInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/AttributeValueOutOfSyncInspection.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.CodeAnalysis.Inspections.Attributes; -using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; @@ -9,7 +9,7 @@ using Rubberduck.Resources.Inspections; using Rubberduck.VBEditor.SafeComWrappers; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Indicates that the value of a hidden VB attribute is out of sync with the corresponding Rubberduck annotation comment. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs index c41b553f82..780a59d1bd 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/BooleanAssignedInIfElseInspection.cs @@ -1,12 +1,11 @@ using System.Linq; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Identifies conditional assignments to mutually exclusive Boolean literal values in conditional branches. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ConstantNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ConstantNotUsedInspection.cs index 5661913fe3..353ecd16e1 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ConstantNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ConstantNotUsedInspection.cs @@ -1,12 +1,12 @@ using System.Linq; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Resources.Inspections; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Extensions; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Locates 'Const' declarations that are never referenced. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs index 01e88a6ddf..a2bba2fa07 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefTypeStatementInspection.cs @@ -1,13 +1,12 @@ using System.Collections.Generic; -using Rubberduck.Inspections.Abstract; +using Antlr4.Runtime.Misc; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.Parsing; +using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Inspections; -using Rubberduck.Parsing.Grammar; -using Rubberduck.Parsing; -using Antlr4.Runtime.Misc; -using Rubberduck.CodeAnalysis.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Warns about Def[Type] statements. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs index 955d12afc4..5f0ed93fe4 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultMemberRequiredInspection.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultProjectNameInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultProjectNameInspection.cs index 281e25be14..27e8299ad5 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultProjectNameInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DefaultProjectNameInspection.cs @@ -1,10 +1,10 @@ -using Rubberduck.CodeAnalysis.Inspections.Attributes; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Attributes; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// This inspection means to indicate when the project has not been renamed. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/DuplicatedAnnotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/DuplicatedAnnotationInspection.cs index 754f7d6e4d..5c52f4bd25 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/DuplicatedAnnotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/DuplicatedAnnotationInspection.cs @@ -1,13 +1,13 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Warns about duplicated annotations. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyCaseBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyCaseBlockInspection.cs index bf91c75e68..b10c6b0910 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyCaseBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyCaseBlockInspection.cs @@ -1,14 +1,13 @@ using Antlr4.Runtime.Misc; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Parsing.Grammar; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.Parsing; using Rubberduck.Parsing.Common; -using Rubberduck.Resources.Inspections; +using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Experimentals; -using Rubberduck.Parsing; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete.EmptyBlock { /// /// Identifies empty 'Case' blocks that can be safely removed. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyDoWhileBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyDoWhileBlockInspection.cs index f07ba39905..f771350185 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyDoWhileBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyDoWhileBlockInspection.cs @@ -1,14 +1,13 @@ using Antlr4.Runtime.Misc; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.Parsing; using Rubberduck.Parsing.Common; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Experimentals; -using Rubberduck.Parsing; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete.EmptyBlock { /// /// Identifies empty 'Do...Loop While' blocks that can be safely removed. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyElseBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyElseBlockInspection.cs index dde85335cc..6399df7bf6 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyElseBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyElseBlockInspection.cs @@ -1,14 +1,13 @@ using Antlr4.Runtime.Misc; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.Parsing; using Rubberduck.Parsing.Common; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Experimentals; -using Rubberduck.Parsing; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete.EmptyBlock { /// /// Identifies empty 'Else' blocks that can be safely removed. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyForEachBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyForEachBlockInspection.cs index d21eca5b77..fc9b402d8c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyForEachBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyForEachBlockInspection.cs @@ -1,14 +1,13 @@ using Antlr4.Runtime.Misc; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.Parsing; using Rubberduck.Parsing.Common; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Experimentals; -using Rubberduck.Parsing; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete.EmptyBlock { /// /// Identifies empty 'For Each...Next' blocks that can be safely removed. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyForLoopBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyForLoopBlockInspection.cs index 5f5d96a29c..d00ddc3a16 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyForLoopBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyForLoopBlockInspection.cs @@ -1,14 +1,13 @@ using Antlr4.Runtime.Misc; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.Parsing; using Rubberduck.Parsing.Common; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Experimentals; -using Rubberduck.Parsing; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete.EmptyBlock { /// /// Identifies empty 'For...Next' blocks that can be safely removed. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyIfBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyIfBlockInspection.cs index a6312f3764..f20c119c50 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyIfBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyIfBlockInspection.cs @@ -1,13 +1,12 @@ using Antlr4.Runtime; using Antlr4.Runtime.Misc; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete.EmptyBlock { /// /// Identifies empty 'If' blocks. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyWhileWendBlockInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyWhileWendBlockInspection.cs index 021c449033..ed82c59e0a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyWhileWendBlockInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyBlock/EmptyWhileWendBlockInspection.cs @@ -1,14 +1,13 @@ using Antlr4.Runtime.Misc; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.Parsing; using Rubberduck.Parsing.Common; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Experimentals; -using Rubberduck.Parsing; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete.EmptyBlock { /// /// Identifies empty 'While...Wend' blocks that can be safely removed. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyMethodInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyMethodInspection.cs index 2ae5634261..a6de51ba4b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyMethodInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyMethodInspection.cs @@ -1,11 +1,11 @@ -using Rubberduck.Inspections.Abstract; -using Rubberduck.Resources.Inspections; -using Rubberduck.Parsing.VBA; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Extensions; using Rubberduck.Parsing.Symbols; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Identifies empty module member blocks. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyModuleInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyModuleInspection.cs index c25be03ab3..1350acff4b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyModuleInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyModuleInspection.cs @@ -1,13 +1,13 @@ using System.Linq; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Parsing.VBA.Parsing; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Flags empty code modules. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs index ea34ef3b30..4a4c01b802 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EmptyStringLiteralInspection.cs @@ -1,11 +1,10 @@ -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Flags uses of an empty string literal (""). diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/EncapsulatePublicFieldInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/EncapsulatePublicFieldInspection.cs index f63c7958d6..c5b34fbff3 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/EncapsulatePublicFieldInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/EncapsulatePublicFieldInspection.cs @@ -1,10 +1,10 @@ -using Rubberduck.Inspections.Abstract; -using Rubberduck.Resources.Inspections; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Flags publicly exposed instance fields. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs index 38fccd3ddf..676af1ef62 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ApplicationWorksheetFunctionInspection.cs @@ -1,14 +1,14 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.CodeAnalysis.Inspections.Attributes; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Resources.Inspections; +using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete.Excel { /// /// Warns about late-bound WorksheetFunction calls made against the extended interface of the Application object. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelMemberMayReturnNothingInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelMemberMayReturnNothingInspection.cs index bdf49c3e7d..7db4f33fa7 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelMemberMayReturnNothingInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelMemberMayReturnNothingInspection.cs @@ -1,13 +1,13 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.CodeAnalysis.Inspections.Attributes; -using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete.Excel { /// Locates instances of member calls made against the result of a Range.Find/FindNext/FindPrevious method, without prior validation. /// diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs index c0f1c69d4a..cdd2dd77ce 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ExcelUdfNameIsValidCellReferenceInspection.cs @@ -2,9 +2,8 @@ using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; -using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.CodeAnalysis.Inspections.Attributes; -using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; @@ -12,7 +11,7 @@ using Rubberduck.VBEditor; using Rubberduck.VBEditor.SafeComWrappers; -namespace Rubberduck.Inspections.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete.Excel { /// /// Locates public User-Defined Function procedures accidentally named after a cell reference. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs index 1c6aa9289e..90b539f06a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveSheetReferenceInspection.cs @@ -1,13 +1,13 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.CodeAnalysis.Inspections.Attributes; -using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.Symbols; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete.Excel { /// /// Locates unqualified Worksheet.Range/Cells/Columns/Rows member calls that implicitly refer to ActiveSheet. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveWorkbookReferenceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveWorkbookReferenceInspection.cs index dbc9a4f7f7..3ae9129ff0 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveWorkbookReferenceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/ImplicitActiveWorkbookReferenceInspection.cs @@ -1,13 +1,13 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.CodeAnalysis.Inspections.Attributes; -using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.Symbols; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete.Excel { /// /// Locates unqualified Workbook.Worksheets/Sheets/Names member calls that implicitly refer to ActiveWorkbook. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs index d1f64f0439..2c1dc64dea 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/Excel/SheetAccessedUsingStringInspection.cs @@ -1,18 +1,18 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.CodeAnalysis.Inspections.Attributes; using Rubberduck.Common; -using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.VBEditor.SafeComWrappers; -using Rubberduck.VBEditor.SafeComWrappers.Abstract; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; using Rubberduck.VBEditor.ComManagement; +using Rubberduck.VBEditor.SafeComWrappers; +using Rubberduck.VBEditor.SafeComWrappers.Abstract; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete.Excel { /// /// Locates ThisWorkbook.Worksheets and ThisWorkbook.Sheets calls that appear to be dereferencing a worksheet that is already accessible at compile-time with a global-scope identifier. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueAlwaysDiscardedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueAlwaysDiscardedInspection.cs index 4a3c7dbee5..b4d87b75a1 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueAlwaysDiscardedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueAlwaysDiscardedInspection.cs @@ -1,16 +1,16 @@ using System.Collections.Generic; using System.Linq; using Antlr4.Runtime; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Warns when a user function's return value is discarded at all its call sites. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueDiscardedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueDiscardedInspection.cs index ea442ba3ef..7ab9a27db7 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueDiscardedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/FunctionReturnValueDiscardedInspection.cs @@ -1,14 +1,13 @@ using Antlr4.Runtime; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Warns when a user function's return value is not used at a call site. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/HostSpecificExpressionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/HostSpecificExpressionInspection.cs index 83fd3f07f0..ca6a155ec3 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/HostSpecificExpressionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/HostSpecificExpressionInspection.cs @@ -1,10 +1,10 @@ -using Rubberduck.Inspections.Abstract; -using Rubberduck.Resources.Inspections; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Warns about host-evaluated square-bracketed expressions. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/HungarianNotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/HungarianNotationInspection.cs index e8722cd3dd..8ee61f7bca 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/HungarianNotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/HungarianNotationInspection.cs @@ -1,15 +1,15 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Extensions; using Rubberduck.CodeAnalysis.Settings; using Rubberduck.Common; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.SettingsProvider; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Flags identifiers that use [Systems] Hungarian Notation prefixes. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs index c92a9f35d5..5f1ce62f45 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs @@ -1,19 +1,18 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Results; using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Symbols; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; using Rubberduck.VBEditor; using Rubberduck.VBEditor.SafeComWrappers; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Flags invalid Rubberduck annotation comments. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplementedInterfaceMemberInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplementedInterfaceMemberInspection.cs index f20307598d..73a09122c6 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplementedInterfaceMemberInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplementedInterfaceMemberInspection.cs @@ -1,14 +1,14 @@ -using Rubberduck.Inspections.Abstract; -using Rubberduck.Resources.Inspections; -using System.Linq; -using Rubberduck.Parsing.Symbols; -using Rubberduck.Inspections.Inspections.Extensions; +using System.Linq; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Extensions; using Rubberduck.Common; using Rubberduck.Parsing.Annotations; +using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Identifies class modules that define an interface with one or more members containing a concrete implementation. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitByRefModifierInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitByRefModifierInspection.cs index a55df0168d..1f39049a1a 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitByRefModifierInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitByRefModifierInspection.cs @@ -1,10 +1,10 @@ -using Rubberduck.Inspections.Abstract; -using Rubberduck.Resources.Inspections; -using Rubberduck.Parsing.VBA; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Highlights implicit ByRef modifiers in user code. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs index c915a0baaa..77b839062b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitDefaultMemberAccessInspection.cs @@ -1,12 +1,11 @@ -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Resources.Inspections; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Extensions; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Identifies the use of non-indexed default member accesses. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitPublicMemberInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitPublicMemberInspection.cs index d88fd064e9..e4d2a50341 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitPublicMemberInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitPublicMemberInspection.cs @@ -1,10 +1,10 @@ -using Rubberduck.Inspections.Abstract; -using Rubberduck.Resources.Inspections; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Highlights implicit Public access modifiers in user code. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs index 14850c79d8..f7e76471d1 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitRecursiveDefaultMemberAccessInspection.cs @@ -1,12 +1,11 @@ -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Resources.Inspections; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Extensions; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Identifies the use of indexed default member accesses that require a recursive default member resolution. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs index 8306056fc1..21faf1e96d 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitUnboundDefaultMemberAccessInspection.cs @@ -1,14 +1,13 @@ using System.Collections.Generic; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Resources.Inspections; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Extensions; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; using Rubberduck.VBEditor; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Identifies the use of indexed default member accesses for which the default member cannot be determined at compile time. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitVariantReturnTypeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitVariantReturnTypeInspection.cs index a5f59e87a9..e948978f31 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitVariantReturnTypeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitVariantReturnTypeInspection.cs @@ -1,9 +1,9 @@ -using Rubberduck.Inspections.Abstract; -using Rubberduck.Resources.Inspections; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Warns about 'Function' and 'Property Get' procedures that don't have an explicit return type. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs index 8c1f956392..2d15bd1a07 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ImplicitlyTypedConstInspection.cs @@ -1,9 +1,9 @@ -using Rubberduck.Inspections.Abstract; -using Rubberduck.Parsing.VBA; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Warns about constants that don't have an explicitly defined type. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs index 0388d87c8f..f982328de0 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedDefaultMemberAccessInspection.cs @@ -1,13 +1,12 @@ -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Resources.Inspections; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Extensions; +using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Identifies the use of indexed default member accesses. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs index 395048993a..7fb53b2d9f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedRecursiveDefaultMemberAccessInspection.cs @@ -1,13 +1,12 @@ -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Resources.Inspections; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Extensions; +using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Identifies the use of indexed default member accesses that require a recursive default member resolution. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs index d5d2edc7fa..a4918d6c03 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IndexedUnboundDefaultMemberAccessInspection.cs @@ -1,15 +1,14 @@ using System.Collections.Generic; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Resources.Inspections; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Extensions; +using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; using Rubberduck.VBEditor; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Identifies the use of indexed default member accesses for which the default member cannot be determined at compile time. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IntegerDataTypeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IntegerDataTypeInspection.cs index 7fe4053901..cf7ac24fdf 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IntegerDataTypeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IntegerDataTypeInspection.cs @@ -1,11 +1,11 @@ -using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Extensions; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Identifies obsolete 16-bit integer variables. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs index cfa4973ba9..c7c4545de7 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingOnInappropriateArgumentInspection.cs @@ -1,11 +1,11 @@ -using Rubberduck.Inspections.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Identifies uses of 'IsMissing' involving non-variant, non-optional, or array parameters. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs index 44e63c57ef..bc810e1fe5 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/IsMissingWithNonArgumentParameterInspection.cs @@ -1,10 +1,10 @@ -using Rubberduck.Inspections.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Identifies uses of 'IsMissing' involving a non-parameter argument. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/LineLabelNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/LineLabelNotUsedInspection.cs index f8a2300a7f..2e3088d2f3 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/LineLabelNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/LineLabelNotUsedInspection.cs @@ -1,13 +1,13 @@ using System.Linq; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Resources.Inspections; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Extensions; +using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Identifies line labels that are never referenced, and therefore superfluous. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MemberNotOnInterfaceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MemberNotOnInterfaceInspection.cs index 1f9f0cd853..a0aa4825ae 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MemberNotOnInterfaceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MemberNotOnInterfaceInspection.cs @@ -1,15 +1,15 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.Parsing; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; using Rubberduck.VBEditor; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Warns about member calls against an extensible interface, that cannot be validated at compile-time. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs index 667c119634..3b1a2c2535 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAnnotationArgumentInspection.cs @@ -1,17 +1,16 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Symbols; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; using Rubberduck.VBEditor; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Warns about a malformed Rubberduck annotation that is missing one or more arguments. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAttributeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAttributeInspection.cs index 49de3e1578..3c3d6c6747 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAttributeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingAttributeInspection.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.CodeAnalysis.Inspections.Attributes; -using Rubberduck.Inspections.Abstract; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; @@ -9,7 +9,7 @@ using Rubberduck.Resources.Inspections; using Rubberduck.VBEditor.SafeComWrappers; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Indicates that a Rubberduck annotation is documenting the presence of a VB attribute that is actually missing. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingMemberAnnotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingMemberAnnotationInspection.cs index d8e0b44899..70361228dd 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingMemberAnnotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingMemberAnnotationInspection.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; @@ -8,7 +8,7 @@ using Rubberduck.Resources.Inspections; using Rubberduck.VBEditor.SafeComWrappers; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Indicates that a hidden VB attribute is present for a member, but no Rubberduck annotation is documenting it. @@ -76,7 +76,7 @@ private static bool MissesCorrespondingMemberAnnotation(Declaration declaration, private static string AttributeBaseName(Declaration declaration, AttributeNode attribute) { - return Attributes.AttributeBaseName(attribute.Name, declaration.IdentifierName); + return Parsing.Symbols.Attributes.AttributeBaseName(attribute.Name, declaration.IdentifierName); } protected override string ResultDescription(Declaration declaration, (string AttributeName, IReadOnlyList AttriguteValues) properties) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingModuleAnnotationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingModuleAnnotationInspection.cs index bcb493dd22..e5a18f42c8 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingModuleAnnotationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MissingModuleAnnotationInspection.cs @@ -1,13 +1,13 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Indicates that a hidden VB attribute is present for a module, but no Rubberduck annotation is documenting it. @@ -57,7 +57,7 @@ private static (string AttributeName, IReadOnlyList AttributeValues) Pro private static bool IsDefaultAttribute(Declaration declaration, AttributeNode attribute) { - return Attributes.IsDefaultAttribute(declaration.QualifiedModuleName.ComponentType, attribute.Name, attribute.Values); + return Parsing.Symbols.Attributes.IsDefaultAttribute(declaration.QualifiedModuleName.ComponentType, attribute.Name, attribute.Values); } private static bool MissesCorrespondingModuleAnnotation(Declaration declaration, AttributeNode attribute) diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs index 90c6f8bb4c..e653a356cd 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleScopeDimKeywordInspection.cs @@ -1,12 +1,11 @@ using Antlr4.Runtime.Misc; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Warns about module-level declarations made using the 'Dim' keyword. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleWithoutFolderInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleWithoutFolderInspection.cs index 8eaa0ae81c..4cb51c42de 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleWithoutFolderInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ModuleWithoutFolderInspection.cs @@ -1,12 +1,12 @@ using System.Linq; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Resources.Inspections; -using Rubberduck.Parsing.VBA; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Indicates that a user module is missing a @Folder Rubberduck annotation. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MoveFieldCloserToUsageInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MoveFieldCloserToUsageInspection.cs index 4224993d5d..6b0368eacd 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MoveFieldCloserToUsageInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MoveFieldCloserToUsageInspection.cs @@ -1,11 +1,11 @@ using System.Linq; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Resources.Inspections; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Locates module-level fields that can be moved to a smaller scope. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs index ce6b2984a3..4f83ec5954 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs @@ -1,12 +1,11 @@ using Antlr4.Runtime.Misc; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.VBA; using Rubberduck.Resources; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Flags parameters declared across multiple physical lines of code. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs index 282d755b09..77194b9c13 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MultipleDeclarationsInspection.cs @@ -1,13 +1,12 @@ using Antlr4.Runtime; using Antlr4.Runtime.Misc; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Flags declaration statements spanning multiple physical lines of code. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/NonReturningFunctionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/NonReturningFunctionInspection.cs index ec3b85c950..a28cdfbc55 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/NonReturningFunctionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/NonReturningFunctionInspection.cs @@ -1,13 +1,13 @@ using System.Linq; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Warns about 'Function' and 'Property Get' procedures whose return value is not assigned. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs index 64ce6d3644..11a6dccd3c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectVariableNotSetInspection.cs @@ -2,16 +2,16 @@ using System.Collections.Generic; using System.Linq; using Antlr4.Runtime; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Resources.Inspections; -using Rubberduck.Parsing.Symbols; -using Rubberduck.Parsing.VBA; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; using Rubberduck.VBEditor; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Warns about assignments that appear to be assigning an object reference without the 'Set' keyword. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs index 0994e47f7b..bad877aef6 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObjectWhereProcedureIsRequiredInspection.cs @@ -1,15 +1,14 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Results; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; using Rubberduck.VBEditor; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Identifies places in which an object is used but a procedure is required and a default member exists on the object. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs index 52bb2fd3e1..eb1eb11ce1 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallStatementInspection.cs @@ -1,12 +1,11 @@ -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Locates explicit 'Call' statements. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs index f8d3dbf7df..5e75e61b36 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCallingConventionInspection.cs @@ -1,12 +1,11 @@ -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Warns about 'Declare' statements that are using the obsolete/unsupported 'CDecl' calling convention on Windows. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs index e40d6aef37..253d08d752 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteCommentSyntaxInspection.cs @@ -1,11 +1,10 @@ -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Locates legacy 'Rem' comments. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs index 4a1461e6da..a705c18477 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteErrorSyntaxInspection.cs @@ -1,11 +1,10 @@ -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Locates legacy 'Error' statements. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteGlobalInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteGlobalInspection.cs index 3ed3963886..acb432163c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteGlobalInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteGlobalInspection.cs @@ -1,11 +1,11 @@ -using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Resources.Inspections; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Extensions; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Locates legacy 'Global' declaration statements. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs index 6cfb576e45..02658acc22 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteLetStatementInspection.cs @@ -1,11 +1,10 @@ -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Locates explicit 'Let' assignments. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs index b1ef32794f..4ea1c783ab 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteMemberUsageInspection.cs @@ -1,12 +1,12 @@ using System.Linq; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Flags usages of members marked as obsolete with an @Obsolete("justification") Rubberduck annotation. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs index f5a7a65ff9..6efbab6cb3 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteTypeHintInspection.cs @@ -1,15 +1,14 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Results; using Rubberduck.Parsing.Symbols; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; using Rubberduck.VBEditor; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Flags declarations where a type hint is used in place of an 'As' clause. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs index 89835e1523..e017dbd0e2 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ObsoleteWhileWendStatementInspection.cs @@ -1,4 +1,4 @@ -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.VBA; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs index ecdbe1f893..592d50dff5 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/OnLocalErrorInspection.cs @@ -1,12 +1,11 @@ -using Rubberduck.Inspections.Abstract; +using Antlr4.Runtime.Misc; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; -using Antlr4.Runtime.Misc; -using Rubberduck.CodeAnalysis.Inspections; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Flags obsolete 'On Local Error' statements. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs index 2c3fe8cc49..04dc42ee6c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionBaseInspection.cs @@ -1,11 +1,10 @@ -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Flags modules that specify Option Base 1. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs index 7ccdb6ed5f..1c47ae0fae 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/OptionExplicitInspection.cs @@ -1,15 +1,14 @@ using System.Collections.Generic; using Antlr4.Runtime.Misc; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; using Rubberduck.VBEditor; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Flags modules that omit Option Explicit. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterCanBeByValInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterCanBeByValInspection.cs index 35a298489d..03565b0d87 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterCanBeByValInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterCanBeByValInspection.cs @@ -1,15 +1,15 @@ using System.Diagnostics; using System.Linq; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; using Rubberduck.VBEditor; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Flags parameters that are passed by reference (ByRef), but could be passed by value (ByVal). diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterNotUsedInspection.cs index 8532c77866..e7c3e2046b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterNotUsedInspection.cs @@ -1,13 +1,13 @@ using System.Diagnostics; using System.Linq; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Common; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Identifies parameter declarations that are not used. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureCanBeWrittenAsFunctionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureCanBeWrittenAsFunctionInspection.cs index 6e7314c4f0..6a18dd3e2c 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureCanBeWrittenAsFunctionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureCanBeWrittenAsFunctionInspection.cs @@ -1,13 +1,13 @@ using System.Linq; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Warns about 'Sub' procedures that could be refactored into a 'Function'. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs index f2e72f1fa1..ed33097ccb 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureNotUsedInspection.cs @@ -1,13 +1,13 @@ using System.Linq; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Resources.Inspections; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Extensions; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Locates procedures that are never invoked from user code. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs index bb7829930a..10391ee5bd 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ProcedureRequiredInspection.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantByRefModifierInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantByRefModifierInspection.cs index 1afdc52aea..67c914ab84 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantByRefModifierInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantByRefModifierInspection.cs @@ -1,10 +1,10 @@ -using Rubberduck.Inspections.Abstract; -using Rubberduck.Resources.Inspections; -using Rubberduck.Parsing.VBA; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Identifies redundant ByRef modifiers. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs index b8531f0022..ecfaf9c9d7 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/RedundantOptionInspection.cs @@ -1,12 +1,11 @@ using Antlr4.Runtime; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Identifies redundant module options that are set to their implicit default. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SelfAssignedDeclarationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SelfAssignedDeclarationInspection.cs index e864cc4b02..831f96f8c9 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SelfAssignedDeclarationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SelfAssignedDeclarationInspection.cs @@ -1,12 +1,12 @@ using System.Linq; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Identifies auto-assigned object declarations. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs index d1acf1ae66..ad4a1d4842 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SetAssignmentWithIncompatibleObjectTypeInspection.cs @@ -1,5 +1,5 @@ using System.Linq; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ShadowedDeclarationInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ShadowedDeclarationInspection.cs index 188aa8cdfa..1c2e07a92e 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ShadowedDeclarationInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ShadowedDeclarationInspection.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Inspections.Extensions; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Extensions; using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; @@ -10,7 +10,7 @@ using Rubberduck.VBEditor; using Rubberduck.VBEditor.SafeComWrappers; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Identifies identifiers that hide/"shadow" other identifiers otherwise accessible in that scope. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs index 94a8398e78..07a98b01ff 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepIsNotSpecifiedInspection.cs @@ -1,12 +1,11 @@ -using Rubberduck.Inspections.Abstract; -using Rubberduck.Resources.Inspections; -using Rubberduck.Parsing.VBA; -using Antlr4.Runtime.Misc; -using Rubberduck.CodeAnalysis.Inspections; +using Antlr4.Runtime.Misc; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.VBA; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Locates 'For' loops where the 'Step' token is omitted. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs index 05a241a7a2..27550bd0b9 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/StepOneIsRedundantInspection.cs @@ -1,12 +1,11 @@ -using Rubberduck.Inspections.Abstract; -using Rubberduck.Resources.Inspections; -using Rubberduck.Parsing.VBA; -using Antlr4.Runtime.Misc; -using Rubberduck.CodeAnalysis.Inspections; +using Antlr4.Runtime.Misc; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.VBA; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Locates 'For' loops where the 'Step' token is specified with the default increment value (1). diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs index ae51bdd092..c035365536 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/StopKeywordInspection.cs @@ -1,12 +1,11 @@ using Antlr4.Runtime.Misc; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; +using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Locates 'Stop' instructions in user code. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuperfluousAnnotationArgumentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuperfluousAnnotationArgumentInspection.cs index 972109dc80..c59d77683b 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuperfluousAnnotationArgumentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuperfluousAnnotationArgumentInspection.cs @@ -1,17 +1,16 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Results; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Annotations; using Rubberduck.Parsing.Symbols; -using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.VBA; using Rubberduck.Parsing.VBA.DeclarationCaching; +using Rubberduck.Resources.Inspections; using Rubberduck.VBEditor; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Warns about Rubberduck annotations with more arguments than allowed. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs index 4bb14eab52..9dcefecfaa 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/SuspiciousLetAssignmentInspection.cs @@ -1,9 +1,8 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.CodeAnalysis.Inspections; -using Rubberduck.Inspections.Abstract; -using Rubberduck.Inspections.Inspections.Extensions; -using Rubberduck.Inspections.Results; +using Rubberduck.CodeAnalysis.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Extensions; +using Rubberduck.CodeAnalysis.Inspections.Results; using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; @@ -12,7 +11,7 @@ using Rubberduck.Resources.Inspections; using Rubberduck.VBEditor; -namespace Rubberduck.Inspections.Concrete +namespace Rubberduck.CodeAnalysis.Inspections.Concrete { /// /// Identifies assignments without Set for which both sides are objects. diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/KeywordsUsedAsMemberInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/KeywordsUsedAsMemberInspection.cs index a74dff78ee..35fd4f1f7f 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/KeywordsUsedAsMemberInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ThunderCode/KeywordsUsedAsMemberInspection.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.Inspections.Abstract; +using Rubberduck.CodeAnalysis.Inspections.Abstract; using Rubberduck.JunkDrawer.Extensions; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; @@ -8,7 +8,7 @@ using Rubberduck.Parsing.VBA.DeclarationCaching; using Rubberduck.Resources.Inspections; -namespace Rubberduck.Inspections.Inspections.Concrete.ThunderCode +namespace Rubberduck.CodeAnalysis.Inspections.Concrete.ThunderCode { ///