From 5db7f040caad72fa2796e31a50f65c280f8730b6 Mon Sep 17 00:00:00 2001 From: GerardPaligot Date: Fri, 12 Feb 2016 11:56:27 +0100 Subject: [PATCH] fix(noclasspath): NPE throws with annotations on primitive type. Closes #529 --- .../support/compiler/jdt/JDTTreeBuilder.java | 4 ++-- .../test/reference/TypeReferenceTest.java | 20 +++++++++++++++++++ src/test/resources/noclasspath/A.java | 18 +++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 src/test/resources/noclasspath/A.java diff --git a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java index bbf6cf28bca..83c06cd0d5b 100644 --- a/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/JDTTreeBuilder.java @@ -2558,7 +2558,7 @@ public boolean visit(MarkerAnnotation annotation, BlockScope scope) { private boolean visitMarkerAnnoation(MarkerAnnotation annotation, BlockScope scope) { CtAnnotation a = factory.Core().createAnnotation(); - CtTypeReference t = references.getTypeReference(annotation.resolvedType); + CtTypeReference t = references.getTypeReference(annotation.resolvedType, annotation.type); a.setAnnotationType(t); context.enter(a, annotation); skipTypeInAnnotation = true; @@ -2738,7 +2738,7 @@ public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) { } private boolean isContainsInTypeAnnotation(TypeBinding binding, Annotation a) { - return !binding.hasTypeAnnotations() || !containsInTypeAnnotation(a, binding.getTypeAnnotations()); + return binding == null || !binding.hasTypeAnnotations() || !containsInTypeAnnotation(a, binding.getTypeAnnotations()); } private boolean containsInTypeAnnotation(Annotation a, AnnotationBinding[] typeAnnotations) { diff --git a/src/test/java/spoon/test/reference/TypeReferenceTest.java b/src/test/java/spoon/test/reference/TypeReferenceTest.java index cd7ee172bd4..2dbfa094cbb 100644 --- a/src/test/java/spoon/test/reference/TypeReferenceTest.java +++ b/src/test/java/spoon/test/reference/TypeReferenceTest.java @@ -7,6 +7,7 @@ import spoon.compiler.SpoonResourceHelper; import spoon.reflect.code.CtFieldRead; import spoon.reflect.code.CtInvocation; +import spoon.reflect.code.CtNewClass; import spoon.reflect.declaration.CtClass; import spoon.reflect.declaration.CtField; import spoon.reflect.declaration.CtInterface; @@ -392,6 +393,25 @@ public void testInvocationWithFieldAccessInNoClasspath() throws Exception { TestUtils.canBeBuilt("./src/test/resources/noclasspath/TestBot.java", 8, true); } + @Test + public void testAnnotationOnMethodWithPrimitiveReturnTypeInNoClasspath() throws Exception { + // contract: In no classpath mode, if we have an annotation declared on a method and overridden + // from a super class in an anonymous class, we should rewrite correctly the annotation and don't + // throw a NPE. + final Launcher launcher = new Launcher(); + launcher.addInputResource("./src/test/resources/noclasspath/A.java"); + launcher.setSourceOutputDirectory("./target/class-declaration"); + launcher.getEnvironment().setNoClasspath(true); + launcher.run(); + + final CtClass aClass = launcher.getFactory().Class().get("A"); + final CtClass anonymousClass = aClass.getElements(new TypeFilter<>(CtNewClass.class)).get(0).getAnonymousClass(); + final CtMethod run = anonymousClass.getMethod("run"); + assertNotNull(run); + assertEquals(1, run.getAnnotations().size()); + assertEquals("@Override" + System.lineSeparator(), run.getAnnotations().get(0).toString()); + } + class A { class Tacos { } diff --git a/src/test/resources/noclasspath/A.java b/src/test/resources/noclasspath/A.java new file mode 100644 index 00000000000..1e8cbddb64a --- /dev/null +++ b/src/test/resources/noclasspath/A.java @@ -0,0 +1,18 @@ +import example.B; + +class A extends B { + + private Runnable runnable; + + public void foo() { + synchronized (lock) { + runnable = new Runnable() { + + @Override + public void run() { + + } + }; + } + } +} \ No newline at end of file