protected CompilationUnitDeclaration endParse(int act) { if (this.hasRecoveredOnExpression) { CompilationResult unitResult = this.compilationUnit.compilationResult; if (act != ERROR_ACTION) { // expression recovery worked // flush previously recorded problems for (int i = 0; i < unitResult.problemCount; i++) { unitResult.problems[i] = null; // discard problem } unitResult.problemCount = 0; if (this.referenceContext instanceof AbstractMethodDeclaration) { ((AbstractMethodDeclaration) this.referenceContext).ignoreFurtherInvestigation = false; } if (this.referenceContext instanceof CompilationUnitDeclaration) { ((CompilationUnitDeclaration) this.referenceContext).ignoreFurtherInvestigation = false; } // consume expresion as a return statement consumeStatementReturn(); int fieldsCount = (this.evaluationContext.localVariableNames == null ? 0 : this.evaluationContext.localVariableNames.length) + (this.evaluationContext.declaringTypeName == null ? 0 : 1); if (this.astPtr > (this.diet ? 0 : 2 + fieldsCount)) { // in diet mode, the ast stack was empty when we went for method body // otherwise it contained the type, the generated fields for local variables, // the generated field for 'this' and the method consumeBlockStatements(); } consumeMethodBody(); if (!this.diet) { consumeMethodDeclaration(true); if (fieldsCount > 0) { consumeClassBodyDeclarations(); } consumeClassBodyDeclarationsopt(); consumeClassDeclaration(); consumeInternalCompilationUnitWithTypes(); consumeCompilationUnit(); } this.lastAct = ACCEPT_ACTION; } else { // might have more than one error recorded: // 1. during regular parse // 2. during expression recovery // -> must filter out one of them, the earliest one is less accurate int maxRegularPos = 0, problemCount = unitResult.problemCount; for (int i = 0; i < this.problemCountBeforeRecovery; i++) { // skip unmatched bracket problems if (unitResult.problems[i].getID() == IProblem.UnmatchedBracket) continue; int start = unitResult.problems[i].getSourceStart(); if (start > maxRegularPos && start <= this.codeSnippetEnd) { maxRegularPos = start; } } int maxRecoveryPos = 0; for (int i = this.problemCountBeforeRecovery; i < problemCount; i++) { // skip unmatched bracket problems if (unitResult.problems[i].getID() == IProblem.UnmatchedBracket) continue; int start = unitResult.problems[i].getSourceStart(); if (start > maxRecoveryPos && start <= this.codeSnippetEnd) { maxRecoveryPos = start; } } if (maxRecoveryPos > maxRegularPos) { System.arraycopy( unitResult.problems, this.problemCountBeforeRecovery, unitResult.problems, 0, problemCount - this.problemCountBeforeRecovery); unitResult.problemCount -= this.problemCountBeforeRecovery; } else { unitResult.problemCount -= (problemCount - this.problemCountBeforeRecovery); } for (int i = unitResult.problemCount; i < problemCount; i++) { unitResult.problems[i] = null; // discard problem } } } return super.endParse(act); }
/** * Bytecode generation for a method * * @param classScope * @param classFile */ public void generateCode(ClassScope classScope, ClassFile classFile) { classFile.codeStream.wideMode = false; // reset wideMode to false if (this.ignoreFurtherInvestigation) { // method is known to have errors, dump a problem method if (this.binding == null) return; // handle methods with invalid signature or duplicates int problemsLength; CategorizedProblem[] problems = this.scope.referenceCompilationUnit().compilationResult.getProblems(); CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length]; System.arraycopy(problems, 0, problemsCopy, 0, problemsLength); classFile.addProblemMethod(this, this.binding, problemsCopy); return; } int problemResetPC = 0; CompilationResult unitResult = null; int problemCount = 0; if (classScope != null) { TypeDeclaration referenceContext = classScope.referenceContext; if (referenceContext != null) { unitResult = referenceContext.compilationResult(); problemCount = unitResult.problemCount; } } boolean restart = false; boolean abort = false; // regular code generation do { try { problemResetPC = classFile.contentsOffset; this.generateCode(classFile); restart = false; } catch (AbortMethod e) { // a fatal error was detected during code generation, need to restart code gen if possible if (e.compilationResult == CodeStream.RESTART_IN_WIDE_MODE) { // a branch target required a goto_w, restart code gen in wide mode. classFile.contentsOffset = problemResetPC; classFile.methodCount--; classFile.codeStream.resetInWideMode(); // request wide mode // reset the problem count to prevent reporting the same warning twice if (unitResult != null) { unitResult.problemCount = problemCount; } restart = true; } else if (e.compilationResult == CodeStream.RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE) { classFile.contentsOffset = problemResetPC; classFile.methodCount--; classFile.codeStream.resetForCodeGenUnusedLocals(); // reset the problem count to prevent reporting the same warning twice if (unitResult != null) { unitResult.problemCount = problemCount; } restart = true; } else { restart = false; abort = true; } } } while (restart); // produce a problem method accounting for this fatal error if (abort) { int problemsLength; CategorizedProblem[] problems = this.scope.referenceCompilationUnit().compilationResult.getAllProblems(); CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length]; System.arraycopy(problems, 0, problemsCopy, 0, problemsLength); classFile.addProblemMethod(this, this.binding, problemsCopy, problemResetPC); } }