簡體   English   中英

Kotlin - 如何從注釋處理器獲取 KClass<*> 注釋參數

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

我有以下注釋:

@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值。

所以這就是我現在陷入困境的地方,感謝任何幫助。 謝謝!

讓我們從第二種方法不起作用的原因開始:

此方法返回的注釋可能包含一個元素,其值為 Class 類型。 無法直接返回此值:定位和加載 class(例如要使用的 class 加載程序)所需的信息不可用,並且 class 可能根本無法加載。 嘗試通過在返回的注釋上調用相關方法來讀取 Class object 將導致 MirroredTypeException,從中可以提取相應的 TypeMirror。 同樣,嘗試讀取 Class[]-valued 元素將導致 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

如果您使用的是 KSP,則解決方案可能如下所示:

使用實驗性 API 並假設您在注釋中引用的 KClass 可用:

resolver.getSymbolsWithAnnotation("com.example.Model")
    .map {
        val consumerType = try {
            it.getAnnotationsByType(Model::class).single().consumer
            null
        } catch (e: KSTypeNotPresentException) {
            e.ksType
        }
        val consumerDeclaration = consumerType!!.declaration as KSClassDeclaration // etc
    }

如果你不能這樣做,那么維護注釋的 KSP 視圖會更靈活:

resolver.getSymbolsWithAnnotation("com.example.Model")
    .map { ksAnnotated ->
        val args = ksAnnotated.annotations.single {
            it.shortName.asString() == "Model" && it.annotationType.resolve().declaration.qualifiedName?.asString() == "com.example.Model"
        }.arguments

        val consumerType = args.single { it.name?.asString() == "owner" }.value as KSType
        val consumerDeclaration = consumerType.declaration as KSClassDeclaration // etc 
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM