1
1
using Rubberduck . Inspections . Abstract ;
2
2
using System . Linq ;
3
- using Rubberduck . Parsing ;
4
3
using Rubberduck . VBEditor ;
5
4
using Rubberduck . Inspections . Resources ;
6
5
using Rubberduck . Parsing . Grammar ;
@@ -18,16 +17,16 @@ public class AssignedByValParameterMakeLocalCopyQuickFix : QuickFixBase
18
17
{
19
18
private readonly Declaration _target ;
20
19
private readonly IAssignedByValParameterQuickFixDialogFactory _dialogFactory ;
20
+ private readonly IEnumerable < string > _forbiddenNames ;
21
21
private string _localCopyVariableName ;
22
- private string [ ] _variableNamesAccessibleToProcedureContext ;
23
22
24
23
public AssignedByValParameterMakeLocalCopyQuickFix ( Declaration target , QualifiedSelection selection , IAssignedByValParameterQuickFixDialogFactory dialogFactory )
25
24
: base ( target . Context , selection , InspectionsUI . AssignedByValParameterMakeLocalCopyQuickFix )
26
25
{
27
26
_target = target ;
28
27
_dialogFactory = dialogFactory ;
29
- _variableNamesAccessibleToProcedureContext = GetVariableNamesAccessibleToProcedureContext ( _target . Context . Parent . Parent ) ;
30
- SetValidLocalCopyVariableNameSuggestion ( ) ;
28
+ _forbiddenNames = GetIdentifierNamesAccessibleToProcedureContext ( target . Context . Parent . Parent ) ;
29
+ _localCopyVariableName = ComputeSuggestedName ( ) ;
31
30
}
32
31
33
32
public override bool CanFixInModule { get { return false ; } }
@@ -49,10 +48,9 @@ public override void Fix()
49
48
50
49
private void RequestLocalCopyVariableName ( )
51
50
{
52
- using ( var view = _dialogFactory . Create ( _target . IdentifierName , _target . DeclarationType . ToString ( ) ) )
51
+ using ( var view = _dialogFactory . Create ( _target . IdentifierName , _target . DeclarationType . ToString ( ) , _forbiddenNames ) )
53
52
{
54
53
view . NewName = _localCopyVariableName ;
55
- view . IdentifierNamesAlreadyDeclared = _variableNamesAccessibleToProcedureContext ;
56
54
view . ShowDialog ( ) ;
57
55
IsCancelled = view . DialogResult == DialogResult . Cancel ;
58
56
if ( ! IsCancelled )
@@ -62,63 +60,66 @@ private void RequestLocalCopyVariableName()
62
60
}
63
61
}
64
62
65
- private void SetValidLocalCopyVariableNameSuggestion ( )
63
+ private string ComputeSuggestedName ( )
66
64
{
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
+ }
69
70
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 ++ )
72
72
{
73
- _localCopyVariableName = "x" + _localCopyVariableName ;
74
- if ( VariableNameIsValid ( _localCopyVariableName ) )
73
+ var result = newName + attempt ;
74
+ if ( VariableNameIsValid ( result ) )
75
75
{
76
- return ;
76
+ return result ;
77
77
}
78
78
}
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 ;
82
80
}
83
81
84
82
private bool VariableNameIsValid ( string variableName )
85
83
{
86
84
var validator = new VariableNameValidator ( variableName ) ;
87
85
return validator . IsValidName ( )
88
- && ! _variableNamesAccessibleToProcedureContext
89
- . Any ( name => name . Equals ( variableName , System . StringComparison . InvariantCultureIgnoreCase ) ) ;
86
+ && ! _forbiddenNames . Any ( name => name . Equals ( variableName , System . StringComparison . InvariantCultureIgnoreCase ) ) ;
90
87
}
91
88
92
89
private void ReplaceAssignedByValParameterReferences ( )
93
90
{
94
91
var module = Selection . QualifiedName . Component . CodeModule ;
95
- foreach ( IdentifierReference identifierReference in _target . References )
92
+ foreach ( var identifierReference in _target . References )
96
93
{
97
94
module . ReplaceIdentifierReferenceName ( identifierReference , _localCopyVariableName ) ;
98
95
}
99
96
}
100
97
101
98
private void InsertLocalVariableDeclarationAndAssignment ( )
102
99
{
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
+
104
106
string [ ] lines = { BuildLocalCopyDeclaration ( ) , BuildLocalCopyAssignment ( ) } ;
105
107
var module = Selection . QualifiedName . Component . CodeModule ;
106
- module . InsertLines ( blocks . FirstOrDefault ( ) . Start . Line , lines ) ;
108
+ module . InsertLines ( block . Start . Line , lines ) ;
107
109
}
108
110
109
111
private string BuildLocalCopyDeclaration ( )
110
112
{
111
- return Tokens . Dim + " " + _localCopyVariableName + " " + Tokens . As
112
- + " " + _target . AsTypeName ;
113
+ return Tokens . Dim + " " + _localCopyVariableName + " " + Tokens . As + " " + _target . AsTypeName ;
113
114
}
114
115
115
116
private string BuildLocalCopyAssignment ( )
116
117
{
117
- return ( SymbolList . ValueTypes . Contains ( _target . AsTypeName ) ? string . Empty : Tokens . Set + " " )
118
+ return ( _target . AsTypeDeclaration is ClassModuleDeclaration ? Tokens . Set + " " : string . Empty )
118
119
+ _localCopyVariableName + " = " + _target . IdentifierName ;
119
120
}
120
121
121
- private string [ ] GetVariableNamesAccessibleToProcedureContext ( RuleContext ruleContext )
122
+ private IEnumerable < string > GetIdentifierNamesAccessibleToProcedureContext ( RuleContext ruleContext )
122
123
{
123
124
var allIdentifiers = new HashSet < string > ( ) ;
124
125
@@ -137,29 +138,31 @@ private string[] GetVariableNamesAccessibleToProcedureContext(RuleContext ruleCo
137
138
return allIdentifiers . ToArray ( ) ;
138
139
}
139
140
140
- private HashSet < string > GetIdentifierNames ( IReadOnlyList < RuleContext > ruleContexts )
141
+ private IEnumerable < string > GetIdentifierNames ( IEnumerable < RuleContext > ruleContexts )
141
142
{
142
143
var identifiers = new HashSet < string > ( ) ;
143
- foreach ( RuleContext ruleContext in ruleContexts )
144
+ foreach ( var identifiersForThisContext in ruleContexts . Select ( GetIdentifierNames ) )
144
145
{
145
- var identifiersForThisContext = GetIdentifierNames ( ruleContext ) ;
146
146
identifiers . UnionWith ( identifiersForThisContext ) ;
147
147
}
148
148
return identifiers ;
149
149
}
150
150
151
- private HashSet < string > GetIdentifierNames ( RuleContext ruleContext )
151
+ private static HashSet < string > GetIdentifierNames ( RuleContext ruleContext )
152
152
{
153
+ // note: this looks like something that's already handled somewhere else...
154
+
153
155
//Recursively work through the tree to get all IdentifierContexts
154
156
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 ( ) ;
156
158
var children = GetChildren ( ruleContext ) ;
157
159
158
- foreach ( IParseTree child in children )
160
+ foreach ( var child in children )
159
161
{
160
- if ( child is VBAParser . IdentifierContext )
162
+ var context = child as VBAParser . IdentifierContext ;
163
+ if ( context != null )
161
164
{
162
- var childName = Identifier . GetName ( ( VBAParser . IdentifierContext ) child ) ;
165
+ var childName = Identifier . GetName ( context ) ;
163
166
if ( ! tokenValues . Contains ( childName ) )
164
167
{
165
168
results . Add ( childName ) ;
@@ -176,12 +179,12 @@ private HashSet<string> GetIdentifierNames(RuleContext ruleContext)
176
179
return results ;
177
180
}
178
181
179
- private static List < IParseTree > GetChildren ( RuleContext ruleCtx )
182
+ private static IEnumerable < IParseTree > GetChildren ( IParseTree tree )
180
183
{
181
184
var result = new List < IParseTree > ( ) ;
182
- for ( int index = 0 ; index < ruleCtx . ChildCount ; index ++ )
185
+ for ( var index = 0 ; index < tree . ChildCount ; index ++ )
183
186
{
184
- result . Add ( ruleCtx . GetChild ( index ) ) ;
187
+ result . Add ( tree . GetChild ( index ) ) ;
185
188
}
186
189
return result ;
187
190
}
0 commit comments