Add KFunction.name, support reflection for function references
#KT-7694 Fixed
This commit is contained in:
+8
@@ -0,0 +1,8 @@
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class A
|
||||
|
||||
fun box(): String {
|
||||
assertEquals("<init>", ::A.name)
|
||||
return "OK"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
fun box(): String {
|
||||
fun OK() {}
|
||||
|
||||
return ::OK.name
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import kotlin.platform.platformName
|
||||
|
||||
@platformName("Fail")
|
||||
fun OK() {}
|
||||
|
||||
fun box() = ::OK.name
|
||||
@@ -0,0 +1,16 @@
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
fun foo() {}
|
||||
|
||||
class A {
|
||||
fun bar() = ""
|
||||
}
|
||||
|
||||
fun Int.baz() = this
|
||||
|
||||
fun box(): String {
|
||||
assertEquals("foo", ::foo.name)
|
||||
assertEquals("bar", A::bar.name)
|
||||
assertEquals("baz", Int::baz.name)
|
||||
return "OK"
|
||||
}
|
||||
+42
@@ -2821,6 +2821,21 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib/reflection/constructors")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Constructors extends AbstractBlackBoxCodegenTest {
|
||||
public void testAllFilesPresentInConstructors() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithStdlib/reflection/constructors"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("constructorName.kt")
|
||||
public void testConstructorName() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/constructors/constructorName.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib/reflection/enclosing")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
@@ -2974,6 +2989,33 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib/reflection/functions")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Functions extends AbstractBlackBoxCodegenTest {
|
||||
public void testAllFilesPresentInFunctions() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithStdlib/reflection/functions"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("localFunctionName.kt")
|
||||
public void testLocalFunctionName() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/functions/localFunctionName.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("platformName.kt")
|
||||
public void testPlatformName() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/functions/platformName.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simpleNames.kt")
|
||||
public void testSimpleNames() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/functions/simpleNames.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib/reflection/genericSignature")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
@@ -19,4 +19,4 @@ package kotlin.reflect
|
||||
/**
|
||||
* Represents a function with introspection capabilities.
|
||||
*/
|
||||
public interface KFunction<out R> : Function<R>
|
||||
public interface KFunction<out R> : KCallable<R>, Function<R>
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ import java.util.Arrays
|
||||
public class ReflectJavaClass(
|
||||
private val klass: Class<*>
|
||||
) : ReflectJavaElement(), ReflectJavaAnnotationOwner, ReflectJavaModifierListOwner, JavaClass {
|
||||
override val element: AnnotatedElement get() = klass
|
||||
override val element: Class<*> get() = klass
|
||||
|
||||
override val modifiers: Int get() = klass.getModifiers()
|
||||
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ import java.lang.reflect.Method
|
||||
import java.lang.reflect.TypeVariable
|
||||
|
||||
public class ReflectJavaTypeParameter(
|
||||
private val typeVariable: TypeVariable<*>
|
||||
public val typeVariable: TypeVariable<*>
|
||||
) : ReflectJavaElement(), JavaTypeParameter {
|
||||
override fun getUpperBounds(): List<ReflectJavaClassifierType> {
|
||||
val bounds = typeVariable.getBounds().map { bound -> ReflectJavaClassifierType(bound) }
|
||||
|
||||
+31
-26
@@ -16,9 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.builtins.functions
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
|
||||
@@ -32,7 +30,7 @@ class FunctionClassScope(
|
||||
private val storageManager: StorageManager,
|
||||
private val functionClass: FunctionClassDescriptor
|
||||
) : JetScopeImpl() {
|
||||
private val allFunctions = storageManager.createLazyValue {
|
||||
private val allDescriptors = storageManager.createLazyValue {
|
||||
if (functionClass.functionKind == FunctionClassDescriptor.Kind.Function) {
|
||||
val invoke = FunctionInvokeDescriptor.create(functionClass)
|
||||
(listOf(invoke) + createFakeOverrides(invoke)).toReadOnlyList()
|
||||
@@ -45,35 +43,42 @@ class FunctionClassScope(
|
||||
override fun getContainingDeclaration() = functionClass
|
||||
|
||||
override fun getDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean): Collection<DeclarationDescriptor> {
|
||||
if (!kindFilter.acceptsKinds(DescriptorKindFilter.FUNCTIONS_MASK)) return listOf()
|
||||
return allFunctions()
|
||||
if (!kindFilter.acceptsKinds(DescriptorKindFilter.CALLABLES.kindMask)) return listOf()
|
||||
return allDescriptors()
|
||||
}
|
||||
|
||||
override fun getFunctions(name: Name): Collection<FunctionDescriptor> {
|
||||
return allFunctions().filter { it.getName() == name }
|
||||
return allDescriptors().filterIsInstance<FunctionDescriptor>().filter { it.getName() == name }
|
||||
}
|
||||
|
||||
private fun createFakeOverrides(invoke: FunctionDescriptor?): List<FunctionDescriptor> {
|
||||
val result = ArrayList<FunctionDescriptor>(3)
|
||||
val allSuperDescriptors = functionClass.getTypeConstructor().getSupertypes().flatMap { it.getMemberScope().getAllDescriptors() }
|
||||
for ((name, descriptors) in allSuperDescriptors.groupBy { it.getName() }) {
|
||||
@suppress("UNCHECKED_CAST")
|
||||
OverridingUtil.generateOverridesInFunctionGroup(
|
||||
name,
|
||||
/* membersFromSupertypes = */ descriptors as Collection<FunctionDescriptor>,
|
||||
/* membersFromCurrent = */ if (name == invoke?.getName()) listOf(invoke) else listOf(),
|
||||
functionClass,
|
||||
object : OverridingUtil.DescriptorSink {
|
||||
override fun addFakeOverride(fakeOverride: CallableMemberDescriptor) {
|
||||
OverridingUtil.resolveUnknownVisibilityForMember(fakeOverride, null)
|
||||
result.add(fakeOverride as FunctionDescriptor)
|
||||
}
|
||||
override fun getProperties(name: Name): Collection<VariableDescriptor> {
|
||||
return allDescriptors().filterIsInstance<PropertyDescriptor>().filter { it.getName() == name }
|
||||
}
|
||||
|
||||
override fun conflict(fromSuper: CallableMemberDescriptor, fromCurrent: CallableMemberDescriptor) {
|
||||
error("Conflict in scope of ${getContainingDeclaration()}: $fromSuper vs $fromCurrent")
|
||||
private fun createFakeOverrides(invoke: FunctionDescriptor?): List<DeclarationDescriptor> {
|
||||
val result = ArrayList<DeclarationDescriptor>(3)
|
||||
val allSuperDescriptors = functionClass.getTypeConstructor().getSupertypes()
|
||||
.flatMap { it.getMemberScope().getAllDescriptors() }
|
||||
.filterIsInstance<CallableMemberDescriptor>()
|
||||
for ((name, group) in allSuperDescriptors.groupBy { it.getName() }) {
|
||||
for ((isFunction, descriptors) in group.groupBy { it is FunctionDescriptor }) {
|
||||
OverridingUtil.generateOverridesInFunctionGroup(
|
||||
name,
|
||||
/* membersFromSupertypes = */ descriptors,
|
||||
/* membersFromCurrent = */ if (isFunction && name == invoke?.getName()) listOf(invoke) else listOf(),
|
||||
functionClass,
|
||||
object : OverridingUtil.DescriptorSink {
|
||||
override fun addFakeOverride(fakeOverride: CallableMemberDescriptor) {
|
||||
OverridingUtil.resolveUnknownVisibilityForMember(fakeOverride, null)
|
||||
result.add(fakeOverride)
|
||||
}
|
||||
|
||||
override fun conflict(fromSuper: CallableMemberDescriptor, fromCurrent: CallableMemberDescriptor) {
|
||||
error("Conflict in scope of ${getContainingDeclaration()}: $fromSuper vs $fromCurrent")
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package kotlin.reflect.jvm.internal
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.load.java.structure.reflect.classId
|
||||
import org.jetbrains.kotlin.load.java.structure.reflect.classLoader
|
||||
@@ -29,8 +30,8 @@ import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf
|
||||
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf.JvmType.PrimitiveType.*
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Method
|
||||
import kotlin.reflect.KotlinReflectionInternalError
|
||||
import kotlin.reflect.KDeclarationContainer
|
||||
import kotlin.reflect.KotlinReflectionInternalError
|
||||
|
||||
abstract class KCallableContainerImpl : KDeclarationContainer {
|
||||
// Note: this is stored here on a soft reference to prevent GC from destroying the weak reference to it in the moduleByClassLoader cache
|
||||
@@ -44,7 +45,7 @@ abstract class KCallableContainerImpl : KDeclarationContainer {
|
||||
|
||||
fun findPropertyDescriptor(name: String, receiverDesc: String? = null): PropertyDescriptor {
|
||||
val properties = scope
|
||||
.getProperties(Name.identifier(name))
|
||||
.getProperties(Name.guess(name))
|
||||
.filter { descriptor ->
|
||||
descriptor is PropertyDescriptor &&
|
||||
descriptor.getName().asString() == name &&
|
||||
@@ -55,16 +56,34 @@ abstract class KCallableContainerImpl : KDeclarationContainer {
|
||||
}
|
||||
|
||||
if (properties.size() != 1) {
|
||||
val debugText = if (receiverDesc == null) name else "$receiverDesc.$name"
|
||||
val debugText = if (receiverDesc == null) name else "'$receiverDesc.$name'"
|
||||
throw KotlinReflectionInternalError(
|
||||
if (properties.isEmpty()) "Property '$debugText' not resolved in $this"
|
||||
else "${properties.size()} properties '$debugText' resolved in $this"
|
||||
if (properties.isEmpty()) "Property $debugText not resolved in $this"
|
||||
else "${properties.size()} properties $debugText resolved in $this: $properties"
|
||||
)
|
||||
}
|
||||
|
||||
return properties.single() as PropertyDescriptor
|
||||
}
|
||||
|
||||
fun findFunctionDescriptor(name: String, signature: String): FunctionDescriptor {
|
||||
val functions = scope
|
||||
.getFunctions(Name.guess(name))
|
||||
.filter { descriptor ->
|
||||
RuntimeTypeMapper.mapSignature(descriptor) == signature
|
||||
}
|
||||
|
||||
if (functions.size() != 1) {
|
||||
val debugText = "'$name' (JVM signature: $signature)"
|
||||
throw KotlinReflectionInternalError(
|
||||
if (functions.isEmpty()) "Function $debugText not resolved in $this"
|
||||
else "${functions.size()} functions $debugText resolved in $this: $functions"
|
||||
)
|
||||
}
|
||||
|
||||
return functions.single()
|
||||
}
|
||||
|
||||
// TODO: check resulting method's return type
|
||||
fun findMethodBySignature(signature: JvmProtoBuf.JvmMethodSignature, nameResolver: NameResolver, declared: Boolean): Method? {
|
||||
val name = nameResolver.getString(signature.getName())
|
||||
|
||||
@@ -19,6 +19,7 @@ package kotlin.reflect.jvm.internal
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.resolve.scopes.ChainedScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.JetScope
|
||||
import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies
|
||||
import kotlin.reflect.*
|
||||
@@ -39,7 +40,9 @@ class KClassImpl<T>(override val jClass: Class<T>) : KCallableContainerImpl(), K
|
||||
|
||||
private val classId: ClassId get() = RuntimeTypeMapper.mapJvmClassToKotlinClassId(jClass)
|
||||
|
||||
override val scope: JetScope get() = descriptor.getDefaultType().getMemberScope()
|
||||
override val scope: JetScope get() = ChainedScope(
|
||||
descriptor, "KClassImpl scope", descriptor.getDefaultType().getMemberScope(), descriptor.getStaticScope()
|
||||
)
|
||||
|
||||
override val simpleName: String? get() {
|
||||
if (jClass.isAnonymousClass()) return null
|
||||
|
||||
@@ -16,6 +16,41 @@
|
||||
|
||||
package kotlin.reflect.jvm.internal
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import kotlin.jvm.internal.FunctionImpl
|
||||
import kotlin.reflect.KFunction
|
||||
|
||||
abstract class KFunctionImpl<out R> : FunctionImpl()
|
||||
abstract class KFunctionImpl private constructor(
|
||||
container: KCallableContainerImpl,
|
||||
name: String,
|
||||
signature: String,
|
||||
descriptorInitialValue: FunctionDescriptor?
|
||||
) : KFunction<Any?>, FunctionImpl() {
|
||||
constructor(container: KCallableContainerImpl, name: String, signature: String): this(container, name, signature, null)
|
||||
|
||||
constructor(container: KCallableContainerImpl, descriptor: FunctionDescriptor): this(
|
||||
container, descriptor.getName().asString(), RuntimeTypeMapper.mapSignature(descriptor), descriptor
|
||||
)
|
||||
|
||||
protected val descriptor: FunctionDescriptor by ReflectProperties.lazySoft<FunctionDescriptor>(descriptorInitialValue) {
|
||||
container.findFunctionDescriptor(name, signature)
|
||||
}
|
||||
|
||||
override val name: String get() = descriptor.getName().asString()
|
||||
|
||||
override fun getArity(): Int {
|
||||
// TODO: test?
|
||||
return descriptor.getValueParameters().size() +
|
||||
(if (descriptor.getDispatchReceiverParameter() != null) 1 else 0) +
|
||||
(if (descriptor.getExtensionReceiverParameter() != null) 1 else 0)
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is KFunctionImpl && descriptor == other.descriptor
|
||||
|
||||
override fun hashCode(): Int =
|
||||
descriptor.hashCode()
|
||||
|
||||
override fun toString(): String =
|
||||
ReflectionObjectRenderer.renderFunction(descriptor)
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public class ReflectionFactoryImpl extends ReflectionFactory {
|
||||
|
||||
@Override
|
||||
public KFunction function(FunctionReference f) {
|
||||
return f;
|
||||
return new KTopLevelFreeFunctionImpl((KPackageImpl) f.getOwner(), f.getName(), f.getSignature());
|
||||
}
|
||||
|
||||
// Properties
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package kotlin.reflect.jvm.internal
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
@@ -23,29 +25,47 @@ import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
object ReflectionObjectRenderer {
|
||||
private val renderer = DescriptorRenderer.FQ_NAMES_IN_TYPES
|
||||
|
||||
private fun StringBuilder.appendReceiverType(receiver: ReceiverParameterDescriptor?) {
|
||||
if (receiver != null) {
|
||||
append(renderer.renderType(receiver.getType()))
|
||||
append(".")
|
||||
}
|
||||
}
|
||||
|
||||
private fun StringBuilder.appendReceiversAndName(callable: CallableDescriptor) {
|
||||
val dispatchReceiver = callable.getDispatchReceiverParameter()
|
||||
val extensionReceiver = callable.getExtensionReceiverParameter()
|
||||
|
||||
appendReceiverType(dispatchReceiver)
|
||||
|
||||
val addParentheses = dispatchReceiver != null && extensionReceiver != null
|
||||
if (addParentheses) append("(")
|
||||
appendReceiverType(extensionReceiver)
|
||||
if (addParentheses) append(")")
|
||||
|
||||
append(renderer.renderName(callable.getName()))
|
||||
}
|
||||
|
||||
// TODO: include visibility, return type
|
||||
fun renderProperty(descriptor: PropertyDescriptor): String {
|
||||
fun StringBuilder.appendReceiverType(receiver: ReceiverParameterDescriptor?) {
|
||||
if (receiver != null) {
|
||||
append(renderer.renderType(receiver.getType()))
|
||||
append(".")
|
||||
}
|
||||
}
|
||||
|
||||
return StringBuilder {
|
||||
append(if (descriptor.isVar()) "var " else "val ")
|
||||
appendReceiversAndName(descriptor)
|
||||
}.toString()
|
||||
}
|
||||
|
||||
val dispatchReceiver = descriptor.getDispatchReceiverParameter()
|
||||
val extensionReceiver = descriptor.getExtensionReceiverParameter()
|
||||
fun renderFunction(descriptor: FunctionDescriptor): String {
|
||||
// TODO: add tests
|
||||
return StringBuilder {
|
||||
append("fun ")
|
||||
appendReceiversAndName(descriptor)
|
||||
|
||||
appendReceiverType(dispatchReceiver)
|
||||
descriptor.getValueParameters().joinTo(this, separator = ", ", prefix = "(", postfix = ")") {
|
||||
renderer.renderType(it.getType()) // TODO: vararg
|
||||
}
|
||||
|
||||
val addParentheses = dispatchReceiver != null && extensionReceiver != null
|
||||
if (addParentheses) append("(")
|
||||
appendReceiverType(extensionReceiver)
|
||||
if (addParentheses) append(")")
|
||||
|
||||
append(renderer.renderName(descriptor.getName()))
|
||||
append(": ")
|
||||
append(renderer.renderType(descriptor.getReturnType()!!))
|
||||
}.toString()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,16 +19,24 @@ package kotlin.reflect.jvm.internal
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.load.java.structure.reflect.classId
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
|
||||
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
|
||||
import org.jetbrains.kotlin.load.java.structure.*
|
||||
import org.jetbrains.kotlin.load.java.structure.reflect.*
|
||||
import org.jetbrains.kotlin.load.kotlin.SignatureDeserializer
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf
|
||||
import org.jetbrains.kotlin.types.JetType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import kotlin.reflect.KotlinReflectionInternalError
|
||||
|
||||
object RuntimeTypeMapper {
|
||||
// TODO: this logic must be shared with JetTypeMapper
|
||||
@@ -62,6 +70,61 @@ object RuntimeTypeMapper {
|
||||
return classDescriptor.classId.desc
|
||||
}
|
||||
|
||||
fun mapSignature(function: FunctionDescriptor): String {
|
||||
if (function is DeserializedSimpleFunctionDescriptor) {
|
||||
val proto = function.getProto()
|
||||
if (!proto.hasExtension(JvmProtoBuf.methodSignature)) {
|
||||
throw KotlinReflectionInternalError("No metadata found for $function")
|
||||
}
|
||||
val signature = proto.getExtension(JvmProtoBuf.methodSignature)
|
||||
return SignatureDeserializer(function.getNameResolver()).methodSignatureString(signature)
|
||||
}
|
||||
else if (function is JavaMethodDescriptor) {
|
||||
val method = (function.getSource() as? JavaSourceElement)?.javaElement as? JavaMethod ?:
|
||||
throw KotlinReflectionInternalError("Incorrect resolution sequence for Java method $function")
|
||||
|
||||
return StringBuilder {
|
||||
append(method.getName().asString())
|
||||
|
||||
append("(")
|
||||
for (parameter in method.getValueParameters()) {
|
||||
appendJavaType(parameter.getType())
|
||||
}
|
||||
append(")")
|
||||
|
||||
appendJavaType(method.getReturnType())
|
||||
}.toString()
|
||||
}
|
||||
else throw KotlinReflectionInternalError("Unknown origin of $function (${function.javaClass})")
|
||||
}
|
||||
|
||||
// TODO: verify edge cases when it's possible to reference generic functions
|
||||
private tailRecursive fun StringBuilder.appendJavaType(type: JavaType) {
|
||||
when (type) {
|
||||
is JavaPrimitiveType -> {
|
||||
append(type.getType()?.let { JvmPrimitiveType.get(it).getDesc() } ?: "V")
|
||||
}
|
||||
is JavaArrayType -> {
|
||||
append("[")
|
||||
appendJavaType(type.getComponentType())
|
||||
}
|
||||
is JavaWildcardType -> {
|
||||
val bound = type.getBound()
|
||||
if (bound != null && type.isExtends()) appendJavaType(bound)
|
||||
else append("Ljava/lang/Object;")
|
||||
}
|
||||
is JavaClassifierType -> {
|
||||
val classifier = type.getClassifier()
|
||||
when (classifier) {
|
||||
is ReflectJavaClass ->
|
||||
append(classifier.element.desc)
|
||||
is ReflectJavaTypeParameter ->
|
||||
appendJavaType(ReflectJavaType.create(classifier.typeVariable.getBounds().first()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun mapJvmClassToKotlinClassId(klass: Class<*>): ClassId {
|
||||
if (klass.isArray()) {
|
||||
klass.getComponentType().primitiveType?.let {
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package kotlin.reflect.jvm.internal
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import kotlin.reflect.KTopLevelFunction
|
||||
|
||||
class KTopLevelFreeFunctionImpl : KFunctionImpl, KTopLevelFunction<Any?> {
|
||||
constructor(container: KPackageImpl, name: String, signature: String): super(container, name, signature)
|
||||
|
||||
constructor(container: KPackageImpl, descriptor: FunctionDescriptor): super(container, descriptor)
|
||||
}
|
||||
Reference in New Issue
Block a user