google / ksp

Kotlin Symbol Processing API
https://github.com/google/ksp
Apache License 2.0
2.89k stars 274 forks source link

Annotations on enum entires on K2 are missing #1962

Closed ansman closed 5 months ago

ansman commented 5 months ago

I have a test case in my annotation processor that reads the annotations on enum entires. When trying it on K2 with KSP2, the test fails. Upon investigating, it's because there are no annotations present.

The enum in question looks like this:

@JsonSerializable
enum class SomeEnum {
    VALUE1,
    VALUE2,
    @JsonProperty(name = "VALUE3-alt")
    VALUE3,
    VALUE4,
    VALUE5
}

@Retention(AnnotationRetention.SOURCE)
@MustBeDocumented
@Target(AnnotationTarget.FIELD)
annotation class JsonProperty(val name: String)

I dumped all annotations on all declarations using this:

for (decl in targetElement.declarations) {
    logger.logKotshiError(decl.simpleName.asString(), decl)
    logger.logKotshiError(decl.annotations.toList().toString(), decl)
}

and this is what's printed:

e: [ksp] Kotshi: <init>
e: [ksp] Kotshi: []
e: [ksp] Kotshi: VALUE1
e: [ksp] Kotshi: []
e: [ksp] Kotshi: VALUE2
e: [ksp] Kotshi: []
e: [ksp] Kotshi: VALUE3
e: [ksp] Kotshi: []
e: [ksp] Kotshi: VALUE4
e: [ksp] Kotshi: []
e: [ksp] Kotshi: VALUE5
e: [ksp] Kotshi: []
e: [ksp] Kotshi: values
e: [ksp] Kotshi: []
e: [ksp] Kotshi: valueOf
e: [ksp] Kotshi: []
e: [ksp] Kotshi: entries
e: [ksp] Kotshi: []

On KSP1, this is logged:

e: [ksp] /Users/nicklas/Repositories/personal/kotshi/tests/src/main/kotlin/se/ansman/kotshi/SomeEnum.kt:7: Kotshi: VALUE1
e: [ksp] /Users/nicklas/Repositories/personal/kotshi/tests/src/main/kotlin/se/ansman/kotshi/SomeEnum.kt:7: Kotshi: []
e: [ksp] /Users/nicklas/Repositories/personal/kotshi/tests/src/main/kotlin/se/ansman/kotshi/SomeEnum.kt:8: Kotshi: VALUE2
e: [ksp] /Users/nicklas/Repositories/personal/kotshi/tests/src/main/kotlin/se/ansman/kotshi/SomeEnum.kt:8: Kotshi: []
e: [ksp] /Users/nicklas/Repositories/personal/kotshi/tests/src/main/kotlin/se/ansman/kotshi/SomeEnum.kt:11: Kotshi: VALUE3
e: [ksp] /Users/nicklas/Repositories/personal/kotshi/tests/src/main/kotlin/se/ansman/kotshi/SomeEnum.kt:11: Kotshi: [@JsonProperty]
e: [ksp] /Users/nicklas/Repositories/personal/kotshi/tests/src/main/kotlin/se/ansman/kotshi/SomeEnum.kt:13: Kotshi: VALUE4
e: [ksp] /Users/nicklas/Repositories/personal/kotshi/tests/src/main/kotlin/se/ansman/kotshi/SomeEnum.kt:13: Kotshi: [@Json]
e: [ksp] /Users/nicklas/Repositories/personal/kotshi/tests/src/main/kotlin/se/ansman/kotshi/SomeEnum.kt:14: Kotshi: VALUE5
e: [ksp] /Users/nicklas/Repositories/personal/kotshi/tests/src/main/kotlin/se/ansman/kotshi/SomeEnum.kt:14: Kotshi: []
e: [ksp] /Users/nicklas/Repositories/personal/kotshi/tests/src/main/kotlin/se/ansman/kotshi/SomeEnum.kt:6: Kotshi: <init>
e: [ksp] /Users/nicklas/Repositories/personal/kotshi/tests/src/main/kotlin/se/ansman/kotshi/SomeEnum.kt:6: Kotshi: []
ZacSweers commented 5 months ago

We're seeing this as well

ZacSweers commented 5 months ago

As a workaround you can get the underlying annotations field and surface a fake delegating class

val reflectiveAnnotations =
  @Suppress("UNCHECKED_CAST")
  (AbstractKSDeclarationImpl::class
      .java
      .getDeclaredField("originalAnnotations\$delegate")
      .apply { isAccessible = true }
      .get(entry) as Lazy<Sequence<KSAnnotation>>)
    .value

val newClassWithAnnotations =
  object : KSClassDeclaration by entry {
    override val annotations: Sequence<KSAnnotation>
      get() = reflectiveAnnotations
  }