Finding field annotations using obj::class.declaredMemberProperties


#1

In the following test, the field id of class TestData is marked with the annotation Foo. Why is the output of .annotations and .findAnnotation() empty though?

How can check if a field is annotated by a certain annotation?

I asked this as well on https://stackoverflow.com/questions/51218309 but got no answer. Is it the same bug as https://youtrack.jetbrains.com/issue/KT-10837 although I don’t have “use-site” annotations?

import kotlin.test.Test
import kotlin.reflect.full.declaredMemberProperties
import kotlin.reflect.full.findAnnotation
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertTrue

class MissingAnnotationTest {

    @Target(AnnotationTarget.FIELD)
    @Retention(AnnotationRetention.RUNTIME)
    annotation class Foo

    data class TestData(@Foo val id: Int)

    @Test
    fun test() {
        val obj = TestData(123)
        val idProp = obj::class.declaredMemberProperties.first { it.name == "id" }

        println("# property: " + idProp) // "val ...TestData.id: kotlin.Int"
        println("# annotations: " + idProp.annotations) // [] - but why?
        println("# findAnnotations<Foo>: " + idProp.findAnnotation<Foo>()) // null - but why?

        assertTrue(idProp.name.endsWith("TestData.id: kotlin.Int"))
        assertEquals(1, idProp.annotations.size, "Bug! No annotations found!")
        assertNotNull(idProp.findAnnotation<Foo>())
    }

}

#2

The problem is that you are trying to get the annotation of the property. Kotlin’s property get compiled to a getter and a backing field on the JVM. If you try to get the annotations of the property, you don’t get the annotation of the underlying field. Your code would find the annotations if you changed the target from FIELD to property (I forgot how the enum is called exactly).
If you want the annotations of the backing field you have to get them from property.javaField.getAnnotation(Annotation::class.java).


#3

Thanks for the quick answer, now I understand the difference between fields, properties and member functions.