diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 3e63b397035..f4686863462 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -23480,6 +23480,30 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/jvmPackageName"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Test + @TestMetadata("anonymousObject.kt") + public void testAnonymousObject() throws Exception { + runTest("compiler/testData/codegen/box/jvmPackageName/anonymousObject.kt"); + } + + @Test + @TestMetadata("anonymousObjectInInheritedMultifilePart.kt") + public void testAnonymousObjectInInheritedMultifilePart() throws Exception { + runTest("compiler/testData/codegen/box/jvmPackageName/anonymousObjectInInheritedMultifilePart.kt"); + } + + @Test + @TestMetadata("anonymousObjectInMultifilePart.kt") + public void testAnonymousObjectInMultifilePart() throws Exception { + runTest("compiler/testData/codegen/box/jvmPackageName/anonymousObjectInMultifilePart.kt"); + } + + @Test + @TestMetadata("localClass.kt") + public void testLocalClass() throws Exception { + runTest("compiler/testData/codegen/box/jvmPackageName/localClass.kt"); + } + @Test @TestMetadata("metadataField.kt") public void testMetadataField() throws Exception { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FileClassLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FileClassLowering.kt index 9864dcfae27..13a5d8f142e 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FileClassLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FileClassLowering.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil import org.jetbrains.kotlin.fileClasses.JvmSimpleFileClassInfo import org.jetbrains.kotlin.ir.PsiIrFileEntry @@ -78,13 +79,7 @@ private class FileClassLowering(val context: JvmBackendContext) : FileLoweringPa private fun createFileClass(irFile: IrFile, fileClassMembers: List): IrClass { val fileEntry = irFile.fileEntry - val fileClassInfo = when (fileEntry) { - is PsiIrFileEntry -> - JvmFileClassUtil.getFileClassInfoNoResolve(fileEntry.psiFile as KtFile) - is NaiveSourceBasedFileEntryImpl -> - JvmSimpleFileClassInfo(PackagePartClassUtils.getPackagePartFqName(irFile.fqName, fileEntry.name), false) - else -> error("unknown kind of file entry: $fileEntry") - } + val fileClassInfo = irFile.getFileClassInfo() val isMultifilePart = fileClassInfo.withJvmMultifileClass val onlyPrivateDeclarationsAndFeatureIsEnabled = @@ -95,10 +90,14 @@ private class FileClassLowering(val context: JvmBackendContext) : FileLoweringPa isPrivate || isInlineOnly } + val fileClassOrigin = + if (!isMultifilePart || context.state.languageVersionSettings.getFlag(JvmAnalysisFlags.inheritMultifileParts)) + IrDeclarationOrigin.FILE_CLASS + else + IrDeclarationOrigin.SYNTHETIC_FILE_CLASS return IrClassImpl( 0, fileEntry.maxOffset, - if (!isMultifilePart || context.state.languageVersionSettings.getFlag(JvmAnalysisFlags.inheritMultifileParts)) - IrDeclarationOrigin.FILE_CLASS else IrDeclarationOrigin.SYNTHETIC_FILE_CLASS, + fileClassOrigin, symbol = IrClassSymbolImpl(), name = fileClassInfo.fileClassFqName.shortName(), kind = ClassKind.CLASS, @@ -148,3 +147,14 @@ private class FileClassLowering(val context: JvmBackendContext) : FileLoweringPa private val JVM_NAME = IdSignature.PublicSignature("kotlin.jvm", "JvmName", null, 0) } } + + +fun IrFile.getFileClassInfo(): JvmFileClassInfo = + when (val fileEntry = this.fileEntry) { + is PsiIrFileEntry -> + JvmFileClassUtil.getFileClassInfoNoResolve(fileEntry.psiFile as KtFile) + is NaiveSourceBasedFileEntryImpl -> + JvmSimpleFileClassInfo(PackagePartClassUtils.getPackagePartFqName(fqName, fileEntry.name), false) + else -> + error("unknown kind of file entry: $fileEntry") + } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InventNamesForLocalClasses.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InventNamesForLocalClasses.kt index 85888006531..0d6e22b97a1 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InventNamesForLocalClasses.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InventNamesForLocalClasses.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.ir.expressions.IrFunctionReference import org.jetbrains.kotlin.ir.expressions.IrPropertyReference import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.util.isAnonymousObject +import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.NameUtils @@ -54,15 +55,22 @@ class InventNamesForLocalClasses(private val context: JvmBackendContext) : FileL if (!data.isLocal) { // This is not a local class, so we need not invent a name for it, the type mapper will correctly compute it // by navigating through its containers. - - val internalName = data.enclosingName?.let { enclosingName -> + val enclosingName = data.enclosingName + val internalName = if (enclosingName != null) { "$enclosingName$${declaration.name.asString()}" - } ?: (declaration.parent as IrFile).let { file -> - JvmClassName.byFqNameWithoutInnerClasses(file.fqName.child(declaration.name)).internalName + } else { + val file = declaration.parent as? IrFile + ?: throw AssertionError("Top-level class expected: ${declaration.render()}") + val classFqn = + if (declaration.origin == IrDeclarationOrigin.FILE_CLASS || + declaration.origin == IrDeclarationOrigin.SYNTHETIC_FILE_CLASS + ) + file.getFileClassInfo().fileClassFqName + else + file.fqName.child(declaration.name) + JvmClassName.byFqNameWithoutInnerClasses(classFqn).internalName } - declaration.acceptChildren(this, data.withName(internalName)) - return } diff --git a/compiler/testData/codegen/box/jvmPackageName/anonymousObject.kt b/compiler/testData/codegen/box/jvmPackageName/anonymousObject.kt new file mode 100644 index 00000000000..db17cbe667b --- /dev/null +++ b/compiler/testData/codegen/box/jvmPackageName/anonymousObject.kt @@ -0,0 +1,33 @@ +// TARGET_BACKEND: JVM +// WITH_RUNTIME +// IGNORE_FIR_DIAGNOSTICS + +// Duplicate JVM class name 'xx/ZKt' +// IGNORE_BACKEND: ANDROID + +// FILE: anonymousObject.kt +import x.* + +fun box(): String = + "O".z().toString() + + "K".iz().toString() + +// FILE: z.kt +@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") +@file:kotlin.jvm.JvmPackageName("xx") +package x + +fun String.z(): Any { + return object { + override fun toString(): String = + this@z + } +} + +inline fun String.iz(): Any { + return object { + override fun toString(): String = + this@iz + } +} + diff --git a/compiler/testData/codegen/box/jvmPackageName/anonymousObjectInInheritedMultifilePart.kt b/compiler/testData/codegen/box/jvmPackageName/anonymousObjectInInheritedMultifilePart.kt new file mode 100644 index 00000000000..c142ce779b6 --- /dev/null +++ b/compiler/testData/codegen/box/jvmPackageName/anonymousObjectInInheritedMultifilePart.kt @@ -0,0 +1,44 @@ +// TARGET_BACKEND: JVM +// WITH_RUNTIME +// IGNORE_FIR_DIAGNOSTICS +// IGNORE_LIGHT_ANALYSIS + +// Duplicate JVM class name 'xx/ZKt' +// IGNORE_BACKEND: ANDROID + +// !INHERIT_MULTIFILE_PARTS + +// FILE: anonymousObject.kt +import x.* + +fun box(): String = + "O".z().toString() + + "K".iz().toString() + +// FILE: z.kt +@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") +@file:kotlin.jvm.JvmMultifileClass +@file:kotlin.jvm.JvmName("ZKt") +@file:kotlin.jvm.JvmPackageName("xx") +package x + +fun String.z(): Any { + return object { + override fun toString(): String = + this@z + } +} + +// FILE: z2.kt +@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") +@file:kotlin.jvm.JvmMultifileClass +@file:kotlin.jvm.JvmName("ZKt") +@file:kotlin.jvm.JvmPackageName("xx") +package x + +inline fun String.iz(): Any { + return object { + override fun toString(): String = + this@iz + } +} diff --git a/compiler/testData/codegen/box/jvmPackageName/anonymousObjectInMultifilePart.kt b/compiler/testData/codegen/box/jvmPackageName/anonymousObjectInMultifilePart.kt new file mode 100644 index 00000000000..57cf029975b --- /dev/null +++ b/compiler/testData/codegen/box/jvmPackageName/anonymousObjectInMultifilePart.kt @@ -0,0 +1,41 @@ +// TARGET_BACKEND: JVM +// WITH_RUNTIME +// IGNORE_FIR_DIAGNOSTICS + +// Duplicate JVM class name 'xx/ZKt' +// IGNORE_BACKEND: ANDROID + +// FILE: anonymousObject.kt +import x.* + +fun box(): String = + "O".z().toString() + + "K".iz().toString() + +// FILE: z.kt +@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") +@file:kotlin.jvm.JvmMultifileClass +@file:kotlin.jvm.JvmName("ZKt") +@file:kotlin.jvm.JvmPackageName("xx") +package x + +fun String.z(): Any { + return object { + override fun toString(): String = + this@z + } +} + +// FILE: z2.kt +@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") +@file:kotlin.jvm.JvmMultifileClass +@file:kotlin.jvm.JvmName("ZKt") +@file:kotlin.jvm.JvmPackageName("xx") +package x + +inline fun String.iz(): Any { + return object { + override fun toString(): String = + this@iz + } +} diff --git a/compiler/testData/codegen/box/jvmPackageName/localClass.kt b/compiler/testData/codegen/box/jvmPackageName/localClass.kt new file mode 100644 index 00000000000..13fde7e7ba4 --- /dev/null +++ b/compiler/testData/codegen/box/jvmPackageName/localClass.kt @@ -0,0 +1,26 @@ +// TARGET_BACKEND: JVM +// WITH_RUNTIME +// IGNORE_FIR_DIAGNOSTICS + +// Duplicate JVM class name 'xx/ZKt' +// IGNORE_BACKEND: ANDROID + +// FILE: anonymousObject.kt +import x.* + +fun box(): String = + "OK".z().toString() + +// FILE: z.kt +@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") +@file:kotlin.jvm.JvmPackageName("xx") +package x + +fun String.z(): Any { + class Local { + override fun toString(): String = + this@z + } + + return Local() +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index 5ab09f1239f..e8e52b25d58 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -23462,6 +23462,30 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/jvmPackageName"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); } + @Test + @TestMetadata("anonymousObject.kt") + public void testAnonymousObject() throws Exception { + runTest("compiler/testData/codegen/box/jvmPackageName/anonymousObject.kt"); + } + + @Test + @TestMetadata("anonymousObjectInInheritedMultifilePart.kt") + public void testAnonymousObjectInInheritedMultifilePart() throws Exception { + runTest("compiler/testData/codegen/box/jvmPackageName/anonymousObjectInInheritedMultifilePart.kt"); + } + + @Test + @TestMetadata("anonymousObjectInMultifilePart.kt") + public void testAnonymousObjectInMultifilePart() throws Exception { + runTest("compiler/testData/codegen/box/jvmPackageName/anonymousObjectInMultifilePart.kt"); + } + + @Test + @TestMetadata("localClass.kt") + public void testLocalClass() throws Exception { + runTest("compiler/testData/codegen/box/jvmPackageName/localClass.kt"); + } + @Test @TestMetadata("metadataField.kt") public void testMetadataField() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 26fbf57f29b..28a50a9b8ed 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -23480,6 +23480,30 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/jvmPackageName"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Test + @TestMetadata("anonymousObject.kt") + public void testAnonymousObject() throws Exception { + runTest("compiler/testData/codegen/box/jvmPackageName/anonymousObject.kt"); + } + + @Test + @TestMetadata("anonymousObjectInInheritedMultifilePart.kt") + public void testAnonymousObjectInInheritedMultifilePart() throws Exception { + runTest("compiler/testData/codegen/box/jvmPackageName/anonymousObjectInInheritedMultifilePart.kt"); + } + + @Test + @TestMetadata("anonymousObjectInMultifilePart.kt") + public void testAnonymousObjectInMultifilePart() throws Exception { + runTest("compiler/testData/codegen/box/jvmPackageName/anonymousObjectInMultifilePart.kt"); + } + + @Test + @TestMetadata("localClass.kt") + public void testLocalClass() throws Exception { + runTest("compiler/testData/codegen/box/jvmPackageName/localClass.kt"); + } + @Test @TestMetadata("metadataField.kt") public void testMetadataField() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 66c7c4e8f89..7e68bf1a52d 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -19771,6 +19771,26 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/jvmPackageName"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); } + @TestMetadata("anonymousObject.kt") + public void testAnonymousObject() throws Exception { + runTest("compiler/testData/codegen/box/jvmPackageName/anonymousObject.kt"); + } + + @TestMetadata("anonymousObjectInInheritedMultifilePart.kt") + public void testAnonymousObjectInInheritedMultifilePart() throws Exception { + runTest("compiler/testData/codegen/box/jvmPackageName/anonymousObjectInInheritedMultifilePart.kt"); + } + + @TestMetadata("anonymousObjectInMultifilePart.kt") + public void testAnonymousObjectInMultifilePart() throws Exception { + runTest("compiler/testData/codegen/box/jvmPackageName/anonymousObjectInMultifilePart.kt"); + } + + @TestMetadata("localClass.kt") + public void testLocalClass() throws Exception { + runTest("compiler/testData/codegen/box/jvmPackageName/localClass.kt"); + } + @TestMetadata("metadataField.kt") public void testMetadataField() throws Exception { runTest("compiler/testData/codegen/box/jvmPackageName/metadataField.kt");