Retrieve annotations from KType

对着背影说爱祢 提交于 2021-01-28 03:24:37

问题


I have a simple TYPE_USE annotation:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})
public @interface Cool {
}

And the following sample Kotlin class:

class Item(
        id: Long? = null,
        var names: List<@Cool String> = emptyList())

Is there any way to extract the annotation using Java reflection?

Item.class.getMethod("getName").getAnnotatedReturnType() loses the annotations, same with getting the field.

Can I even get the annotation from Kotlin?

Item::class.memberProperties.elementAt(0).returnType return a KType which has the annotation, but I don't see a way to extract it. Nor to obtain an AnnotatedType from KType, even though I have JDK8 extensions.

All I see is KType#javaType but this returns Type, not AnnotatedType... so it looses the annotations again.


回答1:


Edit: this is a bug and has been reported. There is not yet a target version, but its priority has been set to Major. This was fixed in Kotlin 1.3.


TL; DR: no...?


The item annotated with @Cool is the first type argument, so you need to retrieve it:

val type = Item::class.memberProperties.elementAt(0).returnType

val arg = type.arguments[0]
println(arg) // KTypeProjection(variance=INVARIANT, type=@Cool kotlin.String)

Unfortunately there doesn't seem to be a way to retrieve the annotations on a KType (as you have mentioned).

Strangely, this is a very internal process. Looking into the source for KTypeImpl shows that toString is implemented via ReflectionObjectRenderer.renderType(type), (where type is a KotlinType) which is delegated to DescriptorRenderer.FQ_NAMES_IN_TYPES, which we can see is a DescriptorRenderer with modifiers ALL.

The renderer checks if the type is a subclass of kotlin.reflect.jvm.internal.impl.descriptors.annotations.Annotated, and then accesses its annotations property.

I tried this:

val retType = Item::class.memberProperties.elementAt(0).returnType

val arg = retType.arguments[0]
println(arg) // KTypeProjection(variance=INVARIANT, type=@Cool kotlin.String)

val type = arg.type!!
println(type)

val field = type::class.memberProperties.first { it.name == "type" }
val kotlinType = field.call(type) as Annotated
println(kotlinType)

println(kotlinType.annotations)

Unfortunately, I get a ClassNotFoundException for org.jetbrains.kotlin.types.KotlinType, so that option is gone.

Equally strangely, KType is not a subtype of KAnnotatedElement (which is why it has no annotations property).

I suppose this may have been an oversight, since KTypeImpl wraps a KotlinType, which does contain annotations.



来源:https://stackoverflow.com/questions/48948311/retrieve-annotations-from-ktype

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!