Reflection: add KClass.{supertypes,superclasses,allSupertypes,allSuperclasses}

Some things are not implemented yet for allSupertypes, such as KType->Type
mapping of types and generic substitution of built-in types
This commit is contained in:
Alexander Udalov
2016-07-12 18:42:46 +03:00
parent 486ea62c72
commit 4cd252d9d5
9 changed files with 262 additions and 4 deletions
@@ -0,0 +1,31 @@
// WITH_REFLECT
// FULL_JDK
import java.lang.reflect.ParameterizedType
import java.lang.reflect.TypeVariable
import kotlin.reflect.jvm.javaType
import kotlin.test.assertEquals
import kotlin.test.assertTrue
import kotlin.test.fail
open class Klass
interface Interface<T, U>
interface Interface2
class A<Z> : Interface<String, Z>, Klass(), Interface2
fun box(): String {
val (i, k, i2) = A::class.supertypes.map { it.javaType }
i as? ParameterizedType ?: fail("Not a parameterized type: $i")
assertEquals(Interface::class.java, i.rawType)
val args = i.actualTypeArguments
assertEquals(String::class.java, args[0], "Not String: ${args[0]}")
assertTrue(args[1].let { it is TypeVariable<*> && it.name == "Z" && it.genericDeclaration == A::class.java }, "Not Z: ${args[1]}")
assertEquals(Klass::class.java, k)
assertEquals(Interface2::class.java, i2)
return "OK"
}
@@ -0,0 +1,42 @@
// WITH_REFLECT
import java.io.Serializable
import kotlin.reflect.*
import kotlin.test.assertEquals
inline fun <reified T : Any> check(vararg callables: KCallable<*>) {
val types = callables.map { it.returnType }
assertEquals(types, T::class.supertypes)
assertEquals(types.map { it.classifier as KClass<*> }, T::class.superclasses)
}
inline fun <reified T : Any> checkAll(vararg callables: KCallable<*>) {
val types = callables.map { it.returnType }
// Calling toSet because the order of returned types/classes is not specified
assertEquals(types.toSet(), T::class.allSupertypes.toSet())
assertEquals(types.map { it.classifier as KClass<*> }.toSet(), T::class.allSuperclasses.toSet())
}
fun comparableOfString(): Comparable<String> = null!!
fun charSequence(): CharSequence = null!!
fun serializable(): Serializable = null!!
fun any(): Any = null!!
fun number(): Number = null!!
fun comparableOfInt(): Comparable<Int> = null!!
fun cloneable(): Cloneable = null!!
fun box(): String {
check<Any>()
checkAll<Any>()
check<String>(::comparableOfString, ::charSequence, ::serializable)
checkAll<String>(::comparableOfString, ::charSequence, ::serializable, ::any)
check<Int>(::number, ::comparableOfInt, ::serializable)
checkAll<Int>(::number, ::comparableOfInt, ::serializable, ::any)
check<Array<Any>>(::cloneable, ::serializable)
checkAll<Array<Any>>(::cloneable, ::serializable, ::any)
return "OK"
}
@@ -0,0 +1,25 @@
// WITH_REFLECT
import kotlin.reflect.allSupertypes
import kotlin.test.assertEquals
interface A<A1, A2>
interface B<B1, B2> : A<B2, B1>
interface C<C1> : B<C1, String>
interface D : C<Int>
interface StringList : List<String>
fun box(): String {
assertEquals(
listOf(String::class, Int::class),
D::class.allSupertypes.single { it.classifier == A::class }.arguments.map { it.type!!.classifier }
)
val collectionType = StringList::class.allSupertypes.single { it.classifier == Collection::class }
val arg = collectionType.arguments.single().type!!
// TODO: this does not work currently because for some reason two different instances of TypeParameterDescriptor are created for List
// assertEquals(String::class, arg.classifier)
return "OK"
}
@@ -0,0 +1,49 @@
// WITH_REFLECT
import kotlin.reflect.*
import kotlin.test.assertEquals
open class Simple
class OneClass : Simple()
interface Interface
interface Interface2
class ClassAndTwoInterfaces : Interface, Simple(), Interface2
fun any(): Any = null!!
fun simple(): Simple = null!!
fun interface_(): Interface = null!!
fun interface2(): Interface2 = null!!
fun box(): String {
with(Simple::class) {
assertEquals(listOf(::any.returnType), supertypes)
assertEquals(listOf(Any::class), superclasses)
// Calling toSet because the order of returned types/classes is not specified
assertEquals(setOf(::any.returnType), allSupertypes.toSet())
assertEquals(setOf(Any::class), allSuperclasses.toSet())
}
with (OneClass::class) {
assertEquals(listOf(::simple.returnType), supertypes)
assertEquals(listOf(Simple::class), superclasses)
assertEquals(setOf(::simple.returnType, ::any.returnType), allSupertypes.toSet())
assertEquals(setOf(Simple::class, Any::class), allSuperclasses.toSet())
}
with (Interface::class) {
assertEquals(listOf(::any.returnType), supertypes)
assertEquals(listOf(Any::class), superclasses)
assertEquals(setOf(::any.returnType), allSupertypes.toSet())
assertEquals(setOf(Any::class), allSuperclasses.toSet())
}
with (ClassAndTwoInterfaces::class) {
assertEquals(listOf(::interface_.returnType, ::simple.returnType, ::interface2.returnType), supertypes)
assertEquals(listOf(Interface::class, Simple::class, Interface2::class), superclasses)
assertEquals(setOf(::interface_.returnType, ::simple.returnType, ::interface2.returnType, ::any.returnType), allSupertypes.toSet())
assertEquals(setOf(Interface::class, Simple::class, Interface2::class, Any::class), allSuperclasses.toSet())
}
return "OK"
}