Reflection: add KVariance, KTypeParameter.{variance,upperBounds,equals,hashCode}
This commit is contained in:
+39
@@ -0,0 +1,39 @@
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNotEquals
|
||||
|
||||
class A<T>
|
||||
class B<T>
|
||||
|
||||
class Fun {
|
||||
fun <T> foo(): T = null!!
|
||||
}
|
||||
|
||||
class Fourple<A, B, in C, out D>
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(A::class.typeParameters, A::class.typeParameters)
|
||||
assertEquals(A::class.typeParameters.single().hashCode(), A::class.typeParameters.single().hashCode())
|
||||
|
||||
fun getFoo() = Fun::class.members.single { it.name == "foo" }
|
||||
assertEquals(getFoo().typeParameters, getFoo().typeParameters)
|
||||
assertEquals(getFoo().typeParameters.single().hashCode(), getFoo().typeParameters.single().hashCode())
|
||||
|
||||
assertNotEquals(A::class.typeParameters.single(), B::class.typeParameters.single())
|
||||
|
||||
val fi = Fourple::class.typeParameters
|
||||
val fj = Fourple::class.typeParameters
|
||||
for (i in 0..fi.size - 1) {
|
||||
for (j in 0..fj.size - 1) {
|
||||
if (i == j) {
|
||||
assertEquals(fi[i], fj[j])
|
||||
assertEquals(fi[i].hashCode(), fj[j].hashCode())
|
||||
} else {
|
||||
assertNotEquals(fi[i], fj[j])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.KVariance
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class Triple<in A, B, out C> {
|
||||
fun <T> foo(): T = null!!
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(
|
||||
listOf(
|
||||
KVariance.IN,
|
||||
KVariance.INVARIANT,
|
||||
KVariance.OUT
|
||||
),
|
||||
Triple::class.typeParameters.map { it.variance }
|
||||
)
|
||||
|
||||
assertEquals(KVariance.INVARIANT, Triple::class.members.single { it.name == "foo" }.typeParameters.single().variance)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.KTypeProjection
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class DefaultBound<T>
|
||||
class NullableAnyBound<T : Any?>
|
||||
class NotNullAnyBound<T : Any>
|
||||
class TwoBounds<T : Cloneable> where T : Comparable<T>
|
||||
|
||||
class OtherParameterBound<T : U, U : Number>
|
||||
|
||||
class RecursiveGeneric<T : Enum<T>>
|
||||
|
||||
class FunctionTypeParameter {
|
||||
fun <A : Cloneable> foo(): Cloneable = null!!
|
||||
}
|
||||
|
||||
// helper functions to obtain KType instances
|
||||
fun nullableAny(): Any? = null
|
||||
fun notNullAny(): Any = null!!
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(listOf(::nullableAny.returnType), DefaultBound::class.typeParameters.single().upperBounds)
|
||||
assertEquals(listOf(::nullableAny.returnType), NullableAnyBound::class.typeParameters.single().upperBounds)
|
||||
assertEquals(listOf(::notNullAny.returnType), NotNullAnyBound::class.typeParameters.single().upperBounds)
|
||||
|
||||
TwoBounds::class.typeParameters.single().let {
|
||||
val (cl, cm) = it.upperBounds
|
||||
assertEquals(Cloneable::class, cl.classifier)
|
||||
assertEquals(listOf(), cl.arguments)
|
||||
|
||||
assertEquals(Comparable::class, cm.classifier)
|
||||
val cmt = cm.arguments.single()
|
||||
assertTrue(cmt is KTypeProjection.Invariant)
|
||||
assertEquals(it, cmt.type!!.classifier)
|
||||
}
|
||||
|
||||
OtherParameterBound::class.typeParameters.let {
|
||||
val (t, u) = it
|
||||
assertEquals(u, t.upperBounds.single().classifier)
|
||||
assertEquals(Number::class, u.upperBounds.single().classifier)
|
||||
}
|
||||
|
||||
FunctionTypeParameter::class.members.single { it.name == "foo" }.let { foo ->
|
||||
assertEquals(foo.returnType, foo.typeParameters.single().upperBounds.single())
|
||||
}
|
||||
|
||||
val recursiveGenericTypeParameter = RecursiveGeneric::class.typeParameters.single()
|
||||
val recursiveGenericBound = recursiveGenericTypeParameter.upperBounds.single()
|
||||
assertEquals(Enum::class, recursiveGenericBound.classifier)
|
||||
recursiveGenericBound.arguments.single().let { projection ->
|
||||
assertTrue(projection is KTypeProjection.Invariant)
|
||||
assertEquals(recursiveGenericTypeParameter, projection.type!!.classifier)
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.KVariance
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class Fourple<A, B, C, D>
|
||||
fun foo(): Fourple<String, in String, out String, *> = null!!
|
||||
|
||||
fun listOfStrings(): List<String> = null!!
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(
|
||||
listOf(
|
||||
KVariance.INVARIANT,
|
||||
KVariance.IN,
|
||||
KVariance.OUT,
|
||||
null
|
||||
),
|
||||
::foo.returnType.arguments.map { it.variance }
|
||||
)
|
||||
|
||||
// Declaration-site variance should have no effect on the variance of the type projection:
|
||||
assertEquals(KVariance.INVARIANT, ::listOfStrings.returnType.arguments.first().variance)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user