Reflection: add KClass.{isSubclassOf,isSuperclassOf}, KType.{isSubtypeOf,isSupertypeOf}

The behavior in primitives.kt is likely to be reconsidered

 #KT-8998 Fixed
This commit is contained in:
Alexander Udalov
2016-07-26 18:29:02 +03:00
parent 4cd252d9d5
commit 3702f4a7a7
9 changed files with 308 additions and 0 deletions
@@ -0,0 +1,48 @@
// WITH_REFLECT
import kotlin.reflect.*
import kotlin.test.assertTrue
import kotlin.test.assertFalse
open class Klass
interface Interface<T>
class Bar : Interface<String>, Klass()
fun check(subclass: KClass<*>, superclass: KClass<*>, shouldBeSubclass: Boolean) {
if (shouldBeSubclass) {
assertTrue(subclass.isSubclassOf(superclass))
assertTrue(superclass.isSuperclassOf(subclass))
} else {
assertFalse(subclass.isSubclassOf(superclass))
assertFalse(superclass.isSuperclassOf(subclass))
}
}
fun box(): String {
check(Any::class, Any::class, true)
check(String::class, Any::class, true)
check(Any::class, String::class, false)
check(String::class, String::class, true)
check(Int::class, Int::class, true)
check(Int::class, Any::class, true)
check(List::class, Collection::class, true)
check(List::class, Iterable::class, true)
check(Collection::class, Iterable::class, true)
check(Set::class, List::class, false)
check(Array<String>::class, Array<Any>::class, false)
check(Array<Any>::class, Array<String>::class, false)
check(Function3::class, Function4::class, false)
check(Function4::class, Function3::class, false)
check(Bar::class, Klass::class, true)
check(Bar::class, Interface::class, true)
check(Klass::class, Bar::class, false)
check(Interface::class, Bar::class, false)
check(Klass::class, Interface::class, false)
return "OK"
}
@@ -0,0 +1,20 @@
// WITH_REFLECT
import kotlin.reflect.isSubclassOf
import kotlin.test.assertTrue
import kotlin.test.assertFalse
fun box(): String {
// KClass instances for primitive int and wrapper java.lang.Integer are different
val primitiveInt = Int::class.javaPrimitiveType!!.kotlin
val wrapperInt = Int::class.javaObjectType.kotlin
assertTrue(primitiveInt.isSubclassOf(primitiveInt))
assertTrue(wrapperInt.isSubclassOf(wrapperInt))
// Currently KClass for int != KClass for java.lang.Integer, thus they are not a subclass of each other either
// TODO: reconsider this decision
assertFalse(primitiveInt.isSubclassOf(wrapperInt))
assertFalse(wrapperInt.isSubclassOf(primitiveInt))
return "OK"
}
@@ -0,0 +1,31 @@
// WITH_REFLECT
// FILE: J.java
public interface J {
String platformString();
}
// FILE: K.kt
import kotlin.reflect.*
import kotlin.test.assertTrue
fun string(): String = null!!
fun nullableString(): String? = null!!
fun check(subCallable: KCallable<*>, superCallable: KCallable<*>) {
val subtype = subCallable.returnType
val supertype = superCallable.returnType
assertTrue(subtype.isSubtypeOf(supertype))
assertTrue(supertype.isSupertypeOf(subtype))
}
fun box(): String {
check(::string, J::platformString)
check(J::platformString, ::string)
check(::nullableString, J::platformString)
check(J::platformString, ::nullableString)
check(J::platformString, J::platformString)
return "OK"
}
@@ -0,0 +1,30 @@
// WITH_REFLECT
import kotlin.reflect.*
import kotlin.test.assertTrue
import kotlin.test.assertFalse
open class G<T>
class A : G<String>()
fun gOfString(): G<String> = null!!
fun gOfInt(): G<Int> = null!!
fun box(): String {
val gs = ::gOfString.returnType
val gi = ::gOfInt.returnType
val a = ::A.returnType
assertTrue(a.isSubtypeOf(gs))
assertTrue(gs.isSupertypeOf(a))
assertFalse(a.isSubtypeOf(gi))
assertFalse(gi.isSupertypeOf(a))
assertFalse(gs.isSubtypeOf(gi))
assertFalse(gs.isSupertypeOf(gi))
assertFalse(gi.isSubtypeOf(gs))
assertFalse(gi.isSupertypeOf(gs))
return "OK"
}
@@ -0,0 +1,64 @@
// WITH_REFLECT
import kotlin.reflect.*
import kotlin.test.assertTrue
import kotlin.test.assertFalse
fun check(subCallable: KCallable<*>, superCallable: KCallable<*>, shouldBeSubtype: Boolean) {
val subtype = subCallable.returnType
val supertype = superCallable.returnType
if (shouldBeSubtype) {
assertTrue(subtype.isSubtypeOf(supertype))
assertTrue(supertype.isSupertypeOf(subtype))
} else {
assertFalse(subtype.isSubtypeOf(supertype))
assertFalse(supertype.isSupertypeOf(subtype))
}
}
open class O
class X : O()
fun any(): Any = null!!
fun string(): String = null!!
fun nullableString(): String? = null!!
fun int(): Int = null!!
fun nothing(): Nothing = null!!
fun nullableNothing(): Nothing? = null!!
fun function2(): (Any, Any) -> Any = null!!
fun function3(): (Any, Any, Any) -> Any = null!!
fun box(): String {
check(::any, ::any, true)
check(::int, ::int, true)
check(::nothing, ::nothing, true)
check(::nullableNothing, ::nullableNothing, true)
check(::string, ::any, true)
check(::nullableString, ::any, false)
check(::int, ::any, true)
check(::O, ::any, true)
check(::X, ::any, true)
check(::nothing, ::any, true)
check(::nothing, ::string, true)
check(::nothing, ::nullableString, true)
check(::nullableNothing, ::nullableString, true)
check(::nullableNothing, ::string, false)
check(::string, ::nullableString, true)
check(::nullableString, ::string, false)
check(::X, ::O, true)
check(::O, ::X, false)
check(::int, ::string, false)
check(::string, ::int, false)
check(::any, ::string, false)
check(::any, ::nullableString, false)
check(::function2, ::function3, false)
check(::function3, ::function2, false)
return "OK"
}
@@ -0,0 +1,41 @@
// WITH_REFLECT
import kotlin.reflect.isSubtypeOf
import kotlin.test.assertTrue
import kotlin.test.assertFalse
class G<T>
fun number(): G<Number> = null!!
fun outNumber(): G<out Number> = null!!
fun inNumber(): G<in Number> = null!!
fun star(): G<*> = null!!
fun box(): String {
val n = ::number.returnType
val o = ::outNumber.returnType
val i = ::inNumber.returnType
val st = ::star.returnType
// G<Number> <: G<out Number>
assertTrue(n.isSubtypeOf(o))
assertFalse(o.isSubtypeOf(n))
// G<Number> <: G<in Number>
assertTrue(n.isSubtypeOf(i))
assertFalse(i.isSubtypeOf(n))
// G<Number> <: G<*>
assertTrue(n.isSubtypeOf(st))
assertFalse(st.isSubtypeOf(n))
// G<out Number> <: G<*>
assertTrue(o.isSubtypeOf(st))
assertFalse(st.isSubtypeOf(o))
// G<in Number> <: G<*>
assertTrue(i.isSubtypeOf(st))
assertFalse(st.isSubtypeOf(i))
return "OK"
}