Support KClass.constructors in reflection

This commit is contained in:
Alexander Udalov
2015-07-13 18:59:10 +03:00
parent da5cffdb60
commit 81ef1c19d8
12 changed files with 190 additions and 51 deletions
@@ -16,6 +16,7 @@
package kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.load.java.structure.reflect.classId
@@ -43,6 +44,8 @@ abstract class KCallableContainerImpl : KDeclarationContainer {
abstract val scope: JetScope
abstract val constructorDescriptors: Collection<ConstructorDescriptor>
fun findPropertyDescriptor(name: String, signature: String): PropertyDescriptor {
val properties = scope
.getProperties(Name.guess(name))
@@ -63,8 +66,7 @@ abstract class KCallableContainerImpl : KDeclarationContainer {
}
fun findFunctionDescriptor(name: String, signature: String): FunctionDescriptor {
val functions = scope
.getFunctions(Name.guess(name))
val functions = (if (name == "<init>") constructorDescriptors.toList() else scope.getFunctions(Name.guess(name)))
.filter { descriptor ->
RuntimeTypeMapper.mapSignature(descriptor) == signature
}
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies
import kotlin.reflect.KCallable
import kotlin.reflect.KClass
import kotlin.reflect.KFunction
import kotlin.reflect.KotlinReflectionInternalError
class KClassImpl<T>(override val jClass: Class<T>) : KCallableContainerImpl(), KClass<T> {
@@ -43,6 +44,15 @@ class KClassImpl<T>(override val jClass: Class<T>) : KCallableContainerImpl(), K
descriptor, "KClassImpl scope", descriptor.getDefaultType().getMemberScope(), descriptor.getStaticScope()
)
override val constructorDescriptors: Collection<ConstructorDescriptor>
get() {
val descriptor = descriptor
if (descriptor.getKind() == ClassKind.CLASS || descriptor.getKind() == ClassKind.ENUM_CLASS) {
return descriptor.getConstructors()
}
return emptyList()
}
override val simpleName: String? get() {
if (jClass.isAnonymousClass()) return null
@@ -77,44 +87,57 @@ class KClassImpl<T>(override val jClass: Class<T>) : KCallableContainerImpl(), K
override val members: Collection<KCallable<*>>
get() = getMembers(declaredOnly = false, nonExtensions = true, extensions = true).toList()
fun getMembers(declaredOnly: Boolean, nonExtensions: Boolean, extensions: Boolean): Sequence<KCallable<*>> =
scope.getAllDescriptors().asSequence()
.filter { descriptor ->
descriptor !is MemberDescriptor || descriptor.getVisibility() != Visibilities.INVISIBLE_FAKE
}
.map { descriptor ->
descriptor.accept(object : DeclarationDescriptorVisitorEmptyBodies<KCallable<*>?, Nothing>() {
private fun skipCallable(descriptor: CallableMemberDescriptor): Boolean {
if (declaredOnly && !descriptor.getKind().isReal()) return true
@suppress("UNCHECKED_CAST")
override val constructors: Collection<KFunction<T>>
get() = constructorDescriptors.map {
KFunctionImpl(this, it) as KFunction<T>
}
val isExtension = descriptor.getExtensionReceiverParameter() != null
if (isExtension && !extensions) return true
if (!isExtension && !nonExtensions) return true
fun getMembers(declaredOnly: Boolean, nonExtensions: Boolean, extensions: Boolean): Sequence<KCallable<*>> {
val visitor = object : DeclarationDescriptorVisitorEmptyBodies<KCallable<*>?, Nothing>() {
private fun skipCallable(descriptor: CallableMemberDescriptor): Boolean {
if (declaredOnly && !descriptor.getKind().isReal()) return true
return false
}
val isExtension = descriptor.getExtensionReceiverParameter() != null
if (isExtension && !extensions) return true
if (!isExtension && !nonExtensions) return true
override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, data: Nothing?): KCallable<*>? {
if (skipCallable(descriptor)) return null
return false
}
return if (descriptor.getExtensionReceiverParameter() == null) {
if (descriptor.isVar()) KMutableProperty1Impl<T, Any?>(this@KClassImpl, descriptor)
else KProperty1Impl<T, Any?>(this@KClassImpl, descriptor)
}
else {
if (descriptor.isVar()) KMutableProperty2Impl<T, Any?, Any?>(this@KClassImpl, descriptor)
else KProperty2Impl<T, Any?, Any?>(this@KClassImpl, descriptor)
}
}
override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, data: Nothing?): KCallable<*>? {
if (skipCallable(descriptor)) return null
override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: Nothing?): KCallable<*>? {
if (skipCallable(descriptor)) return null
return if (descriptor.getExtensionReceiverParameter() == null) {
if (descriptor.isVar()) KMutableProperty1Impl<T, Any?>(this@KClassImpl, descriptor)
else KProperty1Impl<T, Any?>(this@KClassImpl, descriptor)
}
else {
if (descriptor.isVar()) KMutableProperty2Impl<T, Any?, Any?>(this@KClassImpl, descriptor)
else KProperty2Impl<T, Any?, Any?>(this@KClassImpl, descriptor)
}
}
return KFunctionImpl(this@KClassImpl, descriptor)
}
}, null)
}
.filterNotNull()
override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: Nothing?): KCallable<*>? {
if (skipCallable(descriptor)) return null
return KFunctionImpl(this@KClassImpl, descriptor)
}
override fun visitConstructorDescriptor(descriptor: ConstructorDescriptor, data: Nothing?): KCallable<*>? {
throw IllegalStateException("No constructors should appear in this scope: $descriptor")
}
}
return scope.getAllDescriptors().asSequence()
.filter { descriptor ->
descriptor !is MemberDescriptor || descriptor.getVisibility() != Visibilities.INVISIBLE_FAKE
}
.map { descriptor ->
descriptor.accept(visitor, null)
}
.filterNotNull()
}
override fun equals(other: Any?): Boolean =
other is KClassImpl<*> && jClass == other.jClass
@@ -16,6 +16,7 @@
package kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.resolve.scopes.JetScope
import kotlin.jvm.internal.FunctionReference
import kotlin.reflect.KotlinReflectionInternalError
@@ -65,5 +66,8 @@ object EmptyContainerForLocal : KCallableContainerImpl() {
override val scope: JetScope
get() = fail()
override val constructorDescriptors: Collection<ConstructorDescriptor>
get() = fail()
private fun fail() = throw KotlinReflectionInternalError("Introspecting local functions is not yet supported in Kotlin reflection")
}
@@ -16,10 +16,11 @@
package kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.load.java.structure.reflect.classId
import org.jetbrains.kotlin.resolve.scopes.JetScope
import kotlin.jvm.internal.KotlinPackage
import kotlin.reflect.*
import kotlin.reflect.KPackage
class KPackageImpl(override val jClass: Class<*>) : KCallableContainerImpl(), KPackage {
val descriptor by ReflectProperties.lazySoft {
@@ -31,6 +32,9 @@ class KPackageImpl(override val jClass: Class<*>) : KCallableContainerImpl(), KP
override val scope: JetScope get() = descriptor.memberScope
override val constructorDescriptors: Collection<ConstructorDescriptor>
get() = emptyList()
override fun equals(other: Any?): Boolean =
other is KPackageImpl && jClass == other.jClass
@@ -31,22 +31,22 @@ import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf
import kotlin.reflect.KotlinReflectionInternalError
object RuntimeTypeMapper {
fun mapSignature(function: FunctionDescriptor): String {
if (function is DeserializedSimpleFunctionDescriptor) {
val proto = function.getProto()
if (function is DeserializedCallableMemberDescriptor) {
val proto = function.proto
if (!proto.hasExtension(JvmProtoBuf.methodSignature)) {
// If it's a deserialized function but has no JVM signature, it must be from built-ins
return mapIntrinsicFunctionSignature(function) ?:
throw KotlinReflectionInternalError("No metadata found for $function")
}
val signature = proto.getExtension(JvmProtoBuf.methodSignature)
return SignatureDeserializer(function.getNameResolver()).methodSignatureString(signature)
return SignatureDeserializer(function.nameResolver).methodSignatureString(signature)
}
else if (function is JavaMethodDescriptor) {
val method = (function.getSource() as? JavaSourceElement)?.javaElement as? JavaMethod ?:
@@ -130,7 +130,7 @@ object RuntimeTypeMapper {
else throw KotlinReflectionInternalError("Unknown origin of $property (${property.javaClass})")
}
private fun mapIntrinsicFunctionSignature(function: DeserializedSimpleFunctionDescriptor): String? {
private fun mapIntrinsicFunctionSignature(function: FunctionDescriptor): String? {
val parameters = function.getValueParameters()
when (function.getName().asString()) {