Skip to content

Commit 38d0361

Browse files
committed
Merge pull request #687 from rubberduck-vba/GrammarIsFun
resolver fix
2 parents e75e9b0 + 4c1a6e3 commit 38d0361

File tree

1 file changed

+46
-24
lines changed

1 file changed

+46
-24
lines changed

Rubberduck.Parsing/Symbols/IdentifierReferenceResolver.cs

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ private enum ContextAccessorType
2121

2222
private readonly IReadOnlyList<DeclarationType> _moduleTypes;
2323
private readonly IReadOnlyList<DeclarationType> _memberTypes;
24+
private readonly IReadOnlyList<DeclarationType> _returningMemberTypes;
25+
26+
private readonly IReadOnlyList<Accessibility> _projectScopePublicModifiers;
2427

2528
private readonly Stack<Declaration> _withBlockQualifiers;
2629
private readonly HashSet<RuleContext> _alreadyResolved;
@@ -37,7 +40,7 @@ public IdentifierReferenceResolver(QualifiedModuleName qualifiedModuleName, Decl
3740
{
3841
DeclarationType.Module,
3942
DeclarationType.Class,
40-
DeclarationType.Project
43+
DeclarationType.Project,
4144
});
4245

4346
_memberTypes = new List<DeclarationType>(new[]
@@ -46,7 +49,21 @@ public IdentifierReferenceResolver(QualifiedModuleName qualifiedModuleName, Decl
4649
DeclarationType.Procedure,
4750
DeclarationType.PropertyGet,
4851
DeclarationType.PropertyLet,
49-
DeclarationType.PropertySet
52+
DeclarationType.PropertySet,
53+
});
54+
55+
_returningMemberTypes = new List<DeclarationType>(new[]
56+
{
57+
DeclarationType.Function,
58+
DeclarationType.PropertyGet,
59+
});
60+
61+
_projectScopePublicModifiers = new List<Accessibility>(new[]
62+
{
63+
Accessibility.Public,
64+
Accessibility.Global,
65+
Accessibility.Friend,
66+
Accessibility.Implicit,
5067
});
5168

5269
SetCurrentScope();
@@ -161,10 +178,7 @@ private Declaration ResolveType(VBAParser.ComplexTypeContext context)
161178
{
162179
return matches.SingleOrDefault(item =>
163180
item.ProjectName == libraryName
164-
&& (item.Accessibility == Accessibility.Public
165-
|| item.Accessibility == Accessibility.Global
166-
|| item.Accessibility == Accessibility.Friend
167-
|| item.Accessibility == Accessibility.Implicit)
181+
&& _projectScopePublicModifiers.Contains(item.Accessibility)
168182
&& (_moduleTypes.Contains(item.DeclarationType))
169183
|| (item.DeclarationType == DeclarationType.UserDefinedType
170184
&& item.ComponentName == _currentScope.ComponentName));
@@ -229,6 +243,7 @@ private Declaration ResolveInternal(ParserRuleContext callSiteContext, Declarati
229243
localScope = _currentScope;
230244
}
231245

246+
var parentContext = callSiteContext.Parent;
232247
var identifierName = callSiteContext.GetText();
233248
Declaration callee = null;
234249
if (localScope.DeclarationType == DeclarationType.Variable)
@@ -242,18 +257,18 @@ private Declaration ResolveInternal(ParserRuleContext callSiteContext, Declarati
242257
}
243258
else
244259
{
245-
callee = FindLocalScopeDeclaration(identifierName, localScope)
246-
?? FindModuleScopeProcedure(identifierName, localScope, accessorType, isAssignmentTarget)
247-
?? FindModuleScopeDeclaration(identifierName, localScope)
248-
?? FindProjectScopeDeclaration(identifierName);
260+
callee = FindLocalScopeDeclaration(identifierName, localScope, parentContext, isAssignmentTarget)
261+
?? FindModuleScopeProcedure(identifierName, localScope, accessorType, isAssignmentTarget)
262+
?? FindModuleScopeDeclaration(identifierName, localScope)
263+
?? FindProjectScopeDeclaration(identifierName);
249264
}
250265

251266
if (callee == null)
252267
{
253268
// calls inside With block can still refer to identifiers in _currentScope
254269
localScope = _currentScope;
255270
identifierName = callSiteContext.GetText();
256-
callee = FindLocalScopeDeclaration(identifierName, localScope)
271+
callee = FindLocalScopeDeclaration(identifierName, localScope, parentContext, isAssignmentTarget)
257272
?? FindModuleScopeProcedure(identifierName, localScope, accessorType, isAssignmentTarget)
258273
?? FindModuleScopeDeclaration(identifierName, localScope)
259274
?? FindProjectScopeDeclaration(identifierName);
@@ -692,14 +707,12 @@ private Declaration FindFunctionOrPropertyGetter(string identifierName, Declarat
692707

693708
var matches = _declarations[identifierName];
694709
var parent = matches.SingleOrDefault(item =>
695-
item.Scope == localScope.Scope
696-
&& (item.DeclarationType == DeclarationType.Function
697-
|| item.DeclarationType == DeclarationType.PropertyGet));
710+
item.Scope == localScope.Scope);
698711

699712
return parent;
700713
}
701714

702-
private Declaration FindLocalScopeDeclaration(string identifierName, Declaration localScope = null)
715+
private Declaration FindLocalScopeDeclaration(string identifierName, Declaration localScope = null, RuleContext parentContext = null, bool isAssignmentTarget= false)
703716
{
704717
if (localScope == null)
705718
{
@@ -712,21 +725,30 @@ private Declaration FindLocalScopeDeclaration(string identifierName, Declaration
712725
return null;
713726
}
714727

715-
if (localScope.IdentifierName == identifierName
716-
&& (localScope.DeclarationType == DeclarationType.Function
717-
|| localScope.DeclarationType == DeclarationType.PropertyGet))
718-
{
719-
return FindFunctionOrPropertyGetter(identifierName, localScope);
720-
}
721-
722728
var matches = _declarations[identifierName];
723729

724730
try
725731
{
726-
return matches.SingleOrDefault(item =>
732+
var results = matches.Where(item =>
727733
item.ParentScope == localScope.Scope
728734
&& localScope.Context.GetSelection().Contains(item.Selection)
729-
&& !_moduleTypes.Contains(item.DeclarationType));
735+
&& !_moduleTypes.Contains(item.DeclarationType))
736+
.ToList();
737+
738+
if (results.Count > 1 && isAssignmentTarget
739+
&& _returningMemberTypes.Contains(localScope.DeclarationType)
740+
&& localScope.IdentifierName == identifierName
741+
&& parentContext is VBAParser.ICS_S_VariableOrProcedureCallContext)
742+
{
743+
// if we have multiple matches and we're in a returning member,
744+
// in an in-statement variable or procedure call context that's
745+
// the target of an assignment, then we have to assume we're looking
746+
// at the assignment of the member's return value:
747+
return FindFunctionOrPropertyGetter(identifierName, localScope);
748+
}
749+
750+
// if we're not returning a function/getter value, then there can be only one:
751+
return results.SingleOrDefault();
730752
}
731753
catch (InvalidOperationException)
732754
{

0 commit comments

Comments
 (0)