Erik Hofer
Erik Hofer

Reputation: 2656

Java annotation processing: reference generated type in other generated code

@GenerateInterface class A {}

@GenerateInterface class B {
  void setA(IA a) {}
}

My annotation processor should generate these interfaces:

interface IA {}

interface IB {
  void setA(IA a);
}

B compiles fine with correct import statement. IB however, misses the parameter IA a. I use javapoet to generate the interfaces. Code for compying the method parameters:

method.getParameters().forEach(p -> {
  ParameterSpec.Builder parameterBuilder = ParameterSpec.builder(
      TypeName.get(p.asType()),
      p.getSimpleName().toString(),
      p.getModifiers().toArray(new Modifier[p.getModifiers().size()]));
  p.getAnnotationMirrors().stream()
      .map(AnnotationSpec::get)
      .forEach(parameterBuilder::addAnnotation);
  methodBuilder.addParameter(parameterBuilder.build());
});

method is an ExecutableElement. p.asType() only holds the simple name IA. At this point, IA has possibly not been generated yet, so no fully qualified name is available.

At the moment I generate interfaces one by one for each annotated class. As far as I understand I first of all need a list of all annotated classes and their derived interface names. Then when I encounter a parameter that is of a yet to be generated type, get the fully qualified name from the list above to insert a correct import statement.

Is there a smart way to do this? Can I at least distinguish yet to be compiled types from already compiled ones?

Edit: full code

Upvotes: 2

Views: 421

Answers (1)

xcesco
xcesco

Reputation: 4838

I'm working on an Annotation Processor for my Kripton Persistence Library and I have a similar problem. My problem is similar but not the same: in my generated classes I referer other generated classes that are generated in the same round.

The solution that I apply is simply "generate" the TypeName by hand. In my Annotation Processor, I use a specific class, which source you can found here.

Kripton will generate classes that implement SQLite-based DAO pattern for Android platform. When I generated my DataSource, I need to referer the DAO classes that will be generated in the same round. To do this and avoid the same your problem, I generate the associated TypeName. You can see that on method buildDataSource of the class BindDataSourceBuilder.

Hope that information is still useful for you.

Upvotes: 2

Related Questions