Found this in my own annotation processor.
Let's define these three classes first:
---- MyAnnotation.java ----
public @interface MyAnnotation {
String value();
}
---- MyClass.java ----
@MyAnnotation
public class MyClass {
}
---- MyProcessor.java ----
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedSourceVersion;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic.Kind;
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class MyProcessor extends AbstractProcessor {
@Override
public Set<String> getSupportedAnnotationTypes() {
return Collections.singleton(MyAnnotation.class.getName());
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (TypeElement annotation : annotations) {
for (Element method : roundEnv.getElementsAnnotatedWith(annotation)) {
method.getAnnotation(MyAnnotation.class).value(); // throws IncompleteAnnotationException
}
}
return true;
}
}
This the sequence of action exposing the issue:
1. Compile the processor first:
$ javac MyProcessor.java
2. Compile "user" classes without annotation processor, javac fails with reasonable message telling user to supply the value():
$ javac MyAnnotation.java MyClass.java
MyClass.java:1: error: annotation MyAnnotation is missing value for the attribute value
@MyAnnotation
^
1 error
3. Now do the same, but with annotation processor on board:
$ javac MyAnnotation.java MyClass.java -processor MyProcessor
An annotation processor threw an uncaught exception.
Consult the following stack trace for details.
java.lang.annotation.IncompleteAnnotationException: MyAnnotation missing element value
at sun.reflect.annotation.AnnotationInvocationHandler.invoke(AnnotationInvocationHandler.java:72)
at com.sun.proxy.$Proxy4.value(Unknown Source)
at MyProcessor.process(MyProcessor.java:33)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:793)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:722)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1700(JavacProcessingEnvironment.java:97)
at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1029)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1163)
at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1108)
at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:824)
at com.sun.tools.javac.main.Main.compile(Main.java:439)
at com.sun.tools.javac.main.Main.compile(Main.java:353)
at com.sun.tools.javac.main.Main.compile(Main.java:342)
at com.sun.tools.javac.main.Main.compile(Main.java:333)
at com.sun.tools.javac.Main.compile(Main.java:76)
at com.sun.tools.javac.Main.main(Main.java:61)
BAM! Exception with uber-stacktrace in your head. That means annotation processor got exposed with the incomplete annotation, but before javac could tell user what is wrong?
The most troubling part is that there is no sane API in annotation processor to catch this kind of behavior, except for catching the exception and moving on with printing the exception of its own. My expectation would be, however, that the syntax/semantics checks for the existing classes should be done before exposing them for further processing.
Let's define these three classes first:
---- MyAnnotation.java ----
public @interface MyAnnotation {
String value();
}
---- MyClass.java ----
@MyAnnotation
public class MyClass {
}
---- MyProcessor.java ----
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedSourceVersion;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic.Kind;
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class MyProcessor extends AbstractProcessor {
@Override
public Set<String> getSupportedAnnotationTypes() {
return Collections.singleton(MyAnnotation.class.getName());
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (TypeElement annotation : annotations) {
for (Element method : roundEnv.getElementsAnnotatedWith(annotation)) {
method.getAnnotation(MyAnnotation.class).value(); // throws IncompleteAnnotationException
}
}
return true;
}
}
This the sequence of action exposing the issue:
1. Compile the processor first:
$ javac MyProcessor.java
2. Compile "user" classes without annotation processor, javac fails with reasonable message telling user to supply the value():
$ javac MyAnnotation.java MyClass.java
MyClass.java:1: error: annotation MyAnnotation is missing value for the attribute value
@MyAnnotation
^
1 error
3. Now do the same, but with annotation processor on board:
$ javac MyAnnotation.java MyClass.java -processor MyProcessor
An annotation processor threw an uncaught exception.
Consult the following stack trace for details.
java.lang.annotation.IncompleteAnnotationException: MyAnnotation missing element value
at sun.reflect.annotation.AnnotationInvocationHandler.invoke(AnnotationInvocationHandler.java:72)
at com.sun.proxy.$Proxy4.value(Unknown Source)
at MyProcessor.process(MyProcessor.java:33)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:793)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:722)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$1700(JavacProcessingEnvironment.java:97)
at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1029)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1163)
at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1108)
at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:824)
at com.sun.tools.javac.main.Main.compile(Main.java:439)
at com.sun.tools.javac.main.Main.compile(Main.java:353)
at com.sun.tools.javac.main.Main.compile(Main.java:342)
at com.sun.tools.javac.main.Main.compile(Main.java:333)
at com.sun.tools.javac.Main.compile(Main.java:76)
at com.sun.tools.javac.Main.main(Main.java:61)
BAM! Exception with uber-stacktrace in your head. That means annotation processor got exposed with the incomplete annotation, but before javac could tell user what is wrong?
The most troubling part is that there is no sane API in annotation processor to catch this kind of behavior, except for catching the exception and moving on with printing the exception of its own. My expectation would be, however, that the syntax/semantics checks for the existing classes should be done before exposing them for further processing.
- duplicates
-
JDK-8014016 javac is too late detecting invalid annotation usage
-
- Closed
-