Kotlin - How to get KClass<*> annotation parameter from annotation processor


Ahmed Mourad:

I have the following 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
}

I need to get the value ownerand put it consumerin my annotation processor.

I have tried this approach:

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"
)

but this gives me this error:

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

I also tried this:

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

but this gives me this error:

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.DataOwneris the value ownerpassed to the annotation .

So that's where I'm stuck right now, any help would be greatly appreciated. Thanks!

Alexey Romanov:

Let's start with why the second method doesn't work:

此方法返回的注释可以包含其值为Class类型的元素。该值不能直接返回:定位和加载类所需的信息(例如要使用的类加载器)不可用,并且该类可能根本无法加载。尝试通过在返回的注释上调用相关方法来读取Class对象,将导致MirroredTypeException,可以从中提取相应的TypeMirror。同样,尝试读取Class []值的元素将导致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 }

并返回TypeMirrorDataOwner

Related


How to get annotation parameter in annotation processor

Hiosdra : I'm writing my own annotation processor and I'm trying to make my annotation's parameter like the code below in the procedure method: roundEnv.getElementsAnnotatedWith(annotation).forEach { val annotation = it.getAnnotation(annotation)

How to get annotation parameter in annotation processor

Hiosdra : I'm writing my own annotation processor and I'm trying to make the parameters of my annotations like the code below in the procedure method: roundEnv.getElementsAnnotatedWith(annotation).forEach { val annotation = it.getAnnotation(annotation)

How to get annotation parameter in annotation processor

Hiosdra : I'm writing my own annotation processor and I'm trying to make my annotation's parameter like the code below in the procedure method: roundEnv.getElementsAnnotatedWith(annotation).forEach { val annotation = it.getAnnotation(annotation)

How to get annotation parameter in annotation processor

Hiosdra : I'm writing my own annotation processor and I'm trying to make my annotation's parameter like the code below in the procedure method: roundEnv.getElementsAnnotatedWith(annotation).forEach { val annotation = it.getAnnotation(annotation)

How to write annotation processor for kotlin/native?

Nishida Is it possible to write our annotation processor in kotlin/native or kotlin multiplatform module? If yes, so what? I found this tutorial for kotlin: https://github.com/osamarao/ViewModelAnnotationsKt but I 'm not sure how to implement the same in kotli

How to get annotation of Kotlin property from Java?

Ricardo Meneghin Filho: I have a kotlin class whose properties have Java annotations, but I can't access these annotations using Java reflection: class TestClass(@A var myProperty : String) The following tests appear empty: public class TestKotlinField {

How to get annotation of Kotlin property from Java?

Ricardo Meneghin Filho: I have a kotlin class whose properties have Java annotations, but I can't access these annotations using Java reflection: class TestClass(@A var myProperty : String) The following tests appear empty: public class TestKotlinField {

How to check method parameter type in annotation processor?

Tovey This would be easy if pure reflection was used, but the annotation processor world seems to be different. How do I TypeMirrorreturn from getParameterTypes()to String.class? In my annotation processor, I want to check if the currently accessed method has

How to check method parameter type in annotation processor?

Tovey This would be easy if pure reflection was used, but the annotation processor world seems to be different. How do I TypeMirrorreturn from getParameterTypes()to String.class? In my annotation processor, I want to check if the currently accessed method has

How to check method parameter type in annotation processor?

Tovey This would be easy if pure reflection was used, but the annotation processor world seems to be different. How do I TypeMirrorreturn from getParameterTypes()to String.class? In my annotation processor, I want to check if the currently accessed method has

How to check method parameter type in annotation processor?

Tovey This would be easy if pure reflection was used, but the annotation processor world seems to be different. How do I TypeMirrorreturn from getParameterTypes()to String.class? In my annotation processor, I want to check if the currently accessed method has

How to check method parameter type in annotation processor?

Tovey This would be easy if pure reflection was used, but the annotation processor world seems to be different. How do I TypeMirrorreturn from getParameterTypes()to String.class? In my annotation processor, I want to check if the currently accessed method has

How to get KClass of Kotlin constructor parameter

j Using Kotlin reflection, I am trying to check the KClass for each parameter of the main constructor of a class. Given a simple data class like this: data class MyPerson(val name: String, val age: Int) val modelClass = MyPerson::class I got its main construc

How to get KClass of Kotlin constructor parameter

j Using Kotlin reflection, I am trying to check the KClass for each parameter of the main constructor of a class. Given a simple data class like this: data class MyPerson(val name: String, val age: Int) val modelClass = MyPerson::class I got its main construc

Get fields of class from annotation processor annotation object

Luke: I am working on my first annotation processor. I'm trying to get through a field (which is a method field) of the declared object on the annotated class. E.g: public class Person { private String name; private String surname; } ... public void m

Get fields of class from annotation processor annotation object

Luke: I am working on my first annotation processor. I'm trying to get through a field (which is a method field) of the declared object on the annotated class. E.g: public class Person { private String name; private String surname; } ... public void m