@@ -21,39 +21,86 @@ public ParameterCanBeByValInspection(RubberduckParserState state)
2121 public override IEnumerable < InspectionResultBase > GetInspectionResults ( )
2222 {
2323 var declarations = UserDeclarations . ToList ( ) ;
24+ var issues = new List < ParameterCanBeByValInspectionResult > ( ) ;
2425
25- IEnumerable < Declaration > interfaceMembers = null ;
26- interfaceMembers = declarations . FindInterfaceMembers ( )
27- . Concat ( declarations . FindInterfaceImplementationMembers ( ) )
28- . ToList ( ) ;
26+ var interfaceDeclarationMembers = declarations . FindInterfaceMembers ( ) . ToList ( ) ;
27+ var interfaceScopes = declarations . FindInterfaceImplementationMembers ( ) . Concat ( interfaceDeclarationMembers ) . Select ( s => s . Scope ) ;
2928
30- var formEventHandlerScopes = State . FindFormEventHandlers ( )
31- . Select ( handler => handler . Scope ) ;
29+ issues . AddRange ( GetResults ( declarations , interfaceDeclarationMembers ) ) ;
3230
33- var eventScopes = declarations . Where ( item =>
34- ! item . IsBuiltIn && item . DeclarationType == DeclarationType . Event )
35- . Select ( e => e . Scope ) . Concat ( State . AllDeclarations . FindBuiltInEventHandlers ( ) . Select ( e => e . Scope ) ) ;
31+ var eventMembers = declarations . Where ( item => ! item . IsBuiltIn && item . DeclarationType == DeclarationType . Event ) . ToList ( ) ;
32+ var formEventHandlerScopes = State . FindFormEventHandlers ( ) . Select ( handler => handler . Scope ) ;
33+ var eventHandlerScopes = State . AllDeclarations . FindBuiltInEventHandlers ( ) . Concat ( declarations . FindUserEventHandlers ( ) ) . Select ( e => e . Scope ) ;
34+ var eventScopes = eventMembers . Select ( s => s . Scope )
35+ . Concat ( formEventHandlerScopes )
36+ . Concat ( eventHandlerScopes ) ;
37+
38+ issues . AddRange ( GetResults ( declarations , eventMembers ) ) ;
3639
3740 var declareScopes = declarations . Where ( item =>
3841 item . DeclarationType == DeclarationType . LibraryFunction
3942 || item . DeclarationType == DeclarationType . LibraryProcedure )
4043 . Select ( e => e . Scope ) ;
41-
42- var ignoredScopes = formEventHandlerScopes . Concat ( eventScopes ) . Concat ( declareScopes ) ;
43-
44- var issues = declarations . Where ( declaration =>
44+
45+ issues . AddRange ( declarations . Where ( declaration =>
4546 ! declaration . IsArray
46- && ! ignoredScopes . Contains ( declaration . ParentScope )
47+ && ! declareScopes . Contains ( declaration . ParentScope )
48+ && ! eventScopes . Contains ( declaration . ParentScope )
49+ && ! interfaceScopes . Contains ( declaration . ParentScope )
4750 && declaration . DeclarationType == DeclarationType . Parameter
48- && ! interfaceMembers . Select ( m => m . Scope ) . Contains ( declaration . ParentScope )
4951 && ( ( VBAParser . ArgContext ) declaration . Context ) . BYVAL ( ) == null
5052 && ! IsUsedAsByRefParam ( declarations , declaration )
5153 && ! declaration . References . Any ( reference => reference . IsAssignment ) )
52- . Select ( issue => new ParameterCanBeByValInspectionResult ( this , issue , issue . Context , issue . QualifiedName ) ) ;
54+ . Select ( issue => new ParameterCanBeByValInspectionResult ( this , State , issue , issue . Context , issue . QualifiedName ) ) ) ;
5355
5456 return issues ;
5557 }
5658
59+ private IEnumerable < ParameterCanBeByValInspectionResult > GetResults ( List < Declaration > declarations , List < Declaration > declarationMembers )
60+ {
61+ foreach ( var declaration in declarationMembers )
62+ {
63+ var declarationParameters =
64+ declarations . Where ( d => d . DeclarationType == DeclarationType . Parameter &&
65+ d . ParentDeclaration == declaration )
66+ . OrderBy ( o => o . Selection . StartLine )
67+ . ThenBy ( t => t . Selection . StartColumn )
68+ . ToList ( ) ;
69+
70+ var parametersAreByRef = declarationParameters . Select ( s => true ) . ToList ( ) ;
71+
72+ var members = declarationMembers . Any ( a => a . DeclarationType == DeclarationType . Event )
73+ ? declarations . FindHandlersForEvent ( declaration ) . Select ( s => s . Item2 ) . ToList ( )
74+ : declarations . FindInterfaceImplementationMembers ( declaration ) . ToList ( ) ;
75+
76+ foreach ( var member in members )
77+ {
78+ var parameters =
79+ declarations . Where ( d => d . DeclarationType == DeclarationType . Parameter &&
80+ d . ParentDeclaration == member )
81+ . OrderBy ( o => o . Selection . StartLine )
82+ . ThenBy ( t => t . Selection . StartColumn )
83+ . ToList ( ) ;
84+
85+ for ( var i = 0 ; i < parameters . Count ; i ++ )
86+ {
87+ parametersAreByRef [ i ] = parametersAreByRef [ i ] && ! IsUsedAsByRefParam ( declarations , parameters [ i ] ) &&
88+ ( ( VBAParser . ArgContext ) parameters [ i ] . Context ) . BYVAL ( ) == null &&
89+ ! parameters [ i ] . References . Any ( reference => reference . IsAssignment ) ;
90+ }
91+ }
92+
93+ for ( var i = 0 ; i < declarationParameters . Count ; i ++ )
94+ {
95+ if ( parametersAreByRef [ i ] )
96+ {
97+ yield return new ParameterCanBeByValInspectionResult ( this , State , declarationParameters [ i ] ,
98+ declarationParameters [ i ] . Context , declarationParameters [ i ] . QualifiedName ) ;
99+ }
100+ }
101+ }
102+ }
103+
57104 private static bool IsUsedAsByRefParam ( IEnumerable < Declaration > declarations , Declaration parameter )
58105 {
59106 // find the procedure calls in the procedure of the parameter.
@@ -74,28 +121,16 @@ private static bool IsUsedAsByRefParam(IEnumerable<Declaration> declarations, De
74121 . ThenBy ( arg => arg . Selection . StartColumn )
75122 . ToArray ( ) ;
76123
77- for ( var i = 0 ; i < calledProcedureArgs . Count ( ) ; i ++ )
124+ foreach ( var declaration in calledProcedureArgs )
78125 {
79- if ( ( ( VBAParser . ArgContext ) calledProcedureArgs [ i ] . Context ) . BYVAL ( ) != null )
126+ if ( ( ( VBAParser . ArgContext ) declaration . Context ) . BYVAL ( ) != null )
80127 {
81128 continue ;
82129 }
83130
84- foreach ( var reference in item )
131+ if ( declaration . References . Any ( reference => reference . IsAssignment ) )
85132 {
86- if ( ! ( reference . Context is VBAParser . ArgContext ) )
87- {
88- continue ;
89- }
90- var context = ( ( dynamic ) reference . Context . Parent ) . argsCall ( ) as VBAParser . ArgContext ;
91- if ( context == null )
92- {
93- continue ;
94- }
95- if ( parameter . IdentifierName == context . GetText ( ) )
96- {
97- return true ;
98- }
133+ return true ;
99134 }
100135 }
101136 }
0 commit comments