/** Create a new round. */ private Round( Round prev, Set<JavaFileObject> newSourceFiles, Map<String, JavaFileObject> newClassFiles) { this(prev.nextContext(), prev.number + 1, prev.nMessagerErrors, prev.compiler.log.nwarnings); this.genClassFiles = prev.genClassFiles; List<JCCompilationUnit> parsedFiles = compiler.parseFiles(newSourceFiles); roots = cleanTrees(prev.roots).appendList(parsedFiles); // Check for errors after parsing if (unrecoverableError()) return; enterClassFiles(genClassFiles); List<ClassSymbol> newClasses = enterClassFiles(newClassFiles); genClassFiles.putAll(newClassFiles); enterTrees(roots); if (unrecoverableError()) return; topLevelClasses = join(getTopLevelClasses(parsedFiles), getTopLevelClassesFromClasses(newClasses)); packageInfoFiles = join(getPackageInfoFiles(parsedFiles), getPackageInfoFilesFromClasses(newClasses)); findAnnotationsPresent(); }
// TODO: internal catch clauses?; catch and rethrow an annotation // processing error public JavaCompiler doProcessing( Context context, List<JCCompilationUnit> roots, List<ClassSymbol> classSymbols, Iterable<? extends PackageSymbol> pckSymbols) { TaskListener taskListener = context.get(TaskListener.class); log = Log.instance(context); Set<PackageSymbol> specifiedPackages = new LinkedHashSet<PackageSymbol>(); for (PackageSymbol psym : pckSymbols) specifiedPackages.add(psym); this.specifiedPackages = Collections.unmodifiableSet(specifiedPackages); Round round = new Round(context, roots, classSymbols); boolean errorStatus; boolean moreToDo; do { // Run processors for round n round.run(false, false); // Processors for round n have run to completion. // Check for errors and whether there is more work to do. errorStatus = round.unrecoverableError(); moreToDo = moreToDo(); round.showDiagnostics(errorStatus || showResolveErrors); // Set up next round. // Copy mutable collections returned from filer. round = round.next( new LinkedHashSet<JavaFileObject>(filer.getGeneratedSourceFileObjects()), new LinkedHashMap<String, JavaFileObject>(filer.getGeneratedClasses())); // Check for errors during setup. if (round.unrecoverableError()) errorStatus = true; } while (moreToDo && !errorStatus); // run last round round.run(true, errorStatus); round.showDiagnostics(true); filer.warnIfUnclosedFiles(); warnIfUnmatchedOptions(); /* * If an annotation processor raises an error in a round, * that round runs to completion and one last round occurs. * The last round may also occur because no more source or * class files have been generated. Therefore, if an error * was raised on either of the last *two* rounds, the compile * should exit with a nonzero exit code. The current value of * errorStatus holds whether or not an error was raised on the * second to last round; errorRaised() gives the error status * of the last round. */ if (messager.errorRaised() || werror && round.warningCount() > 0 && round.errorCount() > 0) errorStatus = true; Set<JavaFileObject> newSourceFiles = new LinkedHashSet<JavaFileObject>(filer.getGeneratedSourceFileObjects()); roots = cleanTrees(round.roots); JavaCompiler compiler = round.finalCompiler(errorStatus); if (newSourceFiles.size() > 0) roots = roots.appendList(compiler.parseFiles(newSourceFiles)); errorStatus = errorStatus || (compiler.errorCount() > 0); // Free resources this.close(); if (taskListener != null) taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING)); if (errorStatus) { if (compiler.errorCount() == 0) compiler.log.nerrors++; return compiler; } if (procOnly && !foundTypeProcessors) { compiler.todo.clear(); } else { if (procOnly && foundTypeProcessors) compiler.shouldStopPolicy = CompileState.FLOW; compiler.enterTrees(roots); } return compiler; }