JavaPoet — запись вызова статического универсального метода

Я хочу написать CodeBlock, который в основном вызывает статический универсальный метод, но вывод, который я получаю с JavaPoet, генерирует ошибки компилятора.

Например, учитывая следующий класс автоматического значения:

@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?


person smac89    schedule 26.04.2018    source источник


Ответы (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()).

person smac89    schedule 28.04.2018