@@ -28,31 +28,24 @@ private enum DeclarationSite
28
28
SameComponent = 3
29
29
}
30
30
31
- private class OptionPrivateModuleListener : VBAParserBaseListener
32
- {
33
- public List < VBAParser . ModuleContext > OptionPrivateModules { get ; } = new List < VBAParser . ModuleContext > ( ) ;
34
-
35
- public override void EnterModule ( VBAParser . ModuleContext context )
36
- {
37
- if ( context . FindChildren < VBAParser . OptionPrivateModuleStmtContext > ( ) . Any ( ) )
38
- {
39
- OptionPrivateModules . Add ( context ) ;
40
- }
41
- }
42
- }
43
-
44
31
private class EnumerationRuleIndexListener : VBAParserBaseListener
45
32
{
46
33
public Dictionary < ParserRuleContext , int > DeclarationIndexes { get ; } = new Dictionary < ParserRuleContext , int > ( ) ;
47
34
48
35
public override void EnterEnumerationStmt ( VBAParser . EnumerationStmtContext context )
49
36
{
50
- DeclarationIndexes . Add ( context , context . Start . TokenIndex ) ;
37
+ if ( ! DeclarationIndexes . ContainsKey ( context ) )
38
+ {
39
+ DeclarationIndexes . Add ( context , context . Start . TokenIndex ) ;
40
+ }
51
41
}
52
42
53
43
public override void EnterEnumerationStmt_Constant ( VBAParser . EnumerationStmt_ConstantContext context )
54
44
{
55
- DeclarationIndexes . Add ( context , context . Start . TokenIndex ) ;
45
+ if ( ! DeclarationIndexes . ContainsKey ( context ) )
46
+ {
47
+ DeclarationIndexes . Add ( context , context . Start . TokenIndex ) ;
48
+ }
56
49
}
57
50
}
58
51
@@ -66,50 +59,37 @@ public ShadowedDeclarationInspection(RubberduckParserState state) : base(state,
66
59
67
60
public override IEnumerable < IInspectionResult > GetInspectionResults ( )
68
61
{
69
- var optionPrivateModuleListener = new OptionPrivateModuleListener ( ) ;
70
- var enumerationRuleIndexListener = new EnumerationRuleIndexListener ( ) ;
71
-
72
- foreach ( var module in State . DeclarationFinder . AllModules . Where ( m => m . ComponentType == ComponentType . StandardModule ) )
73
- {
74
- ParseTreeWalker . Default . Walk ( optionPrivateModuleListener , State . GetParseTree ( module ) ) ;
75
- }
76
-
77
- foreach ( var module in State . AllUserDeclarations . Where ( d => d . DeclarationType == DeclarationType . ProceduralModule || d . DeclarationType == DeclarationType . ClassModule ) )
78
- {
79
- ParseTreeWalker . Default . Walk ( enumerationRuleIndexListener , State . GetParseTree ( module . QualifiedName . QualifiedModuleName ) ) ;
80
- }
81
-
82
62
var builtInEventHandlers = State . DeclarationFinder . FindEventHandlers ( ) . ToHashSet ( ) ;
83
63
84
64
var issues = new List < IInspectionResult > ( ) ;
85
65
86
- var allUserProjects = UserDeclarations . OfType ( DeclarationType . Project ) . Cast < ProjectDeclaration > ( ) ;
66
+ var allUserProjects = State . DeclarationFinder . UserDeclarations ( DeclarationType . Project ) . Cast < ProjectDeclaration > ( ) ;
87
67
88
68
foreach ( var userProject in allUserProjects )
89
69
{
90
70
var referencedProjectIds = userProject . ProjectReferences . Select ( reference => reference . ReferencedProjectId ) . ToHashSet ( ) ;
91
71
92
- var userDeclarations = UserDeclarations . Where ( d =>
93
- d . ProjectId == userProject . ProjectId &&
72
+ var userDeclarations = UserDeclarations . Where ( declaration =>
73
+ declaration . ProjectId == userProject . ProjectId &&
94
74
// User has no control over build-in event handlers or their parameters, so we skip them
95
- ! DeclarationIsPartOfBuiltInEventHandler ( d , builtInEventHandlers ) ) ;
75
+ ! DeclarationIsPartOfBuiltInEventHandler ( declaration , builtInEventHandlers ) ) ;
96
76
97
- foreach ( var declaration in userDeclarations )
77
+ foreach ( var userDeclaration in userDeclarations )
98
78
{
99
- var shadowedDeclaration = State . AllDeclarations . FirstOrDefault ( d =>
100
- ! Equals ( d , declaration ) &&
101
- string . Equals ( d . IdentifierName , declaration . IdentifierName , StringComparison . OrdinalIgnoreCase ) &&
102
- DeclarationCanBeShadowed ( d , declaration , GetDeclarationSite ( d , declaration , referencedProjectIds ) , optionPrivateModuleListener , enumerationRuleIndexListener ) ) ;
79
+ var shadowedDeclaration = State . DeclarationFinder
80
+ . MatchName ( userDeclaration . IdentifierName ) . FirstOrDefault ( declaration =>
81
+ ! declaration . Equals ( userDeclaration ) &&
82
+ DeclarationCanBeShadowed ( declaration , userDeclaration , GetDeclarationSite ( declaration , userDeclaration , referencedProjectIds ) ) ) ;
103
83
104
84
if ( shadowedDeclaration != null )
105
85
{
106
86
issues . Add ( new DeclarationInspectionResult ( this ,
107
87
string . Format ( InspectionsUI . ShadowedDeclarationInspectionResultFormat ,
108
- RubberduckUI . ResourceManager . GetString ( "DeclarationType_" + declaration . DeclarationType , CultureInfo . CurrentUICulture ) ,
109
- declaration . IdentifierName ,
88
+ RubberduckUI . ResourceManager . GetString ( "DeclarationType_" + userDeclaration . DeclarationType , CultureInfo . CurrentUICulture ) ,
89
+ userDeclaration . IdentifierName ,
110
90
RubberduckUI . ResourceManager . GetString ( "DeclarationType_" + shadowedDeclaration . DeclarationType , CultureInfo . CurrentUICulture ) ,
111
91
shadowedDeclaration . IdentifierName ) ,
112
- declaration ) ) ;
92
+ userDeclaration ) ) ;
113
93
}
114
94
}
115
95
}
@@ -124,7 +104,7 @@ private static DeclarationSite GetDeclarationSite(Declaration originalDeclaratio
124
104
return referencedProjectIds . Contains ( originalDeclaration . ProjectId ) ? DeclarationSite . ReferencedProject : DeclarationSite . NotApplicable ;
125
105
}
126
106
127
- if ( originalDeclaration . QualifiedName . QualifiedModuleName . Name != userDeclaration . QualifiedName . QualifiedModuleName . Name )
107
+ if ( originalDeclaration . QualifiedName . QualifiedModuleName . ComponentName != userDeclaration . QualifiedName . QualifiedModuleName . ComponentName )
128
108
{
129
109
return DeclarationSite . OtherComponent ;
130
110
}
@@ -144,8 +124,7 @@ private static bool DeclarationIsPartOfBuiltInEventHandler(Declaration declarati
144
124
return parameterDeclaration != null && builtInEventHandlers . Contains ( parameterDeclaration . ParentDeclaration ) ;
145
125
}
146
126
147
- private static bool DeclarationCanBeShadowed ( Declaration originalDeclaration , Declaration userDeclaration , DeclarationSite originalDeclarationSite ,
148
- OptionPrivateModuleListener optionPrivateModuleListener , EnumerationRuleIndexListener enumerationRuleIndexListener )
127
+ private bool DeclarationCanBeShadowed ( Declaration originalDeclaration , Declaration userDeclaration , DeclarationSite originalDeclarationSite )
149
128
{
150
129
if ( originalDeclarationSite == DeclarationSite . NotApplicable )
151
130
{
@@ -154,20 +133,20 @@ private static bool DeclarationCanBeShadowed(Declaration originalDeclaration, De
154
133
155
134
if ( originalDeclarationSite == DeclarationSite . ReferencedProject )
156
135
{
157
- return DeclarationInReferencedProjectCanBeShadowed ( originalDeclaration , userDeclaration , optionPrivateModuleListener ) ;
136
+ return DeclarationInReferencedProjectCanBeShadowed ( originalDeclaration , userDeclaration ) ;
158
137
}
159
138
160
139
if ( originalDeclarationSite == DeclarationSite . OtherComponent )
161
140
{
162
- return DeclarationInAnotherComponentCanBeShadowed ( originalDeclaration , userDeclaration , optionPrivateModuleListener ) ;
141
+ return DeclarationInAnotherComponentCanBeShadowed ( originalDeclaration , userDeclaration ) ;
163
142
}
164
143
165
- return DeclarationInTheSameComponentCanBeShadowed ( originalDeclaration , userDeclaration , enumerationRuleIndexListener ) ;
144
+ return DeclarationInTheSameComponentCanBeShadowed ( originalDeclaration , userDeclaration ) ;
166
145
}
167
146
168
- private static bool DeclarationInReferencedProjectCanBeShadowed ( Declaration originalDeclaration , Declaration userDeclaration , OptionPrivateModuleListener listener )
147
+ private bool DeclarationInReferencedProjectCanBeShadowed ( Declaration originalDeclaration , Declaration userDeclaration )
169
148
{
170
- if ( DeclarationIsInsideOptionPrivateModule ( originalDeclaration , listener ) )
149
+ if ( DeclarationIsInsideOptionPrivateModule ( originalDeclaration ) )
171
150
{
172
151
return false ;
173
152
}
@@ -231,9 +210,9 @@ private static bool DeclarationInReferencedProjectCanBeShadowed(Declaration orig
231
210
return DeclarationAccessibilityCanBeShadowed ( originalDeclaration ) ;
232
211
}
233
212
234
- private static bool DeclarationInAnotherComponentCanBeShadowed ( Declaration originalDeclaration , Declaration userDeclaration , OptionPrivateModuleListener listener )
213
+ private static bool DeclarationInAnotherComponentCanBeShadowed ( Declaration originalDeclaration , Declaration userDeclaration )
235
214
{
236
- if ( DeclarationIsInsideOptionPrivateModule ( originalDeclaration , listener ) )
215
+ if ( DeclarationIsInsideOptionPrivateModule ( originalDeclaration ) )
237
216
{
238
217
return false ;
239
218
}
@@ -292,7 +271,7 @@ private static bool DeclarationInAnotherComponentCanBeShadowed(Declaration origi
292
271
return DeclarationAccessibilityCanBeShadowed ( originalDeclaration ) ;
293
272
}
294
273
295
- private static bool DeclarationInTheSameComponentCanBeShadowed ( Declaration originalDeclaration , Declaration userDeclaration , EnumerationRuleIndexListener listener )
274
+ private bool DeclarationInTheSameComponentCanBeShadowed ( Declaration originalDeclaration , Declaration userDeclaration )
296
275
{
297
276
// Shadowing the component containing the declaration is not a problem, because it is possible to directly access declarations inside that component
298
277
if ( originalDeclaration . DeclarationType == DeclarationType . ProceduralModule || originalDeclaration . DeclarationType == DeclarationType . ClassModule ||
@@ -323,18 +302,31 @@ private static bool DeclarationInTheSameComponentCanBeShadowed(Declaration origi
323
302
{
324
303
return DeclarationIsLocal ( userDeclaration ) ;
325
304
}
326
-
327
- if ( listener . DeclarationIndexes . ContainsKey ( originalDeclaration . Context ) && listener . DeclarationIndexes . ContainsKey ( userDeclaration . Context ) )
305
+
306
+ // Shadowing between two enumerations or enumeration members is not possible inside one component.
307
+ if ( ( ( originalDeclaration . DeclarationType == DeclarationType . Enumeration
308
+ && userDeclaration . DeclarationType == DeclarationType . EnumerationMember )
309
+ || ( originalDeclaration . DeclarationType == DeclarationType . EnumerationMember
310
+ && userDeclaration . DeclarationType == DeclarationType . Enumeration ) ) )
328
311
{
329
- var originalDeclarationIndex = listener . DeclarationIndexes [ originalDeclaration . Context ] ;
330
- var userDeclarationIndex = listener . DeclarationIndexes [ userDeclaration . Context ] ;
312
+ var listener = new EnumerationRuleIndexListener ( ) ;
313
+ if ( ! listener . DeclarationIndexes . ContainsKey ( originalDeclaration . Context ) )
314
+ {
315
+ ParseTreeWalker . Default . Walk ( listener ,
316
+ State . GetParseTree ( originalDeclaration . QualifiedName . QualifiedModuleName ) ) ;
317
+ }
331
318
332
- // The same declaration type means that both declarations are enumerations or enumeration members, and such shadowing is not possible inside one component
333
- return originalDeclaration . DeclarationType != userDeclaration . DeclarationType &&
334
- // First declaration wins
335
- originalDeclarationIndex > userDeclarationIndex &&
336
- // Enumeration member can have the same name as enclosing enumeration
337
- ! Equals ( originalDeclaration . ParentDeclaration , userDeclaration ) ;
319
+ if ( listener . DeclarationIndexes . ContainsKey ( originalDeclaration . Context ) &&
320
+ listener . DeclarationIndexes . ContainsKey ( userDeclaration . Context ) )
321
+ {
322
+ var originalDeclarationIndex = listener . DeclarationIndexes [ originalDeclaration . Context ] ;
323
+ var userDeclarationIndex = listener . DeclarationIndexes [ userDeclaration . Context ] ;
324
+
325
+ // First declaration wins
326
+ return originalDeclarationIndex > userDeclarationIndex
327
+ // Enumeration member can have the same name as enclosing enumeration
328
+ && ! userDeclaration . Equals ( originalDeclaration . ParentDeclaration ) ;
329
+ }
338
330
}
339
331
340
332
// Events don't have a body, so their parameters can't be accessed
@@ -355,20 +347,20 @@ private static bool DeclarationAccessibilityCanBeShadowed(Declaration originalDe
355
347
( originalDeclaration . DeclarationType == DeclarationType . EnumerationMember && originalDeclaration . ParentDeclaration . Accessibility == Accessibility . Public ) ;
356
348
}
357
349
358
- private static bool DeclarationIsInsideOptionPrivateModule ( Declaration declaration , OptionPrivateModuleListener listener )
350
+ private static bool DeclarationIsInsideOptionPrivateModule ( Declaration declaration )
359
351
{
360
352
if ( declaration . QualifiedName . QualifiedModuleName . ComponentType != ComponentType . StandardModule )
361
353
{
362
354
return false ;
363
355
}
364
356
365
- var moduleDeclaration = declaration as ProceduralModuleDeclaration ;
357
+ var moduleDeclaration = Declaration . GetModuleParent ( declaration ) as ProceduralModuleDeclaration ;
366
358
if ( moduleDeclaration != null )
367
359
{
368
360
return moduleDeclaration . IsPrivateModule ;
369
361
}
370
362
371
- return listener . OptionPrivateModules . Any ( moduleContext => ParserRuleContextHelper . HasParent ( declaration . Context , moduleContext ) ) ;
363
+ return false ;
372
364
}
373
365
374
366
private static bool DeclarationIsProjectOrComponent ( Declaration declaration )
0 commit comments