@@ -21,39 +21,86 @@ public ParameterCanBeByValInspection(RubberduckParserState state)
21
21
public override IEnumerable < InspectionResultBase > GetInspectionResults ( )
22
22
{
23
23
var declarations = UserDeclarations . ToList ( ) ;
24
+ var issues = new List < ParameterCanBeByValInspectionResult > ( ) ;
24
25
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 ) ;
29
28
30
- var formEventHandlerScopes = State . FindFormEventHandlers ( )
31
- . Select ( handler => handler . Scope ) ;
29
+ issues . AddRange ( GetResults ( declarations , interfaceDeclarationMembers ) ) ;
32
30
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 ) ) ;
36
39
37
40
var declareScopes = declarations . Where ( item =>
38
41
item . DeclarationType == DeclarationType . LibraryFunction
39
42
|| item . DeclarationType == DeclarationType . LibraryProcedure )
40
43
. 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 =>
45
46
! declaration . IsArray
46
- && ! ignoredScopes . Contains ( declaration . ParentScope )
47
+ && ! declareScopes . Contains ( declaration . ParentScope )
48
+ && ! eventScopes . Contains ( declaration . ParentScope )
49
+ && ! interfaceScopes . Contains ( declaration . ParentScope )
47
50
&& declaration . DeclarationType == DeclarationType . Parameter
48
- && ! interfaceMembers . Select ( m => m . Scope ) . Contains ( declaration . ParentScope )
49
51
&& ( ( VBAParser . ArgContext ) declaration . Context ) . BYVAL ( ) == null
50
52
&& ! IsUsedAsByRefParam ( declarations , declaration )
51
53
&& ! 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 ) ) ) ;
53
55
54
56
return issues ;
55
57
}
56
58
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
+
57
104
private static bool IsUsedAsByRefParam ( IEnumerable < Declaration > declarations , Declaration parameter )
58
105
{
59
106
// find the procedure calls in the procedure of the parameter.
@@ -74,28 +121,16 @@ private static bool IsUsedAsByRefParam(IEnumerable<Declaration> declarations, De
74
121
. ThenBy ( arg => arg . Selection . StartColumn )
75
122
. ToArray ( ) ;
76
123
77
- for ( var i = 0 ; i < calledProcedureArgs . Count ( ) ; i ++ )
124
+ foreach ( var declaration in calledProcedureArgs )
78
125
{
79
- if ( ( ( VBAParser . ArgContext ) calledProcedureArgs [ i ] . Context ) . BYVAL ( ) != null )
126
+ if ( ( ( VBAParser . ArgContext ) declaration . Context ) . BYVAL ( ) != null )
80
127
{
81
128
continue ;
82
129
}
83
130
84
- foreach ( var reference in item )
131
+ if ( declaration . References . Any ( reference => reference . IsAssignment ) )
85
132
{
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 ;
99
134
}
100
135
}
101
136
}
0 commit comments