Reflection: add KType.classifier

#KT-8998 In Progress
This commit is contained in:
Alexander Udalov
2016-07-12 16:09:29 +03:00
parent 2ab0f489b5
commit c1dd831e65
8 changed files with 284 additions and 1 deletions
@@ -21,6 +21,14 @@ package kotlin.reflect
* or a type parameter of some declaration, plus nullability.
*/
public interface KType {
/**
* The declaration of the classifier used in this type.
* For example, in the type `List<String>` the classifier would be the [KClass] instance for [List].
*
* Returns `null` if this type is not denotable in Kotlin, for example if it is an intersection type.
*/
public val classifier: KClassifier?
/**
* `true` if this type was marked nullable in the source code.
*
@@ -27,6 +27,13 @@ val Class<*>.safeClassLoader: ClassLoader
fun Class<*>.isEnumClassOrSpecializedEnumEntryClass(): Boolean =
Enum::class.java.isAssignableFrom(this)
private val WRAPPER_TO_PRIMITIVE = listOf(
Boolean::class, Byte::class, Char::class, Double::class, Float::class, Int::class, Long::class, Short::class
).map { it.javaObjectType to it.javaPrimitiveType }.toMap()
val Class<*>.primitiveByWrapper: Class<*>?
get() = WRAPPER_TO_PRIMITIVE[this]
/**
* NOTE: does not perform a Java -> Kotlin mapping. If this is not expected, consider using KClassImpl#classId instead
*/
@@ -16,9 +16,18 @@
package kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.load.java.structure.reflect.createArrayType
import org.jetbrains.kotlin.load.java.structure.reflect.primitiveByWrapper
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import java.lang.reflect.Type
import kotlin.reflect.KClass
import kotlin.reflect.KClassifier
import kotlin.reflect.KType
import kotlin.reflect.KTypeParameter
internal class KTypeImpl(
val type: KotlinType,
@@ -26,11 +35,49 @@ internal class KTypeImpl(
) : KType {
internal val javaType: Type by ReflectProperties.lazySoft(computeJavaType)
override val classifier: KClassifier?
get() = convert(type)
private fun convert(type: KotlinType): KClassifier? {
val descriptor = type.constructor.declarationDescriptor
when (descriptor) {
is ClassDescriptor -> {
val jClass = descriptor.toJavaClass() ?: return null
if (jClass.isArray) {
// There may be no argument if it's a primitive array (such as IntArray)
val argument = type.arguments.singleOrNull()?.type ?: return KClassImpl(jClass)
val elementClassifier = convert(argument)
val elementType = when (elementClassifier) {
is KClass<*> -> elementClassifier
is KTypeParameter -> {
// For arrays of type parameters (`Array<T>`) we return the KClass representing `Array<Any>`
// since there's no other sensible option
// TODO: return `Array<erasure-of-T>`
Any::class
}
else -> TODO("Arrays of type alias classifiers are not yet supported")
}
return KClassImpl(elementType.java.createArrayType())
}
if (!TypeUtils.isNullableType(type)) {
return KClassImpl(jClass.primitiveByWrapper ?: jClass)
}
return KClassImpl(jClass)
}
is TypeParameterDescriptor -> return KTypeParameterImpl(descriptor)
is TypeAliasDescriptor -> TODO("Type alias classifiers are not yet supported")
else -> return null
}
}
override val isMarkedNullable: Boolean
get() = type.isMarkedNullable
override fun equals(other: Any?) =
other is KTypeImpl && type.equals(other.type)
other is KTypeImpl && type == other.type
override fun hashCode() =
type.hashCode()