Разрешить общие типы объявлений при вызове статического метода

#java #annotations #annotation-processing

#java #примечания #обработка аннотаций

Вопрос:

Я пишу процессор аннотаций, которому необходимо сгенерировать код, вызывающий статический метод, такой как Collectors.toList() (полная подпись: public static <I> Collector<I, ?, List<I>> toList() )

Пример ввода:

 class Pojo<X> {
  public @CollectWith("Collectors.toList()") List<Thing<X>> things;
}
  

Фрагмент кода, сгенерированный выше:

 Collector<Thing<X>, ?, List<Thing<X>>> thingsCollector = Collectors.toList();
  
  • Базовый возвращаемый тип вызова метода всегда Collector<T,A,R>
  • Из контекста вызова код знает R (выше это List<Thing<X>> )
  • Переменные типа T и A I ) неизвестны

Части головоломки

 // Lookup specified Collector method
TypeElement collectors = elements.getTypeElement("java.util.stream.Collectors");
ExecutableElement toListMethod = findMethod(collectors, "toList"); 
DeclaredType toListMethodReturnType = (DeclaredType)toListMethod.getReturnType(); // java.util.stream.Collector<T,?,java.util.List<T>>

// R is already known.
DeclaredType R = ... // java.util.List<Thing<X>>
  

Вопрос: Существует ли какой-либо код, который разрешает отсутствующие переменные типа и может вычислить DeclaredType из thingsCollector , чтобы быть Collector<Thing<X>, ?, List<Thing<X>>> .

Комментарии:

1. Я не понимаю, что вы пытаетесь получить, где у вас сбой? Не могли бы вы, пожалуйста, объяснить

2. Учитывая, что мы знаем R, как нам определить I (или <T, A, R>)

3. Что вы имеете в виду R ? Я вижу r в вашем APT-коде, но returnType это java.util.stream.Collector<T,?,java.util.List<T>> согласно комментарию — вы хотите T ? или List<T> в данном случае? Но чтобы добраться до List<Thing<X>> , вам нужно было бы специализироваться, указав, что T такое ( Things<X> ), а затем прочитать последний параметр типа?

4. Проверьте эту библиотеку . Не уверен, какими функциями он обладает, но это единственное, с чем я когда-либо сталкивался, что звучит уместно. Если я не ошибаюсь, библиотека, которая работает с java.lang.reflect.Type (т. Е. загруженными типами), была бы бесполезна, поскольку процессоры аннотаций работают только с javax.lang.model.type (которые, как я понимаю, являются только дескрипторами типов, а не фактическими загруженными типами), верно? Я думаю, что связанная библиотека предоставляет impl на основе отражения, что может позволить вам использовать библиотеки отражения обычного типа, такие как GenTyRef , но сейчас я просто предполагаю.

5. Если разобраться в этом немного подробнее, то у него есть ReflectionTypes#resolveActualTypeArguments который, кажется, делает именно то, что вам нужно. Не могу преобразовать это в правильный ответ, поскольку сейчас у меня нет компьютера, поэтому я публикую только комментарии. Кстати, связанная с Java проблема была закрыта как поставленная в JDK8, что означает, что это уже на Java, я думаю, нет необходимости во внешней библиотеке.