Surprising behaviour of changing annotation target

#1

Hi

Given the following code:

@Target(AnnotationTarget.FIELD, AnnotationTarget.PROPERTY)
annotation class SomeAnnotation
data class Thing(@SomeAnnotation val foo:String)

If I reflect, the annotation is discovered on the member.

However, if I add an annotation target of VALUE_PARAMETER, the annotation is no longer discoverable on the field, and has moved to the constructor param.

@Target(AnnotationTarget.FIELD, AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER)
annotation class SomeAnnotation
data class Thing(@SomeAnnotation val foo:String)

This feels “surprising”, as to me, as it reads as though the annotation is now present in both locations - the constructor arg and the member. However, the compiler removes it from the member, to place it only on the constructor.

I’m interested in understanding the rationale for the behaviour, and also if it’s possible to change so that the annotation is made present in both.

#2

Each annotation is only applied to one of the targets. This is also the case without the VALUE_PARAMETER target. In that case the annotation is only applied to the property and not to the field. You can decide which target to use with use-site targets.
If you want the annotation to apply to multiple targets, you have to repeat the annotation with the specific targets.

@Target(AnnotationTarget.FIELD, AnnotationTarget.PROPERTY)
annotation class Test

@Test     // here you can omit property as it's the default
@field:Test
val foo = 5
#3

Thanks for the link. The docs are quite clear, and explain the behaviour well.