I am just starting to learn annotation processing in Java. I have @MyAnnotation
which targets ElementType.FIELD
, In my Processor
I am limiting the annotation to only allow non-null unique value
. Which is working as it should.
While logging errors in case where there is infact some duplicate value
set to MyAnnotation.value
, I want to provide the complete path of both the existing annotations in the source code and the new duplicate one.
My Annotation:
@Retention(RetentionPolicy.RUNTIME)
@Target(value = ElementType.FIELD)
public @interface ProviderColumn {
String content_id();
}
Example Parent Class.
public class EnclosingParent {
@ProviderColumn(content_id="Hello")
private String value1;
@ProviderColumn(content_id="Hello")
private String value2;
}
My AnnotationProcessor
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment)
{
UniqueColumnNameChecker columnNameChecker = new UniqueColumnNameChecker();
try {
for (Element annotatedElement : roundEnvironment.getElementsAnnotatedWith(ProviderColumn.class)) {
// We can cast it, because we know that it is of ElementType.FIELD
VariableElement variableElement = (VariableElement) annotatedElement;
try {
ProviderColumnId providerColumnId =
new ProviderColumnId(variableElement);
// How can I get the EnclosingParent.class or even just a complete canonical class name?
// throws a DuplicateAnnotationIdException when it detects duplicate entries.
columnNameChecker.addAnnotationColumnName(providerColumnId);
}
catch (IllegalArgumentException e) {
error(variableElement, e.getMessage());
return true;
}
}
}
catch (DuplicateAnnotationIdException ex) {
error(ex.getMessage());
return true;
}
return true;
}
However I am having trouble figuring out how to obtain enclosing class information from a VariableElement
. Since I'm only starting on AnnotationProcessing
I'm not even sure if this is possible and I haven't been able to find any questions related to this issue on StackOverflow or anywhere else.
Expected error output
Duplicate content_id()='Hello' detected, Found at 'com.example.EnclosingParent.value1' and 'com.example.EnclosingParent.value2'.
Note: I realize I can get parent info if I define a new ElementType.TYPE
Annotation and set to the Enclosing class, but I'm looking to avoid that as it adds additional responsibilities for the third party developer.
Stupid question apparently. I was looking in all the wrong places for the enclosing element, found this excellent Annotation Processor Tutorial which states:
Elements and TypeMirrors
...
You can think of it like a XML file you try to parse (or an abstract syntax tree in compiler construction)
And I realized the Element
itself might contain all the information I need.
Just need to call variableElement.getEnclosingElement()
to get the parent Element
From there on it was easy, you can get enclosing class name like so:
element.getEnclosingElement().asType().toString();
This however doesn't guarantee the enclosing element to be of TypeElement
. So just use instanceof
to ensure that it is.