# HG changeset patch # User jjg # Date 1280457035 25200 # Node ID 2cf925ad67ab22a30907df609288ce24b352fa7d # Parent 8a5c98a695aeb2e06020bdf0a46f5f107bf78b87 6966604: JavacFiler not correctly notified of lastRound Reviewed-by: darcy diff -r 8a5c98a695ae -r 2cf925ad67ab src/share/classes/com/sun/tools/javac/processing/JavacFiler.java --- a/src/share/classes/com/sun/tools/javac/processing/JavacFiler.java Thu Jul 29 19:27:11 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/processing/JavacFiler.java Thu Jul 29 19:30:35 2010 -0700 @@ -539,11 +539,14 @@ /** * Update internal state for a new round. */ - public void newRound(Context context, boolean lastRound) { + public void newRound(Context context) { this.context = context; this.log = Log.instance(context); + clearRoundState(); + } + + void setLastRound(boolean lastRound) { this.lastRound = lastRound; - clearRoundState(); } public void close() { diff -r 8a5c98a695ae -r 2cf925ad67ab src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java --- a/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Thu Jul 29 19:27:11 2010 -0700 +++ b/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Thu Jul 29 19:30:35 2010 -0700 @@ -68,7 +68,6 @@ import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.Convert; import com.sun.tools.javac.util.List; -import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Log; import com.sun.tools.javac.util.JavacMessages; import com.sun.tools.javac.util.Name; @@ -759,7 +758,7 @@ } @Override - public Set scan(Element e, Set p) { + public Set scan(Element e, Set p) { for (AnnotationMirror annotationMirror : elements.getAllAnnotationMirrors(e) ) { Element e2 = annotationMirror.getAnnotationType().asElement(); @@ -784,6 +783,237 @@ } } + /** + * Helper object for a single round of annotation processing. + */ + class Round { + /** The round number. */ + final int number; + /** The context for the round. */ + final Context context; + /** The compiler for the round. */ + final JavaCompiler compiler; + /** The log for the round. */ + final Log log; + + /** The set of annotations to be processed this round. */ + Set annotationsPresent; + /** The set of top level classes to be processed this round. */ + List topLevelClasses; + /** The set of package-info files to be processed this round. */ + List packageInfoFiles; + + /** Create a round. */ + Round(Context context, int number) { + this.context = context; + this.number = number; + compiler = JavaCompiler.instance(context); + log = Log.instance(context); + + // the following is for the benefit of JavacProcessingEnvironment.getContext() + JavacProcessingEnvironment.this.context = context; + + // the following will be populated as needed + annotationsPresent = new LinkedHashSet(); + topLevelClasses = List.nil(); + packageInfoFiles = List.nil(); + } + + /** Create the next round to be used. */ + Round next() { + compiler.close(false); + return new Round(contextForNextRound(), number + 1); + } + + /** Return the number of errors found so far in this round. + * This may include uncoverable errors, such as parse errors, + * and transient errors, such as missing symbols. */ + int errorCount() { + return compiler.errorCount(); + } + + /** Return the number of warnings found so far in this round. */ + int warningCount() { + return compiler.warningCount(); + } + + /** Return whether or not an unrecoverable error has occurred. */ + boolean unrecoverableError() { + return log.unrecoverableError; + } + + /** Find the set of annotations present in the set of top level + * classes and package info files to be processed this round. */ + void findAnnotationsPresent(ComputeAnnotationSet annotationComputer) { + // Use annotation processing to compute the set of annotations present + annotationsPresent = new LinkedHashSet(); + for (ClassSymbol classSym : topLevelClasses) + annotationComputer.scan(classSym, annotationsPresent); + for (PackageSymbol pkgSym : packageInfoFiles) + annotationComputer.scan(pkgSym, annotationsPresent); + } + + /** + * Parse the latest set of generated source files created by the filer. + */ + List parseNewSourceFiles() + throws IOException { + List fileObjects = List.nil(); + for (JavaFileObject jfo : filer.getGeneratedSourceFileObjects() ) { + fileObjects = fileObjects.prepend(jfo); + } + + return compiler.parseFiles(fileObjects); + } + + /** Enter the latest set of generated class files created by the filer. */ + List enterNewClassFiles() { + ClassReader reader = ClassReader.instance(context); + Names names = Names.instance(context); + List list = List.nil(); + + for (Map.Entry entry : filer.getGeneratedClasses().entrySet()) { + Name name = names.fromString(entry.getKey()); + JavaFileObject file = entry.getValue(); + if (file.getKind() != JavaFileObject.Kind.CLASS) + throw new AssertionError(file); + ClassSymbol cs; + if (isPkgInfo(file, JavaFileObject.Kind.CLASS)) { + Name packageName = Convert.packagePart(name); + PackageSymbol p = reader.enterPackage(packageName); + if (p.package_info == null) + p.package_info = reader.enterClass(Convert.shortName(name), p); + cs = p.package_info; + if (cs.classfile == null) + cs.classfile = file; + } else + cs = reader.enterClass(name, file); + list = list.prepend(cs); + } + return list.reverse(); + } + + /** Enter a set of syntax trees. */ + void enterTrees(List roots) { + compiler.enterTrees(roots); + } + + /** Run a processing round. */ + void run(boolean lastRound, boolean errorStatus) { + assert lastRound + ? (topLevelClasses.size() == 0 && annotationsPresent.size() == 0) + : (errorStatus == false); + + printRoundInfo(topLevelClasses, annotationsPresent, lastRound); + + TaskListener taskListener = context.get(TaskListener.class); + if (taskListener != null) + taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND)); + + try { + if (lastRound) { + filer.setLastRound(true); + Set emptyRootElements = Collections.emptySet(); // immutable + RoundEnvironment renv = new JavacRoundEnvironment(true, + errorStatus, + emptyRootElements, + JavacProcessingEnvironment.this); + discoveredProcs.iterator().runContributingProcs(renv); + } else { + discoverAndRunProcs(context, annotationsPresent, topLevelClasses, packageInfoFiles); + } + } finally { + if (taskListener != null) + taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND)); + } + } + + /** Update the processing state for the current context. */ + // Question: should this not be part of next()? + // Note: Calling it from next() breaks some tests. There is an issue + // whether the annotationComputer is using elementUtils with the + // correct context. + void updateProcessingState() { + filer.newRound(context); + messager.newRound(context); + + elementUtils.setContext(context); + typeUtils.setContext(context); + } + + /** Print info about this round. */ + private void printRoundInfo(List topLevelClasses, + Set annotationsPresent, + boolean lastRound) { + if (printRounds || verbose) { + log.printNoteLines("x.print.rounds", + number, + "{" + topLevelClasses.toString(", ") + "}", + annotationsPresent, + lastRound); + } + } + + /** Get the context for the next round of processing. + * Important values are propogated from round to round; + * other values are implicitly reset. + */ + private Context contextForNextRound() { + Context next = new Context(); + + Options options = Options.instance(context); + assert options != null; + next.put(Options.optionsKey, options); + + PrintWriter out = context.get(Log.outKey); + assert out != null; + next.put(Log.outKey, out); + + final boolean shareNames = true; + if (shareNames) { + Names names = Names.instance(context); + assert names != null; + next.put(Names.namesKey, names); + } + + DiagnosticListener dl = context.get(DiagnosticListener.class); + if (dl != null) + next.put(DiagnosticListener.class, dl); + + TaskListener tl = context.get(TaskListener.class); + if (tl != null) + next.put(TaskListener.class, tl); + + JavaFileManager jfm = context.get(JavaFileManager.class); + assert jfm != null; + next.put(JavaFileManager.class, jfm); + if (jfm instanceof JavacFileManager) { + ((JavacFileManager)jfm).setContext(next); + } + + Names names = Names.instance(context); + assert names != null; + next.put(Names.namesKey, names); + + Keywords keywords = Keywords.instance(context); + assert(keywords != null); + next.put(Keywords.keywordsKey, keywords); + + JavaCompiler oldCompiler = JavaCompiler.instance(context); + JavaCompiler nextCompiler = JavaCompiler.instance(next); + nextCompiler.initRound(oldCompiler); + + JavacTaskImpl task = context.get(JavacTaskImpl.class); + if (task != null) { + next.put(JavacTaskImpl.class, task); + task.updateContext(next); + } + + context.clear(); + return next; + } + } + // TODO: internal catch clauses?; catch and rethrow an annotation // processing error @@ -794,60 +1024,37 @@ throws IOException { log = Log.instance(context); - TaskListener taskListener = context.get(TaskListener.class); - JavaCompiler compiler = JavaCompiler.instance(context); - compiler.todo.clear(); // free the compiler's resources + Round round = new Round(context, 1); + round.compiler.todo.clear(); // free the compiler's resources - int round = 0; + // The reverse() in the following line is to maintain behavioural + // compatibility with the previous revision of the code. Strictly speaking, + // it should not be necessary, but a javah golden file test fails without it. + round.topLevelClasses = + getTopLevelClasses(roots).prependList(classSymbols.reverse()); - // List annotationsPresentInSource = collector.findAnnotations(roots); - List topLevelClasses = getTopLevelClasses(roots); - - for (ClassSymbol classSym : classSymbols) - topLevelClasses = topLevelClasses.prepend(classSym); - List packageInfoFiles = - getPackageInfoFiles(roots); + round.packageInfoFiles = getPackageInfoFiles(roots); Set specifiedPackages = new LinkedHashSet(); for (PackageSymbol psym : pckSymbols) specifiedPackages.add(psym); this.specifiedPackages = Collections.unmodifiableSet(specifiedPackages); - // Use annotation processing to compute the set of annotations present - Set annotationsPresent = new LinkedHashSet(); ComputeAnnotationSet annotationComputer = new ComputeAnnotationSet(elementUtils); - for (ClassSymbol classSym : topLevelClasses) - annotationComputer.scan(classSym, annotationsPresent); - for (PackageSymbol pkgSym : packageInfoFiles) - annotationComputer.scan(pkgSym, annotationsPresent); + round.findAnnotationsPresent(annotationComputer); - Context currentContext = context; - - int roundNumber = 0; boolean errorStatus = false; runAround: - while(true) { - if ((fatalErrors && compiler.errorCount() != 0) - || (werror && compiler.warningCount() != 0)) { + while (true) { + if ((fatalErrors && round.errorCount() != 0) + || (werror && round.warningCount() != 0)) { errorStatus = true; break runAround; } - this.context = currentContext; - roundNumber++; - printRoundInfo(roundNumber, topLevelClasses, annotationsPresent, false); - - if (taskListener != null) - taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND)); - - try { - discoverAndRunProcs(currentContext, annotationsPresent, topLevelClasses, packageInfoFiles); - } finally { - if (taskListener != null) - taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND)); - } + round.run(false, false); /* * Processors for round n have run to completion. Prepare @@ -858,65 +1065,54 @@ if (messager.errorRaised()) { errorStatus = true; break runAround; - } else { - if (moreToDo()) { - // annotationsPresentInSource = List.nil(); - annotationsPresent = new LinkedHashSet(); - topLevelClasses = List.nil(); - packageInfoFiles = List.nil(); + } - compiler.close(false); - currentContext = contextForNextRound(currentContext, true); + if (!moreToDo()) + break runAround; // No new files - JavaFileManager fileManager = currentContext.get(JavaFileManager.class); + round = round.next(); - compiler = JavaCompiler.instance(currentContext); - List parsedFiles = sourcesToParsedFiles(compiler); - roots = cleanTrees(roots).appendList(parsedFiles); + List parsedFiles = round.parseNewSourceFiles(); + roots = cleanTrees(roots).appendList(parsedFiles); - // Check for errors after parsing - if (log.unrecoverableError) { - errorStatus = true; - break runAround; - } else { - List newClasses = enterNewClassFiles(currentContext); - compiler.enterTrees(roots); + // Check for errors after parsing + if (round.unrecoverableError()) { + errorStatus = true; + break runAround; + } - // annotationsPresentInSource = - // collector.findAnnotations(parsedFiles); - ListBuffer tlc = new ListBuffer(); - tlc.appendList(getTopLevelClasses(parsedFiles)); - tlc.appendList(getTopLevelClassesFromClasses(newClasses)); - topLevelClasses = tlc.toList(); + List newClasses = round.enterNewClassFiles(); + round.enterTrees(roots); - ListBuffer pif = new ListBuffer(); - pif.appendList(getPackageInfoFiles(parsedFiles)); - pif.appendList(getPackageInfoFilesFromClasses(newClasses)); - packageInfoFiles = pif.toList(); + round.topLevelClasses = join( + getTopLevelClasses(parsedFiles), + getTopLevelClassesFromClasses(newClasses)); - annotationsPresent = new LinkedHashSet(); - for (ClassSymbol classSym : topLevelClasses) - annotationComputer.scan(classSym, annotationsPresent); - for (PackageSymbol pkgSym : packageInfoFiles) - annotationComputer.scan(pkgSym, annotationsPresent); + round.packageInfoFiles = join( + getPackageInfoFiles(parsedFiles), + getPackageInfoFilesFromClasses(newClasses)); - updateProcessingState(currentContext, false); - } - } else - break runAround; // No new files - } + round.findAnnotationsPresent(annotationComputer); + round.updateProcessingState(); } - roots = runLastRound(roundNumber, errorStatus, compiler, roots, taskListener); + + // run last round + round.run(true, errorStatus); + + // Add any sources generated during the last round to the set + // of files to be compiled. + if (moreToDo()) { + List parsedFiles = round.parseNewSourceFiles(); + roots = cleanTrees(roots).appendList(parsedFiles); + } + // Set error status for any files compiled and generated in // the last round - if (log.unrecoverableError || (werror && compiler.warningCount() != 0)) + if (round.unrecoverableError() || (werror && round.warningCount() != 0)) errorStatus = true; - compiler.close(false); - currentContext = contextForNextRound(currentContext, true); - compiler = JavaCompiler.instance(currentContext); + round = round.next(); - filer.newRound(currentContext, true); filer.warnIfUnclosedFiles(); warnIfUnmatchedOptions(); @@ -933,142 +1129,43 @@ */ errorStatus = errorStatus || messager.errorRaised(); - // Free resources this.close(); + TaskListener taskListener = this.context.get(TaskListener.class); if (taskListener != null) taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING)); + JavaCompiler compiler; + if (errorStatus) { + compiler = round.compiler; compiler.log.nwarnings += messager.warningCount(); compiler.log.nerrors += messager.errorCount(); if (compiler.errorCount() == 0) compiler.log.nerrors++; } else if (procOnly && !foundTypeProcessors) { + compiler = round.compiler; compiler.todo.clear(); } else { // Final compilation - compiler.close(false); - currentContext = contextForNextRound(currentContext, true); - this.context = currentContext; - updateProcessingState(currentContext, true); - compiler = JavaCompiler.instance(currentContext); + round = round.next(); + round.updateProcessingState(); + compiler = round.compiler; if (procOnly && foundTypeProcessors) compiler.shouldStopPolicy = CompileState.FLOW; - if (true) { - compiler.enterTrees(cleanTrees(roots)); - } else { - List fileObjects = List.nil(); - for (JCCompilationUnit unit : roots) - fileObjects = fileObjects.prepend(unit.getSourceFile()); - roots = null; - compiler.enterTrees(compiler.parseFiles(fileObjects.reverse())); - } + compiler.enterTrees(cleanTrees(roots)); } return compiler; } - private List sourcesToParsedFiles(JavaCompiler compiler) - throws IOException { - List fileObjects = List.nil(); - for (JavaFileObject jfo : filer.getGeneratedSourceFileObjects() ) { - fileObjects = fileObjects.prepend(jfo); - } - - return compiler.parseFiles(fileObjects); - } - - // Call the last round of annotation processing - private List runLastRound(int roundNumber, - boolean errorStatus, - JavaCompiler compiler, - List roots, - TaskListener taskListener) throws IOException { - roundNumber++; - List noTopLevelClasses = List.nil(); - Set noAnnotations = Collections.emptySet(); - printRoundInfo(roundNumber, noTopLevelClasses, noAnnotations, true); - - Set emptyRootElements = Collections.emptySet(); // immutable - RoundEnvironment renv = new JavacRoundEnvironment(true, - errorStatus, - emptyRootElements, - JavacProcessingEnvironment.this); - if (taskListener != null) - taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND)); - - try { - discoveredProcs.iterator().runContributingProcs(renv); - } finally { - if (taskListener != null) - taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND)); - } - - // Add any sources generated during the last round to the set - // of files to be compiled. - if (moreToDo()) { - List parsedFiles = sourcesToParsedFiles(compiler); - roots = cleanTrees(roots).appendList(parsedFiles); - } - - return roots; - } - - private void updateProcessingState(Context currentContext, boolean lastRound) { - filer.newRound(currentContext, lastRound); - messager.newRound(currentContext); - - elementUtils.setContext(currentContext); - typeUtils.setContext(currentContext); - } - private void warnIfUnmatchedOptions() { if (!unmatchedProcessorOptions.isEmpty()) { log.warning("proc.unmatched.processor.options", unmatchedProcessorOptions.toString()); } } - private void printRoundInfo(int roundNumber, - List topLevelClasses, - Set annotationsPresent, - boolean lastRound) { - if (printRounds || verbose) { - log.printNoteLines("x.print.rounds", - roundNumber, - "{" + topLevelClasses.toString(", ") + "}", - annotationsPresent, - lastRound); - } - } - - private List enterNewClassFiles(Context currentContext) { - ClassReader reader = ClassReader.instance(currentContext); - Names names = Names.instance(currentContext); - List list = List.nil(); - - for (Map.Entry entry : filer.getGeneratedClasses().entrySet()) { - Name name = names.fromString(entry.getKey()); - JavaFileObject file = entry.getValue(); - if (file.getKind() != JavaFileObject.Kind.CLASS) - throw new AssertionError(file); - ClassSymbol cs; - if (isPkgInfo(file, JavaFileObject.Kind.CLASS)) { - Name packageName = Convert.packagePart(name); - PackageSymbol p = reader.enterPackage(packageName); - if (p.package_info == null) - p.package_info = reader.enterClass(Convert.shortName(name), p); - cs = p.package_info; - if (cs.classfile == null) - cs.classfile = file; - } else - cs = reader.enterClass(name, file); - list = list.prepend(cs); - } - return list.reverse(); - } - /** * Free resources related to annotation processing. */ @@ -1123,6 +1220,11 @@ return packages.reverse(); } + // avoid unchecked warning from use of varargs + private static List join(List list1, List list2) { + return list1.appendList(list2); + } + private boolean isPkgInfo(JavaFileObject fo, JavaFileObject.Kind kind) { return fo.isNameCompatible("package-info", kind); } @@ -1131,62 +1233,6 @@ return isPkgInfo(sym.classfile, JavaFileObject.Kind.CLASS) && (sym.packge().package_info == sym); } - private Context contextForNextRound(Context context, boolean shareNames) - throws IOException - { - Context next = new Context(); - - Options options = Options.instance(context); - assert options != null; - next.put(Options.optionsKey, options); - - PrintWriter out = context.get(Log.outKey); - assert out != null; - next.put(Log.outKey, out); - - if (shareNames) { - Names names = Names.instance(context); - assert names != null; - next.put(Names.namesKey, names); - } - - DiagnosticListener dl = context.get(DiagnosticListener.class); - if (dl != null) - next.put(DiagnosticListener.class, dl); - - TaskListener tl = context.get(TaskListener.class); - if (tl != null) - next.put(TaskListener.class, tl); - - JavaFileManager jfm = context.get(JavaFileManager.class); - assert jfm != null; - next.put(JavaFileManager.class, jfm); - if (jfm instanceof JavacFileManager) { - ((JavacFileManager)jfm).setContext(next); - } - - Names names = Names.instance(context); - assert names != null; - next.put(Names.namesKey, names); - - Keywords keywords = Keywords.instance(context); - assert(keywords != null); - next.put(Keywords.keywordsKey, keywords); - - JavaCompiler oldCompiler = JavaCompiler.instance(context); - JavaCompiler nextCompiler = JavaCompiler.instance(next); - nextCompiler.initRound(oldCompiler); - - JavacTaskImpl task = context.get(JavacTaskImpl.class); - if (task != null) { - next.put(JavacTaskImpl.class, task); - task.updateContext(next); - } - - context.clear(); - return next; - } - /* * Called retroactively to determine if a class loader was required, * after we have failed to create one. diff -r 8a5c98a695ae -r 2cf925ad67ab test/tools/javac/diags/examples.not-yet.txt --- a/test/tools/javac/diags/examples.not-yet.txt Thu Jul 29 19:27:11 2010 -0700 +++ b/test/tools/javac/diags/examples.not-yet.txt Thu Jul 29 19:30:35 2010 -0700 @@ -108,7 +108,6 @@ compiler.warn.invalid.archive.file compiler.warn.override.bridge compiler.warn.position.overflow # CRTable: caused by files with long lines >= 1024 chars -compiler.warn.proc.file.create.last.round # See CR 6966604 compiler.warn.proc.type.already.exists # JavacFiler: just mentioned in TODO compiler.warn.unchecked.assign # DEAD, replaced by compiler.misc.unchecked.assign compiler.warn.unchecked.cast.to.type # DEAD, replaced by compiler.misc.unchecked.cast.to.type diff -r 8a5c98a695ae -r 2cf925ad67ab test/tools/javac/diags/examples/ProcFileCreateLastRound/ProcFileCreateLastRound.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/diags/examples/ProcFileCreateLastRound/ProcFileCreateLastRound.java Thu Jul 29 19:30:35 2010 -0700 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.warn.proc.file.create.last.round +// options: -Xlint:processing -processor AnnoProc + +class ProcFileCreateLastRound { } diff -r 8a5c98a695ae -r 2cf925ad67ab test/tools/javac/diags/examples/ProcFileCreateLastRound/processors/AnnoProc.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/diags/examples/ProcFileCreateLastRound/processors/AnnoProc.java Thu Jul 29 19:30:35 2010 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.*; +import java.util.*; +import javax.annotation.processing.*; +import javax.lang.model.*; +import javax.lang.model.element.*; +import javax.tools.*; + +@SupportedAnnotationTypes("*") +public class AnnoProc extends AbstractProcessor { + public boolean process(Set elems, RoundEnvironment renv) { + if (renv.processingOver()) { + Filer filer = processingEnv.getFiler(); + Messager messager = processingEnv.getMessager(); + try { + JavaFileObject fo = filer.createSourceFile("Gen"); + Writer out = fo.openWriter(); + out.write("class Gen { }"); + out.close(); + } catch (IOException e) { + messager.printMessage(Diagnostic.Kind.ERROR, e.toString()); + } + } + return false; + } + + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } +} diff -r 8a5c98a695ae -r 2cf925ad67ab test/tools/javac/processing/filer/TestLastRound.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/processing/filer/TestLastRound.java Thu Jul 29 19:30:35 2010 -0700 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test 6966604 + * @summary JavacFiler not correctly notified of lastRound + * @compile TestLastRound.java + * @compile/fail/ref=TestLastRound.out -XDrawDiagnostics -Werror -proc:only -processor TestLastRound TestLastRound.java + */ + +import java.io.*; +import java.util.*; +import javax.annotation.processing.*; +import javax.lang.model.*; +import javax.lang.model.element.*; +import javax.tools.*; + +@SupportedAnnotationTypes("*") +public class TestLastRound extends AbstractProcessor { + @Override + public boolean process(Set annotations, + RoundEnvironment roundEnv) { + Filer filer = processingEnv.getFiler(); + if (roundEnv.processingOver()) { + try { + JavaFileObject fo = filer.createSourceFile("LastRound.java"); + Writer out = fo.openWriter(); + out.write("class LastRound { }"); + out.close(); + } catch (IOException e) { + } + } + return true; + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } +} diff -r 8a5c98a695ae -r 2cf925ad67ab test/tools/javac/processing/filer/TestLastRound.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/processing/filer/TestLastRound.out Thu Jul 29 19:30:35 2010 -0700 @@ -0,0 +1,3 @@ +- compiler.warn.proc.file.create.last.round: LastRound.java +- compiler.err.warnings.and.werror +1 error diff -r 8a5c98a695ae -r 2cf925ad67ab test/tools/javac/processing/werror/WErrorGen.java --- a/test/tools/javac/processing/werror/WErrorGen.java Thu Jul 29 19:27:11 2010 -0700 +++ b/test/tools/javac/processing/werror/WErrorGen.java Thu Jul 29 19:30:35 2010 -0700 @@ -42,7 +42,7 @@ public boolean process(Set annotations, RoundEnvironment roundEnv) { Filer filer = processingEnv.getFiler(); - if (roundEnv.processingOver()) { + if (++round == 1) { try { JavaFileObject fo = filer.createSourceFile("Gen"); Writer out = fo.openWriter(); @@ -58,4 +58,6 @@ public SourceVersion getSupportedSourceVersion() { return SourceVersion.latest(); } + + int round = 0; }