kotlin 注释处理器中的可空类型

Nullable types in kotlin annotation processor

我正在为 Kotlin 开发注释处理器,因为处理过的元素在 Java 中,所以我没有收到可空值 ? 而不是带有 @Nullable 注释,这很好,但我在接收类型和高阶函数中的 null 参数时遇到问题,对于普通参数。

var someNullField: String? = "" 

我将在处理过程中收到 java.lang.String,其注释中包含 @org.jetbrains.annotations.Nullable

但是 List<String?> 例如 return 我 java.util.List<java.lang.String> 没有任何注释不在主要元素中不在导致未知可空性状态的类型参数中

我尝试使用 javax.lang.model.util.Types 来查找某种结果,但没有找到。

我现在使用的一些代码:

val utils = processingEnvironment.typeUtils
val type = fieldElement.asType()
if (type is DeclaredType) {
    val typeElement = utils.asElement(type)
    type.typeArguments
            .forEach {
                //Trying different ways and just printing for possible results
                val capture = utils.capture(it)
                val erasure = utils.erasure(it)
                val element = utils.asElement(it)
                printMessage("element: $element isNullable: ${element.isNullable()} isNotNull: ${element.isNotNull()}\ncapture: $capture isNullable: ${capture.isNullable()} isNotNull: ${capture.isNotNull()}\nerasure: $erasure isNullable: ${erasure.isNullable()} isNotNull: ${erasure.isNotNull()}")
            }
}

我们将不胜感激。

一点必要的历史:从 Java 6 开始(镜像 API 制作时 public) Java 注释不能用于任何东西,但是相同类型的顶级元素,可通过反射访问。您可以注释 类、方法和字段,但不能注释类型参数 (List<String>) 或局部变量 (String value = ...)。 Sun/Oracle 工程师们已经承认了这个限制,并且在 Java 8 中诞生了所谓的 "type annotations"。

类型注释可以针对任何对象的类型:局部变量的类型数组组件类型, type variable type and even return type (后面的注解放置方式类似,但与旧式注解不同方法!)。类型注释是通过新的 @Target 值创建的:ElementType#TYPE_USE.

Kotlin 人写的时候

List<String?>

这真的意味着

List<@Nullable String>

可以读作:"the list of nullable String elements".

由于 type 本身就是目标,您应该通过检查它的原始 TypeMirror 来获得注释(不要为擦除或捕获的 TypeMirrors 而烦恼,它们没有足够的源代码连接来保留注释)。巧合的是,Mirror API 被重构,产生了新的接口 AnnotatedConstruct,并方便地使 TypeMirror 成为它的后代。


现在有个坏消息:到 Java 8 发布时,对检查类型注释的支持显然还没有生产就绪,所以它被砍掉了。 JSR 已被重写为暗示 "TypeMirror#getAnnotationMirrors" 应该 return 什么都没有。

从 public API 中删除的部分支持仍然可以通过 Oracle 的供应商特定 Tree API (supported in javac only). The TypeMirror, returned by Tree#getTypeMirror may contain the annotation the way you are expecting it to. But since it is buggy, you will only be able to get annotations via series of hacks, and ultimately, this won't work at all times (such as in case of nested type arguments). See this question 获得,用于该方向的一些研究。

The fix 因为那个烂摊子被合并到 Java 9 中。我还没有测试过它,但看起来 TypeMirror#getAnnotationMirrors 可能最终会起作用。没有计划将修复程序反向移植到旧的 Java 版本。