9

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

var someNullField: String? = "" 

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

但是List<String?>例如将返回我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()}")
            }
}

所有帮助将不胜感激。

4

1 回答 1

6

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

类型注释可以针对任何类型:局部变量类型、数组组件类型、类型变量类型甚至返回类型(稍后的注释放置类似,但与方法上的老式注释不同!)。类型注释是通过新@Target值创建的:ElementType#TYPE_USE

当 Kotlin 人写作时

List<String?>

这真的意味着

List<@Nullable String>

可以读作:“可为空的字符串元素列表”。

由于类型本身是目标,因此您应该通过检查它的原始来获得注释TypeMirror(不要打扰已擦除或捕获的 TypeMirror,它们与源代码的连接不足以保留注释)。巧合的是,对 Mirror API 进行了重构,产生了新的接口AnnotatedConstruct,并且方便地使 TypeMirror 成为它的后代。


现在是坏消息:到 Java 8 发布时,对检查类型注释的支持显然还没有为生产做好准备,所以它被淘汰了。JSR 已被重写以暗示“TypeMirror#getAnnotationMirrors”应该不返回任何内容。

从公共 API 中删除的部分支持仍然可以通过 Oracle 的特定于供应商的Tree API获得(仅在 javac 中支持)。Tree#getTypeMirror 返回的 TypeMirror可能包含您期望的注释。但是由于它是错误的,您只能通过一系列 hack 获得注释,最终,这不会在任何时候都有效(例如在嵌套类型参数的情况下)。有关该方向的一些研究,请参阅此问题

Java 9 中已合并了该问题的修复程序。我还没有对其进行测试,但看起来 TypeMirror#getAnnotationMirrors 最终可能会起作用。没有计划将修复程序向后移植到较旧的 Java 版本。

于 2017-08-20T07:14:13.300 回答