0

我想编写一个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();
        }
    }
}

现在说我想生成一个对testBuilderfor 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

4

1 回答 1

0

您只需要注意泛型类型是方法的一部分,而不是类,因此当您编写方法调用时,请尝试将泛型与您编写方法调用的部分相关联。

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())。

于 2018-04-28T19:02:31.847 回答