From 4be0e00071a12f1d22a0c4de924013e6e39f7683 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Fri, 19 Jul 2019 17:33:47 +0200 Subject: [PATCH] JVM IR: support multi-file classes Without the `-Xmultifile-parts-inherit` mode for now. This is implemented as follows: FileClassLowering collects information about multifile parts and the corresponding facades, which a later GenerateMultifileFacades phase uses to generate new IrFile instances and add it to the module fragment that's being compiled. Note that GenerateMultifileFacades is in the end of lowering phases because delegates in the facade should be generated for all additional functions generated by certain lowerings (default arguments, JvmOverloads, etc.). If GenerateMultifileFacades was right after FileClassLowering, they would still be generated, but we'd then process them in lowerings mentioned above, which would result in duplicated logic in the bytecode. There's a new bytecode text test which checks that this doesn't happen for functions with default arguments. --- .../kotlin/backend/jvm/DeclarationOrigins.kt | 1 + .../kotlin/backend/jvm/JvmBackendContext.kt | 3 + .../jetbrains/kotlin/backend/jvm/JvmLower.kt | 3 +- .../backend/jvm/codegen/ClassCodegen.kt | 22 ++- .../backend/jvm/codegen/ExpressionCodegen.kt | 20 ++- .../backend/jvm/codegen/irCodegenUtils.kt | 1 + .../backend/jvm/lower/FileClassLowering.kt | 6 + .../jvm/lower/GenerateMultifileFacades.kt | 135 ++++++++++++++++++ .../kotlin/psi2ir/PsiSourceManager.kt | 4 +- .../codegen/box/jvmName/multifileClass.kt | 2 - .../jvmName/multifileClassWithLocalClass.kt | 2 - .../box/jvmOverloads/multifileClass.kt | 16 +++ ...allMultifileClassMemberFromOtherPackage.kt | 2 - .../callsToMultifileClassFromOtherPackage.kt | 1 - ...ineMultifileClassMemberFromOtherPackage.kt | 1 - .../multifileClassPartsInitialization.kt | 1 - .../multifileClassWith2Files.kt | 1 - .../multifileClassWithCrossCall.kt | 1 - .../multifileClassWithPrivate.kt | 1 - .../optimized/callableRefToFun.kt | 1 - .../box/multifileClasses/optimized/calls.kt | 1 - .../optimized/overlappingFuns.kt | 1 - .../box/multifileClasses/privateConstVal.kt | 1 - .../samePartNameDifferentFacades.kt | 1 - .../multifileClasses/sealedClassHierarchy.kt | 1 - .../expectClassInJvmMultifileFacade.kt | 1 - .../callFunctionsInMultifileClass.kt | 2 - .../localDelegated/multiFileClass.kt | 2 - .../noPrivateNoAccessorsInMultiFileFacade.kt | 2 - .../noPrivateNoAccessorsInMultiFileFacade2.kt | 2 - .../syntheticAccessorInMultiFile.kt | 2 - .../privateInInlineInMultiFileFacade.kt | 1 - .../defaultFunctionInMultifileClass.kt | 19 +++ ...ileClassInlineFunctionAccessingProperty.kt | 1 - .../codegen/BlackBoxCodegenTestGenerated.java | 5 + .../codegen/BytecodeTextTestGenerated.java | 5 + .../LightAnalysisModeTestGenerated.java | 5 + .../ir/IrBlackBoxCodegenTestGenerated.java | 5 + .../ir/IrBytecodeTextTestGenerated.java | 5 + .../other/packageFacadeToClass/directives.txt | 1 - 40 files changed, 239 insertions(+), 48 deletions(-) create mode 100644 compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/GenerateMultifileFacades.kt create mode 100644 compiler/testData/codegen/box/jvmOverloads/multifileClass.kt create mode 100644 compiler/testData/codegen/bytecodeText/multifileClasses/defaultFunctionInMultifileClass.kt delete mode 100644 jps-plugin/testData/incremental/withJava/other/packageFacadeToClass/directives.txt diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/DeclarationOrigins.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/DeclarationOrigins.kt index 94b2588f8c9..4999eb23eab 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/DeclarationOrigins.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/DeclarationOrigins.kt @@ -26,6 +26,7 @@ interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin { object DEFAULT_IMPLS : IrDeclarationOriginImpl("DEFAULT_IMPLS") object DEFAULT_IMPLS_BRIDGE : IrDeclarationOriginImpl("DEFAULT_IMPLS_BRIDGE") object DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC : IrDeclarationOriginImpl("DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC", isSynthetic = true) + object MULTIFILE_BRIDGE : IrDeclarationOriginImpl("MULTIFILE_BRIDGE") object FIELD_FOR_OUTER_THIS : IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS") object LAMBDA_IMPL : IrDeclarationOriginImpl("LAMBDA_IMPL") object FUNCTION_REFERENCE_IMPL : IrDeclarationOriginImpl("FUNCTION_REFERENCE_IMPL", isSynthetic = true) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt index 5bc78df535c..57b7e1d3938 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi2ir.PsiSourceManager +import org.jetbrains.kotlin.resolve.jvm.JvmClassName class JvmBackendContext( val state: GenerationState, @@ -63,6 +64,8 @@ class JvmBackendContext( internal val localDelegatedProperties = mutableMapOf>() + internal val multifileFacadesToAdd = mutableMapOf>() + override var inVerbosePhase: Boolean = false override val configuration get() = state.configuration diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt index 7a198bcb961..25855992d8a 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt @@ -184,7 +184,8 @@ val jvmPhases = namedIrModulePhase( description = "IR lowering", lower = expectDeclarationsRemovingPhase then fileClassPhase then - performByIrFile(lower = jvmFilePhases) + performByIrFile(lower = jvmFilePhases) then + generateMultifileFacadesPhase ) class JvmLower(val context: JvmBackendContext) { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt index 0dbbc101c16..beeebf479a9 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ClassCodegen.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.backend.jvm.codegen import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry import org.jetbrains.kotlin.backend.jvm.lower.constantValue import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.binding.CodegenBinding @@ -50,14 +51,12 @@ open class ClassCodegen protected constructor( val type: Type = typeMapper.mapClass(irClass) - private val fileEntry = context.psiSourceManager.getFileEntry(irClass.fileParent) - val visitor: ClassBuilder = createClassBuilder() open fun createClassBuilder() = state.factory.newVisitor( OtherOrigin(descriptor.psiElement, descriptor), type, - listOf(File(fileEntry.name)) + irClass.fileParent.loadSourceFilesInfo() ) private var sourceMapper: DefaultSourceMapper? = null @@ -97,9 +96,12 @@ open class ClassCodegen protected constructor( continuationCodegen.generate() } - /* TODO: Temporary workaround: ClassBuilder needs a pathless name. */ - val shortName = File(fileEntry.name).name - visitor.visitSource(shortName, null) + val fileEntry = context.psiSourceManager.getFileEntry(irClass.fileParent) + if (fileEntry != null) { + /* TODO: Temporary workaround: ClassBuilder needs a pathless name. */ + val shortName = File(fileEntry.name).name + visitor.visitSource(shortName, null) + } for (declaration in irClass.declarations) { generateDeclaration(declaration) @@ -164,6 +166,14 @@ open class ClassCodegen protected constructor( visitor.done() } + private fun IrFile.loadSourceFilesInfo(): List { + val entry = fileEntry + if (entry is MultifileFacadeFileEntry) { + return entry.partFiles.flatMap { it.loadSourceFilesInfo() } + } + return listOf(File(context.psiSourceManager.getFileEntry(this)!!.name)) + } + companion object { fun generate(irClass: IrClass, context: JvmBackendContext) { val state = context.state diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index 0c7987ee878..4841357c30f 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods import org.jetbrains.kotlin.backend.jvm.intrinsics.JavaClassProperty import org.jetbrains.kotlin.backend.jvm.intrinsics.Not +import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry import org.jetbrains.kotlin.backend.jvm.lower.constantValue import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass import org.jetbrains.kotlin.codegen.* @@ -140,11 +141,13 @@ class ExpressionCodegen( if (offset < 0) { return } - val lineNumber = fileEntry.getLineNumber(offset) + 1 - assert(lineNumber > 0) - if (lastLineNumber != lineNumber) { - lastLineNumber = lineNumber - mv.visitLineNumber(lineNumber, markNewLabel()) + if (fileEntry != null) { + val lineNumber = fileEntry.getLineNumber(offset) + 1 + assert(lineNumber > 0) + if (lastLineNumber != lineNumber) { + lastLineNumber = lineNumber + mv.visitLineNumber(lineNumber, markNewLabel()) + } } } @@ -188,7 +191,8 @@ class ExpressionCodegen( // Although these are accessible from Java, the functions they bridge to already have the assertions. irFunction.origin == IrDeclarationOrigin.BRIDGE_SPECIAL || irFunction.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE || - irFunction.origin == JvmLoweredDeclarationOrigin.JVM_STATIC_WRAPPER + irFunction.origin == JvmLoweredDeclarationOrigin.JVM_STATIC_WRAPPER || + irFunction.origin == JvmLoweredDeclarationOrigin.MULTIFILE_BRIDGE if (!isInlineLambda && !isSyntheticOrBridge && !Visibilities.isPrivate(irFunction.visibility)) { irFunction.extensionReceiverParameter?.let { generateNonNullAssertion(it) } irFunction.valueParameters.forEach(::generateNonNullAssertion) @@ -1086,7 +1090,9 @@ class ExpressionCodegen( typeMapper.mapToCallableMethod(irCall.symbol.owner, isSuper) private fun getOrCreateCallGenerator(element: IrFunctionAccessExpression, data: BlockInfo): IrCallGenerator { - if (!element.symbol.owner.isInlineFunctionCall(context)) { + if (!element.symbol.owner.isInlineFunctionCall(context) || + classCodegen.irClass.fileParent.fileEntry is MultifileFacadeFileEntry + ) { return IrCallGenerator.DefaultCallGenerator } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt index e2e26bab95f..8644d61ba4a 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/irCodegenUtils.kt @@ -85,6 +85,7 @@ internal val DeclarationDescriptorWithSource.psiElement: PsiElement? fun JvmBackendContext.getSourceMapper(declaration: IrClass): DefaultSourceMapper { val sourceManager = this.psiSourceManager val fileEntry = sourceManager.getFileEntry(declaration.fileParent) + check(fileEntry != null) { "No PSI file entry found for class: ${declaration.dump()}" } // NOTE: apparently inliner requires the source range to cover the // whole file the class is declared in rather than the class only. // TODO: revise 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 74170c1e37f..dfa71c6800a 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 @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl import org.jetbrains.kotlin.psi2ir.PsiSourceManager +import org.jetbrains.kotlin.resolve.jvm.JvmClassName import org.jetbrains.kotlin.resolve.source.KotlinSourceElement import java.util.* @@ -107,6 +108,11 @@ private class FileClassLowering(val context: JvmBackendContext) : FileLoweringPa if (fileClassInfo.withJvmMultifileClass) AsmUtil.asmTypeByFqNameWithoutInnerClasses(fileClassInfo.facadeClassFqName) else null context.state.factory.packagePartRegistry.addPart(irFile.fqName, partClassType.internalName, facadeClassType?.internalName) + + if (facadeClassType != null) { + val jvmClassName = JvmClassName.byInternalName(facadeClassType.internalName) + context.multifileFacadesToAdd.getOrPut(jvmClassName) { ArrayList() }.add(this) + } } // TODO file annotations } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/GenerateMultifileFacades.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/GenerateMultifileFacades.kt new file mode 100644 index 00000000000..605c94c72d1 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/GenerateMultifileFacades.kt @@ -0,0 +1,135 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.jvm.lower + +import org.jetbrains.kotlin.backend.common.deepCopyWithWrappedDescriptors +import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor +import org.jetbrains.kotlin.backend.common.lower.InitializersLowering +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig +import org.jetbrains.kotlin.backend.common.phaser.PhaserState +import org.jetbrains.kotlin.backend.common.phaser.SameTypeCompilerPhase +import org.jetbrains.kotlin.backend.common.phaser.namedIrModulePhase +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin +import org.jetbrains.kotlin.backend.jvm.codegen.fileParent +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor +import org.jetbrains.kotlin.ir.SourceManager +import org.jetbrains.kotlin.ir.SourceRangeInfo +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.builders.declarations.buildClass +import org.jetbrains.kotlin.ir.builders.irBlockBody +import org.jetbrains.kotlin.ir.builders.irCall +import org.jetbrains.kotlin.ir.builders.irGet +import org.jetbrains.kotlin.ir.builders.irReturn +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl +import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols +import org.jetbrains.kotlin.ir.util.dump +import org.jetbrains.kotlin.resolve.jvm.JvmClassName + +internal val generateMultifileFacadesPhase = namedIrModulePhase( + name = "GenerateMultifileFacades", + description = "Generate JvmMultifileClass facades, based on the information provided by FileClassLowering", + prerequisite = setOf(fileClassPhase), + lower = object : SameTypeCompilerPhase { + override fun invoke( + phaseConfig: PhaseConfig, + phaserState: PhaserState, + context: JvmBackendContext, + input: IrModuleFragment + ): IrModuleFragment { + input.files.addAll(generateMultifileFacades(input.descriptor, context)) + context.multifileFacadesToAdd.clear() + return input + } + } +) + +internal class MultifileFacadeFileEntry( + private val className: JvmClassName, + val partFiles: List +) : SourceManager.FileEntry { + override val name: String + get() = "" + + override val maxOffset: Int + get() = UNDEFINED_OFFSET + + override fun getSourceRangeInfo(beginOffset: Int, endOffset: Int): SourceRangeInfo = + error("Multifile facade doesn't support debug info: $className") + + override fun getLineNumber(offset: Int): Int = + error("Multifile facade doesn't support debug info: $className") + + override fun getColumnNumber(offset: Int): Int = + error("Multifile facade doesn't support debug info: $className") +} + +private fun generateMultifileFacades(module: ModuleDescriptor, context: JvmBackendContext): List = + context.multifileFacadesToAdd.map { (jvmClassName, partClasses) -> + val fileEntry = MultifileFacadeFileEntry(jvmClassName, partClasses.map(IrClass::fileParent)) + val file = IrFileImpl(fileEntry, EmptyPackageFragmentDescriptor(module, jvmClassName.packageFqName)) + + val facadeClass = buildClass { + name = jvmClassName.fqNameForTopLevelClassMaybeWithDollars.shortName() + }.apply { + parent = file + createImplicitParameterDeclarationWithWrappedDescriptor() + } + file.declarations.add(facadeClass) + + for (partClass in partClasses) { + for (member in partClass.declarations) { + member.createMultifileDelegateIfNeeded(context, facadeClass) + } + } + + file + } + +private fun IrDeclaration.createMultifileDelegateIfNeeded(context: JvmBackendContext, facadeClass: IrClass) { + if (this !is IrFunction || + Visibilities.isPrivate(visibility) || + name == InitializersLowering.clinitName || + origin == JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR + ) return + + // TODO: perform copy of the signature only, without body + val function = deepCopyWithSymbols(facadeClass) + function.body = context.createIrBuilder(symbol).irBlockBody { + val functionForCall = computeFunctionForCall() + +irReturn(irCall(functionForCall).also { call -> + function.extensionReceiverParameter?.let { parameter -> + call.extensionReceiver = irGet(parameter) + } + for (parameter in function.valueParameters) { + call.putValueArgument(parameter.index, irGet(parameter)) + } + }) + } + function.origin = JvmLoweredDeclarationOrigin.MULTIFILE_BRIDGE + + facadeClass.declarations.add(function) +} + +// This deep copy is needed while we still use KotlinTypeMapper to map signatures in method calls. Without it, KotlinTypeMapper takes +// the descriptor and assumes that a call to that function must go through the public facade (see mapOwner call in mapToCallableMethod), +// which results in endless recursion here. With this copy, we trick it into thinking that the function is actually a static function +// in a class whose name is the name of the multi-file part, as opposed to being top level. +private fun IrFunction.computeFunctionForCall(): IrFunction { + val property = (this as? IrSimpleFunction)?.correspondingPropertySymbol?.owner + ?: return deepCopyWithWrappedDescriptors(parent) + + val propertyCopy = property.deepCopyWithWrappedDescriptors(property.parent) + return when (this) { + property.getter -> propertyCopy.getter!! + property.setter -> propertyCopy.setter!! + else -> error("Property accessor must be getter or setter: ${dump()}") + } +} diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/PsiSourceManager.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/PsiSourceManager.kt index a8248376fa2..16128d05ac5 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/PsiSourceManager.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/PsiSourceManager.kt @@ -95,6 +95,6 @@ class PsiSourceManager : SourceManager { fun getKtFile(irFile: IrFile): KtFile? = (irFile.fileEntry as? PsiFileEntry)?.let { ktFileByFileEntry[it] } - override fun getFileEntry(irFile: IrFile): SourceManager.FileEntry = - fileEntriesByIrFile[irFile]!! + override fun getFileEntry(irFile: IrFile): SourceManager.FileEntry? = + fileEntriesByIrFile[irFile] } diff --git a/compiler/testData/codegen/box/jvmName/multifileClass.kt b/compiler/testData/codegen/box/jvmName/multifileClass.kt index 49f6cf42c80..4c5164ba4b2 100644 --- a/compiler/testData/codegen/box/jvmName/multifileClass.kt +++ b/compiler/testData/codegen/box/jvmName/multifileClass.kt @@ -1,6 +1,4 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM - // WITH_RUNTIME @file:JvmName("Test") diff --git a/compiler/testData/codegen/box/jvmName/multifileClassWithLocalClass.kt b/compiler/testData/codegen/box/jvmName/multifileClassWithLocalClass.kt index 746b8b28962..64928a95637 100644 --- a/compiler/testData/codegen/box/jvmName/multifileClassWithLocalClass.kt +++ b/compiler/testData/codegen/box/jvmName/multifileClassWithLocalClass.kt @@ -1,6 +1,4 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM - // WITH_RUNTIME @file:JvmName("Test") diff --git a/compiler/testData/codegen/box/jvmOverloads/multifileClass.kt b/compiler/testData/codegen/box/jvmOverloads/multifileClass.kt new file mode 100644 index 00000000000..54125ce7b75 --- /dev/null +++ b/compiler/testData/codegen/box/jvmOverloads/multifileClass.kt @@ -0,0 +1,16 @@ +// TARGET_BACKEND: JVM +// WITH_RUNTIME +// FILE: facade.kt + +@file:JvmName("Facade") +@file:JvmMultifileClass + +package test + +@JvmOverloads +fun foo(o: String = "O", k: String = "K"): String = o + k + +// FILE: test.kt + +fun box(): String = + Class.forName("test.Facade").getMethod("foo").invoke(null) as String diff --git a/compiler/testData/codegen/box/multifileClasses/callMultifileClassMemberFromOtherPackage.kt b/compiler/testData/codegen/box/multifileClasses/callMultifileClassMemberFromOtherPackage.kt index b598d3a3cbe..82b3cd049b4 100644 --- a/compiler/testData/codegen/box/multifileClasses/callMultifileClassMemberFromOtherPackage.kt +++ b/compiler/testData/codegen/box/multifileClasses/callMultifileClassMemberFromOtherPackage.kt @@ -1,6 +1,4 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM - // WITH_RUNTIME // FILE: box.kt diff --git a/compiler/testData/codegen/box/multifileClasses/callsToMultifileClassFromOtherPackage.kt b/compiler/testData/codegen/box/multifileClasses/callsToMultifileClassFromOtherPackage.kt index b14d0892d51..0dec11f9a46 100644 --- a/compiler/testData/codegen/box/multifileClasses/callsToMultifileClassFromOtherPackage.kt +++ b/compiler/testData/codegen/box/multifileClasses/callsToMultifileClassFromOtherPackage.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // WITH_RUNTIME // FILE: 1.kt diff --git a/compiler/testData/codegen/box/multifileClasses/inlineMultifileClassMemberFromOtherPackage.kt b/compiler/testData/codegen/box/multifileClasses/inlineMultifileClassMemberFromOtherPackage.kt index f497a250f69..8631b9ac874 100644 --- a/compiler/testData/codegen/box/multifileClasses/inlineMultifileClassMemberFromOtherPackage.kt +++ b/compiler/testData/codegen/box/multifileClasses/inlineMultifileClassMemberFromOtherPackage.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // WITH_RUNTIME // FILE: box.kt diff --git a/compiler/testData/codegen/box/multifileClasses/multifileClassPartsInitialization.kt b/compiler/testData/codegen/box/multifileClasses/multifileClassPartsInitialization.kt index df04e954a8c..e13c83cb457 100644 --- a/compiler/testData/codegen/box/multifileClasses/multifileClassPartsInitialization.kt +++ b/compiler/testData/codegen/box/multifileClasses/multifileClassPartsInitialization.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // WITH_RUNTIME // FILE: box.kt diff --git a/compiler/testData/codegen/box/multifileClasses/multifileClassWith2Files.kt b/compiler/testData/codegen/box/multifileClasses/multifileClassWith2Files.kt index be65f05276b..5d69607f932 100644 --- a/compiler/testData/codegen/box/multifileClasses/multifileClassWith2Files.kt +++ b/compiler/testData/codegen/box/multifileClasses/multifileClassWith2Files.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // WITH_RUNTIME // FILE: Baz.java diff --git a/compiler/testData/codegen/box/multifileClasses/multifileClassWithCrossCall.kt b/compiler/testData/codegen/box/multifileClasses/multifileClassWithCrossCall.kt index 1252a69101c..6c33e3a4c96 100644 --- a/compiler/testData/codegen/box/multifileClasses/multifileClassWithCrossCall.kt +++ b/compiler/testData/codegen/box/multifileClasses/multifileClassWithCrossCall.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // WITH_RUNTIME // FILE: Baz.java diff --git a/compiler/testData/codegen/box/multifileClasses/multifileClassWithPrivate.kt b/compiler/testData/codegen/box/multifileClasses/multifileClassWithPrivate.kt index 575d5f5ab45..76826d27c68 100644 --- a/compiler/testData/codegen/box/multifileClasses/multifileClassWithPrivate.kt +++ b/compiler/testData/codegen/box/multifileClasses/multifileClassWithPrivate.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // WITH_RUNTIME // FILE: Baz.java diff --git a/compiler/testData/codegen/box/multifileClasses/optimized/callableRefToFun.kt b/compiler/testData/codegen/box/multifileClasses/optimized/callableRefToFun.kt index b79cfd2061d..26471b5a732 100644 --- a/compiler/testData/codegen/box/multifileClasses/optimized/callableRefToFun.kt +++ b/compiler/testData/codegen/box/multifileClasses/optimized/callableRefToFun.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // IGNORE_LIGHT_ANALYSIS // WITH_RUNTIME diff --git a/compiler/testData/codegen/box/multifileClasses/optimized/calls.kt b/compiler/testData/codegen/box/multifileClasses/optimized/calls.kt index 97cbe8b3144..5bb73767b12 100644 --- a/compiler/testData/codegen/box/multifileClasses/optimized/calls.kt +++ b/compiler/testData/codegen/box/multifileClasses/optimized/calls.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // IGNORE_LIGHT_ANALYSIS // WITH_RUNTIME diff --git a/compiler/testData/codegen/box/multifileClasses/optimized/overlappingFuns.kt b/compiler/testData/codegen/box/multifileClasses/optimized/overlappingFuns.kt index c4d10a6bc95..145e6125970 100644 --- a/compiler/testData/codegen/box/multifileClasses/optimized/overlappingFuns.kt +++ b/compiler/testData/codegen/box/multifileClasses/optimized/overlappingFuns.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // IGNORE_LIGHT_ANALYSIS // WITH_RUNTIME diff --git a/compiler/testData/codegen/box/multifileClasses/privateConstVal.kt b/compiler/testData/codegen/box/multifileClasses/privateConstVal.kt index 9481cd99efd..1e6eb93207f 100644 --- a/compiler/testData/codegen/box/multifileClasses/privateConstVal.kt +++ b/compiler/testData/codegen/box/multifileClasses/privateConstVal.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // WITH_RUNTIME // FILE: foo.kt diff --git a/compiler/testData/codegen/box/multifileClasses/samePartNameDifferentFacades.kt b/compiler/testData/codegen/box/multifileClasses/samePartNameDifferentFacades.kt index 11089f2e217..eeb69d5d451 100644 --- a/compiler/testData/codegen/box/multifileClasses/samePartNameDifferentFacades.kt +++ b/compiler/testData/codegen/box/multifileClasses/samePartNameDifferentFacades.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // WITH_RUNTIME // FILE: 1/part.kt diff --git a/compiler/testData/codegen/box/multifileClasses/sealedClassHierarchy.kt b/compiler/testData/codegen/box/multifileClasses/sealedClassHierarchy.kt index 8900cfceaca..9aff61d2774 100644 --- a/compiler/testData/codegen/box/multifileClasses/sealedClassHierarchy.kt +++ b/compiler/testData/codegen/box/multifileClasses/sealedClassHierarchy.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // WITH_RUNTIME diff --git a/compiler/testData/codegen/box/multiplatform/expectClassInJvmMultifileFacade.kt b/compiler/testData/codegen/box/multiplatform/expectClassInJvmMultifileFacade.kt index 94315d4fc49..ac6c73b74f4 100644 --- a/compiler/testData/codegen/box/multiplatform/expectClassInJvmMultifileFacade.kt +++ b/compiler/testData/codegen/box/multiplatform/expectClassInJvmMultifileFacade.kt @@ -1,5 +1,4 @@ // !LANGUAGE: +MultiPlatformProjects -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // WITH_RUNTIME // FILE: common.kt diff --git a/compiler/testData/codegen/box/reflection/multifileClasses/callFunctionsInMultifileClass.kt b/compiler/testData/codegen/box/reflection/multifileClasses/callFunctionsInMultifileClass.kt index 85bb3bbc138..2bcd9c82c3a 100644 --- a/compiler/testData/codegen/box/reflection/multifileClasses/callFunctionsInMultifileClass.kt +++ b/compiler/testData/codegen/box/reflection/multifileClasses/callFunctionsInMultifileClass.kt @@ -1,6 +1,4 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM - // WITH_REFLECT // FILE: Test1.kt diff --git a/compiler/testData/codegen/box/reflection/properties/localDelegated/multiFileClass.kt b/compiler/testData/codegen/box/reflection/properties/localDelegated/multiFileClass.kt index 9ac5044ebdf..2e2794ae240 100644 --- a/compiler/testData/codegen/box/reflection/properties/localDelegated/multiFileClass.kt +++ b/compiler/testData/codegen/box/reflection/properties/localDelegated/multiFileClass.kt @@ -1,7 +1,5 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // WITH_REFLECT - // FILE: 1.kt @file:JvmMultifileClass diff --git a/compiler/testData/codegen/box/topLevelPrivate/noPrivateNoAccessorsInMultiFileFacade.kt b/compiler/testData/codegen/box/topLevelPrivate/noPrivateNoAccessorsInMultiFileFacade.kt index 3076a19c32a..33b2b195fa5 100644 --- a/compiler/testData/codegen/box/topLevelPrivate/noPrivateNoAccessorsInMultiFileFacade.kt +++ b/compiler/testData/codegen/box/topLevelPrivate/noPrivateNoAccessorsInMultiFileFacade.kt @@ -1,6 +1,4 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM - // WITH_RUNTIME @file:kotlin.jvm.JvmMultifileClass diff --git a/compiler/testData/codegen/box/topLevelPrivate/noPrivateNoAccessorsInMultiFileFacade2.kt b/compiler/testData/codegen/box/topLevelPrivate/noPrivateNoAccessorsInMultiFileFacade2.kt index d0d5c6996d6..eea28c9b194 100644 --- a/compiler/testData/codegen/box/topLevelPrivate/noPrivateNoAccessorsInMultiFileFacade2.kt +++ b/compiler/testData/codegen/box/topLevelPrivate/noPrivateNoAccessorsInMultiFileFacade2.kt @@ -1,6 +1,4 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM - // WITH_RUNTIME @file:kotlin.jvm.JvmMultifileClass diff --git a/compiler/testData/codegen/box/topLevelPrivate/syntheticAccessorInMultiFile.kt b/compiler/testData/codegen/box/topLevelPrivate/syntheticAccessorInMultiFile.kt index 3a5f63232c7..c7c72020467 100644 --- a/compiler/testData/codegen/box/topLevelPrivate/syntheticAccessorInMultiFile.kt +++ b/compiler/testData/codegen/box/topLevelPrivate/syntheticAccessorInMultiFile.kt @@ -1,6 +1,4 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM - // WITH_RUNTIME @file:kotlin.jvm.JvmMultifileClass diff --git a/compiler/testData/codegen/boxInline/private/privateInInlineInMultiFileFacade.kt b/compiler/testData/codegen/boxInline/private/privateInInlineInMultiFileFacade.kt index e6069e1ae80..e5a4efe858c 100644 --- a/compiler/testData/codegen/boxInline/private/privateInInlineInMultiFileFacade.kt +++ b/compiler/testData/codegen/boxInline/private/privateInInlineInMultiFileFacade.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // FILE: 1.kt // WITH_RUNTIME diff --git a/compiler/testData/codegen/bytecodeText/multifileClasses/defaultFunctionInMultifileClass.kt b/compiler/testData/codegen/bytecodeText/multifileClasses/defaultFunctionInMultifileClass.kt new file mode 100644 index 00000000000..f353e1d53b2 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/multifileClasses/defaultFunctionInMultifileClass.kt @@ -0,0 +1,19 @@ +// TARGET_BACKEND: JVM +// WITH_RUNTIME +// FILE: part1.kt + +@file:JvmName("Facade") +@file:JvmMultifileClass + +fun foo(o: String = "O", k: String = "K"): String = o + k + +// FILE: part2.kt + +@file:JvmName("Facade") +@file:JvmMultifileClass + +val bar = "" + +// Default argument handling should not happen in the facade, only in parts. +// @Facade.class: +// 0 LDC diff --git a/compiler/testData/compileKotlinAgainstKotlin/multifileClassInlineFunctionAccessingProperty.kt b/compiler/testData/compileKotlinAgainstKotlin/multifileClassInlineFunctionAccessingProperty.kt index 3046446e0ec..467db537c76 100644 --- a/compiler/testData/compileKotlinAgainstKotlin/multifileClassInlineFunctionAccessingProperty.kt +++ b/compiler/testData/compileKotlinAgainstKotlin/multifileClassInlineFunctionAccessingProperty.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // TARGET_BACKEND: JVM // FILE: A.kt diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 55dde22ae5d..e7c5a725180 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -14899,6 +14899,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/jvmOverloads/manyParameters.kt"); } + @TestMetadata("multifileClass.kt") + public void testMultifileClass() throws Exception { + runTest("compiler/testData/codegen/box/jvmOverloads/multifileClass.kt"); + } + @TestMetadata("multipleDefaultParameters.kt") public void testMultipleDefaultParameters() throws Exception { runTest("compiler/testData/codegen/box/jvmOverloads/multipleDefaultParameters.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index a09d276ae6f..37e4157b258 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -3120,6 +3120,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/multifileClasses"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); } + @TestMetadata("defaultFunctionInMultifileClass.kt") + public void testDefaultFunctionInMultifileClass() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/multifileClasses/defaultFunctionInMultifileClass.kt"); + } + @TestMetadata("optimizedMultifileClassFacadeMethods.kt") public void testOptimizedMultifileClassFacadeMethods() throws Exception { runTest("compiler/testData/codegen/bytecodeText/multifileClasses/optimizedMultifileClassFacadeMethods.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index ddedeb9d93d..dced11244da 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -14899,6 +14899,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/jvmOverloads/manyParameters.kt"); } + @TestMetadata("multifileClass.kt") + public void testMultifileClass() throws Exception { + runTest("compiler/testData/codegen/box/jvmOverloads/multifileClass.kt"); + } + @TestMetadata("multipleDefaultParameters.kt") public void testMultipleDefaultParameters() throws Exception { runTest("compiler/testData/codegen/box/jvmOverloads/multipleDefaultParameters.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index acbe6081944..4ce18bd7748 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -13789,6 +13789,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/jvmOverloads/manyParameters.kt"); } + @TestMetadata("multifileClass.kt") + public void testMultifileClass() throws Exception { + runTest("compiler/testData/codegen/box/jvmOverloads/multifileClass.kt"); + } + @TestMetadata("multipleDefaultParameters.kt") public void testMultipleDefaultParameters() throws Exception { runTest("compiler/testData/codegen/box/jvmOverloads/multipleDefaultParameters.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java index a4c48f5eca1..15b4fa92db3 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBytecodeTextTestGenerated.java @@ -3090,6 +3090,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/bytecodeText/multifileClasses"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true); } + @TestMetadata("defaultFunctionInMultifileClass.kt") + public void testDefaultFunctionInMultifileClass() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/multifileClasses/defaultFunctionInMultifileClass.kt"); + } + @TestMetadata("optimizedMultifileClassFacadeMethods.kt") public void testOptimizedMultifileClassFacadeMethods() throws Exception { runTest("compiler/testData/codegen/bytecodeText/multifileClasses/optimizedMultifileClassFacadeMethods.kt"); diff --git a/jps-plugin/testData/incremental/withJava/other/packageFacadeToClass/directives.txt b/jps-plugin/testData/incremental/withJava/other/packageFacadeToClass/directives.txt deleted file mode 100644 index 5099b2ad971..00000000000 --- a/jps-plugin/testData/incremental/withJava/other/packageFacadeToClass/directives.txt +++ /dev/null @@ -1 +0,0 @@ -// IGNORE_BACKEND: JVM_IR