JavaPoet - 编写对静态泛型方法的调用

时间:2018-04-26 17:15:21

标签: java annotations auto-value 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来获取:{/ p>

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 个答案:

答案 0 :(得分: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())。