Support KClass.functions and declaredFunctions

This commit is contained in:
Alexander Udalov
2015-07-08 03:59:35 +03:00
parent 50dbda1e1a
commit da5cffdb60
7 changed files with 105 additions and 9 deletions
@@ -18,6 +18,27 @@ package kotlin.reflect
import kotlin.reflect.jvm.internal.KClassImpl
/**
* Returns all functions declared in this class and all of its superclasses.
* If this is a Java class, it includes all non-static methods declared in the class and the superclasses,
* as well as static methods declared in the class.
*/
public val <T> KClass<T>.functions: Collection<KFunction<*>>
get() = (this as KClassImpl<T>)
.getMembers(declaredOnly = false, nonExtensions = true, extensions = true)
.filterIsInstance<KFunction<*>>()
.toList()
/**
* Returns all functions declared in this class.
* If this is a Java class, it includes both non-static and static methods.
*/
public val KClass<*>.declaredFunctions: Collection<KFunction<*>>
get() = (this as KClassImpl)
.getMembers(declaredOnly = true, nonExtensions = true, extensions = true)
.filterIsInstance<KFunction<*>>()
.toList()
/**
* Returns non-extension properties declared in this class and all of its superclasses.
*/
@@ -16,9 +16,7 @@
package kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.descriptors.MemberDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.resolve.scopes.ChainedScope
@@ -86,14 +84,20 @@ class KClassImpl<T>(override val jClass: Class<T>) : KCallableContainerImpl(), K
}
.map { descriptor ->
descriptor.accept(object : DeclarationDescriptorVisitorEmptyBodies<KCallable<*>?, Nothing>() {
override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, data: Nothing?): KCallable<*>? {
if (declaredOnly && !descriptor.getKind().isReal()) return null
private fun skipCallable(descriptor: CallableMemberDescriptor): Boolean {
if (declaredOnly && !descriptor.getKind().isReal()) return true
val isExtension = descriptor.getExtensionReceiverParameter() != null
if (isExtension && !extensions) return null
if (!isExtension && !nonExtensions) return null
if (isExtension && !extensions) return true
if (!isExtension && !nonExtensions) return true
return if (!isExtension) {
return false
}
override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, 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)
}
@@ -102,6 +106,12 @@ class KClassImpl<T>(override val jClass: Class<T>) : KCallableContainerImpl(), K
else KProperty2Impl<T, Any?, Any?>(this@KClassImpl, descriptor)
}
}
override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: Nothing?): KCallable<*>? {
if (skipCallable(descriptor)) return null
return KFunctionImpl(this@KClassImpl, descriptor)
}
}, null)
}
.filterNotNull()
@@ -41,7 +41,9 @@ object RuntimeTypeMapper {
if (function is DeserializedSimpleFunctionDescriptor) {
val proto = function.getProto()
if (!proto.hasExtension(JvmProtoBuf.methodSignature)) {
throw KotlinReflectionInternalError("No metadata found for $function")
// 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)
@@ -128,6 +130,31 @@ object RuntimeTypeMapper {
else throw KotlinReflectionInternalError("Unknown origin of $property (${property.javaClass})")
}
private fun mapIntrinsicFunctionSignature(function: DeserializedSimpleFunctionDescriptor): String? {
val parameters = function.getValueParameters()
when (function.getName().asString()) {
"equals" -> {
if (parameters.size() == 1 && KotlinBuiltIns.isNullableAny(parameters.single().getType())) {
return "equals(Ljava/lang/Object;)Z"
}
}
"hashCode" -> {
if (parameters.isEmpty()) {
return "hashCode()I"
}
}
"toString" -> {
if (parameters.isEmpty()) {
return "toString()Ljava/lang/String;"
}
}
// TODO: generalize and support other functions from built-ins
}
return null
}
fun mapJvmClassToKotlinClassId(klass: Class<*>): ClassId {
if (klass.isArray()) {
klass.getComponentType().primitiveType?.let {