public void Resolve(VBAParser.ResumeStmtContext context) { if (context.expression() == null) { return; } ResolveLabel(context.expression(), context.expression().GetText()); }
private static int?DetermineResumeStmtExecutionBranchLine(VBAParser.ResumeStmtContext resumeStmt, IdentifierReference resultCandidate, Dictionary <string, int> labelIdLineNumberPairs) { var onErrorGotoLabelToLineNumber = resultCandidate.ParentScoping.Context.GetDescendents <VBAParser.OnErrorStmtContext>() .Where(errorStmtCtxt => IsBranchingOnErrorGoToLabel(errorStmtCtxt)) .ToDictionary(k => k.expression()?.GetText() ?? "No Label", v => v.Start.Line); var errorHandlerLabelsAndLines = labelIdLineNumberPairs .Where(pair => onErrorGotoLabelToLineNumber.ContainsKey(pair.Key)); //Labels must be located at the start of a line. //If the resultCandidate line precedes all error handling related labels, //a Resume statement cannot be invoked (successfully) for the resultCandidate if (!errorHandlerLabelsAndLines.Any(kvp => kvp.Value <= resultCandidate.Context.Start.Line)) { return(null); } var resumeStmtExpression = resumeStmt.expression()?.GetText(); //For Resume and Resume Next, expression() is null if (string.IsNullOrEmpty(resumeStmtExpression)) { var errorHandlerLabelForTheResumeStatement = errorHandlerLabelsAndLines .Where(kvp => resumeStmt.Start.Line >= kvp.Value) .OrderBy(kvp => resumeStmt.Start.Line - kvp.Value) .Select(kvp => kvp.Key) .FirstOrDefault(); //Since the execution branch line for Resume and Resume Next statements //is indeterminant by static analysis, the On***GoTo statement //is used as the execution branch line return(onErrorGotoLabelToLineNumber[errorHandlerLabelForTheResumeStatement]); } //Resume <label> return(labelIdLineNumberPairs[resumeStmtExpression]); }