@@ -159,7 +159,7 @@ private Declaration ResolveType(VBAParser.ComplexTypeContext context)
159
159
{
160
160
return _declarations [ identifier . GetText ( ) ] . SingleOrDefault ( item =>
161
161
item . ProjectName == libraryName
162
- && _moduleTypes . Contains ( item . DeclarationType ) ) ;
162
+ && ( _moduleTypes . Contains ( item . DeclarationType ) ) || item . DeclarationType == DeclarationType . UserDefinedType ) ;
163
163
}
164
164
165
165
return null ;
@@ -194,28 +194,46 @@ private Declaration ResolveType(Declaration parent)
194
194
return null ;
195
195
}
196
196
197
- // look in current project first.
198
197
var result = _declarations [ parent . AsTypeName ] . SingleOrDefault ( item =>
199
- _moduleTypes . Contains ( item . DeclarationType )
200
- && item . ProjectName == _currentScope . ProjectName ) ;
198
+ item . DeclarationType == DeclarationType . UserDefinedType
199
+ && item . Project == _currentScope . Project
200
+ && item . ComponentName == _currentScope . ComponentName ) ;
201
+
202
+ if ( result == null )
203
+ {
204
+ result = _declarations [ parent . AsTypeName ] . SingleOrDefault ( item =>
205
+ _moduleTypes . Contains ( item . DeclarationType )
206
+ && item . Project == _currentScope . Project ) ;
207
+ }
201
208
202
209
if ( result == null )
203
210
{
204
- // look in all projects (including VbaStdLib library).
205
211
result = _declarations [ parent . AsTypeName ] . SingleOrDefault ( item =>
206
212
_moduleTypes . Contains ( item . DeclarationType ) ) ;
207
213
}
208
214
209
215
return result ;
210
216
}
211
217
218
+ private static readonly Type [ ] IdentifierContexts =
219
+ {
220
+ typeof ( VBAParser . AmbiguousIdentifierContext ) ,
221
+ typeof ( VBAParser . CertainIdentifierContext )
222
+ } ;
223
+
212
224
private Declaration ResolveInternal ( ParserRuleContext callSiteContext , Declaration localScope , ContextAccessorType accessorType = ContextAccessorType . GetValueOrReference , VBAParser . DictionaryCallStmtContext fieldCall = null , bool hasExplicitLetStatement = false , bool isAssignmentTarget = false )
213
225
{
214
226
if ( callSiteContext == null )
215
227
{
216
228
return null ;
217
229
}
218
230
231
+ if ( ! IdentifierContexts . Contains ( callSiteContext . GetType ( ) ) )
232
+ {
233
+ throw new ArgumentException ( "'" + callSiteContext . GetType ( ) . Name + "' is not an identifier context." , "callSiteContext" ) ;
234
+ }
235
+
236
+
219
237
/* VBA allows ambiguous identifiers; if foo is declared at both
220
238
* local and module scope, local scope takes precedence.
221
239
* Identifier reference resolution should therefore start search for
@@ -242,10 +260,20 @@ private Declaration ResolveInternal(ParserRuleContext callSiteContext, Declarati
242
260
}
243
261
244
262
var identifierName = callSiteContext . GetText ( ) ;
245
- var callee = FindLocalScopeDeclaration ( identifierName , localScope )
263
+ Declaration callee ;
264
+ if ( localScope . DeclarationType == DeclarationType . Variable )
265
+ {
266
+ // localScope is a UDT
267
+ var udt = ResolveType ( localScope ) ;
268
+ callee = _declarations [ identifierName ] . SingleOrDefault ( item => item . Context . Parent == udt . Context ) ;
269
+ }
270
+ else
271
+ {
272
+ callee = FindLocalScopeDeclaration ( identifierName , localScope )
246
273
?? FindModuleScopeDeclaration ( identifierName , localScope )
247
274
?? FindModuleScopeProcedure ( identifierName , localScope , accessorType , isAssignmentTarget )
248
275
?? FindProjectScopeDeclaration ( identifierName ) ;
276
+ }
249
277
250
278
if ( callee == null )
251
279
{
@@ -265,7 +293,7 @@ private Declaration ResolveInternal(ParserRuleContext callSiteContext, Declarati
265
293
266
294
var reference = CreateReference ( callSiteContext , callee , isAssignmentTarget , hasExplicitLetStatement ) ;
267
295
callee . AddReference ( reference ) ;
268
- _alreadyResolved . Add ( callSiteContext . Parent ) ;
296
+ _alreadyResolved . Add ( reference . Context ) ;
269
297
270
298
if ( fieldCall != null )
271
299
{
@@ -308,7 +336,7 @@ private Declaration ResolveInternal(VBAParser.DictionaryCallStmtContext fieldCal
308
336
var identifierContext = fieldCall . ambiguousIdentifier ( ) ;
309
337
var reference = CreateReference ( identifierContext , result , isAssignmentTarget , hasExplicitLetStatement ) ;
310
338
result . AddReference ( reference ) ;
311
- _alreadyResolved . Add ( fieldCall ) ;
339
+ _alreadyResolved . Add ( reference . Context ) ;
312
340
313
341
return result ;
314
342
}
@@ -346,7 +374,7 @@ private Declaration ResolveInternal(VBAParser.ICS_S_MembersCallContext context,
346
374
{
347
375
var parentReference = CreateReference ( parent . Context , parent ) ;
348
376
parent . AddReference ( parentReference ) ;
349
- _alreadyResolved . Add ( parent . Context ) ;
377
+ _alreadyResolved . Add ( parentReference . Context ) ;
350
378
}
351
379
352
380
var chainedCalls = context . iCS_S_MemberCall ( ) ;
@@ -404,7 +432,7 @@ private Declaration ResolveInternal(VBAParser.ICS_B_ProcedureCallContext context
404
432
405
433
var reference = CreateReference ( identifierContext , callee ) ;
406
434
callee . AddReference ( reference ) ;
407
- _alreadyResolved . Add ( context ) ;
435
+ _alreadyResolved . Add ( reference . Context ) ;
408
436
409
437
return callee ;
410
438
}
@@ -422,7 +450,9 @@ private void ResolveIdentifier(VBAParser.AmbiguousIdentifierContext context)
422
450
return ;
423
451
}
424
452
425
- identifier . AddReference ( CreateReference ( context , identifier ) ) ;
453
+ var reference = CreateReference ( context , identifier ) ;
454
+ identifier . AddReference ( reference ) ;
455
+ _alreadyResolved . Add ( reference . Context ) ;
426
456
}
427
457
428
458
public void Resolve ( VBAParser . ICS_B_ProcedureCallContext context )
@@ -465,7 +495,7 @@ public void Resolve(VBAParser.ICS_B_MemberProcedureCallContext context)
465
495
{
466
496
var reference = CreateReference ( identifierContext , member ) ;
467
497
member . AddReference ( reference ) ;
468
- _alreadyResolved . Add ( context ) ;
498
+ _alreadyResolved . Add ( reference . Context ) ;
469
499
}
470
500
471
501
var fieldCall = context . dictionaryCallStmt ( ) ;
@@ -474,17 +504,54 @@ public void Resolve(VBAParser.ICS_B_MemberProcedureCallContext context)
474
504
475
505
public void Resolve ( VBAParser . ICS_S_VariableOrProcedureCallContext context )
476
506
{
477
- TryResolve ( context ) ;
507
+ ResolveInternal ( context , _currentScope ) ;
478
508
}
479
509
480
510
public void Resolve ( VBAParser . ICS_S_ProcedureOrArrayCallContext context )
481
511
{
482
- TryResolve ( context ) ;
512
+ ResolveInternal ( context , _currentScope ) ;
483
513
}
484
514
485
515
public void Resolve ( VBAParser . ICS_S_MembersCallContext context )
486
516
{
487
- TryResolve ( context ) ;
517
+ if ( context == null )
518
+ {
519
+ return ;
520
+ }
521
+
522
+ var parent = ResolveInternal ( context . iCS_S_ProcedureOrArrayCall ( ) , _currentScope )
523
+ ?? ResolveInternal ( context . iCS_S_VariableOrProcedureCall ( ) , _currentScope ) ;
524
+
525
+ if ( parent != null )
526
+ {
527
+ var identifierContext = ( ( dynamic ) parent . Context ) . ambiguousIdentifier ( ) as VBAParser . AmbiguousIdentifierContext ;
528
+
529
+ var parentReference = CreateReference ( identifierContext , parent ) ;
530
+ parent . AddReference ( parentReference ) ;
531
+ _alreadyResolved . Add ( parentReference . Context ) ;
532
+ }
533
+
534
+ var chainedCalls = context . iCS_S_MemberCall ( ) ;
535
+ foreach ( var memberCall in chainedCalls )
536
+ {
537
+ var member = ResolveInternal ( memberCall . iCS_S_ProcedureOrArrayCall ( ) , parent )
538
+ ?? ResolveInternal ( memberCall . iCS_S_VariableOrProcedureCall ( ) , parent ) ;
539
+
540
+ if ( member == null )
541
+ {
542
+ return ;
543
+ }
544
+
545
+ parent = member ;
546
+ }
547
+
548
+ var fieldCall = context . dictionaryCallStmt ( ) ;
549
+ if ( fieldCall == null )
550
+ {
551
+ return ;
552
+ }
553
+
554
+ ResolveInternal ( fieldCall , parent ) ;
488
555
}
489
556
490
557
public void Resolve ( VBAParser . ICS_S_DictionaryCallContext context )
@@ -552,6 +619,7 @@ public void Resolve(VBAParser.AsTypeClauseContext context)
552
619
if ( type != null )
553
620
{
554
621
type . AddReference ( reference ) ;
622
+ _alreadyResolved . Add ( reference . Context ) ;
555
623
}
556
624
}
557
625
@@ -566,7 +634,8 @@ public void Resolve(VBAParser.ForNextStmtContext context)
566
634
567
635
if ( identifiers . Count > 1 )
568
636
{
569
- identifier . AddReference ( CreateReference ( identifiers [ 1 ] , identifier ) ) ;
637
+ var endForBlockReference = CreateReference ( identifiers [ 1 ] , identifier ) ;
638
+ identifier . AddReference ( endForBlockReference ) ;
570
639
}
571
640
}
572
641
@@ -631,16 +700,40 @@ private Declaration FindParentCall(VBAParser.VsAssignContext context)
631
700
?? ResolveInternal ( calleeContext as VBAParser . ICS_S_MembersCallContext , _currentScope ) ;
632
701
}
633
702
703
+ private Declaration FindFunctionOrPropertyGetter ( string identifierName , Declaration localScope = null )
704
+ {
705
+ if ( localScope == null )
706
+ {
707
+ localScope = _currentScope ;
708
+ }
709
+
710
+ var matches = _declarations [ identifierName ] ;
711
+ var parent = matches . SingleOrDefault ( item =>
712
+ item . Scope == localScope . Scope
713
+ && ( item . DeclarationType == DeclarationType . Function
714
+ || item . DeclarationType == DeclarationType . PropertyGet ) ) ;
715
+
716
+ return parent ;
717
+ }
718
+
634
719
private Declaration FindLocalScopeDeclaration ( string identifierName , Declaration localScope = null )
635
720
{
636
721
if ( localScope == null )
637
722
{
638
723
localScope = _currentScope ;
639
724
}
640
725
641
- var parent = _declarations [ identifierName ] . SingleOrDefault ( item =>
726
+ if ( localScope . DeclarationType == DeclarationType . Function ||
727
+ localScope . DeclarationType == DeclarationType . PropertyGet )
728
+ {
729
+ return FindFunctionOrPropertyGetter ( identifierName , localScope ) ;
730
+ }
731
+
732
+ var matches = _declarations [ identifierName ] ;
733
+ var parent = matches . SingleOrDefault ( item =>
642
734
item . ParentScope == localScope . Scope
643
735
&& ! _moduleTypes . Contains ( item . DeclarationType ) ) ;
736
+
644
737
return parent ;
645
738
}
646
739
@@ -651,7 +744,8 @@ private Declaration FindModuleScopeDeclaration(string identifierName, Declaratio
651
744
localScope = _currentScope ;
652
745
}
653
746
654
- return _declarations [ identifierName ] . SingleOrDefault ( item =>
747
+ var matches = _declarations [ identifierName ] ;
748
+ return matches . SingleOrDefault ( item =>
655
749
item . ParentScope == localScope . ParentScope
656
750
&& ! item . DeclarationType . HasFlag ( DeclarationType . Member )
657
751
&& ! _moduleTypes . Contains ( item . DeclarationType ) ) ;
@@ -664,17 +758,19 @@ private Declaration FindModuleScopeProcedure(string identifierName, Declaration
664
758
localScope = _currentScope ;
665
759
}
666
760
667
- return _declarations [ identifierName ] . SingleOrDefault ( item =>
761
+ var matches = _declarations [ identifierName ] ;
762
+ return matches . SingleOrDefault ( item =>
668
763
IsProcedure ( item ) || IsPropertyAccessor ( item , accessorType , localScope , isAssignmentTarget ) ) ;
669
764
}
670
765
671
766
private Declaration FindProjectScopeDeclaration ( string identifierName )
672
767
{
673
768
// assume unqualified variable call, i.e. unique declaration.
674
- return _declarations [ identifierName ] . SingleOrDefault ( item =>
675
- ( item . Accessibility == Accessibility . Public
769
+ return _declarations [ identifierName ] . SingleOrDefault ( item =>
770
+ ! item . DeclarationType . HasFlag ( DeclarationType . Member )
771
+ && ( item . Accessibility == Accessibility . Public
676
772
|| item . Accessibility == Accessibility . Global
677
- || _moduleTypes . Contains ( item . DeclarationType ) ) ) ;
773
+ || _moduleTypes . Contains ( item . DeclarationType ) /* because static classes are accessed just like modules */ ) ) ;
678
774
}
679
775
680
776
private bool IsProcedure ( Declaration item )
0 commit comments