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.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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<IrClass, List<IrLocalDelegatedPropertySymbol>>()
|
||||
|
||||
internal val multifileFacadesToAdd = mutableMapOf<JvmClassName, MutableList<IrClass>>()
|
||||
|
||||
override var inVerbosePhase: Boolean = false
|
||||
|
||||
override val configuration get() = state.configuration
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+16
-6
@@ -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<File> {
|
||||
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
|
||||
|
||||
+13
-7
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+6
@@ -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
|
||||
}
|
||||
|
||||
+135
@@ -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<JvmBackendContext, IrModuleFragment> {
|
||||
override fun invoke(
|
||||
phaseConfig: PhaseConfig,
|
||||
phaserState: PhaserState<IrModuleFragment>,
|
||||
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<IrFile>
|
||||
) : SourceManager.FileEntry {
|
||||
override val name: String
|
||||
get() = "<multi-file facade $className>"
|
||||
|
||||
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<IrFile> =
|
||||
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()}")
|
||||
}
|
||||
}
|
||||
@@ -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]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_RUNTIME
|
||||
|
||||
@file:JvmName("Test")
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_RUNTIME
|
||||
|
||||
@file:JvmName("Test")
|
||||
|
||||
@@ -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
|
||||
-2
@@ -1,6 +1,4 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_RUNTIME
|
||||
// FILE: box.kt
|
||||
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// FILE: 1.kt
|
||||
|
||||
Vendored
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// FILE: box.kt
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// FILE: box.kt
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// FILE: Baz.java
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// FILE: Baz.java
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// FILE: Baz.java
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_LIGHT_ANALYSIS
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_LIGHT_ANALYSIS
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_LIGHT_ANALYSIS
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// FILE: foo.kt
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// FILE: 1/part.kt
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
// !LANGUAGE: +MultiPlatformProjects
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
// FILE: common.kt
|
||||
|
||||
-2
@@ -1,6 +1,4 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_REFLECT
|
||||
// FILE: Test1.kt
|
||||
|
||||
|
||||
-2
@@ -1,7 +1,5 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_REFLECT
|
||||
|
||||
// FILE: 1.kt
|
||||
|
||||
@file:JvmMultifileClass
|
||||
|
||||
-2
@@ -1,6 +1,4 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_RUNTIME
|
||||
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
|
||||
-2
@@ -1,6 +1,4 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_RUNTIME
|
||||
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_RUNTIME
|
||||
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
|
||||
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FILE: 1.kt
|
||||
// WITH_RUNTIME
|
||||
|
||||
+19
@@ -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
|
||||
Vendored
-1
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
// FILE: A.kt
|
||||
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
-1
@@ -1 +0,0 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
Reference in New Issue
Block a user