Reflection: simplify KTypeProjection

This commit is contained in:
Alexander Udalov
2016-08-08 13:10:24 +03:00
parent a7f4037206
commit 7f142253bf
10 changed files with 74 additions and 84 deletions
+37 -47
View File
@@ -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)
}
}
}