Reflection: add KType.classifier
#KT-8998 In Progress
This commit is contained in:
@@ -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.
|
||||
*
|
||||
|
||||
+7
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user