在注释处理器中获取没有任何注释的字段类型

Getting type of field without any annotations in annotation processor

我已经为此苦苦挣扎了一段时间,依靠各种神秘的转换和对 toString 的操作来让它工作,但必须有一种 正确的 方式来做这个。

我有一个注释处理器,如下所示:

@SupportedAnnotationTypes("processor.EchoFields")
@SupportedSourceVersion(SourceVersion.RELEASE_11)
public class TestProcessor extends AbstractProcessor {
    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        roundEnvironment.getElementsAnnotatedWith(EchoFields.class)
                .stream()
                .filter(e -> e.getKind() == ElementKind.CLASS)
                .map(TypeElement.class::cast)
                .forEach(this::echoFields);
        return false;
    }

    private void echoFields(TypeElement element) {
        log("Fields of class %s", element);
        element.getEnclosedElements().stream()
                .filter(e -> e.getKind() == ElementKind.FIELD)
                .map(VariableElement.class::cast)
                .forEach(this::echoField);
    }

    private void echoField(VariableElement element) {
        log("\tField %s of type %s", element.getSimpleName().toString(), element.asType().toString());
        for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) {
            log("\t\t%s", annotationMirror);
        }
    }

    private void log(String format, Object... parameters) {
        processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, String.format(format, parameters));
    }

}

当 运行 在我的测试中 class 看起来像这样:

@EchoFields
public class Pojo {

    @TypeAnnotation
    @FieldAnnotation
    private List<String> aListOfStrings;
}

(@TypeAnnotation@FieldAnnotation 有目标 TYPE(_USE)FIELD分别)

我得到以下输出:

Note: Fields of class consumer.Pojo
Note:   Field aListOfStrings of type @processor.TypeAnnotation java.util.List<java.lang.String>
Note:           @processor.FieldAnnotation

而我想要的是:

Note: Fields of class consumer.Pojo
Note:   Field aListOfStrings of type java.util.List<java.lang.String>
Note:           @processor.TypeAnnotation
Note:           @processor.FieldAnnotation

重要的部分是 java.util.List<java.lang.String> 没有 @processor.TypeAnnotation - 列出 @processor.TypeAnnotation 和注释只是一个奖励,而不是我 需要.

不过我似乎找不到任何方法来做到这一点。每次我发现删除注释的内容时,我也会丢失类型参数 (java.lang.String)。我在实现注释处理 API 的 classes 中四处寻找,那里肯定有一些方法可以做我想做的事——但我找不到通过 [=57] 调用它们的任何方法=] API 并且我不想依赖实现细节(特别是因为当我在 JDK 8 上尝试这个时我得到了截然不同的实现)。

https://github.com/Raniz85/processor-test 有一个 运行 可用的 Gradle 项目,只需克隆和 运行 ./gradlew build

由于 TypeAnnotation 被标记为 TYPE+TYPE_USE(请注意 TYPE 与此问题无关)而不是 FIELD,因此它根本不是字段上的注释,但是实际上是在字段的声明类型上。您也可以在其他事物上放置 TYPE_USE 注释,例如局部变量 - 但您不能从普通的注释处理器中读取它们。来自 :

The TYPE_USE annotations are a bit tricky, because the compiler treats them differently, than the "old usage" annotations.

So as you correctly observed, they are not passed to annotation processor, and your process() method will never receive them.

在不知道你试图解决什么问题的情况下,很难说你是否真的想要 TYPE_USE,或者你是否只是在试验注释可能的不同可能目标有。可能你只想在这里使用 FIELD,因为你正在编写一个注释处理器(它遍历你的 API,而不是源代码本身,所以你会错过本地变量上的任何 TYPE_USE 等).

--

此外,在使用 TypeMirror.toString() 或 Element.toString() 时要非常小心,在某些环境中,它们不会输出您所期望的。使用 Name 类型,或类似于 javapoet 的 TypeName 层次结构。