I've struggled with this for a while now, relying on various arcane casts and manipulation of toString to get it working, but there has to be a proper way of doing this.
I've got an annotation processor that looks like this:
@SupportedAnnotationTypes("processor.EchoFields")
@SupportedSourceVersion(SourceVersion.RELEASE_11)
public class TestProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
roundEnvironment.getElementsAnnotatedWith(EchoFields.class)
.stream()
.filter(e -> e.getKind() == ElementKind.CLASS)
.map(TypeElement.class::cast)
.forEach(this::echoFields);
return false;
}
private void echoFields(TypeElement element) {
log("Fields of class %s", element);
element.getEnclosedElements().stream()
.filter(e -> e.getKind() == ElementKind.FIELD)
.map(VariableElement.class::cast)
.forEach(this::echoField);
}
private void echoField(VariableElement element) {
log("\tField %s of type %s", element.getSimpleName().toString(), element.asType().toString());
for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) {
log("\t\t%s", annotationMirror);
}
}
private void log(String format, Object... parameters) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, String.format(format, parameters));
}
}
When run on my test class that looks like this:
@EchoFields
public class Pojo {
@TypeAnnotation
@FieldAnnotation
private List<String> aListOfStrings;
}
(@TypeAnnotation, and @FieldAnnotation have targets TYPE(_USE) and FIELD respectively)
I get the following output:
Note: Fields of class consumer.Pojo
Note: Field aListOfStrings of type @processor.TypeAnnotation java.util.List<java.lang.String>
Note: @processor.FieldAnnotation
Whereas what I want is this:
Note: Fields of class consumer.Pojo
Note: Field aListOfStrings of type java.util.List<java.lang.String>
Note: @processor.TypeAnnotation
Note: @processor.FieldAnnotation
With the important part being java.util.List<java.lang.String>
without @processor.TypeAnnotation
- Listing @processor.TypeAnnotation
with the annotations is just a bonus and not something I need.
I can't seem to find any way of doing this though. Every time I find something that removes the annotation I also lose the type parameters (java.lang.String
). I've poked around in the classes implementing the annotation processing API and there is definitely methods there that do what I want - but I can't find any way of invoking them through the public API and I don't want to rely on implementation details (especially since I got vastly different implementations when I tried this on JDK 8).
There's a runnable Gradle project at https://github.com/Raniz85/processor-test, just clone and run ./gradlew build