Hello, I have an annotation that takes a KClass, I wanted to access information of that class in pro...
c
Hello, I have an annotation that takes a KClass, I wanted to access information of that class in processor but it's not in class path, was wondering if theres a way to work around this? Do I have no choice but to provide the class information I need in annotation instead
j
How does the code compile if it's not on the compilation unit's classpath?
c
It passes the KClass
annotation class Foo(val clazz: KClass<...>
the KSP processor works fine until I try accessing the KClass since its not in class path which I get exception in runtime
I'm trying to reference that KClass in code that I'm generating but seems I have no choice but to have the fully qualified name passed instead of KClass and generate import and calls based on that :(
j
I'm on mobile so I can show code. I'll have to find a reference to doing this later.
c
No rush, appreciate any help
j
I believe you can cast these
KClass
definitions to a
KClassDeclaration
using
as
if they have come from an annotation value
d
Something similar has come up a few times before in this Slack, maybe we need a PR to put it in the docs as it is quite a common use case? We have found that obtaining the concrete instance of the annotation with the KClass arguments is premature. Maintaining the KSP view of the annotation is easier, and KSP will see the
KClass
args as
KSType
, from which you can get the declaration:
Copy code
val ksType = ksAnnotated.getAnnotationsByType(Foo::class).single().arguments.single { it.name.asString() == "clazz" }.value as KSType
val declaration = ksType.declaration
val simpleName = declaration.simpleName.asString() // Bar etc.
c
Interesting, I'll try it out later but does look good, thanks blob smile Definitely would be nice to be mentioned somewhere in docs, not entirely intuitive imo
j
Not sure if it’s useful anymore but here’s a little extension method I’ve been using to make the syntax for this slightly nicer:
Copy code
inline fun <reified A : Annotation> KSAnnotation.getKClassArgument(
  property: KProperty1<A, *>
): KSType {
  val argument = this.arguments.find { it.name?.asString() == property.name } ?: run {
    val validNames = this.arguments.mapNotNull { it.name?.asString() }.joinToString(", ")
    error("Could not find annotation argument ${property.name}. (Valid names: $validNames)")
  }
  
  return (argument.value as? KSType) ?: error("${property.name} is not a valid KSType")
}
Assuming we have an annotation like this:
Copy code
annotation class MyAnnotation(val klass: KClass<*>)
Then we can use the extension like so:
Copy code
myAnnotationReference.getKClassArgument(MyAnnotation::klass)
c
Ah that helped me realize what I was missing, thank you, was using
getAnnotationsByType
which returns the instance of the annotation and not the
KSAnnotation
😛