1
1
using System ;
2
+ using System . Collections . Generic ;
2
3
using Rubberduck . Parsing . Symbols ;
3
4
using System . Linq ;
4
5
using Antlr4 . Runtime ;
5
- using Antlr4 . Runtime . Atn ;
6
6
using Rubberduck . Parsing . Grammar ;
7
- using Rubberduck . Parsing . VBA . DeclarationCaching ;
8
7
9
8
namespace Rubberduck . Parsing . Binding
10
9
{
@@ -16,7 +15,6 @@ public sealed class DictionaryAccessDefaultBinding : IExpressionBinding
16
15
private readonly ArgumentList _argumentList ;
17
16
18
17
private const int DEFAULT_MEMBER_RECURSION_LIMIT = 32 ;
19
- private int _defaultMemberRecursionLimitCounter = 0 ;
20
18
21
19
public DictionaryAccessDefaultBinding (
22
20
ParserRuleContext expression ,
@@ -97,7 +95,7 @@ private IBoundExpression CreateFailedExpression(IBoundExpression lExpression)
97
95
return failedExpr ;
98
96
}
99
97
100
- private IBoundExpression ResolveViaDefaultMember ( IBoundExpression lExpression , string asTypeName , Declaration asTypeDeclaration )
98
+ private IBoundExpression ResolveViaDefaultMember ( IBoundExpression lExpression , string asTypeName , Declaration asTypeDeclaration , int recursionDepth = 0 )
101
99
{
102
100
if ( Tokens . Variant . Equals ( asTypeName , StringComparison . InvariantCultureIgnoreCase )
103
101
|| Tokens . Object . Equals ( asTypeName , StringComparison . InvariantCultureIgnoreCase ) )
@@ -128,44 +126,54 @@ The declared type of <l-expression> is Object or Variant.
128
126
129
127
var parameters = ( ( IParameterizedDeclaration ) defaultMember ) . Parameters . ToList ( ) ;
130
128
131
- if ( parameters . Count > 0
132
- && parameters . Count ( param => ! param . IsOptional ) <= 1
133
- && ( Tokens . String . Equals ( parameters [ 0 ] . AsTypeName , StringComparison . InvariantCultureIgnoreCase )
134
- || Tokens . Variant . Equals ( parameters [ 0 ] . AsTypeName , StringComparison . InvariantCultureIgnoreCase ) ) )
129
+ if ( IsCompatibleWithOneStringArgument ( parameters ) )
135
130
{
136
131
/*
137
132
This default member’s parameter list is compatible with <argument-list>. In this case, the
138
133
dictionary access expression references this default member and takes on its classification and
139
134
declared type.
140
135
*/
141
136
ResolveArgumentList ( defaultMember ) ;
142
- return new DictionaryAccessExpression ( defaultMember , defaultMemberClassification , _expression ,
143
- lExpression , _argumentList ) ;
137
+ return new DictionaryAccessExpression ( defaultMember , defaultMemberClassification , _expression , lExpression , _argumentList ) ;
144
138
}
145
139
146
140
if ( parameters . Count ( param => ! param . IsOptional ) == 0
147
- && DEFAULT_MEMBER_RECURSION_LIMIT > _defaultMemberRecursionLimitCounter )
141
+ && DEFAULT_MEMBER_RECURSION_LIMIT > recursionDepth )
148
142
{
149
143
/*
150
144
This default member cannot accept any parameters. In this case, the static analysis restarts
151
145
recursively, as if this default member was specified instead for <l-expression> with the
152
146
same <argument-list>.
153
147
*/
154
- _defaultMemberRecursionLimitCounter ++ ;
155
148
156
- var defaultMemberAsLExpression =
157
- new SimpleNameExpression ( defaultMember , defaultMemberClassification , _expression ) ;
158
- var defaultMemberAsTypeName = defaultMember . AsTypeName ;
159
- var defaultMemberAsTypeDeclaration = defaultMember . AsTypeDeclaration ;
160
-
161
- return ResolveViaDefaultMember ( defaultMemberAsLExpression , defaultMemberAsTypeName ,
162
- defaultMemberAsTypeDeclaration ) ;
149
+ return ResolveRecursiveDefaultMember ( defaultMember , defaultMemberClassification , recursionDepth ) ;
163
150
}
164
151
165
152
ResolveArgumentList ( null ) ;
166
153
return CreateFailedExpression ( lExpression ) ;
167
154
}
168
155
156
+ private static bool IsCompatibleWithOneStringArgument ( List < ParameterDeclaration > parameters )
157
+ {
158
+ return parameters . Count > 0
159
+ && parameters . Count ( param => ! param . IsOptional ) <= 1
160
+ && ( Tokens . String . Equals ( parameters [ 0 ] . AsTypeName , StringComparison . InvariantCultureIgnoreCase )
161
+ || Tokens . Variant . Equals ( parameters [ 0 ] . AsTypeName , StringComparison . InvariantCultureIgnoreCase ) ) ;
162
+ }
163
+
164
+ private IBoundExpression ResolveRecursiveDefaultMember ( Declaration defaultMember , ExpressionClassification defaultMemberClassification , int recursionDepth )
165
+ {
166
+ var defaultMemberAsLExpression = new SimpleNameExpression ( defaultMember , defaultMemberClassification , _expression ) ;
167
+ var defaultMemberAsTypeName = defaultMember . AsTypeName ;
168
+ var defaultMemberAsTypeDeclaration = defaultMember . AsTypeDeclaration ;
169
+
170
+ return ResolveViaDefaultMember (
171
+ defaultMemberAsLExpression ,
172
+ defaultMemberAsTypeName ,
173
+ defaultMemberAsTypeDeclaration ,
174
+ recursionDepth + 1 ) ;
175
+ }
176
+
169
177
private static bool IsPropertyGetLetFunctionProcedure ( Declaration declaration )
170
178
{
171
179
var declarationType = declaration . DeclarationType ;
0 commit comments