Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get package name of a annotated class within AnnotationProcessor

I have a class which I process with an AnnotationProcessor. While in the process I have an instance of javax.lang.model.element.Element where I can i.e. get the name of the the annotated class by .getSimpleName(). What I know need is the packageName (com.software.cool) of the annotated class.

Any idea how to go through the API to receive it?

like image 519
xetra11 Avatar asked Oct 12 '17 14:10

xetra11


People also ask

How annotation processor works java?

Annotation Processing APIEach annotation processor, in turn, is called on the corresponding sources. If any files are generated during this process, another round is started with the generated files as its input. This process continues until no new files are generated during the processing stage.


2 Answers

You definitely do not want to use getQualifiedName: it will produce surprising results in some cases. For example, it is impossible to distinguish last part of package name and parent class of inner classes: in "java.util.Map.Entry" is "Map" a part of package name or the name of containing class for Entry? What if instead of "java.util.Map.Entry" it is "a.b.c.d" (a typical case for Proguard-processed code)?

Likewise, for classes in default (unnamed) package there won't be anything before the dot…

With getQualifiedName your parsing code will be complex and unreliable. Generally speaking, when you have to use string representations of Element you are doing something wrong.

This is the proper pattern for getting package of element:

Element enclosing = element;
while (enclosing.getKind() != ElementKind.PACKAGE) {
    enclosing = enclosing.getEnclosingElement();
}
PackageElement packageElement = (PackageElement) enclosing;

This will correctly get package in all cases.

like image 45
user1643723 Avatar answered Oct 30 '22 03:10

user1643723


The best way to go is to ProcessingEnvironment.getElementUtils() which has a very handy method called getPackageOf. In order to get ProcessingEnviroment you have to override init method within AbstractProcessor implementation.

public class DynamicServiceProcessor extends AbstractProcessor {

private ProcessingEnvironment processingEnvironment;
private Elements elementUtils;

@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
    super.init(processingEnvironment);
    this.processingEnvironment = processingEnvironment;
    this.elementUtils = processingEnvironment.getElementUtils();
}

@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
    ...
    for (Element element : roundEnvironment.getElementsAnnotatedWith(DynamicService.class)) {
        PackageElement packageElement = processingEnvironment.getElementUtils().getPackageOf(element);
    }
    ...
like image 143
Serge Avatar answered Oct 30 '22 02:10

Serge