Skip to content

Commit 96a16ad

Browse files
committed
PR#2733 tweaks
1 parent 5ff02dd commit 96a16ad

9 files changed

+143
-183
lines changed

RetailCoder.VBE/Inspections/AssignedByValParameterInspection.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
using Rubberduck.Inspections.Abstract;
44
using Rubberduck.Inspections.Resources;
55
using Rubberduck.Inspections.Results;
6-
using Rubberduck.Parsing.Grammar;
76
using Rubberduck.Parsing.Symbols;
87
using Rubberduck.Parsing.VBA;
98
using Rubberduck.UI.Refactorings;
@@ -12,7 +11,7 @@ namespace Rubberduck.Inspections
1211
{
1312
public sealed class AssignedByValParameterInspection : InspectionBase
1413
{
15-
private IAssignedByValParameterQuickFixDialogFactory _dialogFactory;
14+
private readonly IAssignedByValParameterQuickFixDialogFactory _dialogFactory;
1615
public AssignedByValParameterInspection(RubberduckParserState state, IAssignedByValParameterQuickFixDialogFactory dialogFactory)
1716
: base(state)
1817
{

RetailCoder.VBE/Inspections/QuickFixes/AssignedByValParameterMakeLocalCopyQuickFix.cs

Lines changed: 40 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using Rubberduck.Inspections.Abstract;
22
using System.Linq;
3-
using Rubberduck.Parsing;
43
using Rubberduck.VBEditor;
54
using Rubberduck.Inspections.Resources;
65
using Rubberduck.Parsing.Grammar;
@@ -18,16 +17,16 @@ public class AssignedByValParameterMakeLocalCopyQuickFix : QuickFixBase
1817
{
1918
private readonly Declaration _target;
2019
private readonly IAssignedByValParameterQuickFixDialogFactory _dialogFactory;
20+
private readonly IEnumerable<string> _forbiddenNames;
2121
private string _localCopyVariableName;
22-
private string[] _variableNamesAccessibleToProcedureContext;
2322

2423
public AssignedByValParameterMakeLocalCopyQuickFix(Declaration target, QualifiedSelection selection, IAssignedByValParameterQuickFixDialogFactory dialogFactory)
2524
: base(target.Context, selection, InspectionsUI.AssignedByValParameterMakeLocalCopyQuickFix)
2625
{
2726
_target = target;
2827
_dialogFactory = dialogFactory;
29-
_variableNamesAccessibleToProcedureContext = GetVariableNamesAccessibleToProcedureContext(_target.Context.Parent.Parent);
30-
SetValidLocalCopyVariableNameSuggestion();
28+
_forbiddenNames = GetIdentifierNamesAccessibleToProcedureContext(target.Context.Parent.Parent);
29+
_localCopyVariableName = ComputeSuggestedName();
3130
}
3231

3332
public override bool CanFixInModule { get { return false; } }
@@ -49,10 +48,9 @@ public override void Fix()
4948

5049
private void RequestLocalCopyVariableName()
5150
{
52-
using( var view = _dialogFactory.Create(_target.IdentifierName, _target.DeclarationType.ToString()))
51+
using( var view = _dialogFactory.Create(_target.IdentifierName, _target.DeclarationType.ToString(), _forbiddenNames))
5352
{
5453
view.NewName = _localCopyVariableName;
55-
view.IdentifierNamesAlreadyDeclared = _variableNamesAccessibleToProcedureContext;
5654
view.ShowDialog();
5755
IsCancelled = view.DialogResult == DialogResult.Cancel;
5856
if (!IsCancelled)
@@ -62,63 +60,66 @@ private void RequestLocalCopyVariableName()
6260
}
6361
}
6462

65-
private void SetValidLocalCopyVariableNameSuggestion()
63+
private string ComputeSuggestedName()
6664
{
67-
_localCopyVariableName = "x" + _target.IdentifierName.CapitalizeFirstLetter();
68-
if (VariableNameIsValid(_localCopyVariableName)) { return; }
65+
var newName = "local" + _target.IdentifierName.CapitalizeFirstLetter();
66+
if (VariableNameIsValid(newName))
67+
{
68+
return newName;
69+
}
6970

70-
//If the initial suggestion is not valid, keep pre-pending x's until it is
71-
for ( int attempt = 2; attempt < 10; attempt++)
71+
for ( var attempt = 2; attempt < 10; attempt++)
7272
{
73-
_localCopyVariableName = "x" + _localCopyVariableName;
74-
if (VariableNameIsValid(_localCopyVariableName))
73+
var result = newName + attempt;
74+
if (VariableNameIsValid(result))
7575
{
76-
return;
76+
return result;
7777
}
7878
}
79-
//if "xxFoo" to "xxxxxxxxxxFoo" isn't unique, give up and go with the original suggestion.
80-
//The QuickFix will leave the code as-is unless it receives a name that is free of conflicts
81-
_localCopyVariableName = "x" + _target.IdentifierName.CapitalizeFirstLetter();
79+
return newName;
8280
}
8381

8482
private bool VariableNameIsValid(string variableName)
8583
{
8684
var validator = new VariableNameValidator(variableName);
8785
return validator.IsValidName()
88-
&& !_variableNamesAccessibleToProcedureContext
89-
.Any(name => name.Equals(variableName, System.StringComparison.InvariantCultureIgnoreCase));
86+
&& !_forbiddenNames.Any(name => name.Equals(variableName, System.StringComparison.InvariantCultureIgnoreCase));
9087
}
9188

9289
private void ReplaceAssignedByValParameterReferences()
9390
{
9491
var module = Selection.QualifiedName.Component.CodeModule;
95-
foreach (IdentifierReference identifierReference in _target.References)
92+
foreach (var identifierReference in _target.References)
9693
{
9794
module.ReplaceIdentifierReferenceName(identifierReference, _localCopyVariableName);
9895
}
9996
}
10097

10198
private void InsertLocalVariableDeclarationAndAssignment()
10299
{
103-
var blocks = QuickFixHelper.GetBlockStmtContextsForContext(_target.Context.Parent.Parent);
100+
var block = QuickFixHelper.GetBlockStmtContextsForContext(_target.Context.Parent.Parent).FirstOrDefault();
101+
if (block == null)
102+
{
103+
return;
104+
}
105+
104106
string[] lines = { BuildLocalCopyDeclaration(), BuildLocalCopyAssignment() };
105107
var module = Selection.QualifiedName.Component.CodeModule;
106-
module.InsertLines(blocks.FirstOrDefault().Start.Line, lines);
108+
module.InsertLines(block.Start.Line, lines);
107109
}
108110

109111
private string BuildLocalCopyDeclaration()
110112
{
111-
return Tokens.Dim + " " + _localCopyVariableName + " " + Tokens.As
112-
+ " " + _target.AsTypeName;
113+
return Tokens.Dim + " " + _localCopyVariableName + " " + Tokens.As + " " + _target.AsTypeName;
113114
}
114115

115116
private string BuildLocalCopyAssignment()
116117
{
117-
return (SymbolList.ValueTypes.Contains(_target.AsTypeName) ? string.Empty : Tokens.Set + " ")
118+
return (_target.AsTypeDeclaration is ClassModuleDeclaration ? Tokens.Set + " " : string.Empty)
118119
+ _localCopyVariableName + " = " + _target.IdentifierName;
119120
}
120121

121-
private string[] GetVariableNamesAccessibleToProcedureContext(RuleContext ruleContext)
122+
private IEnumerable<string> GetIdentifierNamesAccessibleToProcedureContext(RuleContext ruleContext)
122123
{
123124
var allIdentifiers = new HashSet<string>();
124125

@@ -137,29 +138,31 @@ private string[] GetVariableNamesAccessibleToProcedureContext(RuleContext ruleCo
137138
return allIdentifiers.ToArray();
138139
}
139140

140-
private HashSet<string> GetIdentifierNames(IReadOnlyList<RuleContext> ruleContexts)
141+
private IEnumerable<string> GetIdentifierNames(IEnumerable<RuleContext> ruleContexts)
141142
{
142143
var identifiers = new HashSet<string>();
143-
foreach (RuleContext ruleContext in ruleContexts)
144+
foreach (var identifiersForThisContext in ruleContexts.Select(GetIdentifierNames))
144145
{
145-
var identifiersForThisContext = GetIdentifierNames(ruleContext);
146146
identifiers.UnionWith(identifiersForThisContext);
147147
}
148148
return identifiers;
149149
}
150150

151-
private HashSet<string> GetIdentifierNames(RuleContext ruleContext)
151+
private static HashSet<string> GetIdentifierNames(RuleContext ruleContext)
152152
{
153+
// note: this looks like something that's already handled somewhere else...
154+
153155
//Recursively work through the tree to get all IdentifierContexts
154156
var results = new HashSet<string>();
155-
var tokenValues = typeof(Tokens).GetFields().Select(item => item.GetValue(null)).Cast<string>().Select(item => item);
157+
var tokenValues = typeof(Tokens).GetFields().Select(item => item.GetValue(null)).Cast<string>().Select(item => item).ToArray();
156158
var children = GetChildren(ruleContext);
157159

158-
foreach (IParseTree child in children)
160+
foreach (var child in children)
159161
{
160-
if (child is VBAParser.IdentifierContext)
162+
var context = child as VBAParser.IdentifierContext;
163+
if (context != null)
161164
{
162-
var childName = Identifier.GetName((VBAParser.IdentifierContext)child);
165+
var childName = Identifier.GetName(context);
163166
if (!tokenValues.Contains(childName))
164167
{
165168
results.Add(childName);
@@ -176,12 +179,12 @@ private HashSet<string> GetIdentifierNames(RuleContext ruleContext)
176179
return results;
177180
}
178181

179-
private static List<IParseTree> GetChildren(RuleContext ruleCtx)
182+
private static IEnumerable<IParseTree> GetChildren(IParseTree tree)
180183
{
181184
var result = new List<IParseTree>();
182-
for (int index = 0; index < ruleCtx.ChildCount; index++)
185+
for (var index = 0; index < tree.ChildCount; index++)
183186
{
184-
result.Add(ruleCtx.GetChild(index));
187+
result.Add(tree.GetChild(index));
185188
}
186189
return result;
187190
}

RetailCoder.VBE/Inspections/Results/AssignedByValParameterInspectionResult.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace Rubberduck.Inspections.Results
1111
public class AssignedByValParameterInspectionResult : InspectionResultBase
1212
{
1313
private IEnumerable<QuickFixBase> _quickFixes;
14-
private IAssignedByValParameterQuickFixDialogFactory _dialogFactory;
14+
private readonly IAssignedByValParameterQuickFixDialogFactory _dialogFactory;
1515

1616
public AssignedByValParameterInspectionResult(IInspection inspection, Declaration target, IAssignedByValParameterQuickFixDialogFactory dialogFactory)
1717
: base(inspection, target)

RetailCoder.VBE/Inspections/VariableNameValidator.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ public VariableNameValidator() { }
1515
private const int MinVariableNameLength = 3;
1616

1717
/**** Meaningful Name Characteristics ************/
18-
public bool HasVowels
18+
19+
private bool HasVowels
1920
{
2021
get
2122
{
@@ -25,7 +26,7 @@ public bool HasVowels
2526
}
2627
}
2728

28-
public bool HasConsonants
29+
private bool HasConsonants
2930
{
3031
get
3132
{
@@ -35,7 +36,7 @@ public bool HasConsonants
3536
}
3637
}
3738

38-
public bool IsSingleRepeatedLetter
39+
private bool IsSingleRepeatedLetter
3940
{
4041
get
4142
{
@@ -45,8 +46,8 @@ public bool IsSingleRepeatedLetter
4546
}
4647
}
4748

48-
public bool IsTooShort { get { return _identifier.Length < MinVariableNameLength; } }
49-
public bool EndsWithNumber { get { return char.IsDigit(_identifier.Last()); } }
49+
private bool IsTooShort { get { return _identifier.Length < MinVariableNameLength; } }
50+
private bool EndsWithNumber { get { return char.IsDigit(_identifier.Last()); } }
5051

5152
/**** Invalid Name Characteristics ************/
5253
public bool StartsWithNumber { get { return FirstLetterIsDigit(); } }

RetailCoder.VBE/UI/Refactorings/AssignedByValParameterQuickFixDialog.cs

Lines changed: 12 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Windows.Forms;
34
using Rubberduck.Inspections;
45
using System.Linq;
@@ -7,15 +8,15 @@ namespace Rubberduck.UI.Refactorings
78
{
89
public partial class AssignedByValParameterQuickFixDialog : Form, IAssignedByValParameterQuickFixDialog
910
{
10-
private string[] _identifierNamesAlreadyDeclared;
11-
private string _identifierName;
11+
private readonly string _identifierName;
12+
private readonly IEnumerable<string> _forbiddenNames;
1213

13-
internal AssignedByValParameterQuickFixDialog(string identifierName, string declarationType)
14+
internal AssignedByValParameterQuickFixDialog(string identifierName, string declarationType, IEnumerable<string> forbiddenNames)
1415
{
1516
InitializeComponent();
1617
InitializeCaptions(identifierName, declarationType);
1718
_identifierName = identifierName;
18-
_identifierNamesAlreadyDeclared = Enumerable.Empty<string>().ToArray();
19+
_forbiddenNames = forbiddenNames;
1920
}
2021

2122
private void InitializeCaptions(string identifierName, string targetDeclarationType)
@@ -47,17 +48,12 @@ public string NewName
4748
SetControlsProperties();
4849
}
4950
}
50-
public string[] IdentifierNamesAlreadyDeclared
51-
{
52-
get { return _identifierNamesAlreadyDeclared; }
53-
set { _identifierNamesAlreadyDeclared = value; }
54-
}
5551

5652
private string GetVariableNameFeedback()
5753
{
5854
var validator = new VariableNameValidator(NewName);
5955

60-
if (UserInputIsBlank())
56+
if (string.IsNullOrEmpty(NewName))
6157
{
6258
return string.Empty;
6359
}
@@ -73,11 +69,11 @@ private string GetVariableNameFeedback()
7369
{
7470
return string.Format(RubberduckUI.AssignedByValDialog_ReservedKeywordFormat, NewName);
7571
}
76-
if (IsByValIdentifier())
72+
if (NewName.Equals(_identifierName, StringComparison.OrdinalIgnoreCase))
7773
{
7874
return string.Format(RubberduckUI.AssignedByValDialog_IsByValIdentifierFormat, NewName);
7975
}
80-
if (NewNameAlreadyUsed())
76+
if (_forbiddenNames.Any(name => name.Equals(NewName, StringComparison.OrdinalIgnoreCase)))
8177
{
8278
return string.Format(RubberduckUI.AssignedByValDialog_NewNameAlreadyUsedFormat, NewName);
8379
}
@@ -91,27 +87,10 @@ private string GetVariableNameFeedback()
9187
private void SetControlsProperties()
9288
{
9389
var validator = new VariableNameValidator(NewName);
94-
var userInputIsValid = validator.IsValidName() && !NewNameAlreadyUsed();
95-
OkButton.Visible = userInputIsValid;
96-
OkButton.Enabled = userInputIsValid;
97-
InvalidNameValidationIcon.Visible = !userInputIsValid;
98-
}
99-
100-
private bool UserInputIsBlank()
101-
{
102-
return NewName.Equals(string.Empty);
103-
}
104-
105-
private bool IsByValIdentifier()
106-
{
107-
return NewName.Equals(_identifierName, StringComparison.OrdinalIgnoreCase);
108-
}
109-
110-
private bool NewNameAlreadyUsed()
111-
{
112-
//Comparison needs to be case-insensitive, or VBE will often change an existing
113-
//same-spelling local variable's casing to conform with the NewName
114-
return _identifierNamesAlreadyDeclared.Any(n => n.Equals(NewName, StringComparison.OrdinalIgnoreCase));
90+
var isValid = validator.IsValidName() && !_forbiddenNames.Any(name => name.Equals(NewName, StringComparison.OrdinalIgnoreCase));
91+
OkButton.Visible = isValid;
92+
OkButton.Enabled = isValid;
93+
InvalidNameValidationIcon.Visible = !isValid;
11594
}
11695
}
11796
}
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11

2+
using System.Collections.Generic;
3+
24
namespace Rubberduck.UI.Refactorings
35
{
46
public class AssignedByValParameterQuickFixDialogFactory : IAssignedByValParameterQuickFixDialogFactory
57
{
6-
IAssignedByValParameterQuickFixDialog IAssignedByValParameterQuickFixDialogFactory.Create(string identifier, string identifierType)
8+
IAssignedByValParameterQuickFixDialog IAssignedByValParameterQuickFixDialogFactory.Create(string identifier, string identifierType, IEnumerable<string> forbiddenNames)
79
{
8-
return new AssignedByValParameterQuickFixDialog(identifier, identifierType);
10+
return new AssignedByValParameterQuickFixDialog(identifier, identifierType, forbiddenNames);
911
}
1012
}
1113
}

RetailCoder.VBE/UI/Refactorings/IAssignedByValParameterQuickFixDialog.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,5 @@ public interface IAssignedByValParameterQuickFixDialog : IDialogView
1111
{
1212
DialogResult DialogResult { get;}
1313
string NewName { get; set; }
14-
string[] IdentifierNamesAlreadyDeclared { get; set; }
1514
}
1615
}

RetailCoder.VBE/UI/Refactorings/IAssignedByValParameterQuickFixDialogFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ namespace Rubberduck.UI.Refactorings
1010
{
1111
public interface IAssignedByValParameterQuickFixDialogFactory
1212
{
13-
IAssignedByValParameterQuickFixDialog Create(string identifier, string identifierType);
13+
IAssignedByValParameterQuickFixDialog Create(string identifier, string identifierType, IEnumerable<string> forbiddenNames);
1414
}
1515
}

0 commit comments

Comments
 (0)