6993963: Project Coin: Use precise exception analysis for effectively final catch parameters
Summary: More precise rethrow analysis should be extended to effectively-final exception parameters. Multicatch parameters should be made implicitly final.
Reviewed-by: jjg, darcy
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java Tue Nov 02 12:01:35 2010 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java Thu Nov 04 12:57:48 2010 +0000
@@ -247,6 +247,11 @@
*/
public static final long OVERRIDE_BRIDGE = 1L<<41;
+ /**
+ * Flag that marks an 'effectively final' local variable
+ */
+ public static final long EFFECTIVELY_FINAL = 1L<<42;
+
/** Modifier masks.
*/
public static final int
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Tue Nov 02 12:01:35 2010 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Thu Nov 04 12:57:48 2010 +0000
@@ -256,6 +256,8 @@
} else {
log.error(pos, "cant.assign.val.to.final.var", v);
}
+ } else if ((v.flags() & EFFECTIVELY_FINAL) != 0) {
+ v.flags_field &= ~EFFECTIVELY_FINAL;
}
}
@@ -799,6 +801,7 @@
memberEnter.memberEnter(tree, env);
annotate.flush();
}
+ tree.sym.flags_field |= EFFECTIVELY_FINAL;
}
VarSymbol v = tree.sym;
@@ -1061,11 +1064,8 @@
localEnv.dup(c, localEnv.info.dup(localEnv.info.scope.dup()));
Type ctype = attribStat(c.param, catchEnv);
if (TreeInfo.isMultiCatch(c)) {
- //check that multi-catch parameter is marked as final
- if ((c.param.sym.flags() & FINAL) == 0) {
- log.error(c.param.pos(), "multicatch.param.must.be.final", c.param.sym);
- }
- c.param.sym.flags_field = c.param.sym.flags() | DISJUNCTION;
+ //multi-catch parameter is implicitly marked as final
+ c.param.sym.flags_field |= FINAL | DISJUNCTION;
}
if (c.param.sym.kind == Kinds.VAR) {
c.param.sym.setData(ElementKind.EXCEPTION_PARAMETER);
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java Tue Nov 02 12:01:35 2010 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java Thu Nov 04 12:57:48 2010 +0000
@@ -226,7 +226,7 @@
*/
Bits uninits;
- HashMap<Symbol, List<Type>> multicatchTypes;
+ HashMap<Symbol, List<Type>> preciseRethrowTypes;
/** The set of variables that are definitely unassigned everywhere
* in current try block. This variable is maintained lazily; it is
@@ -332,7 +332,7 @@
if (!chk.isUnchecked(tree.pos(), exc)) {
if (!chk.isHandled(exc, caught))
pendingExits.append(new PendingExit(tree, exc));
- thrown = chk.incl(exc, thrown);
+ thrown = chk.incl(exc, thrown);
}
}
@@ -1077,12 +1077,12 @@
scan(param);
inits.incl(param.sym.adr);
uninits.excl(param.sym.adr);
- multicatchTypes.put(param.sym, chk.intersect(ctypes, rethrownTypes));
+ preciseRethrowTypes.put(param.sym, chk.intersect(ctypes, rethrownTypes));
scanStat(l.head.body);
initsEnd.andSet(inits);
uninitsEnd.andSet(uninits);
nextadr = nextadrCatch;
- multicatchTypes.remove(param.sym);
+ preciseRethrowTypes.remove(param.sym);
aliveEnd |= alive;
}
if (tree.finalizer != null) {
@@ -1215,10 +1215,10 @@
Symbol sym = TreeInfo.symbol(tree.expr);
if (sym != null &&
sym.kind == VAR &&
- (sym.flags() & FINAL) != 0 &&
- multicatchTypes.get(sym) != null &&
+ (sym.flags() & (FINAL | EFFECTIVELY_FINAL)) != 0 &&
+ preciseRethrowTypes.get(sym) != null &&
allowRethrowAnalysis) {
- for (Type t : multicatchTypes.get(sym)) {
+ for (Type t : preciseRethrowTypes.get(sym)) {
markThrown(tree, t);
}
}
@@ -1422,7 +1422,7 @@
firstadr = 0;
nextadr = 0;
pendingExits = new ListBuffer<PendingExit>();
- multicatchTypes = new HashMap<Symbol, List<Type>>();
+ preciseRethrowTypes = new HashMap<Symbol, List<Type>>();
alive = true;
this.thrown = this.caught = null;
this.classDef = null;
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Tue Nov 02 12:01:35 2010 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Nov 04 12:57:48 2010 +0000
@@ -187,8 +187,6 @@
automatic resource {0} may not be assigned
compiler.err.multicatch.parameter.may.not.be.assigned=\
multi-catch parameter {0} may not be assigned
-compiler.err.multicatch.param.must.be.final=\
- multi-catch parameter {0} must be final
compiler.err.finally.without.try=\
''finally'' without ''try''
compiler.err.foreach.not.applicable.to.type=\
--- a/langtools/test/tools/javac/diags/examples/MulticatchMustBeFinal.java Tue Nov 02 12:01:35 2010 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * 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.err.multicatch.param.must.be.final
-
-class MulticatchMustBeFinal {
- void e1() throws NullPointerException { }
- void e2() throws IllegalArgumentException { }
-
- void m() {
- try {
- e1();
- e2();
- } catch (NullPointerException | IllegalArgumentException e) {
- e.printStackTrace();
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/multicatch/Neg01eff_final.java Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,28 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 6943289
+ *
+ * @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
+ * @author darcy
+ * @compile/fail/ref=Neg01eff_final.out -XDrawDiagnostics Neg01eff_final.java
+ * @compile -source 6 -XDrawDiagnostics Neg01eff_final.java
+ *
+ */
+
+class Neg01eff_final {
+ static class A extends Exception {}
+ static class B1 extends A {}
+ static class B2 extends A {}
+
+ class Test {
+ void m() throws A {
+ try {
+ throw new B1();
+ } catch (A ex1) {
+ try {
+ throw ex1; // used to throw A, now throws B1!
+ } catch (B2 ex2) { }//unreachable
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/multicatch/Neg01eff_final.out Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,2 @@
+Neg01eff_final.java:24:19: compiler.err.except.never.thrown.in.try: Neg01eff_final.B2
+1 error
--- a/langtools/test/tools/javac/multicatch/Neg02.java Tue Nov 02 12:01:35 2010 +0000
+++ b/langtools/test/tools/javac/multicatch/Neg02.java Thu Nov 04 12:57:48 2010 +0000
@@ -20,6 +20,8 @@
else {
throw new B();
}
- } catch (A | B ex) { }
+ } catch (final A | B ex) {
+ ex = new B();
+ }
}
}
--- a/langtools/test/tools/javac/multicatch/Neg02.out Tue Nov 02 12:01:35 2010 +0000
+++ b/langtools/test/tools/javac/multicatch/Neg02.out Thu Nov 04 12:57:48 2010 +0000
@@ -1,2 +1,2 @@
-Neg02.java:23:24: compiler.err.multicatch.param.must.be.final: ex
+Neg02.java:24:13: compiler.err.multicatch.parameter.may.not.be.assigned: ex
1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/multicatch/Neg02eff_final.java Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,27 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 6943289 6993963
+ *
+ * @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
+ * @author mcimadamore
+ * @compile/fail/ref=Neg02eff_final.out -XDrawDiagnostics Neg02eff_final.java
+ *
+ */
+
+class Neg02eff_final {
+ static class A extends Exception {}
+ static class B extends Exception {}
+
+ void m() {
+ try {
+ if (true) {
+ throw new A();
+ }
+ else {
+ throw new B();
+ }
+ } catch (A | B ex) {
+ ex = new B();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/multicatch/Neg02eff_final.out Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,2 @@
+Neg02eff_final.java:24:13: compiler.err.multicatch.parameter.may.not.be.assigned: ex
+1 error
--- a/langtools/test/tools/javac/multicatch/Neg03.java Tue Nov 02 12:01:35 2010 +0000
+++ b/langtools/test/tools/javac/multicatch/Neg03.java Thu Nov 04 12:57:48 2010 +0000
@@ -9,19 +9,22 @@
*/
class Neg03 {
- static class A extends Exception {}
- static class B extends Exception {}
- void m() {
+ static class A extends Exception { public void m() {}; public Object f;}
+ static class B1 extends A {}
+ static class B2 extends A {}
+
+ void m() throws B1, B2 {
try {
if (true) {
- throw new A();
+ throw new B1();
}
else {
- throw new B();
+ throw new B2();
}
- } catch (final A | B ex) {
- ex = new B();
+ } catch (Exception ex) {
+ ex = new B2(); //effectively final analysis disabled!
+ throw ex;
}
}
}
--- a/langtools/test/tools/javac/multicatch/Neg03.out Tue Nov 02 12:01:35 2010 +0000
+++ b/langtools/test/tools/javac/multicatch/Neg03.out Thu Nov 04 12:57:48 2010 +0000
@@ -1,2 +1,2 @@
-Neg03.java:24:13: compiler.err.multicatch.parameter.may.not.be.assigned: ex
+Neg03.java:27:13: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/multicatch/Neg04eff_final.java Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,31 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 6943289
+ *
+ * @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
+ * @author mcimadamore
+ * @compile/fail/ref=Neg04eff_final.out -XDrawDiagnostics Neg04eff_final.java
+ *
+ */
+
+class Neg04eff_final {
+ static class A extends Exception {}
+ static class B extends Exception {}
+
+ void test() throws B {
+ try {
+ if (true) {
+ throw new A();
+ } else if (false) {
+ throw new B();
+ } else {
+ throw (Throwable)new Exception();
+ }
+ }
+ catch (A e) {}
+ catch (Exception e) {
+ throw e;
+ }
+ catch (Throwable t) {}
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/multicatch/Neg04eff_final.out Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,2 @@
+Neg04eff_final.java:27:13: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/multicatch/Neg05.java Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,33 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 6943289
+ *
+ * @summary Project Coin: Improved Exception Handling for Java (aka 'multicatch')
+ * @author mcimadamore
+ * @compile/fail/ref=Neg05.out -XDrawDiagnostics Neg05.java
+ *
+ */
+
+class Neg02 {
+
+ static class Foo<X> {
+ Foo(X x) {}
+ }
+
+ static interface Base<X> {}
+ static class A extends Exception implements Base<String> {}
+ static class B extends Exception implements Base<Integer> {}
+
+ void m() {
+ try {
+ if (true) {
+ throw new A();
+ }
+ else {
+ throw new B();
+ }
+ } catch (A | B ex) {
+ Foo<?> f = new Foo<>(ex);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/multicatch/Neg05.out Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,2 @@
+Neg05.java:30:31: compiler.err.cant.apply.diamond.1: (compiler.misc.diamond: Neg02.Foo), (compiler.misc.diamond.invalid.arg: java.lang.Exception&Neg02.Base<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<? extends java.lang.Object&java.io.Serializable&java.lang.Comparable<?>>>, (compiler.misc.diamond: Neg02.Foo))
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/multicatch/Pos06.java Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,27 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 6993963
+ *
+ * @summary Project Coin: Use precise exception analysis for effectively final catch parameters
+ * @author mcimadamore
+ * @compile Pos06.java
+ *
+ */
+
+class Pos06 {
+ static class A extends Exception {}
+ static class B extends Exception {}
+
+ void m() {
+ try {
+ if (true) {
+ throw new A();
+ }
+ else {
+ throw new B();
+ }
+ } catch (A | B ex) {
+ System.out.println(ex);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/multicatch/Pos07.java Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,49 @@
+/*
+ * 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
+ * @bug 6993963
+ * @summary Project Coin: Use precise exception analysis for effectively final catch parameters
+ * @compile Pos07.java
+ */
+
+class Pos07 {
+
+ static class A extends Exception { public void m() {}; public Object f;}
+ static class B1 extends A {}
+ static class B2 extends A {}
+
+ void m() throws B1, B2 {
+ try {
+ if (true) {
+ throw new B1();
+ }
+ else {
+ throw new B2();
+ }
+ } catch (Exception ex) { //effectively final analysis
+ throw ex;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/multicatch/model/Check.java Thu Nov 04 12:57:48 2010 +0000
@@ -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.
+ */
+
+/**
+ * Annotation used by ModelChecker to mark the class whose model is to be checked
+ */
+@interface Check {}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/multicatch/model/Member.java Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,31 @@
+/*
+ * 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 javax.lang.model.element.ElementKind;
+
+/**
+ * Annotation used by ModelChecker to mark a member that is to be checked
+ */
+@interface Member {
+ ElementKind value();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/multicatch/model/Model01.java Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,48 @@
+/*
+ * 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 javax.lang.model.element.ElementKind;
+
+@Check
+class Test {
+
+ class A extends Exception {
+ @Member(ElementKind.METHOD)
+ public void m() {};
+ @Member(ElementKind.FIELD)
+ public Object f;
+ }
+
+ class B1 extends A {}
+ class B2 extends A {}
+
+ void test(){
+ try {
+ if (true)
+ throw new B1();
+ else
+ throw new B2();
+ }
+ catch(B1 | B2 ex) { }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/multicatch/model/ModelChecker.java Thu Nov 04 12:57:48 2010 +0000
@@ -0,0 +1,95 @@
+/*
+ * 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
+ * @bug 6993963
+ * @summary Project Coin: Use precise exception analysis for effectively final catch parameters
+ * @library ../../lib
+ * @build JavacTestingAbstractProcessor ModelChecker
+ * @compile -processor ModelChecker Model01.java
+ */
+
+import com.sun.source.tree.VariableTree;
+import com.sun.source.util.TreePathScanner;
+import com.sun.source.util.Trees;
+import com.sun.source.util.TreePath;
+
+import java.util.Set;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.TypeElement;
+
+@SupportedAnnotationTypes("Check")
+public class ModelChecker extends JavacTestingAbstractProcessor {
+
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ if (roundEnv.processingOver())
+ return true;
+
+ Trees trees = Trees.instance(processingEnv);
+
+ TypeElement testAnno = elements.getTypeElement("Check");
+ for (Element elem: roundEnv.getElementsAnnotatedWith(testAnno)) {
+ TreePath p = trees.getPath(elem);
+ new MulticatchParamTester(trees).scan(p, null);
+ }
+ return true;
+ }
+
+ class MulticatchParamTester extends TreePathScanner<Void, Void> {
+ Trees trees;
+
+ public MulticatchParamTester(Trees trees) {
+ super();
+ this.trees = trees;
+ }
+
+ @Override
+ public Void visitVariable(VariableTree node, Void p) {
+ Element ex = trees.getElement(getCurrentPath());
+ if (ex.getSimpleName().contentEquals("ex")) {
+ assertTrue(ex.getKind() == ElementKind.EXCEPTION_PARAMETER, "Expected EXCEPTION_PARAMETER - found " + ex.getKind());
+ for (Element e : types.asElement(ex.asType()).getEnclosedElements()) {
+ Member m = e.getAnnotation(Member.class);
+ if (m != null) {
+ assertTrue(e.getKind() == m.value(), "Expected " + m.value() + " - found " + e.getKind());
+ }
+ }
+ assertTrue(assertionCount == 3, "Expected 3 assertions - found " + assertionCount);
+ }
+ return super.visitVariable(node, p);
+ }
+ }
+
+ private static void assertTrue(boolean cond, String msg) {
+ assertionCount++;
+ if (!cond)
+ throw new AssertionError(msg);
+ }
+
+ static int assertionCount = 0;
+}