Reflection: simplify KTypeProjection
This commit is contained in:
@@ -10,8 +10,8 @@ class Foo<K, V>
|
||||
fun box(): String {
|
||||
val foo = Foo::class.starProjectedType
|
||||
assertEquals(Foo::class, foo.classifier)
|
||||
assertEquals(listOf(KTypeProjection.Star, KTypeProjection.Star), foo.arguments)
|
||||
assertEquals(foo, Foo::class.createType(listOf(KTypeProjection.Star, KTypeProjection.Star)))
|
||||
assertEquals(listOf(KTypeProjection.STAR, KTypeProjection.STAR), foo.arguments)
|
||||
assertEquals(foo, Foo::class.createType(listOf(KTypeProjection.STAR, KTypeProjection.STAR)))
|
||||
|
||||
assertEquals(String::class, String::class.starProjectedType.classifier)
|
||||
assertEquals(listOf(), String::class.starProjectedType.arguments)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.KTypeProjection
|
||||
import kotlin.reflect.KVariance
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class DefaultBound<T>
|
||||
class NullableAnyBound<T : Any?>
|
||||
@@ -33,7 +33,7 @@ fun box(): String {
|
||||
|
||||
assertEquals(Comparable::class, cm.classifier)
|
||||
val cmt = cm.arguments.single()
|
||||
assertTrue(cmt is KTypeProjection.Invariant)
|
||||
assertEquals(KVariance.INVARIANT, cmt.variance)
|
||||
assertEquals(it, cmt.type!!.classifier)
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ fun box(): String {
|
||||
val recursiveGenericBound = recursiveGenericTypeParameter.upperBounds.single()
|
||||
assertEquals(Enum::class, recursiveGenericBound.classifier)
|
||||
recursiveGenericBound.arguments.single().let { projection ->
|
||||
assertTrue(projection is KTypeProjection.Invariant)
|
||||
assertEquals(KVariance.INVARIANT, projection.variance)
|
||||
assertEquals(recursiveGenericTypeParameter, projection.type!!.classifier)
|
||||
}
|
||||
|
||||
|
||||
@@ -11,29 +11,29 @@ fun box(): String {
|
||||
assertEquals(String::class.createType(), String::class.createType())
|
||||
|
||||
assertEquals(
|
||||
Foo::class.createType(listOf(KTypeProjection.Star)),
|
||||
Foo::class.createType(listOf(KTypeProjection.Star))
|
||||
Foo::class.createType(listOf(KTypeProjection.STAR)),
|
||||
Foo::class.createType(listOf(KTypeProjection.STAR))
|
||||
)
|
||||
|
||||
val i = Int::class.createType()
|
||||
assertEquals(
|
||||
Foo::class.createType(listOf(KTypeProjection.Invariant(i))),
|
||||
Foo::class.createType(listOf(KTypeProjection.Invariant(i)))
|
||||
Foo::class.createType(listOf(KTypeProjection.invariant(i))),
|
||||
Foo::class.createType(listOf(KTypeProjection.invariant(i)))
|
||||
)
|
||||
|
||||
assertNotEquals(
|
||||
Foo::class.createType(listOf(KTypeProjection.In(i))),
|
||||
Foo::class.createType(listOf(KTypeProjection.Out(i)))
|
||||
Foo::class.createType(listOf(KTypeProjection.contravariant(i))),
|
||||
Foo::class.createType(listOf(KTypeProjection.covariant(i)))
|
||||
)
|
||||
|
||||
assertNotEquals(
|
||||
Foo::class.createType(listOf(KTypeProjection.Out(Any::class.createType(nullable = true)))),
|
||||
Foo::class.createType(listOf(KTypeProjection.Star))
|
||||
Foo::class.createType(listOf(KTypeProjection.covariant(Any::class.createType(nullable = true)))),
|
||||
Foo::class.createType(listOf(KTypeProjection.STAR))
|
||||
)
|
||||
|
||||
assertNotEquals(
|
||||
Foo::class.createType(listOf(KTypeProjection.Star), nullable = false),
|
||||
Foo::class.createType(listOf(KTypeProjection.Star), nullable = true)
|
||||
Foo::class.createType(listOf(KTypeProjection.STAR), nullable = false),
|
||||
Foo::class.createType(listOf(KTypeProjection.STAR), nullable = true)
|
||||
)
|
||||
|
||||
return "OK"
|
||||
|
||||
@@ -15,7 +15,7 @@ class A<T1> {
|
||||
fun foo(): A<Int>.B<Double, Float>.C<Long> = null!!
|
||||
|
||||
fun box(): String {
|
||||
fun KClass<*>.inv() = KTypeProjection.Invariant(this.createType())
|
||||
fun KClass<*>.inv() = KTypeProjection.invariant(this.createType())
|
||||
|
||||
val type = A.B.C::class.createType(listOf(Long::class.inv(), Double::class.inv(), Float::class.inv(), Int::class.inv()))
|
||||
assertEquals("A<kotlin.Int>.B<kotlin.Double, kotlin.Float>.C<kotlin.Long>", type.toString())
|
||||
|
||||
+2
-2
@@ -11,8 +11,8 @@ fun box(): String {
|
||||
assertEquals("Foo", Foo::class.createType().toString())
|
||||
assertEquals("Foo?", Foo::class.createType(nullable = true).toString())
|
||||
|
||||
assertEquals("Bar<kotlin.String>", Bar::class.createType(listOf(KTypeProjection.Invariant(String::class.createType()))).toString())
|
||||
assertEquals("Bar<kotlin.Int>?", Bar::class.createType(listOf(KTypeProjection.Invariant(Int::class.createType())), nullable = true).toString())
|
||||
assertEquals("Bar<kotlin.String>", Bar::class.createType(listOf(KTypeProjection.invariant(String::class.createType()))).toString())
|
||||
assertEquals("Bar<kotlin.Int>?", Bar::class.createType(listOf(KTypeProjection.invariant(Int::class.createType())), nullable = true).toString())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ class Outer<O> {
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val p = KTypeProjection.Star
|
||||
val p = KTypeProjection.STAR
|
||||
|
||||
test(String::class, listOf(p))
|
||||
test(String::class, listOf(p, p))
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.KTypeProjection
|
||||
import kotlin.reflect.KVariance
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
fun string(): String = null!!
|
||||
|
||||
@@ -19,10 +19,10 @@ fun box(): String {
|
||||
|
||||
assertEquals(
|
||||
listOf(
|
||||
KTypeProjection.Invariant(string),
|
||||
KTypeProjection.In(string),
|
||||
KTypeProjection.Out(string),
|
||||
KTypeProjection.Star
|
||||
KTypeProjection.invariant(string),
|
||||
KTypeProjection.contravariant(string),
|
||||
KTypeProjection.covariant(string),
|
||||
KTypeProjection.STAR
|
||||
),
|
||||
::projections.returnType.arguments
|
||||
)
|
||||
@@ -32,11 +32,11 @@ fun box(): String {
|
||||
)
|
||||
|
||||
val outNumber = ::array.returnType.arguments.single()
|
||||
assertTrue(outNumber is KTypeProjection.Out)
|
||||
assertEquals(KVariance.OUT, outNumber.variance)
|
||||
assertEquals(Number::class, outNumber.type?.classifier)
|
||||
|
||||
// There should be no use-site projection, despite the fact that the corresponding parameter has 'out' variance
|
||||
assertTrue(::list.returnType.arguments.single() is KTypeProjection.Invariant)
|
||||
// There should be no use-site variance, despite the fact that the corresponding parameter has 'out' variance
|
||||
assertEquals(KVariance.INVARIANT, ::list.returnType.arguments.single().variance)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
@@ -68,55 +68,45 @@ public interface KType {
|
||||
* See the [Kotlin language documentation](http://kotlinlang.org/docs/reference/generics.html#type-projections)
|
||||
* for more information.
|
||||
*/
|
||||
public sealed class KTypeProjection {
|
||||
/**
|
||||
* The type specified in the projection, or `null` if this is a star projection.
|
||||
*/
|
||||
public abstract val type: KType?
|
||||
public data class KTypeProjection private constructor(
|
||||
/**
|
||||
* The use-site variance specified in the projection, or `null` if this is a star projection.
|
||||
*/
|
||||
public val variance: KVariance?,
|
||||
/**
|
||||
* The type specified in the projection, or `null` if this is a star projection.
|
||||
*/
|
||||
public val type: KType?
|
||||
) {
|
||||
public companion object {
|
||||
/**
|
||||
* Star projection, denoted by the `*` character.
|
||||
* For example, in the type `KClass<*>`, `*` is the star projection.
|
||||
* See the [Kotlin language documentation](http://kotlinlang.org/docs/reference/generics.html#star-projections)
|
||||
* for more information.
|
||||
*/
|
||||
public val STAR: KTypeProjection = KTypeProjection(null, null)
|
||||
|
||||
/**
|
||||
* The use-site variance specified in the projection, or `null` if this is a star projection.
|
||||
*/
|
||||
public abstract val variance: KVariance?
|
||||
/**
|
||||
* Creates an invariant projection of a given type. Invariant projection is just the type itself,
|
||||
* without any use-site variance modifiers applied to it.
|
||||
* For example, in the type `Set<String>`, `String` is an invariant projection of the type represented by the class `String`.
|
||||
*/
|
||||
public fun invariant(type: KType): KTypeProjection =
|
||||
KTypeProjection(KVariance.INVARIANT, type)
|
||||
|
||||
/**
|
||||
* Invariant projection of a type. Invariant projection is just the type itself, without any use-site variance modifiers applied to it.
|
||||
* For example, in the type `Set<String>`, `String` is an invariant projection of the type represented by the class `String`.
|
||||
*/
|
||||
public data class Invariant(override val type: KType) : KTypeProjection() {
|
||||
override val variance: KVariance?
|
||||
get() = KVariance.INVARIANT
|
||||
}
|
||||
/**
|
||||
* Creates a contravariant projection of a given type, denoted by the `in` modifier applied to a type.
|
||||
* For example, in the type `MutableList<in Number>`, `in Number` is a contravariant projection of the type of class `Number`.
|
||||
*/
|
||||
public fun contravariant(type: KType): KTypeProjection =
|
||||
KTypeProjection(KVariance.IN, type)
|
||||
|
||||
/**
|
||||
* Contravariant projection of a type, denoted by the `in` modifier applied to a type.
|
||||
* For example, in the type `MutableList<in Number>`, `in Number` is a contravariant projection of the type of class `Number`.
|
||||
*/
|
||||
public data class In(override val type: KType) : KTypeProjection() {
|
||||
override val variance: KVariance?
|
||||
get() = KVariance.IN
|
||||
}
|
||||
|
||||
/**
|
||||
* Covariant projection of a type, denoted by the `out` modifier applied to a type.
|
||||
* For example, in the type `Array<out Number>`, `out Number` is a covariant projection of the type of class `Number`.
|
||||
*/
|
||||
public data class Out(override val type: KType) : KTypeProjection() {
|
||||
override val variance: KVariance?
|
||||
get() = KVariance.OUT
|
||||
}
|
||||
|
||||
/**
|
||||
* Star projection, denoted by the `*` character.
|
||||
* For example, in the type `KClass<*>`, `*` is the star projection.
|
||||
* See the [Kotlin language documentation](http://kotlinlang.org/docs/reference/generics.html#star-projections)
|
||||
* for more information.
|
||||
*/
|
||||
public object Star : KTypeProjection() {
|
||||
override val type: KType?
|
||||
get() = null
|
||||
|
||||
override val variance: KVariance?
|
||||
get() = null
|
||||
/**
|
||||
* Creates a covariant projection of a given type, denoted by the `out` modifier applied to a type.
|
||||
* For example, in the type `Array<out Number>`, `out Number` is a covariant projection of the type of class `Number`.
|
||||
*/
|
||||
public fun covariant(type: KType): KTypeProjection =
|
||||
KTypeProjection(KVariance.OUT, type)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,11 +66,11 @@ private fun createKotlinType(
|
||||
val parameters = typeConstructor.parameters
|
||||
return KotlinTypeFactory.simpleType(typeAnnotations, typeConstructor, arguments.mapIndexed { index, typeProjection ->
|
||||
val type = (typeProjection.type as KTypeImpl?)?.type
|
||||
when (typeProjection) {
|
||||
is KTypeProjection.Invariant -> TypeProjectionImpl(Variance.INVARIANT, type!!)
|
||||
is KTypeProjection.In -> TypeProjectionImpl(Variance.IN_VARIANCE, type!!)
|
||||
is KTypeProjection.Out -> TypeProjectionImpl(Variance.OUT_VARIANCE, type!!)
|
||||
is KTypeProjection.Star -> StarProjectionImpl(parameters[index])
|
||||
when (typeProjection.variance) {
|
||||
KVariance.INVARIANT -> TypeProjectionImpl(Variance.INVARIANT, type!!)
|
||||
KVariance.IN -> TypeProjectionImpl(Variance.IN_VARIANCE, type!!)
|
||||
KVariance.OUT -> TypeProjectionImpl(Variance.OUT_VARIANCE, type!!)
|
||||
null -> StarProjectionImpl(parameters[index])
|
||||
}
|
||||
}, nullable)
|
||||
}
|
||||
@@ -89,5 +89,5 @@ val KClassifier.starProjectedType: KType
|
||||
val typeParameters = descriptor.typeConstructor.parameters
|
||||
if (typeParameters.isEmpty()) return createType() // TODO: optimize, get defaultType from ClassDescriptor
|
||||
|
||||
return createType(typeParameters.map { KTypeProjection.Star })
|
||||
return createType(typeParameters.map { KTypeProjection.STAR })
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ internal class KTypeImpl(
|
||||
|
||||
return typeArguments.mapIndexed { i, typeProjection ->
|
||||
if (typeProjection.isStarProjection) {
|
||||
KTypeProjection.Star
|
||||
KTypeProjection.STAR
|
||||
}
|
||||
else {
|
||||
val type = KTypeImpl(typeProjection.type) {
|
||||
@@ -105,9 +105,9 @@ internal class KTypeImpl(
|
||||
}
|
||||
}
|
||||
when (typeProjection.projectionKind) {
|
||||
Variance.INVARIANT -> KTypeProjection.Invariant(type)
|
||||
Variance.IN_VARIANCE -> KTypeProjection.In(type)
|
||||
Variance.OUT_VARIANCE -> KTypeProjection.Out(type)
|
||||
Variance.INVARIANT -> KTypeProjection.invariant(type)
|
||||
Variance.IN_VARIANCE -> KTypeProjection.contravariant(type)
|
||||
Variance.OUT_VARIANCE -> KTypeProjection.covariant(type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user