Skip to content

Commit 4954ef1

Browse files
committed
Optimize and simplify resolution of ForNext and ForEach loops
1 parent 7830a3d commit 4954ef1

File tree

1 file changed

+33
-69
lines changed

1 file changed

+33
-69
lines changed

Rubberduck.Parsing/VBA/ReferenceManagement/IdentifierReferenceResolver.cs

Lines changed: 33 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -614,97 +614,61 @@ public void Resolve(VBAParser.AsTypeClauseContext context)
614614

615615
public void Resolve(VBAParser.ForNextStmtContext context)
616616
{
617+
var expressions = context.expression();
618+
617619
// In "For expr1 = expr2" the "expr1 = expr2" part is treated as a single expression.
618-
var assignmentExpr = ((VBAParser.RelationalOpContext)context.expression()[0]);
619-
var lExpr = assignmentExpr.expression()[0];
620-
var withExpression = GetInnerMostWithExpression();
621-
var firstExpression = _bindingService.ResolveDefault(
622-
_moduleDeclaration,
623-
_currentParent,
624-
lExpr,
625-
withExpression,
626-
StatementResolutionContext.Undefined,
627-
true);
628-
if (firstExpression.Classification != ExpressionClassification.ResolutionFailed)
629-
{
630-
// each iteration counts as an assignment
620+
var assignmentExpr = ((VBAParser.RelationalOpContext)expressions[0]);
621+
ResolveStartValueAssignmentOfForNext(assignmentExpr);
631622

632-
_failedResolutionVisitor.CollectUnresolved(firstExpression, _currentParent, withExpression);
633-
_boundExpressionVisitor.AddIdentifierReferences(
634-
firstExpression,
635-
_qualifiedModuleName,
636-
_currentScope,
637-
_currentParent,
638-
true);
639-
}
640-
var rExpr = assignmentExpr.expression()[1];
641-
var secondExpression = _bindingService.ResolveDefault(
642-
_moduleDeclaration,
643-
_currentParent,
644-
rExpr,
645-
withExpression,
646-
StatementResolutionContext.Undefined,
647-
true);
648-
_failedResolutionVisitor.CollectUnresolved(secondExpression, _currentParent, withExpression);
649-
_boundExpressionVisitor.AddIdentifierReferences(
650-
secondExpression,
651-
_qualifiedModuleName,
652-
_currentScope,
653-
_currentParent);
654-
655-
ResolveDefault(context.expression()[1], true);
623+
ResolveToValueOfForNext(expressions[1]);
656624

657625
var stepStatement = context.stepStmt();
658626
if (stepStatement != null)
659627
{
660628
Resolve(stepStatement);
661629
}
662630

663-
for (var exprIndex = 2; exprIndex < context.expression().Length; exprIndex++)
631+
const int firstNextExpressionIndex = 2;
632+
for (var exprIndex = firstNextExpressionIndex; exprIndex < expressions.Length; exprIndex++)
664633
{
665-
ResolveDefault(context.expression()[exprIndex], false);
634+
ResolveDefault(expressions[exprIndex]);
666635
}
667636
}
668637

638+
private void ResolveStartValueAssignmentOfForNext(VBAParser.RelationalOpContext expression)
639+
{
640+
var expressions = expression.expression();
641+
var elementVariableExpression = expressions[0];
642+
ResolveDefault(elementVariableExpression, requiresLetCoercion: true, isAssignmentTarget: true);
643+
644+
var startValueExpression = expressions[1];
645+
ResolveDefault(startValueExpression, requiresLetCoercion: true);
646+
}
647+
648+
private void ResolveToValueOfForNext(ParserRuleContext expression)
649+
{
650+
ResolveDefault(expression, requiresLetCoercion: true);
651+
}
652+
669653
private void Resolve(VBAParser.StepStmtContext context)
670654
{
671655
ResolveDefault(context.expression(), true);
672656
}
673657

674658
public void Resolve(VBAParser.ForEachStmtContext context)
675659
{
676-
var withExpression = GetInnerMostWithExpression();
677-
var firstExpression = _bindingService.ResolveDefault(
678-
_moduleDeclaration,
679-
_currentParent,
680-
context.expression()[0],
681-
withExpression,
682-
StatementResolutionContext.Undefined,
683-
false);
684-
if (firstExpression.Classification == ExpressionClassification.ResolutionFailed)
685-
{
660+
var expressions = context.expression();
686661

687-
_failedResolutionVisitor.CollectUnresolved(firstExpression, _currentParent, withExpression);
688-
_boundExpressionVisitor.AddIdentifierReferences(
689-
firstExpression,
690-
_qualifiedModuleName,
691-
_currentScope,
692-
_currentParent);
693-
}
694-
else
695-
{
696-
// each iteration counts as an assignment
697-
_failedResolutionVisitor.CollectUnresolved(firstExpression, _currentParent, withExpression);
698-
_boundExpressionVisitor.AddIdentifierReferences(
699-
firstExpression,
700-
_qualifiedModuleName,
701-
_currentScope,
702-
_currentParent,
703-
true);
704-
}
705-
for (var exprIndex = 1; exprIndex < context.expression().Length; exprIndex++)
662+
var elementVariableExpression = expressions[0];
663+
ResolveDefault(elementVariableExpression, isAssignmentTarget: true);
664+
665+
var collectionExpression = expressions[1];
666+
ResolveDefault(collectionExpression);
667+
668+
const int firstNextExpressionIndex = 2;
669+
for (var exprIndex = firstNextExpressionIndex; exprIndex < context.expression().Length; exprIndex++)
706670
{
707-
ResolveDefault(context.expression()[exprIndex], false);
671+
ResolveDefault(expressions[exprIndex]);
708672
}
709673
}
710674

0 commit comments

Comments
 (0)