JavaPoet - запись вызова статического универсального метода
Я хочу написать CodeBlock
который в основном вызывает статический универсальный метод, но вывод, который я получаю с JavaPoet
генерирует ошибки компилятора.
Например, задан следующий класс значений auto:
@AutoValue
public abstract class Test<T> {
public abstract Test1<String> o();
public abstract T p();
@AutoValue
public static abstract class Test1<T> {
public abstract T value();
public static <T> Test1<T> create(T value) {
return Test1.<T>builder()
.value(value)
.build();
}
public static <T> Builder<T> builder() {
return new AutoValue_ValueWithOperator.Builder<>();
}
public static <T> Builder<T> testBuilder() {
return builder();
}
@AutoValue.Builder
public abstract static class Builder<T> {
public abstract Builder<T> value(T value);
public abstract Test1<T> build();
}
}
}
Теперь скажите, что я хотел сгенерировать этот вызов testBuilder
за Test1<String>
(внутри теста), я сначала получаю TypeName
при выполнении:
TypeName elementReturnType = TypeName.get(someTypeMirror);
Теперь, когда я делаю:
CodeBlock.of("$T.testBuilder()" + ".build()", elementReturnType);
Он генерирует код, который выглядит следующим образом:
Test.Test1<String>.testBuilder().build();
Это неправильно, правильный синтаксис должен быть:
Test.Test1.<String>testBuilder().build();
Обратите внимание на размещение универсального параметра... Как я могу сделать это с JavaPoet? У меня есть правильный тип, как вы можете видеть по сгенерированному коду, но он просто поместил универсальный параметр в неправильном месте.
У меня вопрос, как мне добавить общие параметры для вызова метода с помощью JavaPoet CodeBlock
?
1 ответ
Вы просто должны заметить, что универсальный тип является частью метода, а не класса, поэтому, когда вы пишете вызов метода, попробуйте связать универсальный с той частью, где вы пишете вызов метода.
TypeName elementReturnType = TypeName.get(elementTypeMirror);
Предполагая, что у вас есть элемент, представляющий метод для вызова:
ExecutableElement method = ...;
if (methodElement.getTypeParameters().isEmpty()) {
return CodeBlock.of("$T.$N().build()", elementReturnType, methodElement.getSimpleName());
}
String typeParams = MoreTypes
.asDeclared(returnType)
.getTypeArguments()
.stream()
.map(MoreTypes::asTypeElement)
.map(TypeElement::getQualifiedName)
.collect(Collectors.joining("<", ",", ">");
Это даст вам параметры типа, которые вы можете прикрепить к названию имени метода (method.getSimpleName()
).