@@ -53,13 +53,7 @@ public static bool RequiresSetAssignment(IdentifierReference reference, IDeclara
53
53
{
54
54
// get the members of the returning type, a default member could make us lie otherwise
55
55
var classModule = declaration . AsTypeDeclaration as ClassModuleDeclaration ;
56
- if ( classModule ? . DefaultMember == null )
57
- {
58
- return true ;
59
- }
60
- var parameters = ( classModule . DefaultMember as IParameterizedDeclaration ) ? . Parameters ;
61
- // assign declaration is an object without a default parameterless (or with all parameters optional) member - LHS needs a 'Set' keyword.
62
- return parameters != null && parameters . Any ( p => ! p . IsOptional ) ;
56
+ return ! HasPotentiallyNonObjectParameterlessDefaultMember ( classModule ) ;
63
57
}
64
58
65
59
// assigned declaration is a variant. we need to know about the RHS of the assignment.
@@ -76,9 +70,30 @@ public static bool RequiresSetAssignment(IdentifierReference reference, IDeclara
76
70
return false ;
77
71
}
78
72
79
- if ( expression is VBAParser . NewExprContext )
73
+
74
+ var module = Declaration . GetModuleParent ( reference . ParentScoping ) ;
75
+
76
+ if ( expression is VBAParser . NewExprContext newExpr )
80
77
{
81
- // RHS expression is newing up an object reference - LHS needs a 'Set' keyword:
78
+ var newTypeExpression = newExpr . expression ( ) ;
79
+
80
+ // todo resolve expression type
81
+
82
+ //Covers the case of a single type on the RHS of the assignment.
83
+ var simpleTypeName = newTypeExpression . GetDescendent < VBAParser . SimpleNameExprContext > ( ) ;
84
+ if ( simpleTypeName != null && simpleTypeName . GetText ( ) == newTypeExpression . GetText ( ) )
85
+ {
86
+ var qualifiedIdentifierSelection = new QualifiedSelection ( module . QualifiedModuleName ,
87
+ simpleTypeName . identifier ( ) . GetSelection ( ) ) ;
88
+ var identifierText = simpleTypeName . identifier ( ) . GetText ( ) ;
89
+ return declarationFinderProvider . DeclarationFinder . IdentifierReferences ( qualifiedIdentifierSelection )
90
+ . Select ( identifierReference => identifierReference . Declaration )
91
+ . Where ( decl => identifierText == decl . IdentifierName )
92
+ . OfType < ClassModuleDeclaration > ( )
93
+ . Any ( typeDecl => ! HasPotentiallyNonObjectParameterlessDefaultMember ( typeDecl ) ) ;
94
+ }
95
+ //Here, we err on the side of false-positives, but that seems more appropriate than not to treat qualified type expressions incorrectly.
96
+ //Whether there is a legitimate use here for default members is questionable anyway.
82
97
return true ;
83
98
}
84
99
@@ -94,8 +109,6 @@ public static bool RequiresSetAssignment(IdentifierReference reference, IDeclara
94
109
}
95
110
96
111
// todo resolve expression return type
97
- var project = Declaration . GetProjectParent ( reference . ParentScoping ) ;
98
- var module = Declaration . GetModuleParent ( reference . ParentScoping ) ;
99
112
100
113
//Covers the case of a single variable on the RHS of the assignment.
101
114
var simpleName = expression . GetDescendent < VBAParser . SimpleNameExprContext > ( ) ;
@@ -104,15 +117,40 @@ public static bool RequiresSetAssignment(IdentifierReference reference, IDeclara
104
117
var qualifiedIdentifierSelection = new QualifiedSelection ( module . QualifiedModuleName ,
105
118
simpleName . identifier ( ) . GetSelection ( ) ) ;
106
119
return declarationFinderProvider . DeclarationFinder . IdentifierReferences ( qualifiedIdentifierSelection )
107
- . Any ( identifierReference => identifierReference . Declaration . IsObject
108
- && simpleName . identifier ( ) . GetText ( ) == identifierReference . Declaration . IdentifierName ) ;
120
+ . Select ( identifierReference => identifierReference . Declaration )
121
+ . Where ( decl => decl . IsObject
122
+ && simpleName . identifier ( ) . GetText ( ) == decl . IdentifierName )
123
+ . Select ( typeDeclaration => typeDeclaration . AsTypeDeclaration as ClassModuleDeclaration )
124
+ . Any ( typeDecl => ! HasPotentiallyNonObjectParameterlessDefaultMember ( typeDecl ) ) ;
109
125
}
110
126
127
+ var project = Declaration . GetProjectParent ( reference . ParentScoping ) ;
128
+
111
129
//todo: Use code path analysis to ensure that we are really picking up the last assignment to the RHS.
112
130
// is the reference referring to something else in scope that's a object?
113
131
return declarationFinderProvider . DeclarationFinder . MatchName ( expression . GetText ( ) )
114
132
. Any ( decl => ( decl . DeclarationType . HasFlag ( DeclarationType . ClassModule ) || Tokens . Object . Equals ( decl . AsTypeName ) )
115
133
&& AccessibilityCheck . IsAccessible ( project , module , reference . ParentScoping , decl ) ) ;
116
134
}
135
+
136
+ private static bool HasPotentiallyNonObjectParameterlessDefaultMember ( ClassModuleDeclaration classModule )
137
+ {
138
+ var defaultMember = classModule ? . DefaultMember ;
139
+
140
+ if ( defaultMember == null )
141
+ {
142
+ return false ;
143
+ }
144
+
145
+ var parameters = ( defaultMember as IParameterizedDeclaration ) ? . Parameters ;
146
+ // assign declaration is an object without a default parameterless (or with all parameters optional) member - LHS needs a 'Set' keyword.
147
+ if ( parameters != null && parameters . Any ( p => ! p . IsOptional ) )
148
+ {
149
+ return false ;
150
+ }
151
+
152
+ var defaultMemberType = defaultMember . AsTypeDeclaration as ClassModuleDeclaration ;
153
+ return defaultMemberType == null || HasPotentiallyNonObjectParameterlessDefaultMember ( defaultMemberType ) ;
154
+ }
117
155
}
118
156
}
0 commit comments