import java.lang.reflect.Method; import testlib.reflection.qual.ReflectBottom; import testlib.reflection.qual.Sibling1; import testlib.reflection.qual.Sibling2; import testlib.reflection.qual.Top; public class AnonymousClassTest { /** * To build/run outside of the JUnit tests: * * <p>Build with $CHECKERFRAMEWOKR/framework/tests/build/ on the classpath. Need to either use * Java 8 or the langtools compiler, because annotations on cast are used. * * <p>java AnonymousClassTest MyClass$1.getSib1() MyClass$1.setSib1() MyClass$1.setSib1() * MyClass$1.setSib2() MyClass$1.setSib2() MyClass$1.getSib2() */ public static void main(String[] args) { AnonymousClassTest act = new AnonymousClassTest(); act.returnTypePass(); act.argumentTypePass(); act.argumentTypeFail(); act.returnTypeFail(); } @Sibling1 int sibling1; @Sibling2 int sibling2; public void returnTypePass() { try { Class<?> c = Class.forName("AnonymousClassTest$1"); Method m = c.getMethod("getSib1", new Class[] {}); //TODO: Can we resolve anonymous classes? //:: error: (assignment.type.incompatible) @Sibling1 Object a = m.invoke(anonymous, (@ReflectBottom Object[]) null); } catch (Exception ignore) { ignore.printStackTrace(); } } public void argumentTypePass() { String str = "setSib1"; @Sibling1 int val1 = sibling1; @Sibling1 Integer val2 = val1; try { Class<?> c = Class.forName("AnonymousClassTest$1"); Method m = c.getMethod(str, new Class[] {int.class}); //TODO: Can we resolve anonymous classes? //:: error: (argument.type.incompatible) m.invoke(anonymous, val1); //TODO: Can we resolve anonymous classes? //:: error: (argument.type.incompatible) m.invoke(anonymous, val2); } catch (Exception ignore) { ignore.printStackTrace(); } } public void argumentTypeFail() { String str = "setSib2"; @Sibling1 int val1 = sibling1; @Sibling1 Integer val2 = val1; try { Class<?> c = Class.forName("AnonymousClassTest$1"); Method m = c.getMethod(str, new Class[] {int.class}); //:: error: (argument.type.incompatible) m.invoke(anonymous, val1); //:: error: (argument.type.incompatible) m.invoke(anonymous, val2); } catch (Exception ignore) { ignore.printStackTrace(); } } public void returnTypeFail() { try { Class<?> c = Class.forName("AnonymousClassTest$1"); Method m = c.getMethod("getSib2", new Class[] {}); //:: error: (assignment.type.incompatible) @Sibling1 Object a = m.invoke(anonymous, (@ReflectBottom Object[]) null); } catch (Exception ignore) { ignore.printStackTrace(); } } public @ReflectBottom MyClass anonymous = new @ReflectBottom MyClass() { public @Sibling1 int getSib1() { System.out.println("MyClass$1.getSib1()"); return 1; } public @Sibling2 int getSib2() { System.out.println("MyClass$1.getSib2()"); return 1; } public void setSib1(@Sibling1 int a) { System.out.println("MyClass$1.setSib1()"); } public void setSib2(@Sibling2 int a) { System.out.println("MyClass$1.setSib2()"); } }; class MyClass { public @Top int getSib1() { System.out.println("MyClass.getSib1()"); return 1; } public @Top int getSib2() { System.out.println("MyClass.getSib1()"); return 1; } public void setSib1(@ReflectBottom int a) { System.out.println("MyClass.setSib1()"); } public void setSib2(@ReflectBottom int a) { System.out.println("MyClass.setSib2()"); } } }