Last active
March 16, 2021 21:54
-
-
Save udalov/bb6f398c2e643ee69586356fdd67e9b1 to your computer and use it in GitHub Desktop.
DEPRECATED example how to obtain KType instance from reified T. Please use "typeOf" since 1.3.40!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.lang.reflect.* | |
import kotlin.reflect.KClass | |
import kotlin.reflect.KType | |
import kotlin.reflect.KTypeProjection | |
import kotlin.reflect.KVariance | |
import kotlin.reflect.full.createType | |
// --- Interface --- | |
inline fun <reified T : Any> getKType(): KType = | |
object : SuperTypeTokenHolder<T>() {}.getKTypeImpl() | |
// --- Implementation --- | |
@Suppress("unused") | |
open class SuperTypeTokenHolder<T> | |
fun SuperTypeTokenHolder<*>.getKTypeImpl(): KType = | |
javaClass.genericSuperclass.toKType().arguments.single().type!! | |
fun KClass<*>.toInvariantFlexibleProjection(arguments: List<KTypeProjection> = emptyList()): KTypeProjection { | |
// TODO: there should be an API in kotlin-reflect which creates KType instances corresponding to flexible types | |
// Currently we always produce a non-null type, which is obviously wrong | |
val args = if (java.isArray()) listOf(java.componentType.kotlin.toInvariantFlexibleProjection()) else arguments | |
return KTypeProjection.invariant(createType(args, nullable = false)) | |
} | |
fun Type.toKTypeProjection(): KTypeProjection = when (this) { | |
is Class<*> -> this.kotlin.toInvariantFlexibleProjection() | |
is ParameterizedType -> { | |
val erasure = (rawType as Class<*>).kotlin | |
erasure.toInvariantFlexibleProjection((erasure.typeParameters.zip(actualTypeArguments).map { (parameter, argument) -> | |
val projection = argument.toKTypeProjection() | |
projection.takeIf { | |
// Get rid of use-site projections on arguments, where the corresponding parameters already have a declaration-site projection | |
parameter.variance == KVariance.INVARIANT || parameter.variance != projection.variance | |
} ?: KTypeProjection.invariant(projection.type!!) | |
})) | |
} | |
is WildcardType -> when { | |
lowerBounds.isNotEmpty() -> KTypeProjection.contravariant(lowerBounds.single().toKType()) | |
upperBounds.isNotEmpty() -> KTypeProjection.covariant(upperBounds.single().toKType()) | |
// This looks impossible to obtain through Java reflection API, but someone may construct and pass such an instance here anyway | |
else -> KTypeProjection.STAR | |
} | |
is GenericArrayType -> Array<Any>::class.toInvariantFlexibleProjection(listOf(genericComponentType.toKTypeProjection())) | |
is TypeVariable<*> -> TODO() // TODO | |
else -> throw IllegalArgumentException("Unsupported type: $this") | |
} | |
fun Type.toKType(): KType = toKTypeProjection().type!! | |
// --- Usage example --- | |
fun main(args: Array<String>) { | |
println(getKType<List<Map<String, Array<Double>>>>()) | |
println(getKType<List<*>>()) | |
println(getKType<Array<*>>()) | |
println(getKType<Array<Array<String>>>()) | |
println(getKType<Unit>()) | |
} |
@udalov Hello, is this kt file possible to include in my library project?
@udalov Can you mention what license you've released this under so that it can be included in third party projects? Apache 2.0?
@hinls1007 @JLLeitschuh This code is licensed under WTFPL Version 2.
createType
doesn't seem to exist anymore
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I had to change
to
to make it work.
(jdk1.8.0_131, kotlin 1.1.61)