/** * Add the initial set of compilation units into the loop -> build compilation unit declarations, * their bindings and record their results. */ protected void internalBeginToCompile(ICompilationUnit[] sourceUnits, int maxUnits) { if (!this.useSingleThread && maxUnits >= ReadManager.THRESHOLD) this.parser.readManager = new ReadManager(sourceUnits, maxUnits); // Switch the current policy and compilation result for this unit to the requested one. for (int i = 0; i < maxUnits; i++) { CompilationResult unitResult = null; try { if (this.options.verbose) { this.out.println( Messages.bind( Messages.compilation_request, new String[] { String.valueOf(i + 1), String.valueOf(maxUnits), new String(sourceUnits[i].getFileName()) })); } // diet parsing for large collection of units CompilationUnitDeclaration parsedUnit; unitResult = new CompilationResult(sourceUnits[i], i, maxUnits, this.options.maxProblemsPerUnit); long parseStart = System.currentTimeMillis(); if (this.totalUnits < this.parseThreshold) { parsedUnit = this.parser.parse(sourceUnits[i], unitResult); } else { parsedUnit = this.parser.dietParse(sourceUnits[i], unitResult); } long resolveStart = System.currentTimeMillis(); this.stats.parseTime += resolveStart - parseStart; // initial type binding creation this.lookupEnvironment.buildTypeBindings(parsedUnit, null /*no access restriction*/); this.stats.resolveTime += System.currentTimeMillis() - resolveStart; addCompilationUnit(sourceUnits[i], parsedUnit); ImportReference currentPackage = parsedUnit.currentPackage; if (currentPackage != null) { unitResult.recordPackageName(currentPackage.tokens); } // } catch (AbortCompilationUnit e) { // requestor.acceptResult(unitResult.tagAsAccepted()); } catch (AbortCompilation a) { // best effort to find a way for reporting this problem: if (a.compilationResult == null) a.compilationResult = unitResult; throw a; } finally { sourceUnits[i] = null; // no longer hold onto the unit } } if (this.parser.readManager != null) { this.parser.readManager.shutdown(); this.parser.readManager = null; } // binding resolution this.lookupEnvironment.completeTypeBindings(); }
/* * Compiler crash recovery in case of unexpected runtime exceptions */ protected void handleInternalException( Throwable internalException, CompilationUnitDeclaration unit, CompilationResult result) { if (result == null && unit != null) { result = unit.compilationResult; // current unit being processed ? } // Lookup environment may be in middle of connecting types if (result == null && this.lookupEnvironment.unitBeingCompleted != null) { result = this.lookupEnvironment.unitBeingCompleted.compilationResult; } if (result == null) { synchronized (this) { if (this.unitsToProcess != null && this.totalUnits > 0) result = this.unitsToProcess[this.totalUnits - 1].compilationResult; } } // last unit in beginToCompile ? boolean needToPrint = true; if (result != null) { /* create and record a compilation problem */ // only keep leading portion of the trace String[] pbArguments = new String[] { Messages.bind( Messages.compilation_internalError, Util.getExceptionSummary(internalException)), }; result.record( this.problemReporter.createProblem( result.getFileName(), IProblem.Unclassified, pbArguments, pbArguments, Error, // severity 0, // source start 0, // source end 0, // line number 0), // column number unit); /* hand back the compilation result */ if (!result.hasBeenAccepted) { this.requestor.acceptResult(result.tagAsAccepted()); needToPrint = false; } } if (needToPrint) { /* dump a stack trace to the console */ internalException.printStackTrace(); } }
/** * Add an additional compilation unit into the loop -> build compilation unit declarations, their * bindings and record their results. */ public void accept(ICompilationUnit sourceUnit, AccessRestriction accessRestriction) { // Switch the current policy and compilation result for this unit to the requested one. CompilationResult unitResult = new CompilationResult( sourceUnit, this.totalUnits, this.totalUnits, this.options.maxProblemsPerUnit); unitResult.checkSecondaryTypes = true; try { if (this.options.verbose) { String count = String.valueOf(this.totalUnits + 1); this.out.println( Messages.bind( Messages.compilation_request, new String[] {count, count, new String(sourceUnit.getFileName())})); } // diet parsing for large collection of unit CompilationUnitDeclaration parsedUnit; if (this.totalUnits < this.parseThreshold) { parsedUnit = this.parser.parse(sourceUnit, unitResult); } else { parsedUnit = this.parser.dietParse(sourceUnit, unitResult); } parsedUnit.bits |= ASTNode.IsImplicitUnit; // initial type binding creation this.lookupEnvironment.buildTypeBindings(parsedUnit, accessRestriction); addCompilationUnit(sourceUnit, parsedUnit); // binding resolution this.lookupEnvironment.completeTypeBindings(parsedUnit); } catch (AbortCompilationUnit e) { // at this point, currentCompilationUnitResult may not be sourceUnit, but some other // one requested further along to resolve sourceUnit. if (unitResult.compilationUnit == sourceUnit) { // only report once this.requestor.acceptResult(unitResult.tagAsAccepted()); } else { throw e; // want to abort enclosing request to compile } } }
/* * Compiler recovery in case of internal AbortCompilation event */ protected void handleInternalException( AbortCompilation abortException, CompilationUnitDeclaration unit) { /* special treatment for SilentAbort: silently cancelling the compilation process */ if (abortException.isSilent) { if (abortException.silentException == null) { return; } throw abortException.silentException; } /* uncomment following line to see where the abort came from */ // abortException.printStackTrace(); // Exception may tell which compilation result it is related, and which problem caused it CompilationResult result = abortException.compilationResult; if (result == null && unit != null) { result = unit.compilationResult; // current unit being processed ? } // Lookup environment may be in middle of connecting types if (result == null && this.lookupEnvironment.unitBeingCompleted != null) { result = this.lookupEnvironment.unitBeingCompleted.compilationResult; } if (result == null) { synchronized (this) { if (this.unitsToProcess != null && this.totalUnits > 0) result = this.unitsToProcess[this.totalUnits - 1].compilationResult; } } // last unit in beginToCompile ? if (result != null && !result.hasBeenAccepted) { /* distant problem which could not be reported back there? */ if (abortException.problem != null) { recordDistantProblem: { CategorizedProblem distantProblem = abortException.problem; CategorizedProblem[] knownProblems = result.problems; for (int i = 0; i < result.problemCount; i++) { if (knownProblems[i] == distantProblem) { // already recorded break recordDistantProblem; } } if (distantProblem instanceof DefaultProblem) { // fixup filename TODO (philippe) should improve API to make this // official ((DefaultProblem) distantProblem).setOriginatingFileName(result.getFileName()); } result.record(distantProblem, unit); } } else { /* distant internal exception which could not be reported back there */ if (abortException.exception != null) { this.handleInternalException(abortException.exception, null, result); return; } } /* hand back the compilation result */ if (!result.hasBeenAccepted) { this.requestor.acceptResult(result.tagAsAccepted()); } } else { abortException.printStackTrace(); } }
/** * 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); } }