From 9cf0720925948b6b536c4c632795815a0b185381 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 18 Mar 2015 17:14:13 +0300 Subject: [PATCH] Fix KClass.simpleName for local classes --- .../classLiterals/localClassSimpleName.kt | 39 +++++++++++++++++++ ...lackBoxWithStdlibCodegenTestGenerated.java | 6 +++ .../kotlin/reflect/jvm/internal/KClassImpl.kt | 24 ++++++++++-- 3 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/codegen/boxWithStdlib/reflection/classLiterals/localClassSimpleName.kt diff --git a/compiler/testData/codegen/boxWithStdlib/reflection/classLiterals/localClassSimpleName.kt b/compiler/testData/codegen/boxWithStdlib/reflection/classLiterals/localClassSimpleName.kt new file mode 100644 index 00000000000..28fff5a582e --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/reflection/classLiterals/localClassSimpleName.kt @@ -0,0 +1,39 @@ +import kotlin.reflect.KClass +import kotlin.test.assertEquals + +fun check(klass: KClass<*>, expectedName: String) { + assertEquals(expectedName, klass.simpleName) +} + +fun localInMethod() { + fun localInMethod(unused: Any?) { + class Local + check(Local::class, "Local") + + class `Local$With$Dollars` + check(`Local$With$Dollars`::class, "Local\$With\$Dollars") + } + localInMethod(null) + + class Local + check(Local::class, "Local") + + class `Local$With$Dollars` + check(`Local$With$Dollars`::class, "Local\$With\$Dollars") +} + +class LocalInConstructor { + init { + class Local + check(Local::class, "Local") + + class `Local$With$Dollars` + check(`Local$With$Dollars`::class, "Local\$With\$Dollars") + } +} + +fun box(): String { + localInMethod() + LocalInConstructor() + 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 166b912bb8e..674cb078a2a 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -2563,6 +2563,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode doTestWithStdlib(fileName); } + @TestMetadata("localClassSimpleName.kt") + public void testLocalClassSimpleName() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/classLiterals/localClassSimpleName.kt"); + doTestWithStdlib(fileName); + } + @TestMetadata("simpleClassLiteral.kt") public void testSimpleClassLiteral() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/classLiterals/simpleClassLiteral.kt"); 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 69a5fe6ab7e..845b98b6c23 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KClassImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KClassImpl.kt @@ -18,6 +18,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.JetScope import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies import kotlin.reflect.* @@ -28,7 +29,7 @@ class KClassImpl(override val jClass: Class) : KCallableContainerImpl(), K val descriptor by ReflectProperties.lazySoft { val moduleData = jClass.getOrCreateModule() - val classId = RuntimeTypeMapper.mapJvmClassToKotlinClassId(jClass) + val classId = classId val descriptor = if (classId.isLocal()) moduleData.localClassResolver.resolveLocalClass(classId) @@ -37,11 +38,28 @@ class KClassImpl(override val jClass: Class) : KCallableContainerImpl(), K descriptor ?: throw KotlinReflectionInternalError("Class not resolved: $jClass") } + private val classId: ClassId get() = RuntimeTypeMapper.mapJvmClassToKotlinClassId(jClass) + override val scope: JetScope get() = descriptor.getDefaultType().getMemberScope() override val simpleName: String? get() { - val name = descriptor.getName() - return if (name.isSpecial()) null else name.asString() + val classId = classId + return when { + jClass.isAnonymousClass() -> null + classId.isLocal() -> calculateLocalClassName(jClass) + else -> classId.getRelativeClassName().shortName().asString() + } + } + + private fun calculateLocalClassName(jClass: Class<*>): String { + val name = jClass.getSimpleName() + jClass.getEnclosingMethod()?.let { method -> + return name.substringAfter(method.getName() + "$") + } + jClass.getEnclosingConstructor()?.let { constructor -> + return name.substringAfter(constructor.getName() + "$") + } + return name.substringAfter('$') } override val properties: Collection>