Mon, 30 Aug 2010 18:03:35 -0700
6403465: javac should defer diagnostics until it can be determined they are persistent
Reviewed-by: mcimadamore, darcy
1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Fri Aug 27 17:59:08 2010 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Mon Aug 30 18:03:35 2010 -0700 1.3 @@ -578,6 +578,8 @@ 1.4 boolean classExpected, 1.5 boolean interfaceExpected, 1.6 boolean checkExtensible) { 1.7 + if (t.isErroneous()) 1.8 + return t; 1.9 if (t.tag == TYPEVAR && !classExpected && !interfaceExpected) { 1.10 // check that type variable is already visible 1.11 if (t.getUpperBound() == null) { 1.12 @@ -595,7 +597,7 @@ 1.13 } else if (checkExtensible && 1.14 classExpected && 1.15 (t.tsym.flags() & INTERFACE) != 0) { 1.16 - log.error(tree.pos(), "no.intf.expected.here"); 1.17 + log.error(tree.pos(), "no.intf.expected.here"); 1.18 return types.createErrorType(t); 1.19 } 1.20 if (checkExtensible && 1.21 @@ -2845,7 +2847,6 @@ 1.22 if (tree.bounds.tail.nonEmpty()) { 1.23 log.error(tree.bounds.tail.head.pos(), 1.24 "type.var.may.not.be.followed.by.other.bounds"); 1.25 - log.unrecoverableError = true; 1.26 tree.bounds = List.of(tree.bounds.head); 1.27 a.bound = bs.head; 1.28 }
2.1 --- a/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Fri Aug 27 17:59:08 2010 -0700 2.2 +++ b/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Mon Aug 30 18:03:35 2010 -0700 2.3 @@ -59,6 +59,7 @@ 2.4 import javax.annotation.processing.Processor; 2.5 2.6 import static javax.tools.StandardLocation.CLASS_OUTPUT; 2.7 +import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*; 2.8 import static com.sun.tools.javac.util.ListBuffer.lb; 2.9 2.10 // TEMP, until we have a more efficient way to save doc comment info 2.11 @@ -579,10 +580,8 @@ 2.12 TaskEvent e = new TaskEvent(TaskEvent.Kind.PARSE, filename); 2.13 taskListener.started(e); 2.14 } 2.15 - int initialErrorCount = log.nerrors; 2.16 Parser parser = parserFactory.newParser(content, keepComments(), genEndPos, lineDebugInfo); 2.17 tree = parser.parseCompilationUnit(); 2.18 - log.unrecoverableError |= (log.nerrors > initialErrorCount); 2.19 if (verbose) { 2.20 printVerbose("parsing.done", Long.toString(elapsed(msec))); 2.21 } 2.22 @@ -967,8 +966,7 @@ 2.23 keepComments = true; 2.24 if (taskListener != null) 2.25 taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING)); 2.26 - 2.27 - 2.28 + log.deferDiagnostics = true; 2.29 } else { // free resources 2.30 procEnvImpl.close(); 2.31 } 2.32 @@ -985,15 +983,23 @@ 2.33 * @param roots a list of compilation units 2.34 * @return an instance of the compiler in which to complete the compilation 2.35 */ 2.36 + // Implementation note: when this method is called, log.deferredDiagnostics 2.37 + // will have been set true by initProcessAnnotations, meaning that any diagnostics 2.38 + // that are reported will go into the log.deferredDiagnostics queue. 2.39 + // By the time this method exits, log.deferDiagnostics must be set back to false, 2.40 + // and all deferredDiagnostics must have been handled: i.e. either reported 2.41 + // or determined to be transient, and therefore suppressed. 2.42 public JavaCompiler processAnnotations(List<JCCompilationUnit> roots, 2.43 List<String> classnames) { 2.44 if (shouldStop(CompileState.PROCESS)) { 2.45 // Errors were encountered. 2.46 - // If log.unrecoverableError is set, the errors were parse errors 2.47 + // Unless all the errors are resolve errors, the errors were parse errors 2.48 // or other errors during enter which cannot be fixed by running 2.49 // any annotation processors. 2.50 - if (log.unrecoverableError) 2.51 + if (unrecoverableError()) { 2.52 + log.reportDeferredDiagnostics(); 2.53 return this; 2.54 + } 2.55 } 2.56 2.57 // ASSERT: processAnnotations and procEnvImpl should have been set up by 2.58 @@ -1015,6 +1021,7 @@ 2.59 log.error("proc.no.explicit.annotation.processing.requested", 2.60 classnames); 2.61 } 2.62 + log.reportDeferredDiagnostics(); 2.63 return this; // continue regular compilation 2.64 } 2.65 2.66 @@ -1027,6 +1034,7 @@ 2.67 if (!explicitAnnotationProcessingRequested()) { 2.68 log.error("proc.no.explicit.annotation.processing.requested", 2.69 classnames); 2.70 + log.reportDeferredDiagnostics(); 2.71 return this; // TODO: Will this halt compilation? 2.72 } else { 2.73 boolean errors = false; 2.74 @@ -1041,7 +1049,6 @@ 2.75 if (sym.kind == Kinds.PCK) 2.76 sym.complete(); 2.77 if (sym.exists()) { 2.78 - Name name = names.fromString(nameStr); 2.79 if (sym.kind == Kinds.PCK) 2.80 pckSymbols = pckSymbols.prepend((PackageSymbol)sym); 2.81 else 2.82 @@ -1057,23 +1064,36 @@ 2.83 continue; 2.84 } 2.85 } 2.86 - if (errors) 2.87 + if (errors) { 2.88 + log.reportDeferredDiagnostics(); 2.89 return this; 2.90 + } 2.91 } 2.92 } 2.93 try { 2.94 JavaCompiler c = procEnvImpl.doProcessing(context, roots, classSymbols, pckSymbols); 2.95 if (c != this) 2.96 annotationProcessingOccurred = c.annotationProcessingOccurred = true; 2.97 + // doProcessing will have handled deferred diagnostics 2.98 + assert c.log.deferDiagnostics == false; 2.99 + assert c.log.deferredDiagnostics.size() == 0; 2.100 return c; 2.101 } finally { 2.102 procEnvImpl.close(); 2.103 } 2.104 } catch (CompletionFailure ex) { 2.105 log.error("cant.access", ex.sym, ex.getDetailValue()); 2.106 + log.reportDeferredDiagnostics(); 2.107 return this; 2.108 + } 2.109 + } 2.110 2.111 + private boolean unrecoverableError() { 2.112 + for (JCDiagnostic d: log.deferredDiagnostics) { 2.113 + if (d.getKind() == JCDiagnostic.Kind.ERROR && !d.isFlagSet(RESOLVE_ERROR)) 2.114 + return true; 2.115 } 2.116 + return false; 2.117 } 2.118 2.119 boolean explicitAnnotationProcessingRequested() {
3.1 --- a/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Fri Aug 27 17:59:08 2010 -0700 3.2 +++ b/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Mon Aug 30 18:03:35 2010 -0700 3.3 @@ -77,6 +77,7 @@ 3.4 import com.sun.tools.javac.util.Options; 3.5 3.6 import static javax.tools.StandardLocation.*; 3.7 +import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*; 3.8 3.9 /** 3.10 * Objects of this class hold and manage the state needed to support 3.11 @@ -97,6 +98,7 @@ 3.12 private final boolean procOnly; 3.13 private final boolean fatalErrors; 3.14 private final boolean werror; 3.15 + private final boolean showResolveErrors; 3.16 private boolean foundTypeProcessors; 3.17 3.18 private final JavacFiler filer; 3.19 @@ -164,6 +166,7 @@ 3.20 procOnly = options.get("-proc:only") != null || 3.21 options.get("-Xprint") != null; 3.22 fatalErrors = options.get("fatalEnterError") != null; 3.23 + showResolveErrors = options.get("showResolveErrors") != null; 3.24 werror = options.get("-Werror") != null; 3.25 platformAnnotations = initPlatformAnnotations(); 3.26 foundTypeProcessors = false; 3.27 @@ -825,6 +828,7 @@ 3.28 3.29 compiler = JavaCompiler.instance(context); 3.30 log = Log.instance(context); 3.31 + log.deferDiagnostics = true; 3.32 3.33 // the following is for the benefit of JavacProcessingEnvironment.getContext() 3.34 JavacProcessingEnvironment.this.context = context; 3.35 @@ -924,10 +928,24 @@ 3.36 3.37 /** Return whether or not an unrecoverable error has occurred. */ 3.38 boolean unrecoverableError() { 3.39 - return log.unrecoverableError 3.40 - || messager.errorRaised() 3.41 - || (werror && log.nwarnings > 0) 3.42 - || (fatalErrors && log.nerrors > 0); 3.43 + if (messager.errorRaised()) 3.44 + return true; 3.45 + 3.46 + for (JCDiagnostic d: log.deferredDiagnostics) { 3.47 + switch (d.getKind()) { 3.48 + case WARNING: 3.49 + if (werror) 3.50 + return true; 3.51 + break; 3.52 + 3.53 + case ERROR: 3.54 + if (fatalErrors || !d.isFlagSet(RESOLVE_ERROR)) 3.55 + return true; 3.56 + break; 3.57 + } 3.58 + } 3.59 + 3.60 + return false; 3.61 } 3.62 3.63 /** Find the set of annotations present in the set of top level 3.64 @@ -943,7 +961,7 @@ 3.65 } 3.66 3.67 /** Enter a set of generated class files. */ 3.68 - List<ClassSymbol> enterClassFiles(Map<String, JavaFileObject> classFiles) { 3.69 + private List<ClassSymbol> enterClassFiles(Map<String, JavaFileObject> classFiles) { 3.70 ClassReader reader = ClassReader.instance(context); 3.71 Names names = Names.instance(context); 3.72 List<ClassSymbol> list = List.nil(); 3.73 @@ -970,7 +988,7 @@ 3.74 } 3.75 3.76 /** Enter a set of syntax trees. */ 3.77 - void enterTrees(List<JCCompilationUnit> roots) { 3.78 + private void enterTrees(List<JCCompilationUnit> roots) { 3.79 compiler.enterTrees(roots); 3.80 } 3.81 3.82 @@ -1000,6 +1018,15 @@ 3.83 } 3.84 } 3.85 3.86 + void showDiagnostics(boolean showAll) { 3.87 + Set<JCDiagnostic.Kind> kinds = EnumSet.allOf(JCDiagnostic.Kind.class); 3.88 + if (!showAll) { 3.89 + // suppress errors, which are all presumed to be transient resolve errors 3.90 + kinds.remove(JCDiagnostic.Kind.ERROR); 3.91 + } 3.92 + log.reportDeferredDiagnostics(kinds); 3.93 + } 3.94 + 3.95 /** Update the processing state for the current context. */ 3.96 private void updateProcessingState() { 3.97 filer.newRound(context); 3.98 @@ -1111,6 +1138,8 @@ 3.99 errorStatus = round.unrecoverableError(); 3.100 moreToDo = moreToDo(); 3.101 3.102 + round.showDiagnostics(errorStatus || showResolveErrors); 3.103 + 3.104 // Set up next round. 3.105 // Copy mutable collections returned from filer. 3.106 round = round.next( 3.107 @@ -1125,6 +1154,7 @@ 3.108 3.109 // run last round 3.110 round.run(true, errorStatus); 3.111 + round.showDiagnostics(true); 3.112 3.113 filer.warnIfUnclosedFiles(); 3.114 warnIfUnmatchedOptions();
4.1 --- a/src/share/classes/com/sun/tools/javac/util/Log.java Fri Aug 27 17:59:08 2010 -0700 4.2 +++ b/src/share/classes/com/sun/tools/javac/util/Log.java Mon Aug 30 18:03:35 2010 -0700 4.3 @@ -27,8 +27,10 @@ 4.4 4.5 import java.io.*; 4.6 import java.util.Arrays; 4.7 +import java.util.EnumSet; 4.8 import java.util.HashSet; 4.9 import java.util.Map; 4.10 +import java.util.Queue; 4.11 import java.util.Set; 4.12 import javax.tools.DiagnosticListener; 4.13 import javax.tools.JavaFileObject; 4.14 @@ -110,6 +112,12 @@ 4.15 */ 4.16 private JavacMessages messages; 4.17 4.18 + /** 4.19 + * Deferred diagnostics 4.20 + */ 4.21 + public boolean deferDiagnostics; 4.22 + public Queue<JCDiagnostic> deferredDiagnostics = new ListBuffer<JCDiagnostic>(); 4.23 + 4.24 /** Construct a log with given I/O redirections. 4.25 */ 4.26 @Deprecated 4.27 @@ -204,12 +212,6 @@ 4.28 */ 4.29 public int nwarnings = 0; 4.30 4.31 - /** 4.32 - * Whether or not an unrecoverable error has been seen. 4.33 - * Unrecoverable errors prevent subsequent annotation processing. 4.34 - */ 4.35 - public boolean unrecoverableError; 4.36 - 4.37 /** A set of all errors generated so far. This is used to avoid printing an 4.38 * error message more than once. For each error, a pair consisting of the 4.39 * source file name and source code position of the error is added to the set. 4.40 @@ -347,12 +349,32 @@ 4.41 nwarnings++; 4.42 } 4.43 4.44 + /** Report all deferred diagnostics, and clear the deferDiagnostics flag. */ 4.45 + public void reportDeferredDiagnostics() { 4.46 + reportDeferredDiagnostics(EnumSet.allOf(JCDiagnostic.Kind.class)); 4.47 + } 4.48 + 4.49 + /** Report selected deferred diagnostics, and clear the deferDiagnostics flag. */ 4.50 + public void reportDeferredDiagnostics(Set<JCDiagnostic.Kind> kinds) { 4.51 + deferDiagnostics = false; 4.52 + JCDiagnostic d; 4.53 + while ((d = deferredDiagnostics.poll()) != null) { 4.54 + if (kinds.contains(d.getKind())) 4.55 + report(d); 4.56 + } 4.57 + } 4.58 + 4.59 /** 4.60 * Common diagnostic handling. 4.61 * The diagnostic is counted, and depending on the options and how many diagnostics have been 4.62 * reported so far, the diagnostic may be handed off to writeDiagnostic. 4.63 */ 4.64 public void report(JCDiagnostic diagnostic) { 4.65 + if (deferDiagnostics) { 4.66 + deferredDiagnostics.add(diagnostic); 4.67 + return; 4.68 + } 4.69 + 4.70 if (expectDiagKeys != null) 4.71 expectDiagKeys.remove(diagnostic.getCode()); 4.72
5.1 --- a/test/tools/javac/processing/6430209/b6341534.java Fri Aug 27 17:59:08 2010 -0700 5.2 +++ b/test/tools/javac/processing/6430209/b6341534.java Mon Aug 30 18:03:35 2010 -0700 5.3 @@ -51,7 +51,8 @@ 5.4 try { 5.5 PackageElement PE = E.getPackageElement("dir1"); 5.6 List<? extends Element> LEE = PE.getEnclosedElements(); /* <=This line elicits the error message. */ 5.7 - for(Element e : LEE) System.out.println("found " + e.toString() + " in dir1."); 5.8 + for(Element e : LEE) 5.9 + System.out.println("found " + e.toString() + " in dir1."); 5.10 } 5.11 catch(NullPointerException npe) { 5.12 msgr.printMessage(ERROR,npe.toString()); 5.13 @@ -59,7 +60,11 @@ 5.14 return false; 5.15 } 5.16 } 5.17 - if( renv.errorRaised() ) { msgr.printMessage(ERROR, "FAILED");} 5.18 + // on round 1, expect errorRaised == false && processingOver == false 5.19 + // on round 2, expect errorRaised == true && processingOver == true 5.20 + if( renv.errorRaised() != renv.processingOver()) { 5.21 + msgr.printMessage(ERROR, "FAILED"); 5.22 + } 5.23 return true; 5.24 } 5.25
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/test/tools/javac/processing/errors/TestSuppression.java Mon Aug 30 18:03:35 2010 -0700 6.3 @@ -0,0 +1,232 @@ 6.4 +/* 6.5 + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.7 + * 6.8 + * This code is free software; you can redistribute it and/or modify it 6.9 + * under the terms of the GNU General Public License version 2 only, as 6.10 + * published by the Free Software Foundation. 6.11 + * 6.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 6.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 6.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 6.15 + * version 2 for more details (a copy is included in the LICENSE file that 6.16 + * accompanied this code). 6.17 + * 6.18 + * You should have received a copy of the GNU General Public License version 6.19 + * 2 along with this work; if not, write to the Free Software Foundation, 6.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 6.21 + * 6.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 6.23 + * or visit www.oracle.com if you need additional information or have any 6.24 + * questions. 6.25 + */ 6.26 + 6.27 +/* 6.28 + * @test 6.29 + * @bug 6403465 6.30 + * @summary javac should defer diagnostics until it can be determined they are persistent 6.31 + */ 6.32 + 6.33 +import java.io.*; 6.34 +import java.util.*; 6.35 +import javax.annotation.processing.*; 6.36 +import javax.lang.model.*; 6.37 +import javax.lang.model.element.TypeElement; 6.38 +import javax.tools.*; 6.39 + 6.40 +import com.sun.source.util.JavacTask; 6.41 +import com.sun.tools.javac.api.JavacTool; 6.42 +import com.sun.tools.javac.util.JCDiagnostic; 6.43 + 6.44 +import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*; 6.45 + 6.46 + 6.47 +public class TestSuppression { 6.48 + public static void main(String... args) throws Exception { 6.49 + new TestSuppression().run(args); 6.50 + } 6.51 + 6.52 + enum WarningKind { NO, YES }; 6.53 + 6.54 + String[] cases = { 6.55 + // missing class C 6.56 + "class X { C c; }", 6.57 + "class X { C foo() { return null; } }", 6.58 + "class X { void foo(C c) { } }", 6.59 + "class X extends C { }", 6.60 + "class X<T extends C> { }", 6.61 + // missing interface I 6.62 + "class X implements I { }", 6.63 + "interface X extends I { }", 6.64 + // missing exception E 6.65 + "class X { void m() throws E { } }", 6.66 + // missing method m 6.67 + "class X extends C { int i = m(); }", 6.68 + // missing field f 6.69 + "class X extends C { int i = f; }" 6.70 + }; 6.71 + 6.72 + void run(String... args) throws Exception { 6.73 + for (String c: cases) { 6.74 + for (WarningKind wk: WarningKind.values()) { 6.75 + for (int g = 1; g <= 3; g++) { 6.76 + try { 6.77 + test(c, wk, g); 6.78 + } catch (Throwable t) { 6.79 + error("caught: " + t); 6.80 + } 6.81 + if (errors > 0) throw new AssertionError(); 6.82 + } 6.83 + } 6.84 + } 6.85 + 6.86 + System.err.println(count + " test cases"); 6.87 + 6.88 + if (errors > 0) 6.89 + throw new Exception(errors + " errors occurred"); 6.90 + } 6.91 + 6.92 + void test(String src, WarningKind wk, int gen) throws Exception { 6.93 + count++; 6.94 + System.err.println("Test " + count + ": wk:" + wk + " gen:" + gen + " src:" +src); 6.95 + 6.96 + File testDir = new File("test" + count); 6.97 + File srcDir = createDir(testDir, "src"); 6.98 + File gensrcDir = createDir(testDir, "gensrc"); 6.99 + File classesDir = createDir(testDir, "classes"); 6.100 + 6.101 + File x = writeFile(new File(srcDir, "X.java"), src); 6.102 + 6.103 + DiagListener dl = new DiagListener(); 6.104 + JavacTool tool = JavacTool.create(); 6.105 + StandardJavaFileManager fm = tool.getStandardFileManager(dl, null, null); 6.106 + fm.setLocation(StandardLocation.CLASS_PATH, 6.107 + Arrays.asList(classesDir, new File(System.getProperty("test.classes")))); 6.108 + fm.setLocation(StandardLocation.CLASS_OUTPUT, Collections.singleton(classesDir)); 6.109 + fm.setLocation(StandardLocation.SOURCE_OUTPUT, Collections.singleton(gensrcDir)); 6.110 + List<String> args = new ArrayList<String>(); 6.111 +// args.add("-XprintProcessorInfo"); 6.112 + args.add("-XprintRounds"); 6.113 + args.add("-Agen=" + gen); 6.114 + if (wk == WarningKind.YES) 6.115 + args.add("-Xlint:serial"); 6.116 + Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(x); 6.117 + 6.118 + StringWriter sw = new StringWriter(); 6.119 + PrintWriter pw = new PrintWriter(sw); 6.120 + JavacTask task = tool.getTask(pw, fm, dl, args, null, files); 6.121 + task.setProcessors(Arrays.asList(new AnnoProc())); 6.122 + boolean ok = task.call(); 6.123 + pw.close(); 6.124 + 6.125 + System.err.println("ok:" + ok + " diags:" + dl.counts); 6.126 + if (sw.toString().length() > 0) { 6.127 + System.err.println("output:\n" + sw.toString()); 6.128 + } 6.129 + 6.130 + for (Diagnostic.Kind dk: Diagnostic.Kind.values()) { 6.131 + Integer v = dl.counts.get(dk); 6.132 + int found = (v == null) ? 0 : v; 6.133 + int expect = (dk == Diagnostic.Kind.WARNING && wk == WarningKind.YES) ? gen : 0; 6.134 + if (found != expect) { 6.135 + error("Unexpected value for " + dk + ": expected: " + expect + " found: " + found); 6.136 + } 6.137 + } 6.138 + 6.139 + System.err.println(); 6.140 + } 6.141 + 6.142 + File createDir(File parent, String name) { 6.143 + File dir = new File(parent, name); 6.144 + dir.mkdirs(); 6.145 + return dir; 6.146 + } 6.147 + 6.148 + File writeFile(File f, String content) throws IOException { 6.149 + FileWriter out = new FileWriter(f); 6.150 + try { 6.151 + out.write(content); 6.152 + } finally { 6.153 + out.close(); 6.154 + } 6.155 + return f; 6.156 + } 6.157 + 6.158 + <T> void add(List<T> list, T... values) { 6.159 + for (T v: values) 6.160 + list.add(v); 6.161 + } 6.162 + 6.163 + void error(String msg) { 6.164 + System.err.println("Error: " + msg); 6.165 + errors++; 6.166 + } 6.167 + 6.168 + int count; 6.169 + int errors; 6.170 + 6.171 + static class DiagListener implements DiagnosticListener<JavaFileObject> { 6.172 + int total; 6.173 + Map<Diagnostic.Kind,Integer> counts = new TreeMap<Diagnostic.Kind,Integer>(); 6.174 + 6.175 + public void report(Diagnostic<? extends JavaFileObject> diagnostic) { 6.176 + System.err.println((++total) + ": " 6.177 + + "resolveError:" + isResolveError((JCDiagnostic) diagnostic) + "\n" 6.178 + + diagnostic); 6.179 + Diagnostic.Kind dk = diagnostic.getKind(); 6.180 + Integer c = counts.get(dk); 6.181 + counts.put(dk, (c == null ? 1 : c + 1)); 6.182 + } 6.183 + 6.184 + private static boolean isResolveError(JCDiagnostic d) { 6.185 + return d.isFlagSet(RESOLVE_ERROR); 6.186 + } 6.187 + } 6.188 + 6.189 + @SupportedAnnotationTypes("*") 6.190 + @SupportedOptions("gen") 6.191 + public static class AnnoProc extends AbstractProcessor { 6.192 + Filer f; 6.193 + Messager m; 6.194 + int gen; 6.195 + 6.196 + @Override 6.197 + public void init(ProcessingEnvironment processingEnv) { 6.198 + f = processingEnv.getFiler(); 6.199 + m = processingEnv.getMessager(); 6.200 + Map<String,String> options = processingEnv.getOptions(); 6.201 + gen = Integer.parseInt(options.get("gen")); 6.202 + } 6.203 + 6.204 + @Override 6.205 + public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 6.206 + round++; 6.207 + if (round < gen) 6.208 + writeSource("Dummy" + round, "class Dummy" + round + " extends java.util.ArrayList{ }"); 6.209 + else if (round == gen) { 6.210 + writeSource("C", "class C { int f; int m() { return 0; } }"); 6.211 + writeSource("I", "interface I { }"); 6.212 + writeSource("E", "class E extends Exception { }"); 6.213 + } 6.214 + return true; 6.215 + } 6.216 + 6.217 + @Override 6.218 + public SourceVersion getSupportedSourceVersion() { 6.219 + return SourceVersion.latest(); 6.220 + } 6.221 + 6.222 + private void writeSource(String name, String text) { 6.223 + try { 6.224 + JavaFileObject fo = f.createSourceFile(name); 6.225 + Writer out = fo.openWriter(); 6.226 + out.write(text); 6.227 + out.close(); 6.228 + } catch (IOException e) { 6.229 + m.printMessage(Diagnostic.Kind.ERROR, e.toString()); 6.230 + } 6.231 + } 6.232 + 6.233 + int round = 0; 6.234 + } 6.235 +}