3
3
using System . Collections . Generic ;
4
4
using System . Diagnostics ;
5
5
using System . Linq ;
6
+ using System . Runtime . InteropServices . WindowsRuntime ;
6
7
using Antlr4 . Runtime ;
7
8
using NLog ;
8
9
using Rubberduck . Parsing . Annotations ;
@@ -542,46 +543,34 @@ public IEnumerable<Declaration> MatchName(string name)
542
543
: Enumerable . Empty < Declaration > ( ) ;
543
544
}
544
545
545
- public ParameterDeclaration FindParameterFromArgument ( VBAParser . ArgumentExpressionContext argExpression , Declaration enclosingProcedure )
546
+ public ParameterDeclaration FindParameterOfNonDefaultMemberFromSimpleArgumentNotPassedByValExplicitly ( VBAParser . ArgumentExpressionContext argumentExpression , Declaration enclosingProcedure )
546
547
{
547
- if ( argExpression == null ||
548
- argExpression . GetDescendent < VBAParser . ParenthesizedExprContext > ( ) != null ||
549
- argExpression . BYVAL ( ) != null )
550
- {
551
- // not an argument, or argument is parenthesized and thus passed ByVal
552
- return null ;
553
- }
554
-
555
- var callStmt = argExpression . GetAncestor < VBAParser . CallStmtContext > ( ) ;
556
-
557
- var identifier = callStmt ?
558
- . GetDescendent < VBAParser . LExpressionContext > ( )
559
- . GetDescendents < VBAParser . IdentifierContext > ( )
560
- . LastOrDefault ( ) ;
548
+ return FindParameterOfNonDefaultMemberFromSimpleArgumentNotPassedByValExplicitly ( argumentExpression , enclosingProcedure . QualifiedModuleName ) ;
549
+ }
561
550
562
- if ( identifier == null )
563
- {
564
- // if we don't know what we're calling, we can't dig any further
565
- return null ;
566
- }
551
+ public ParameterDeclaration FindParameterOfNonDefaultMemberFromSimpleArgumentNotPassedByValExplicitly ( VBAParser . ArgumentExpressionContext argumentExpression , QualifiedModuleName module )
552
+ {
553
+ //todo: Rename after making it work for more general cases.
567
554
568
- var selection = new QualifiedSelection ( enclosingProcedure . QualifiedModuleName , identifier . GetSelection ( ) ) ;
569
- if ( ! _referencesBySelection . TryGetValue ( selection , out var matches ) )
555
+ if ( argumentExpression == null
556
+ || argumentExpression . GetDescendent < VBAParser . ParenthesizedExprContext > ( ) != null
557
+ || argumentExpression . BYVAL ( ) != null )
570
558
{
559
+ // not a simple argument, or argument is parenthesized and thus passed ByVal
571
560
return null ;
572
561
}
573
562
574
- var procedure = matches . SingleOrDefault ( ) ? . Declaration ;
575
- if ( procedure ? . ParentScopeDeclaration is ClassModuleDeclaration )
563
+ var callingNonDefaultMember = CallingNonDefaultMember ( argumentExpression , module ) ;
564
+ if ( callingNonDefaultMember == null )
576
565
{
577
- // we can't know that the member is on the class' default interface
566
+ // Either we could not resolve the call or there is a default member call involved.
578
567
return null ;
579
568
}
580
569
581
- var parameters = Parameters ( procedure ) ;
570
+ var parameters = Parameters ( callingNonDefaultMember ) ;
582
571
583
572
ParameterDeclaration parameter ;
584
- var namedArg = argExpression . GetAncestor < VBAParser . NamedArgumentContext > ( ) ;
573
+ var namedArg = argumentExpression . GetAncestor < VBAParser . NamedArgumentContext > ( ) ;
585
574
if ( namedArg != null )
586
575
{
587
576
// argument is named: we're lucky
@@ -591,11 +580,11 @@ public ParameterDeclaration FindParameterFromArgument(VBAParser.ArgumentExpressi
591
580
else
592
581
{
593
582
// argument is positional: work out its index
594
- var argList = callStmt . GetDescendent < VBAParser . ArgumentListContext > ( ) ;
595
- var args = argList . GetDescendents < VBAParser . PositionalArgumentContext > ( ) . ToArray ( ) ;
583
+ var argumentList = argumentExpression . GetAncestor < VBAParser . ArgumentListContext > ( ) ;
584
+ var arguments = argumentList . GetDescendents < VBAParser . PositionalArgumentContext > ( ) . ToArray ( ) ;
596
585
597
- var parameterIndex = args
598
- . Select ( ( param , index ) => param . GetDescendent < VBAParser . ArgumentExpressionContext > ( ) == argExpression ? ( param , index ) : ( null , - 1 ) )
586
+ var parameterIndex = arguments
587
+ . Select ( ( param , index ) => param . GetDescendent < VBAParser . ArgumentExpressionContext > ( ) == argumentExpression ? ( param , index ) : ( null , - 1 ) )
599
588
. SingleOrDefault ( item => item . param != null ) . index ;
600
589
601
590
parameter = parameters
@@ -607,6 +596,74 @@ public ParameterDeclaration FindParameterFromArgument(VBAParser.ArgumentExpressi
607
596
return parameter ;
608
597
}
609
598
599
+ private ModuleBodyElementDeclaration CallingNonDefaultMember ( VBAParser . ArgumentExpressionContext argumentExpression , QualifiedModuleName module )
600
+ {
601
+ //todo: Make this work for default member calls.
602
+
603
+ var argumentList = argumentExpression . GetAncestor < VBAParser . ArgumentListContext > ( ) ;
604
+ var cannotHaveDefaultMemberCall = false ;
605
+
606
+ ParserRuleContext callingExpression ;
607
+ switch ( argumentList . Parent )
608
+ {
609
+ case VBAParser . CallStmtContext callStmt :
610
+ cannotHaveDefaultMemberCall = true ;
611
+ callingExpression = callStmt . lExpression ( ) ;
612
+ break ;
613
+ case VBAParser . IndexExprContext indexExpr :
614
+ callingExpression = indexExpr . lExpression ( ) ;
615
+ break ;
616
+ case VBAParser . WhitespaceIndexExprContext indexExpr :
617
+ callingExpression = indexExpr . lExpression ( ) ;
618
+ break ;
619
+ default :
620
+ //This should never happen.
621
+ return null ;
622
+ }
623
+
624
+ VBAParser . IdentifierContext callingIdentifier ;
625
+ if ( cannotHaveDefaultMemberCall )
626
+ {
627
+ callingIdentifier = callingExpression
628
+ . GetDescendents < VBAParser . IdentifierContext > ( )
629
+ . LastOrDefault ( ) ;
630
+ }
631
+ else
632
+ {
633
+ switch ( callingExpression )
634
+ {
635
+ case VBAParser . SimpleNameExprContext simpleName :
636
+ callingIdentifier = simpleName . identifier ( ) ;
637
+ break ;
638
+ case VBAParser . MemberAccessExprContext memberAccess :
639
+ callingIdentifier = memberAccess
640
+ . GetDescendents < VBAParser . IdentifierContext > ( )
641
+ . LastOrDefault ( ) ;
642
+ break ;
643
+ case VBAParser . WithMemberAccessExprContext memberAccess :
644
+ callingIdentifier = memberAccess
645
+ . GetDescendents < VBAParser . IdentifierContext > ( )
646
+ . LastOrDefault ( ) ;
647
+ break ;
648
+ default :
649
+ //This is only possible in case of a default member access.
650
+ return null ;
651
+ }
652
+ }
653
+
654
+ if ( callingIdentifier == null )
655
+ {
656
+ return null ;
657
+ }
658
+
659
+ var referencedMember = IdentifierReferences ( callingIdentifier , module )
660
+ . Select ( reference => reference . Declaration )
661
+ . OfType < ModuleBodyElementDeclaration > ( )
662
+ . FirstOrDefault ( ) ;
663
+
664
+ return referencedMember ;
665
+ }
666
+
610
667
private string ToNormalizedName ( string name )
611
668
{
612
669
var lower = name . ToLowerInvariant ( ) ;
@@ -1253,6 +1310,16 @@ public IEnumerable<IdentifierReference> IdentifierReferences(QualifiedModuleName
1253
1310
: Enumerable . Empty < IdentifierReference > ( ) ;
1254
1311
}
1255
1312
1313
+ /// <summary>
1314
+ /// Gets all identifier references for an IdentifierContext.
1315
+ /// </summary>
1316
+ public IEnumerable < IdentifierReference > IdentifierReferences ( VBAParser . IdentifierContext identifierContext , QualifiedModuleName module )
1317
+ {
1318
+ var qualifiedSelection = new QualifiedSelection ( module , identifierContext . GetSelection ( ) ) ;
1319
+ return IdentifierReferences ( qualifiedSelection )
1320
+ . Where ( identifierReference => identifierReference . IdentifierName . Equals ( identifierContext . GetText ( ) ) ) ;
1321
+ }
1322
+
1256
1323
/// <summary>
1257
1324
/// Gets all identifier references with the specified selection.
1258
1325
/// </summary>
0 commit comments