Support mapping of KType to j.l.reflect.Type

This commit is contained in:
Alexander Udalov
2015-08-04 22:29:54 +03:00
parent 49b689f883
commit d3e39812cb
20 changed files with 397 additions and 23 deletions
@@ -17,20 +17,23 @@
package kotlin.reflect.jvm.internal
import java.lang.reflect.Member
import java.lang.reflect.Modifier
import java.lang.reflect.Type
import java.lang.reflect.Constructor as ReflectConstructor
import java.lang.reflect.Field as ReflectField
import java.lang.reflect.Method as ReflectMethod
internal sealed class FunctionCaller(
private val expectedArgumentNumber: Int
) {
internal abstract class FunctionCaller {
abstract val member: Member
abstract val returnType: Type
abstract val parameterTypes: List<Type>
abstract fun call(args: Array<*>): Any?
protected open fun checkArguments(args: Array<*>) {
if (expectedArgumentNumber != args.size()) {
throw IllegalArgumentException("Callable expects $expectedArgumentNumber arguments, but ${args.size()} were provided.")
if (parameterTypes.size() != args.size()) {
throw IllegalArgumentException("Callable expects ${parameterTypes.size()} arguments, but ${args.size()} were provided.")
}
}
@@ -40,9 +43,16 @@ internal sealed class FunctionCaller(
}
}
class Constructor(val constructor: ReflectConstructor<*>) : FunctionCaller(constructor.parameterTypes.size()) {
class Constructor(val constructor: ReflectConstructor<*>) : FunctionCaller() {
override val member: Member get() = constructor
override val returnType = constructor.declaringClass
override val parameterTypes =
if (returnType.declaringClass == null || Modifier.isStatic(returnType.modifiers))
constructor.genericParameterTypes.toList()
else listOf(returnType.declaringClass, *constructor.genericParameterTypes)
override fun call(args: Array<*>): Any? {
checkArguments(args)
return constructor.newInstance(*args)
@@ -51,10 +61,17 @@ internal sealed class FunctionCaller(
abstract class Method(
val method: ReflectMethod,
requiresInstance: Boolean
) : FunctionCaller(method.parameterTypes.size() + (if (requiresInstance) 1 else 0)) {
private val requiresInstance: Boolean
) : FunctionCaller() {
override val member: Member get() = method
private val isVoidMethod = method.returnType == Void.TYPE
override val returnType = method.genericReturnType
override val parameterTypes =
if (requiresInstance) listOf(method.declaringClass, *method.genericParameterTypes)
else method.genericParameterTypes.toList()
private val isVoidMethod = returnType == Void.TYPE
protected fun callMethod(instance: Any?, args: Array<*>): Any? {
val result = method.invoke(instance, *args)
@@ -86,14 +103,19 @@ internal sealed class FunctionCaller(
}
}
abstract class FieldAccessor(val field: ReflectField, expectedArgumentNumber: Int) : FunctionCaller(expectedArgumentNumber) {
abstract class FieldAccessor(val field: ReflectField) : FunctionCaller() {
override val member: Member get() = field
}
abstract class FieldGetter(
field: ReflectField,
private val requiresInstance: Boolean
) : FieldAccessor(field, if (requiresInstance) 1 else 0) {
) : FieldAccessor(field) {
override val returnType = field.genericType
override val parameterTypes =
if (requiresInstance) listOf(field.declaringClass) else listOf()
override fun call(args: Array<*>): Any? {
checkArguments(args)
return field.get(if (requiresInstance) args.first() else null)
@@ -104,7 +126,13 @@ internal sealed class FunctionCaller(
field: ReflectField,
private val notNull: Boolean,
private val requiresInstance: Boolean
) : FieldAccessor(field, if (requiresInstance) 2 else 1) {
) : FieldAccessor(field) {
override val returnType: Type get() = Void.TYPE
override val parameterTypes =
if (requiresInstance) listOf(field.declaringClass, field.genericType)
else listOf(field.genericType)
override fun checkArguments(args: Array<*>) {
super.checkArguments(args)
if (notNull && args.last() == null) {
@@ -36,15 +36,15 @@ interface KCallableImpl<out R> : KCallable<R>, KAnnotatedElementImpl {
var index = 0
if (descriptor.dispatchReceiverParameter != null) {
result.add(KParameterImpl(index++) { descriptor.dispatchReceiverParameter!! })
result.add(KParameterImpl(this, index++) { descriptor.dispatchReceiverParameter!! })
}
if (descriptor.extensionReceiverParameter != null) {
result.add(KParameterImpl(index++) { descriptor.extensionReceiverParameter!! })
result.add(KParameterImpl(this, index++) { descriptor.extensionReceiverParameter!! })
}
for (i in descriptor.valueParameters.indices) {
result.add(KParameterImpl(index++) { descriptor.valueParameters[i] })
result.add(KParameterImpl(this, index++) { descriptor.valueParameters[i] })
}
result.trimToSize()
@@ -52,7 +52,7 @@ interface KCallableImpl<out R> : KCallable<R>, KAnnotatedElementImpl {
}
override val returnType: KType
get() = KTypeImpl(descriptor.returnType!!)
get() = KTypeImpl(descriptor.returnType!!) { caller.returnType }
@suppress("UNCHECKED_CAST")
override fun call(vararg args: Any?): R = reflectionCall {
@@ -23,8 +23,9 @@ import kotlin.reflect.KParameter
import kotlin.reflect.KType
class KParameterImpl(
val callable: KCallableImpl<*>,
override val index: Int,
private val computeDescriptor: () -> ParameterDescriptor
computeDescriptor: () -> ParameterDescriptor
) : KParameter, KAnnotatedElementImpl {
private val descriptor: ParameterDescriptor by ReflectProperties.lazySoft(computeDescriptor)
@@ -38,5 +39,5 @@ class KParameterImpl(
}
override val type: KType
get() = KTypeImpl(descriptor.getType())
get() = KTypeImpl(descriptor.type) { callable.caller.parameterTypes[index] }
}
@@ -17,9 +17,15 @@
package kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.types.JetType
import java.lang.reflect.Type
import kotlin.reflect.KType
class KTypeImpl(val type: JetType) : KType {
class KTypeImpl(
val type: JetType,
computeJavaType: () -> Type
) : KType {
internal val javaType: Type by ReflectProperties.lazySoft(computeJavaType)
override val isMarkedNullable: Boolean
get() = type.isMarkedNullable
}
@@ -16,10 +16,7 @@
package kotlin.reflect.jvm
import java.lang.reflect.Constructor
import java.lang.reflect.Field
import java.lang.reflect.Method
import java.lang.reflect.Modifier
import java.lang.reflect.*
import kotlin.jvm.internal.Intrinsic
import kotlin.reflect.*
import kotlin.reflect.jvm.internal.*
@@ -87,6 +84,15 @@ public val <T> KFunction<T>.javaConstructor: Constructor<T>?
}
/**
* Returns a Java [Type] instance corresponding to the given Kotlin type.
* Note that one Kotlin type may correspond to different JVM types depending on where it appears. For example, [Unit] corresponds to
* the JVM class [Unit] when it's the type of a parameter, or to `void` when it's the return type of a function.
*/
public val KType.javaType: Type
get() = (this as KTypeImpl).javaType
// Java reflection -> Kotlin reflection