Kotlin 编译器插件:如何检查属性是否有注释?

问题描述 投票:0回答:2

我正在创建一个 Kotlin 编译器插件,其中我需要检查数据类的属性是否有注释:

data class User(
     @MyAnnotation
     val name: String
)

我通过以下方式覆盖

DelegatingClassBuilder.newField

internal class MyClassBuilder(
    delegateBuilder: ClassBuilder
) : DelegatingClassBuilder(delegateBuilder) {
    override fun newField(
        origin: JvmDeclarationOrigin,
        access: Int,
        name: String,
        desc: String,
        signature: String?,
        value: Any?
    ): FieldVisitor {
        val visitor = super.newField(origin, access, name, desc, signature, value)
        val descriptor = origin.descriptor as? PropertyDescriptor ?: return visitor
        if (descriptor.annotations.hasAnnotation(FqName("com.example.MyAnnotation"))) {
            // I never get here
        }
        return visitor
    }
}

问题:无论我的属性是否有注释,

descriptor.annotations
都不会包含我的注释。如果我将注释使用目标更改为其他任何内容,我仍然没有得到注释。

同时,如果我注释一个函数并覆盖

newMethod
,我可以使用非常相似的代码获得该函数的注释。

问题:如何获取数据类中属性的注释?

java kotlin annotations kotlinc
2个回答
2
投票

我想我的回答不会对你有帮助,但对任何有未来问题的人来说。 对于没有Target的字段注释,编译器将生成一个具有注释的函数。 所以,

data class User(@MyAnnotation val name: String)

将编译为以下函数:

  • getName
  • getName$annotations
  • ...

顾名思义,注释

@MyAnnotation
位于
getName$annotations

您可以通过指定目标来避免这种情况:

data class User(@field:MyAnnotation val name: String)

有了目标,就可以直接通过

newField
函数引用;否则,您必须通过
newMethod
函数访问它并提取该字段。如果您为最终用户开发插件,您可能应该实现这两种方法,因为最终用户可能(不)添加目标


0
投票

试试这个:

myObject::class
    .memberProperties
    .forEach {
        if (it.hasAnnotation<FooBar>()) {
             val annotation = it.findAnnotation<FooBar>() 
             // doYourStuff()
        }
            

在数据类中:

@property:FooBar
val myField: Any
© www.soinside.com 2019 - 2024. All rights reserved.