9
9
using Rubberduck . Common ;
10
10
using Antlr4 . Runtime ;
11
11
using System . Collections . Generic ;
12
- using Antlr4 . Runtime . Tree ;
12
+ using Rubberduck . Parsing . VBA ;
13
13
14
14
namespace Rubberduck . Inspections . QuickFixes
15
15
{
16
16
public class AssignedByValParameterMakeLocalCopyQuickFix : QuickFixBase
17
17
{
18
18
private readonly Declaration _target ;
19
19
private readonly IAssignedByValParameterQuickFixDialogFactory _dialogFactory ;
20
+ private readonly RubberduckParserState _parserState ;
20
21
private readonly IEnumerable < string > _forbiddenNames ;
21
22
private string _localCopyVariableName ;
22
23
23
- public AssignedByValParameterMakeLocalCopyQuickFix ( Declaration target , QualifiedSelection selection , IAssignedByValParameterQuickFixDialogFactory dialogFactory )
24
+ public AssignedByValParameterMakeLocalCopyQuickFix ( Declaration target , QualifiedSelection selection , RubberduckParserState parserState , IAssignedByValParameterQuickFixDialogFactory dialogFactory )
24
25
: base ( target . Context , selection , InspectionsUI . AssignedByValParameterMakeLocalCopyQuickFix )
25
26
{
26
27
_target = target ;
27
28
_dialogFactory = dialogFactory ;
28
- _forbiddenNames = GetIdentifierNamesAccessibleToProcedureContext ( target . Context . Parent . Parent ) ;
29
- _localCopyVariableName = ComputeSuggestedName ( ) ;
29
+ _parserState = parserState ;
30
+ _forbiddenNames = GetIdentifierNamesAccessibleToProcedureContext ( ) ;
31
+ _localCopyVariableName = ComputeSuggestedName ( ) ;
30
32
}
31
33
32
34
public override bool CanFixInModule { get { return false ; } }
@@ -95,16 +97,10 @@ private void ReplaceAssignedByValParameterReferences()
95
97
}
96
98
97
99
private void InsertLocalVariableDeclarationAndAssignment ( )
98
- {
99
- var block = QuickFixHelper . GetBlockStmtContextsForContext ( _target . Context . Parent . Parent ) . FirstOrDefault ( ) ;
100
- if ( block == null )
101
- {
102
- return ;
103
- }
104
-
100
+ {
105
101
string [ ] lines = { BuildLocalCopyDeclaration ( ) , BuildLocalCopyAssignment ( ) } ;
106
102
var module = Selection . QualifiedName . Component . CodeModule ;
107
- module . InsertLines ( block . Start . Line , lines ) ;
103
+ module . InsertLines ( ( ( VBAParser . ArgListContext ) _target . Context . Parent ) . Stop . Line + 1 , lines ) ;
108
104
}
109
105
110
106
private string BuildLocalCopyDeclaration ( )
@@ -118,74 +114,60 @@ private string BuildLocalCopyAssignment()
118
114
+ _localCopyVariableName + " = " + _target . IdentifierName ;
119
115
}
120
116
121
- private IEnumerable < string > GetIdentifierNamesAccessibleToProcedureContext ( RuleContext ruleContext )
117
+ private IEnumerable < string > GetIdentifierNamesAccessibleToProcedureContext ( )
122
118
{
123
- var allIdentifiers = new HashSet < string > ( ) ;
124
-
125
- var blocks = QuickFixHelper . GetBlockStmtContextsForContext ( ruleContext ) ;
126
-
127
- var blockStmtIdentifiers = GetIdentifierNames ( blocks ) ;
128
- allIdentifiers . UnionWith ( blockStmtIdentifiers ) ;
129
-
130
- var args = QuickFixHelper . GetArgContextsForContext ( ruleContext ) ;
131
-
132
- var potentiallyUnreferencedParameters = GetIdentifierNames ( args ) ;
133
- allIdentifiers . UnionWith ( potentiallyUnreferencedParameters ) ;
134
-
135
- //TODO: add module and global scope variableNames to the list.
136
-
137
- return allIdentifiers . ToArray ( ) ;
119
+ return _parserState . AllUserDeclarations
120
+ . Where ( candidateDeclaration =>
121
+ (
122
+ IsDeclarationInTheSameProcedure ( candidateDeclaration , _target )
123
+ || IsDeclarationInTheSameModule ( candidateDeclaration , _target )
124
+ || IsProjectGlobalDeclaration ( candidateDeclaration , _target ) )
125
+ ) . Select ( declaration => declaration . IdentifierName ) . Distinct ( ) ;
138
126
}
139
127
140
- private IEnumerable < string > GetIdentifierNames ( IEnumerable < RuleContext > ruleContexts )
128
+ private bool IsDeclarationInTheSameProcedure ( Declaration candidateDeclaration , Declaration scopingDeclaration )
141
129
{
142
- var identifiers = new HashSet < string > ( ) ;
143
- foreach ( var identifiersForThisContext in ruleContexts . Select ( GetIdentifierNames ) )
144
- {
145
- identifiers . UnionWith ( identifiersForThisContext ) ;
146
- }
147
- return identifiers ;
130
+ return candidateDeclaration . ParentScope == scopingDeclaration . ParentScope ;
148
131
}
149
132
150
- private static HashSet < string > GetIdentifierNames ( RuleContext ruleContext )
133
+ private bool IsDeclarationInTheSameModule ( Declaration candidateDeclaration , Declaration scopingDeclaration )
151
134
{
152
- // note: this looks like something that's already handled somewhere else...
153
-
154
- //Recursively work through the tree to get all IdentifierContexts
155
- var results = new HashSet < string > ( ) ;
156
- var tokenValues = typeof ( Tokens ) . GetFields ( ) . Select ( item => item . GetValue ( null ) ) . Cast < string > ( ) . Select ( item => item ) . ToArray ( ) ;
157
- var children = GetChildren ( ruleContext ) ;
135
+ return candidateDeclaration . ComponentName == scopingDeclaration . ComponentName
136
+ && ! IsDeclaredInMethodOrProperty ( candidateDeclaration . ParentDeclaration . Context ) ;
137
+ }
158
138
159
- foreach ( var child in children )
160
- {
161
- var context = child as VBAParser . IdentifierContext ;
162
- if ( context != null )
163
- {
164
- var childName = Identifier . GetName ( context ) ;
165
- if ( ! tokenValues . Contains ( childName ) )
166
- {
167
- results . Add ( childName ) ;
168
- }
169
- }
170
- else
171
- {
172
- if ( ! ( child is TerminalNodeImpl ) )
173
- {
174
- results . UnionWith ( GetIdentifierNames ( ( RuleContext ) child ) ) ;
175
- }
176
- }
177
- }
178
- return results ;
139
+ private bool IsProjectGlobalDeclaration ( Declaration candidateDeclaration , Declaration scopingDeclaration )
140
+ {
141
+ return candidateDeclaration . ProjectName == scopingDeclaration . ProjectName
142
+ && ! ( candidateDeclaration . ParentScopeDeclaration is ClassModuleDeclaration )
143
+ && ( candidateDeclaration . Accessibility == Accessibility . Public
144
+ || ( ( candidateDeclaration . Accessibility == Accessibility . Implicit )
145
+ && ( candidateDeclaration . ParentScopeDeclaration is ProceduralModuleDeclaration ) ) ) ;
179
146
}
180
147
181
- private static IEnumerable < IParseTree > GetChildren ( IParseTree tree )
148
+ private bool IsDeclaredInMethodOrProperty ( RuleContext procedureContext )
182
149
{
183
- var result = new List < IParseTree > ( ) ;
184
- for ( var index = 0 ; index < tree . ChildCount ; index ++ )
150
+ if ( procedureContext is VBAParser . SubStmtContext )
151
+ {
152
+ return true ;
153
+ }
154
+ else if ( procedureContext is VBAParser . FunctionStmtContext )
155
+ {
156
+ return true ;
157
+ }
158
+ else if ( procedureContext is VBAParser . PropertyLetStmtContext )
159
+ {
160
+ return true ;
161
+ }
162
+ else if ( procedureContext is VBAParser . PropertyGetStmtContext )
163
+ {
164
+ return true ;
165
+ }
166
+ else if ( procedureContext is VBAParser . PropertySetStmtContext )
185
167
{
186
- result . Add ( tree . GetChild ( index ) ) ;
168
+ return true ;
187
169
}
188
- return result ;
170
+ return false ;
189
171
}
190
172
}
191
173
}
0 commit comments