diff --git a/compiler/testData/codegen/boxWithStdlib/reflection/constructors/constructorName.kt b/compiler/testData/codegen/boxWithStdlib/reflection/constructors/constructorName.kt new file mode 100644 index 00000000000..155efebed30 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/reflection/constructors/constructorName.kt @@ -0,0 +1,8 @@ +import kotlin.test.assertEquals + +class A + +fun box(): String { + assertEquals("", ::A.name) + return "OK" +} diff --git a/compiler/testData/codegen/boxWithStdlib/reflection/functions/localFunctionName.kt b/compiler/testData/codegen/boxWithStdlib/reflection/functions/localFunctionName.kt new file mode 100644 index 00000000000..361ba4c3ce3 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/reflection/functions/localFunctionName.kt @@ -0,0 +1,5 @@ +fun box(): String { + fun OK() {} + + return ::OK.name +} diff --git a/compiler/testData/codegen/boxWithStdlib/reflection/functions/platformName.kt b/compiler/testData/codegen/boxWithStdlib/reflection/functions/platformName.kt new file mode 100644 index 00000000000..26692f89c18 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/reflection/functions/platformName.kt @@ -0,0 +1,6 @@ +import kotlin.platform.platformName + +@platformName("Fail") +fun OK() {} + +fun box() = ::OK.name diff --git a/compiler/testData/codegen/boxWithStdlib/reflection/functions/simpleNames.kt b/compiler/testData/codegen/boxWithStdlib/reflection/functions/simpleNames.kt new file mode 100644 index 00000000000..417d2391154 --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/reflection/functions/simpleNames.kt @@ -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" +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index 09519dcd9ba..a02c2e6c25e 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -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) diff --git a/core/builtins/src/kotlin/reflect/KFunction.kt b/core/builtins/src/kotlin/reflect/KFunction.kt index 127496163cc..a6c21632060 100644 --- a/core/builtins/src/kotlin/reflect/KFunction.kt +++ b/core/builtins/src/kotlin/reflect/KFunction.kt @@ -19,4 +19,4 @@ package kotlin.reflect /** * Represents a function with introspection capabilities. */ -public interface KFunction : Function +public interface KFunction : KCallable, Function diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaClass.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaClass.kt index 77677a82328..5c916d36c06 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaClass.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaClass.kt @@ -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() diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaTypeParameter.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaTypeParameter.kt index dee11701869..28b7ccf8587 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaTypeParameter.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaTypeParameter.kt @@ -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 { val bounds = typeVariable.getBounds().map { bound -> ReflectJavaClassifierType(bound) } diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/functions/FunctionClassScope.kt b/core/descriptors/src/org/jetbrains/kotlin/builtins/functions/FunctionClassScope.kt index 1efe3d2b79e..97468a9311d 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/functions/FunctionClassScope.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/functions/FunctionClassScope.kt @@ -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 { - 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 { - return allFunctions().filter { it.getName() == name } + return allDescriptors().filterIsInstance().filter { it.getName() == name } } - private fun createFakeOverrides(invoke: FunctionDescriptor?): List { - val result = ArrayList(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, - /* 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 { + return allDescriptors().filterIsInstance().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 { + val result = ArrayList(3) + val allSuperDescriptors = functionClass.getTypeConstructor().getSupertypes() + .flatMap { it.getMemberScope().getAllDescriptors() } + .filterIsInstance() + 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 diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableContainerImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableContainerImpl.kt index b9a91a3f4c7..bedc410dd47 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableContainerImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableContainerImpl.kt @@ -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()) diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KClassImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KClassImpl.kt index d2a12db9b16..5c534a70b9c 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KClassImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KClassImpl.kt @@ -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(override val jClass: Class) : 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 diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt index 42534413c73..7304bbb3239 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt @@ -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 : FunctionImpl() +abstract class KFunctionImpl private constructor( + container: KCallableContainerImpl, + name: String, + signature: String, + descriptorInitialValue: FunctionDescriptor? +) : KFunction, 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(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) +} diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionFactoryImpl.java b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionFactoryImpl.java index 59fbdc4b56b..6aab0752308 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionFactoryImpl.java +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionFactoryImpl.java @@ -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 diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionObjectRenderer.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionObjectRenderer.kt index f4eda03bdba..ad55d9aa085 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionObjectRenderer.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/ReflectionObjectRenderer.kt @@ -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() } } diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/RuntimeTypeMapper.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/RuntimeTypeMapper.kt index 5070f927b96..529f085bf47 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/RuntimeTypeMapper.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/RuntimeTypeMapper.kt @@ -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 { diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/kFunctionImplementations.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/kFunctionImplementations.kt new file mode 100644 index 00000000000..bafd1a4f11f --- /dev/null +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/kFunctionImplementations.kt @@ -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 { + constructor(container: KPackageImpl, name: String, signature: String): super(container, name, signature) + + constructor(container: KPackageImpl, descriptor: FunctionDescriptor): super(container, descriptor) +}