Support Kotlin annotation constructors in reflection
#KT-13106 In Progress
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.*
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
annotation class A1
|
||||
|
||||
annotation class A2(val k: KClass<*>, val s: A1)
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(1, A1::class.constructors.size)
|
||||
assertEquals(A1::class.primaryConstructor, A1::class.constructors.single())
|
||||
|
||||
val cs = A2::class.constructors
|
||||
assertEquals(1, cs.size)
|
||||
assertEquals(A2::class.primaryConstructor, cs.single())
|
||||
val params = cs.single().parameters
|
||||
assertEquals(listOf("k", "s"), params.map { it.name })
|
||||
|
||||
return "OK"
|
||||
}
|
||||
-3
@@ -1,10 +1,8 @@
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.*
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
interface Interface
|
||||
annotation class Anno(val x: Int)
|
||||
object Obj
|
||||
|
||||
class C {
|
||||
@@ -13,7 +11,6 @@ class C {
|
||||
|
||||
fun box(): String {
|
||||
assertTrue(Interface::class.constructors.isEmpty())
|
||||
assertTrue(Anno::class.constructors.isEmpty())
|
||||
assertTrue(Obj::class.constructors.isEmpty())
|
||||
assertTrue(C.Companion::class.constructors.isEmpty())
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
annotation class Anno(val klasses: Array<KClass<*>> = arrayOf(String::class, Int::class))
|
||||
|
||||
fun box(): String {
|
||||
val anno = Anno::class.constructors.single().callBy(emptyMap())
|
||||
assertEquals(listOf(String::class, Int::class), (anno.klasses as Array<KClass<*>>).toList() /* TODO: KT-9453 */)
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.primaryConstructor
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFails
|
||||
|
||||
annotation class NoParams
|
||||
annotation class OneDefault(val s: String = "OK")
|
||||
annotation class OneNonDefault(val s: String)
|
||||
annotation class TwoParamsOneDefault(val s: String, val x: Int = 42)
|
||||
annotation class TwoParamsOneDefaultKClass(val string: String, val klass: KClass<*> = Number::class)
|
||||
annotation class TwoNonDefaults(val string: String, val klass: KClass<*>)
|
||||
|
||||
|
||||
inline fun <reified T : Annotation> create(args: Map<String, Any?>): T {
|
||||
val ctor = T::class.constructors.single()
|
||||
return ctor.callBy(args.mapKeys { entry -> ctor.parameters.single { it.name == entry.key } })
|
||||
}
|
||||
|
||||
inline fun <reified T : Annotation> create(): T = create(emptyMap())
|
||||
|
||||
fun box(): String {
|
||||
create<NoParams>()
|
||||
|
||||
val t1 = create<OneDefault>()
|
||||
assertEquals("OK", t1.s)
|
||||
assertFails { create<OneDefault>(mapOf("s" to 42)) }
|
||||
|
||||
val t2 = create<OneNonDefault>(mapOf("s" to "OK"))
|
||||
assertEquals("OK", t2.s)
|
||||
assertFails { create<OneNonDefault>() }
|
||||
|
||||
val t3 = create<TwoParamsOneDefault>(mapOf("s" to "OK"))
|
||||
assertEquals("OK", t3.s)
|
||||
assertEquals(42, t3.x)
|
||||
val t4 = create<TwoParamsOneDefault>(mapOf("s" to "OK", "x" to 239))
|
||||
assertEquals(239, t4.x)
|
||||
assertFails { create<TwoParamsOneDefault>(mapOf("s" to "Fail", "x" to "Fail")) }
|
||||
|
||||
val t5 = create<TwoParamsOneDefaultKClass>(mapOf("string" to "OK"))
|
||||
assertEquals(Number::class, t5.klass as KClass<*> /* TODO: KT-9453 */)
|
||||
|
||||
assertFails("KClass (not Class) instances should be passed as arguments") {
|
||||
create<TwoNonDefaults>(mapOf("klass" to String::class.java, "string" to "Fail"))
|
||||
}
|
||||
|
||||
val t6 = create<TwoNonDefaults>(mapOf("klass" to String::class, "string" to "OK"))
|
||||
return t6.string
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.primaryConstructor
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFails
|
||||
|
||||
annotation class NoParams
|
||||
annotation class OneDefault(val s: String = "Fail")
|
||||
annotation class TwoNonDefaults(val string: String, val klass: KClass<*>)
|
||||
|
||||
inline fun <reified T : Annotation> create(vararg args: Any?): T =
|
||||
T::class.constructors.single().call(*args)
|
||||
|
||||
fun box(): String {
|
||||
create<NoParams>()
|
||||
assertFails { create<NoParams>("Fail") }
|
||||
|
||||
assertFails { create<OneDefault>() }
|
||||
assertFails { create<OneDefault>(42) }
|
||||
val o = create<OneDefault>("OK")
|
||||
assertEquals("OK", o.s)
|
||||
|
||||
assertFails("call() should fail because arguments were passed in an incorrect order") {
|
||||
create<TwoNonDefaults>(Any::class, "Fail")
|
||||
}
|
||||
assertFails("call() should fail because KClass (not Class) instances should be passed as arguments") {
|
||||
create<TwoNonDefaults>("Fail", Any::class.java)
|
||||
}
|
||||
|
||||
val k = create<TwoNonDefaults>("OK", Int::class)
|
||||
assertEquals(Int::class, k.klass as KClass<*> /* TODO: KT-9453 */)
|
||||
|
||||
return k.string
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
// WITH_REFLECT
|
||||
// FULL_JDK
|
||||
|
||||
import java.lang.reflect.GenericArrayType
|
||||
import java.lang.reflect.ParameterizedType
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.jvm.javaType
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
annotation class Z
|
||||
enum class E
|
||||
|
||||
annotation class Anno(
|
||||
val b: Byte,
|
||||
val s: String,
|
||||
val ss: Array<String>,
|
||||
val z: Z,
|
||||
val zs: Array<Z>,
|
||||
val e: E,
|
||||
val es: Array<E>,
|
||||
val k: KClass<*>,
|
||||
val ka: Array<KClass<*>>
|
||||
)
|
||||
|
||||
fun tmp(): Array<Class<*>> = null!!
|
||||
|
||||
fun box(): String {
|
||||
val t = Anno::class.constructors.single().parameters.map { it.type.javaType }
|
||||
|
||||
assertEquals(Byte::class.java, t[0])
|
||||
assertEquals(String::class.java, t[1])
|
||||
assertEquals(Array<String>::class.java, t[2])
|
||||
assertEquals(Z::class.java, t[3])
|
||||
assertEquals(Array<Z>::class.java, t[4])
|
||||
assertEquals(E::class.java, t[5])
|
||||
assertEquals(Array<E>::class.java, t[6])
|
||||
|
||||
assertTrue(t[7] is ParameterizedType)
|
||||
assertEquals(Class::class.java, (t[7] as ParameterizedType).rawType)
|
||||
|
||||
assertTrue(t[8] is GenericArrayType)
|
||||
val e = (t[8] as GenericArrayType).genericComponentType
|
||||
assertTrue(e is ParameterizedType)
|
||||
assertEquals(Class::class.java, (e as ParameterizedType).rawType)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user