Skip to content

Commit d024143

Browse files
committed
Introduce references for array accesses
These reference the entire index expression and have the new flag IsArrayAccess set to true. To resolve everything correctly, the entire IndexDefaultBinding got an overhaul. Also replaces the tests of ImplicitDefaultMemberAssignmentInspection since they previously only passed because the resolution of the assignment target was wrong.
1 parent d46f190 commit d024143

File tree

9 files changed

+471
-326
lines changed

9 files changed

+471
-326
lines changed

Rubberduck.Parsing/Binding/Bindings/DictionaryAccessDefaultBinding.cs

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
using System;
2+
using System.Collections.Generic;
23
using Rubberduck.Parsing.Symbols;
34
using System.Linq;
45
using Antlr4.Runtime;
5-
using Antlr4.Runtime.Atn;
66
using Rubberduck.Parsing.Grammar;
7-
using Rubberduck.Parsing.VBA.DeclarationCaching;
87

98
namespace Rubberduck.Parsing.Binding
109
{
@@ -16,7 +15,6 @@ public sealed class DictionaryAccessDefaultBinding : IExpressionBinding
1615
private readonly ArgumentList _argumentList;
1716

1817
private const int DEFAULT_MEMBER_RECURSION_LIMIT = 32;
19-
private int _defaultMemberRecursionLimitCounter = 0;
2018

2119
public DictionaryAccessDefaultBinding(
2220
ParserRuleContext expression,
@@ -97,7 +95,7 @@ private IBoundExpression CreateFailedExpression(IBoundExpression lExpression)
9795
return failedExpr;
9896
}
9997

100-
private IBoundExpression ResolveViaDefaultMember(IBoundExpression lExpression, string asTypeName, Declaration asTypeDeclaration)
98+
private IBoundExpression ResolveViaDefaultMember(IBoundExpression lExpression, string asTypeName, Declaration asTypeDeclaration, int recursionDepth = 0)
10199
{
102100
if (Tokens.Variant.Equals(asTypeName, StringComparison.InvariantCultureIgnoreCase)
103101
|| Tokens.Object.Equals(asTypeName, StringComparison.InvariantCultureIgnoreCase))
@@ -128,44 +126,54 @@ The declared type of <l-expression> is Object or Variant.
128126

129127
var parameters = ((IParameterizedDeclaration) defaultMember).Parameters.ToList();
130128

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))
135130
{
136131
/*
137132
This default member’s parameter list is compatible with <argument-list>. In this case, the
138133
dictionary access expression references this default member and takes on its classification and
139134
declared type.
140135
*/
141136
ResolveArgumentList(defaultMember);
142-
return new DictionaryAccessExpression(defaultMember, defaultMemberClassification, _expression,
143-
lExpression, _argumentList);
137+
return new DictionaryAccessExpression(defaultMember, defaultMemberClassification, _expression, lExpression, _argumentList);
144138
}
145139

146140
if (parameters.Count(param => !param.IsOptional) == 0
147-
&& DEFAULT_MEMBER_RECURSION_LIMIT > _defaultMemberRecursionLimitCounter)
141+
&& DEFAULT_MEMBER_RECURSION_LIMIT > recursionDepth)
148142
{
149143
/*
150144
This default member cannot accept any parameters. In this case, the static analysis restarts
151145
recursively, as if this default member was specified instead for <l-expression> with the
152146
same <argument-list>.
153147
*/
154-
_defaultMemberRecursionLimitCounter++;
155148

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);
163150
}
164151

165152
ResolveArgumentList(null);
166153
return CreateFailedExpression(lExpression);
167154
}
168155

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+
169177
private static bool IsPropertyGetLetFunctionProcedure(Declaration declaration)
170178
{
171179
var declarationType = declaration.DeclarationType;

0 commit comments

Comments
 (0)