TypeElement vs TypeMirror as data models for Java annotation processor

Viewed 77

I'm working on a code generator with annotation processing, and divided the logic into 2 steps:

  1. Analyze the annotated element and create data model, and
  2. Use the data model to generate code using JavaPoet.

The annotation processing API provides us TypeMirrors in most cases. From what I've seen online, using TypeElement in data models seems like a good practice (which can be obtained from TypeMirror).

However JavaPoet in most cases accept TypeMirrors directly, and converting them as TypeElement for the data model seems unnecessary.

Is there an advantage of one vs another as data model?

1 Answers

The types represent different levels of abstraction. TypeElement represent the class, declared in the code, while TypeMirror represents that class' specific usage.

For example:

class Foo {
    public void hello() {
    }
}

class Bar {
    public void hello(Foo foo) {
    }
}

In this example there will be 2 instances of TypeElement - for each one of the declared classes. Also there will be 2 instances of ExecutableElement, representing each one of the methods (A.hello and B.hello).

If you will take a look at the ExecutableElement of B.hello(), there will be information about method parameters and their types, while in this case, the types will be represented with TypeMirror. From TypeMirror you always can get corresponding TypeElement.

TypeElement - represents class declaration and contains all the information about the declaration itself

TypeMirror - represents the occurance (the specific usage) of the class in the code and has all the information, which is specific to that occurance. From the occurance you always can get the declaration, but not vice versa.

Despite, both entities (TypeElement and TypeMirror) might look representing the same entities at the first glance, but that's not true. Each one of them has some information, which is available only on that specific level of abstraction.

For example: annotations of the declared class or method - are available in corresponding TypeElement/ExecutableElement, but not in TypeMirror.

Another important aspect of difference is generics:

class Foo<T> {
    public void hello() {
    }
}

class Bar {
    public void hello(Foo<String> foo) {
    }
}

In this example, the TypeElement of Foo will have information about type parameters, their constraints, bounds, etc.

But TypeMirror of the B.hello's first parameter will have specific type argument (String), which was used in this specific occurance of using of Foo class

Related