| // LANGUAGE: +FullValueClasses, -PropertyParamAnnotationDefaultTargetMode |
| // TARGET_BACKEND: JVM |
| // CHECK_BYTECODE_LISTING |
| // WITH_STDLIB |
| // WITH_REFLECT |
| |
| import kotlin.reflect.KClass |
| import kotlin.reflect.KProperty |
| |
| @Repeatable |
| annotation class Ann |
| |
| abstract value class Sealed |
| abstract value class Base: Sealed() |
| |
| @[Ann Ann] |
| value class A @Ann constructor( |
| @[Ann Ann] |
| @param:[Ann Ann] |
| @property:[Ann Ann] |
| @field:[Ann Ann] |
| @get:[Ann Ann] |
| val x: Int, |
| @[Ann Ann] |
| @param:[Ann Ann] |
| @property:[Ann Ann] |
| @field:[Ann Ann] |
| @get:[Ann Ann] |
| val y: Int, |
| ): Base() { |
| operator fun getValue(thisRef: Any?, property: KProperty<*>): Int { |
| return 0 |
| } |
| } |
| |
| @[Ann Ann] |
| value class B @Ann constructor( |
| @[Ann Ann] |
| @param:[Ann Ann] |
| @property:[Ann Ann] |
| @field:[Ann Ann] |
| @get:[Ann Ann] |
| val x: A, |
| @[Ann Ann] |
| @param:[Ann Ann] |
| @property:[Ann Ann] |
| @field:[Ann Ann] |
| @get:[Ann Ann] |
| val y: A?, |
| ) { |
| @JvmName("otherName") |
| fun f() = Unit |
| } |
| |
| typealias NullableA = A? |
| |
| @[Ann Ann] |
| class C @Ann constructor( |
| @[Ann Ann] |
| @param:[Ann Ann] |
| @property:[Ann Ann] |
| @field:[Ann Ann] |
| @get:[Ann Ann] |
| @set:[Ann Ann] |
| @setparam:[Ann Ann] |
| var x: A, |
| @[Ann Ann] |
| @param:[Ann Ann] |
| @property:[Ann Ann] |
| @field:[Ann Ann] |
| @get:[Ann Ann] |
| @set:[Ann Ann] |
| @setparam:[Ann Ann] |
| var y: A?, |
| @[Ann Ann] |
| @param:[Ann Ann] |
| @property:[Ann Ann] |
| @field:[Ann Ann] |
| @get:[Ann Ann] |
| @set:[Ann Ann] |
| @setparam:[Ann Ann] |
| var yTa: NullableA, |
| ) { |
| @delegate:[Ann Ann] |
| @property:[Ann Ann] |
| @get:[Ann Ann] |
| val z by lazy { A(-100, -200) } |
| @delegate:[Ann Ann] |
| @property:[Ann Ann] |
| @get:[Ann Ann] |
| val c by A(-100, -200) |
| @delegate:[Ann Ann] |
| @property:[Ann Ann] |
| @get:[Ann Ann] |
| val d by ::z |
| |
| @JvmField |
| val e = x |
| |
| init { |
| if (2 + 2 == 4) { |
| @[Ann Ann] |
| val x = 4 |
| @[Ann Ann] |
| val y = A(1, 2) |
| } |
| |
| |
| fun f() { |
| if (2 + 2 == 4) { |
| @[Ann Ann] |
| val x = 4 |
| @[Ann Ann] |
| val y = A(1, 2) |
| } |
| } |
| } |
| } |
| |
| |
| @[Ann Ann] |
| fun @receiver:[Ann Ann] A.t(@[Ann Ann] a: A, @[Ann Ann] b: B, @[Ann Ann] c: C) { |
| if (2 + 2 == 4) { |
| @[Ann Ann] |
| val x = 4 |
| @[Ann Ann] |
| val y = A(1, 2) |
| } |
| |
| fun f() { |
| if (2 + 2 == 4) { |
| @[Ann Ann] |
| val x1 = 4 |
| @[Ann Ann] |
| val y1 = A(1, 2) |
| } |
| } |
| } |
| |
| @[Ann Ann] |
| fun @receiver:[Ann Ann] C.t(@[Ann Ann] a: A, @[Ann Ann] b: B, @[Ann Ann] c: C) = 4 |
| |
| @[Ann Ann] |
| var @receiver:[Ann Ann] A.tP |
| @[Ann Ann] |
| get() = A(1, 2) |
| @[Ann Ann] |
| set(@[Ann Ann] _) = Unit |
| |
| @[Ann Ann] |
| var @receiver:[Ann Ann] C.tP |
| @[Ann Ann] |
| get() = A(1, 2) |
| @[Ann Ann] |
| set(@[Ann Ann] _) = Unit |
| |
| fun box(): String { |
| if (!A::class.isValue) return "Failed: A class should be a value class" |
| if (!B::class.isValue) return "Failed: B class should be a value class" |
| if (C::class.isValue) return "Failed: C class should be not a value class" |
| |
| // Check class annotations |
| if (A::class.annotations.count { it is Ann } != 2) return "Failed: A class should have 2 @Ann" |
| if (B::class.annotations.count { it is Ann } != 2) return "Failed: B class should have 2 @Ann" |
| if (C::class.annotations.count { it is Ann } != 2) return "Failed: C class should have 2 @Ann" |
| |
| // Check constructor annotations |
| if (A::class.constructors.first().annotations.count { it is Ann } != 1) return "Failed: A constructor @Ann" |
| if (B::class.constructors.first().annotations.count { it is Ann } != 1) return "Failed: B constructor @Ann" |
| if (C::class.constructors.first().annotations.count { it is Ann } != 1) return "Failed: C constructor @Ann" |
| |
| // Check property annotations for A |
| val aProps = A::class.members.filter { it.name in setOf("x", "y") } |
| for (prop in aProps) { |
| if (prop.annotations.count { it is Ann } != 2) return "Failed: A property ${prop.name} @Ann count" |
| } |
| |
| // Check B's properties |
| val bProps = B::class.members.filter { it.name in setOf("x", "y") } |
| for (prop in bProps) { |
| if (prop.annotations.count { it is Ann } != 2) return "Failed: B property ${prop.name} @Ann count" |
| } |
| |
| // Check C's properties including delegates |
| val cProps = C::class.members.filter { it.name in setOf("x", "y", "yTa", "z", "c", "d") } |
| for (prop in cProps) { |
| if (prop.annotations.count { it is Ann } < 2) return "Failed: C property ${prop.name} @Ann count" |
| } |
| |
| // Check extension function annotations |
| if (A::tP.annotations.count { it is Ann } != 2) return "Failed: A.t extension @Ann count" |
| |
| if (C::tP.annotations.count { it is Ann } != 2) return "Failed: C.t extension @Ann count" |
| fun KClass<*>.superClass() = supertypes.single().classifier as KClass<*> |
| |
| if (!(A::class.superClass().isValue)) return "Failed: Base is not a value class" |
| if (!(A::class.superClass().superClass().isValue)) return "Failed: Sealed is not a value class" |
| |
| return "OK" |
| } |