3
3
using Rubberduck . Parsing . VBA ;
4
4
using Rubberduck . Parsing . VBA . DeclarationCaching ;
5
5
using Rubberduck . Resources . Inspections ;
6
+ using System . Linq ;
6
7
7
8
namespace Rubberduck . CodeAnalysis . Inspections . Concrete
8
9
{
9
10
/// <summary>
10
11
/// Highlights implicit ByRef modifiers in user code.
11
12
/// </summary>
12
13
/// <why>
13
- /// In modern VB (VB.NET), the implicit modifier is ByVal, as it is in most other programming languages.
14
- /// Making the ByRef modifiers explicit can help surface potentially unexpected language defaults.
14
+ /// VBA parameters are implicitly ByRef, which differs from modern VB (VB.NET) and most other programming languages which are implicitly ByVal.
15
+ /// So, explicitly identifing VBA parameter mechanisms (the ByRef and ByVal modifiers) can help surface potentially unexpected language results.
16
+ /// The inspection does not flag an implicit parameter mechanism for the last parameter of Property mutators (Let or Set).
17
+ /// VBA applies a ByVal parameter mechanism to the last parameter in the absence (or presence!) of a modifier.
18
+ /// Exception: UserDefinedType parameters must always be passed as ByRef.
15
19
/// </why>
16
20
/// <example hasResult="true">
17
21
/// <module name="MyModule" type="Standard Module">
@@ -31,6 +35,16 @@ namespace Rubberduck.CodeAnalysis.Inspections.Concrete
31
35
/// ]]>
32
36
/// </module>
33
37
/// </example>
38
+ /// <example hasResult="false">
39
+ /// <module name="MyModule" type="Standard Module">
40
+ /// <![CDATA[
41
+ /// Private theLength As Long
42
+ /// Public Property Let Length(newLength As Long)
43
+ /// theLength = newLength
44
+ /// End Sub
45
+ /// ]]>
46
+ /// </module>
47
+ /// </example>
34
48
internal sealed class ImplicitByRefModifierInspection : DeclarationInspectionBase
35
49
{
36
50
public ImplicitByRefModifierInspection ( IDeclarationFinderProvider declarationFinderProvider )
@@ -41,21 +55,23 @@ protected override bool IsResultDeclaration(Declaration declaration, Declaration
41
55
{
42
56
if ( ! ( declaration is ParameterDeclaration parameter )
43
57
|| ! parameter . IsImplicitByRef
44
- || parameter . IsParamArray )
58
+ || parameter . IsParamArray
59
+ //Exclude parameters of Declare statements
60
+ || ! ( parameter . ParentDeclaration is ModuleBodyElementDeclaration enclosingMethod ) )
45
61
{
46
62
return false ;
47
63
}
48
64
49
- var parentDeclaration = parameter . ParentDeclaration ;
50
-
51
- if ( parentDeclaration is ModuleBodyElementDeclaration enclosingMethod )
52
- {
53
- return ! enclosingMethod . IsInterfaceImplementation
54
- && ! finder . FindEventHandlers ( ) . Contains ( enclosingMethod ) ;
55
- }
65
+ return ! IsPropertyMutatorRHSParameter ( enclosingMethod , parameter )
66
+ && ! enclosingMethod . IsInterfaceImplementation
67
+ && ! finder . FindEventHandlers ( ) . Contains ( enclosingMethod ) ;
68
+ }
56
69
57
- return parentDeclaration . DeclarationType != DeclarationType . LibraryFunction
58
- && parentDeclaration . DeclarationType != DeclarationType . LibraryProcedure ;
70
+ private bool IsPropertyMutatorRHSParameter ( ModuleBodyElementDeclaration enclosingMethod , ParameterDeclaration implicitByRefParameter )
71
+ {
72
+ return ( enclosingMethod . DeclarationType . HasFlag ( DeclarationType . PropertyLet )
73
+ || enclosingMethod . DeclarationType . HasFlag ( DeclarationType . PropertySet ) )
74
+ && enclosingMethod . Parameters . Last ( ) . Equals ( implicitByRefParameter ) ;
59
75
}
60
76
61
77
protected override string ResultDescription ( Declaration declaration )
0 commit comments