Kotlin-如何从注释处理器获取KClass <*>注释参数

时间:2019-10-18 09:35:19

标签: java kotlin annotations

我有以下注释:

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.SOURCE)
@MustBeDocumented
annotation class Model(
    val owner: KClass<*>,
    val consumer: KClass<*>
)

@Model(DataOwner::class, DataConsumer::class)
interface Student {
    val name: String
    val group: Group
}

我需要在注释处理器中获取ownerconsumer的值。

我已经尝试过这种方法:

private inline fun <reified T> findAnnotationValue(
    element: Element,
    annotationClass: KClass<*>,
    valueName: String
): T? {
    return element.annotationMirrors.map {
        it to it.annotationType.asElement() as TypeElement
    }.firstOrNull { (_, element) ->
        element.qualifiedName.contentEquals(annotationClass.qualifiedName)
    }?.let { (mirror, _) ->
        extractValue(mirror, valueName)
    }
}

private inline fun <reified T> extractValue(
    annotationMirror: AnnotationMirror,
    valueName: String
): T? {
    return annotationMirror.elementValues.toList()
        .firstOrNull { (key, _) ->
            key.simpleName.contentEquals(valueName)
        }?.let { (_, value) ->
            value.value as T
        }
}


val ownerClass: KClass<*> = findAnnotationValue(
    element,
    Model::class,
    "owner"
)

但这给了我这个错误:

e: [kapt] An exception occurred: java.lang.ClassCastException: com.sun.tools.javac.code.Type$ClassType cannot be cast to kotlin.reflect.KClass

我也尝试过:

val ownerClass: KClass<*> = element.getAnnotation(Model::class.java).owner

但这给了我这个错误:

e: [kapt] An exception occurred: javax.lang.model.type.MirroredTypeException: Attempt to access Class object for TypeMirror inc.ahmedmourad.systems.tutors.domain.model.DataOwner

inc.ahmedmourad.systems.tutors.domain.model.DataOwner是传递给注释的owner值。

所以这就是我现在停留的地方,我们将为您提供任何帮助。 谢谢!

1 个答案:

答案 0 :(得分:1)

让我们从第二种方法不起作用的原因开始:

  

The annotation returned by this method could contain an element whose value is of type Class. This value cannot be returned directly: information necessary to locate and load a class (such as the class loader to use) is not available, and the class might not be loadable at all. Attempting to read a Class object by invoking the relevant method on the returned annotation will result in a MirroredTypeException, from which the corresponding TypeMirror may be extracted. Similarly, attempting to read a Class[]-valued element will result in a MirroredTypesException.

显然也适用于KClass

因此对于注释中的类,您只能获得TypeMirror(在这种情况下由Type.ClassType实现,但这是您不应该依赖的内部细节),而不是KClass 。要么采用第一种方法,要么

inline fun <reified T : Annotation> Element.getAnnotationClassValue(f: T.() -> KClass<*>) = try { 
    getAnnotation(T::class.java).f() 
    throw Exception("Expected to get a MirroredTypeException")
} catch (e: MirroredTypeException) {
    e.typeMirror
}

可以用作

element.getAnnotationClassValue<Model> { owner }

并返回TypeMirror的{​​{1}}。