Обработка аннотаций Java: ссылка на сгенерированный тип в другом сгенерированном коде

@GenerateInterface class A {}

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

Мой процессор аннотаций должен генерировать эти интерфейсы:

interface IA {}

interface IB {
  void setA(IA a);
}

B компилируется нормально с правильным оператором импорта. IB однако пропускает параметр IA a, Я использую javapoet для генерации интерфейсов. Код для составления параметров метода:

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 является ExecutableElement, p.asType() содержит только простое имя IA, С этой точки зрения, IA возможно, еще не было сгенерировано, поэтому полное имя не доступно.

На данный момент я генерирую интерфейсы один за другим для каждого аннотированного класса. Насколько я понимаю, мне прежде всего нужен список всех аннотированных классов и их производных имен интерфейсов. Затем, когда я сталкиваюсь с параметром, который еще не сгенерирован, введите полное имя из списка выше, чтобы вставить правильный оператор импорта.

Есть ли умный способ сделать это? Можно ли хотя бы отличить скомпилированные типы от уже скомпилированных?

Изменить: полный код

1 ответ

Я работаю над процессором аннотации для моей библиотеки Kripton Persistence, и у меня похожая проблема. Моя проблема похожа, но не та же: в моих сгенерированных классах я ссылаюсь на другие сгенерированные классы, сгенерированные в одном раунде.

Решение, которое я применяю, просто "генерирует" TypeName вручную. В моем процессоре аннотаций я использую определенный класс, источник которого вы можете найти здесь.

Kripton создаст классы, которые реализуют шаблон DAO на основе SQLite для платформы Android. Когда я сгенерировал свой DataSource, мне нужно сослаться на классы DAO, которые будут сгенерированы в одном раунде. Чтобы сделать это и избежать той же проблемы, я создаю связанное имя TypeName. Вы можете увидеть это по методу buildDataSource класса BindDataSourceBuilder.

Надеюсь, что информация все еще полезна для вас.

Другие вопросы по тегам