diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java index c0a014ba50b..a54546f8de0 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/AnonymousObjectTransformer.java @@ -52,8 +52,6 @@ public class AnonymousObjectTransformer extends ObjectTransformer> fieldNames = new HashMap>(); @@ -61,8 +59,7 @@ public class AnonymousObjectTransformer extends ObjectTransformer innerClassNodes = new ArrayList(); ClassBuilder classBuilder = createRemappingClassBuilderViaFactory(inliningContext); final List methodsToTransform = new ArrayList(); @@ -161,7 +157,7 @@ public class AnonymousObjectTransformer extends ObjectTransformer constructorAdditionalFakeParams ) { @@ -293,7 +286,8 @@ public class AnonymousObjectTransformer extends ObjectTransformer newFieldsWithSkipped = TransformationUtilsKt.getNewFieldsToGenerate(allCapturedBuilder.listCaptured()); - List fieldInfoWithSkipped = TransformationUtilsKt.transformToFieldInfo(newLambdaType, newFieldsWithSkipped); + List fieldInfoWithSkipped = TransformationUtilsKt.transformToFieldInfo( + Type.getObjectType(transformationInfo.getNewClassName()), newFieldsWithSkipped); int paramIndex = 0; InstructionAdapter capturedFieldInitializer = new InstructionAdapter(constructorVisitor); @@ -323,7 +317,7 @@ public class AnonymousObjectTransformer extends ObjectTransformer".equals(methodName) && isAnonymousClass(internalName); } + public static boolean isWhenMappingAccess(@NotNull String internalName, @NotNull String fieldName) { + return fieldName.startsWith(WhenByEnumsMapping.MAPPING_ARRAY_FIELD_PREFIX) && internalName.endsWith(WhenByEnumsMapping.MAPPINGS_CLASS_NAME_POSTFIX); + } + public static boolean isAnonymousSingletonLoad(@NotNull String internalName, @NotNull String fieldName) { return JvmAbi.INSTANCE_FIELD.equals(fieldName) && isAnonymousClass(internalName); } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java index 08f615cd47d..0072bc06e9c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/MethodInliner.java @@ -63,7 +63,7 @@ public class MethodInliner { private final List invokeCalls = new ArrayList(); //keeps order - private final List anonymousObjectRegenerations = new ArrayList(); + private final List transformations = new ArrayList(); //current state private final Map currentTypeMapping = new HashMap(); @@ -160,7 +160,7 @@ public class MethodInliner { final MethodNode resultNode = new MethodNode(node.access, node.name, node.desc, node.signature, null); - final Iterator iterator = anonymousObjectRegenerations.iterator(); + final Iterator iterator = transformations.iterator(); final TypeRemapper remapper = TypeRemapper.createFrom(currentTypeMapping); final RemappingMethodAdapter remappingMethodAdapter = new RemappingMethodAdapter( @@ -173,7 +173,7 @@ public class MethodInliner { final int markerShift = InlineCodegenUtil.calcMarkerShift(parameters, node); InlineAdapter lambdaInliner = new InlineAdapter(remappingMethodAdapter, parameters.getArgsSizeOnStack(), sourceMapper) { - private AnonymousObjectTransformationInfo transformationInfo; + private TransformationInfo transformationInfo; private void handleAnonymousObjectRegeneration() { transformationInfo = iterator.next(); @@ -182,17 +182,18 @@ public class MethodInliner { String oldClassName = transformationInfo.getOldClassName(); String newClassName = transformationInfo.getNewClassName(); remapper.addMapping(oldClassName, newClassName); - AnonymousObjectTransformer transformer = - new AnonymousObjectTransformer((AnonymousObjectTransformationInfo) transformationInfo, - inliningContext - .subInlineWithClassRegeneration( - inliningContext.nameGenerator, - currentTypeMapping, - inlineCallSiteInfo), - isSameModule, Type.getObjectType(newClassName) - ); - InlineResult transformResult = transformer.doTransform(transformationInfo, nodeRemapper); + InliningContext childInliningContext = inliningContext.subInlineWithClassRegeneration( + inliningContext.nameGenerator, + currentTypeMapping, + inlineCallSiteInfo + ); + ObjectTransformer transformer = transformationInfo.createTransformer( + childInliningContext, + isSameModule + ); + + InlineResult transformResult = transformer.doTransform(nodeRemapper); result.addAllClassesToRemove(transformResult); result.addChangedType(oldClassName, newClassName); @@ -271,17 +272,18 @@ public class MethodInliner { else if (isAnonymousConstructorCall(owner, name)) { //TODO add method assert transformationInfo != null : " call not corresponds to new call" + owner + " " + name; if (transformationInfo.shouldRegenerate(isSameModule)) { - //put additional captured parameters on stack - for (CapturedParamDesc capturedParamDesc : transformationInfo.getAllRecapturedParameters()) { - visitFieldInsn(Opcodes.GETSTATIC, capturedParamDesc.getContainingLambdaName(), - "$$$" + capturedParamDesc.getFieldName(), capturedParamDesc.getType().getDescriptor()); + if (transformationInfo instanceof AnonymousObjectTransformationInfo) { + //put additional captured parameters on stack + for (CapturedParamDesc capturedParamDesc : ((AnonymousObjectTransformationInfo) transformationInfo).getAllRecapturedParameters()) { + visitFieldInsn(Opcodes.GETSTATIC, capturedParamDesc.getContainingLambdaName(), + "$$$" + capturedParamDesc.getFieldName(), capturedParamDesc.getType().getDescriptor()); + } + super.visitMethodInsn(opcode, transformationInfo.getNewClassName(), name, ((AnonymousObjectTransformationInfo) transformationInfo).getNewConstructorDescriptor(), itf); } - String newInternalName = transformationInfo.getNewClassName(); - super.visitMethodInsn(opcode, newInternalName, name, transformationInfo.getNewConstructorDescriptor(), itf); //TODO: add new inner class also for other contexts if (inliningContext.getParent() instanceof RegeneratedClassContext) { - inliningContext.getParent().typeRemapper.addAdditionalMappings(transformationInfo.getOldClassName(), newInternalName); + inliningContext.getParent().typeRemapper.addAdditionalMappings(transformationInfo.getOldClassName(), transformationInfo.getNewClassName()); } transformationInfo = null; @@ -299,7 +301,7 @@ public class MethodInliner { @Override public void visitFieldInsn(int opcode, @NotNull String owner, @NotNull String name, @NotNull String desc) { - if (opcode == Opcodes.GETSTATIC && isAnonymousSingletonLoad(owner, name)) { + if (opcode == Opcodes.GETSTATIC && (isAnonymousSingletonLoad(owner, name) || isWhenMappingAccess(owner, name))) { handleAnonymousObjectRegeneration(); } super.visitFieldInsn(opcode, owner, name, desc); @@ -486,7 +488,7 @@ public class MethodInliner { offset += i == 0 ? 1 : argTypes[i - 1].getSize(); } - anonymousObjectRegenerations.add( + transformations.add( buildConstructorInvocation( owner, desc, lambdaMapping, awaitClassReification ) @@ -496,16 +498,23 @@ public class MethodInliner { } else if (cur.getOpcode() == Opcodes.GETSTATIC) { FieldInsnNode fieldInsnNode = (FieldInsnNode) cur; - String owner = fieldInsnNode.owner; - if (isAnonymousSingletonLoad(owner, fieldInsnNode.name)) { - anonymousObjectRegenerations.add( + String className = fieldInsnNode.owner; + if (isAnonymousSingletonLoad(className, fieldInsnNode.name)) { + transformations.add( new AnonymousObjectTransformationInfo( - owner, awaitClassReification, isAlreadyRegenerated(owner), true, + className, awaitClassReification, isAlreadyRegenerated(className), true, inliningContext.nameGenerator ) ); awaitClassReification = false; } + else if (isWhenMappingAccess(className, fieldInsnNode.name)) { + transformations.add( + new WhenMappingTransformationInfo( + className, inliningContext.nameGenerator, isAlreadyRegenerated(className), fieldInsnNode) + ); + } + } } AbstractInsnNode prevNode = cur; diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ObjectTransformer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ObjectTransformer.kt index 02c73eebbe7..2f29de934f9 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ObjectTransformer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ObjectTransformer.kt @@ -17,15 +17,19 @@ package org.jetbrains.kotlin.codegen.inline import org.jetbrains.kotlin.codegen.ClassBuilder +import org.jetbrains.kotlin.codegen.optimization.common.InsnSequence import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin -import org.jetbrains.org.objectweb.asm.ClassReader -import org.jetbrains.org.objectweb.asm.ClassVisitor -import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.* +import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode +import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode +import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode +import org.jetbrains.org.objectweb.asm.tree.MethodNode +import java.util.* -abstract class ObjectTransformer(val transformationInfo: T, val state: GenerationState) { +abstract class ObjectTransformer(@JvmField val transformationInfo: T, val state: GenerationState) { - abstract fun doTransform(info: T, parentRemapper: FieldRemapper): InlineResult + abstract fun doTransform(parentRemapper: FieldRemapper): InlineResult @JvmField val transformationResult = InlineResult.create() @@ -51,23 +55,72 @@ abstract class ObjectTransformer(val transformationInfo: class WhenMappingTransformer( whenObjectRegenerationInfo: WhenMappingTransformationInfo, - state: GenerationState, val inliningContext: InliningContext -) : ObjectTransformer(whenObjectRegenerationInfo, state) { +) : ObjectTransformer(whenObjectRegenerationInfo, inliningContext.state) { - override fun doTransform(info: WhenMappingTransformationInfo, parentRemapper: FieldRemapper): InlineResult { + override fun doTransform(parentRemapper: FieldRemapper): InlineResult { val classReader = createClassReader() //TODO add additional check that class is when mapping val classBuilder = createRemappingClassBuilderViaFactory(inliningContext) + /*MAPPING File could contains mappings for several enum classes, we should filter one*/ + val methodNodes = arrayListOf() + val fieldNode = transformationInfo.fieldNode classReader.accept(object : ClassVisitor(InlineCodegenUtil.API, classBuilder.visitor) { - override fun visit(version: Int, access: Int, name: String, signature: String, superName: String, interfaces: Array) { + override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String?, interfaces: Array?) { InlineCodegenUtil.assertVersionNotGreaterThanJava6(version, name) super.visit(version, access, name, signature, superName, interfaces) } + + override fun visitField(access: Int, name: String, desc: String, signature: String?, value: Any?): FieldVisitor? { + return if (name.equals(fieldNode.name)) { + super.visitField(access, name, desc, signature, value) + } + else { + null + } + } + + override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array?): MethodVisitor? { + val methodNode = MethodNode(access, name, desc, signature, exceptions) + methodNodes.add(methodNode) + return methodNode + } }, ClassReader.SKIP_FRAMES) + assert(methodNodes.size == 1, { "When mapping ${fieldNode.owner} class should contain only one method but: " + methodNodes.joinToString { it.name } }) + + var transformedNode = cutOtherMappings(methodNodes.first()) + val result = classBuilder.visitor.visitMethod(transformedNode.access, transformedNode.name, transformedNode.desc, transformedNode.signature, transformedNode.exceptions.toTypedArray()) + transformedNode.accept(result) + return transformationResult } + + + private fun cutOtherMappings(node: MethodNode): MethodNode { + val myArrayAccess = InsnSequence(node.instructions).first { + it is FieldInsnNode && it.name.equals(transformationInfo.fieldNode.name) + } + + val myValuesAccess = generateSequence(myArrayAccess) { it.previous }.first { + isValues(it) + } + + val nextValuesOrEnd = generateSequence(myArrayAccess) { it.next }.first { + isValues(it) || it.opcode == Opcodes.RETURN + } + + val result = MethodNode(node.access, node.name, node.desc, node.signature, node.exceptions.toTypedArray()) + InsnSequence(myValuesAccess, nextValuesOrEnd).forEach { it.accept(result) } + result.visitInsn(Opcodes.RETURN) + + return result + } + + private fun isValues(node: AbstractInsnNode) = node is MethodInsnNode && + node.opcode == Opcodes.INVOKESTATIC && + node.name == "values" && + node.desc == "()[" + Type.getObjectType(node.owner).descriptor } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TransformationInfo.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TransformationInfo.kt index 93fc04c3a0d..03e502721d6 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TransformationInfo.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/TransformationInfo.kt @@ -16,73 +16,91 @@ package org.jetbrains.kotlin.codegen.inline +import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode import java.util.* interface TransformationInfo { - val oldClassName: String + val oldClassName: String - val newClassName: String + val newClassName: String - fun shouldRegenerate(sameModule: Boolean): Boolean + fun shouldRegenerate(sameModule: Boolean): Boolean - fun canRemoveAfterTransformation(): Boolean + fun canRemoveAfterTransformation(): Boolean + fun createTransformer( + inliningContext: InliningContext, + sameModule: Boolean + ): ObjectTransformer<*> } -class WhenMappingTransformationInfo(override val oldClassName: String, val nameGenerator: NameGenerator) : TransformationInfo { +class WhenMappingTransformationInfo( + override val oldClassName: String, + val nameGenerator: NameGenerator, + val alreadyRegenerated: Boolean, + val fieldNode: FieldInsnNode +) : TransformationInfo { - override val newClassName by lazy { - nameGenerator.genLambdaClassName() + oldClassName.substringAfterLast("/") - } + override val newClassName by lazy { + nameGenerator.genLambdaClassName() + oldClassName.substringAfterLast("/") + } - override fun shouldRegenerate(sameModule: Boolean): Boolean { - throw UnsupportedOperationException() - } + override fun shouldRegenerate(sameModule: Boolean): Boolean { + return !alreadyRegenerated && !sameModule + } - override fun canRemoveAfterTransformation(): Boolean { - return true - } + override fun canRemoveAfterTransformation(): Boolean { + return true + } + + override fun createTransformer(inliningContext: InliningContext, sameModule: Boolean): ObjectTransformer<*> { + return WhenMappingTransformer(this, inliningContext); + } } class AnonymousObjectTransformationInfo internal constructor( - override val oldClassName: String, - private val needReification: Boolean, - val lambdasToInline: Map, - private val capturedOuterRegenerated: Boolean, - private val alreadyRegenerated: Boolean, - val constructorDesc: String?, - private val isStaticOrigin: Boolean, - private val nameGenerator: NameGenerator) : TransformationInfo { + override val oldClassName: String, + private val needReification: Boolean, + val lambdasToInline: Map, + private val capturedOuterRegenerated: Boolean, + private val alreadyRegenerated: Boolean, + val constructorDesc: String?, + private val isStaticOrigin: Boolean, + nameGenerator: NameGenerator) : TransformationInfo { - override val newClassName: String by lazy { - nameGenerator.genLambdaClassName() - } + override val newClassName: String by lazy { + nameGenerator.genLambdaClassName() + } - var newConstructorDescriptor: String? = null + lateinit var newConstructorDescriptor: String - var allRecapturedParameters: List? = null + lateinit var allRecapturedParameters: List - var capturedLambdasToInline: Map? = null + lateinit var capturedLambdasToInline: Map - constructor( - ownerInternalName: String, - needReification: Boolean, - alreadyRegenerated: Boolean, - isStaticOrigin: Boolean, - nameGenerator: NameGenerator - ) : this( - ownerInternalName, needReification, - HashMap(), false, alreadyRegenerated, null, isStaticOrigin, nameGenerator) { - } + constructor( + ownerInternalName: String, + needReification: Boolean, + alreadyRegenerated: Boolean, + isStaticOrigin: Boolean, + nameGenerator: NameGenerator + ) : this( + ownerInternalName, needReification, + HashMap(), false, alreadyRegenerated, null, isStaticOrigin, nameGenerator) { + } - override fun shouldRegenerate(sameModule: Boolean): Boolean { - return !alreadyRegenerated && (!lambdasToInline.isEmpty() || !sameModule || capturedOuterRegenerated || needReification) - } + override fun shouldRegenerate(sameModule: Boolean): Boolean { + return !alreadyRegenerated && (!lambdasToInline.isEmpty() || !sameModule || capturedOuterRegenerated || needReification) + } - override fun canRemoveAfterTransformation(): Boolean { - // Note: It is unsafe to remove anonymous class that is referenced by GETSTATIC within lambda - // because it can be local function from outer scope - return !isStaticOrigin - } + override fun canRemoveAfterTransformation(): Boolean { + // Note: It is unsafe to remove anonymous class that is referenced by GETSTATIC within lambda + // because it can be local function from outer scope + return !isStaticOrigin + } + + override fun createTransformer(inliningContext: InliningContext, sameModule: Boolean): ObjectTransformer<*> { + return AnonymousObjectTransformer(this, inliningContext, sameModule); + } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/when/WhenByEnumsMapping.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/when/WhenByEnumsMapping.java index 543508f2078..ec4ce719443 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/when/WhenByEnumsMapping.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/when/WhenByEnumsMapping.java @@ -24,8 +24,8 @@ import java.util.LinkedHashMap; import java.util.Map; public class WhenByEnumsMapping { - private static final String MAPPING_ARRAY_FIELD_PREFIX = "$EnumSwitchMapping$"; - private static final String MAPPINGS_CLASS_NAME_POSTFIX = "$WhenMappings"; + public static final String MAPPING_ARRAY_FIELD_PREFIX = "$EnumSwitchMapping$"; + public static final String MAPPINGS_CLASS_NAME_POSTFIX = "$WhenMappings"; private final Map map = new LinkedHashMap(); private final ClassDescriptor enumClassDescriptor; diff --git a/compiler/testData/codegen/boxInline/anonymousObject/enumWhen/callSite.kt b/compiler/testData/codegen/boxInline/anonymousObject/enumWhen/callSite.kt new file mode 100644 index 00000000000..c92261bac4b --- /dev/null +++ b/compiler/testData/codegen/boxInline/anonymousObject/enumWhen/callSite.kt @@ -0,0 +1,29 @@ +// FILE: 1.kt + +package test + +enum class X { + A, + B +} + +inline fun test(x: X, s: (X) -> String): String { + return s(x) +} + +// FILE: 2.kt +import test.* + +fun box(): String { + return test(X.A) { + when(it) { + X.A-> "O" + X.B-> "K" + } + } + test(X.B) { + when(it) { + X.A-> "O" + X.B-> "K" + } + } +} diff --git a/compiler/testData/codegen/boxInline/anonymousObject/enumWhen/declSite.kt b/compiler/testData/codegen/boxInline/anonymousObject/enumWhen/declSite.kt new file mode 100644 index 00000000000..e5942e3987e --- /dev/null +++ b/compiler/testData/codegen/boxInline/anonymousObject/enumWhen/declSite.kt @@ -0,0 +1,22 @@ +// FILE: 1.kt + +package test + +enum class X { + A, + B +} + +inline fun test(e: X): String { + return when(e) { + X.A-> "O" + X.B-> "K" + } +} + +// FILE: 2.kt +import test.* + +fun box(): String { + return test(X.A) + test(X.B) +} diff --git a/compiler/testData/codegen/boxInline/anonymousObject/enumWhen/declSiteSeveralMappings.kt b/compiler/testData/codegen/boxInline/anonymousObject/enumWhen/declSiteSeveralMappings.kt new file mode 100644 index 00000000000..7e01061e0df --- /dev/null +++ b/compiler/testData/codegen/boxInline/anonymousObject/enumWhen/declSiteSeveralMappings.kt @@ -0,0 +1,34 @@ +// FILE: 1.kt + +package test + +enum class X { + A, + B +} + +enum class Y { + A, + B +} + +inline fun test(e: X): String { + return when(e) { + X.A-> "O" + X.B-> "K" + } +} + +fun funForAdditionalMappingArrayInMappingFile(e: Y): String { + return when(e) { + Y.A-> "O" + Y.B-> "K" + } +} + +// FILE: 2.kt +import test.* + +fun box(): String { + return test(X.A) + test(X.B) +} diff --git a/compiler/testData/codegen/boxInline/anonymousObject/enumWhen/declSiteSeveralMappingsDifOrder.kt b/compiler/testData/codegen/boxInline/anonymousObject/enumWhen/declSiteSeveralMappingsDifOrder.kt new file mode 100644 index 00000000000..a54536a0b2f --- /dev/null +++ b/compiler/testData/codegen/boxInline/anonymousObject/enumWhen/declSiteSeveralMappingsDifOrder.kt @@ -0,0 +1,34 @@ +// FILE: 1.kt + +package test + +enum class X { + A, + B +} + +enum class Y { + A, + B +} + +fun funForAdditionalMappingArrayInMappingFile(e: Y): String { + return when(e) { + Y.A-> "O" + Y.B-> "K" + } +} + +inline fun test(e: X): String { + return when(e) { + X.A-> "O" + X.B-> "K" + } +} + +// FILE: 2.kt +import test.* + +fun box(): String { + return test(X.A) + test(X.B) +} diff --git a/compiler/testData/codegen/bytecodeText/inline/whenMappingOnCallSite.kt b/compiler/testData/codegen/bytecodeText/inline/whenMappingOnCallSite.kt new file mode 100644 index 00000000000..b15b2922494 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/inline/whenMappingOnCallSite.kt @@ -0,0 +1,28 @@ +package test + +enum class X { + A, + B +} + +inline fun test(x: X, s: (X) -> String): String { + return s(x) +} + + +fun box(): String { + return test(X.A) { + when(it) { + X.A-> "O" + X.B-> "K" + } + } + test(X.B) { + when(it) { + X.A-> "O" + X.B-> "K" + } + } +} + +// no additional mappings cause when in inline lambda (same module) +// 1 class test/.*\$WhenMappings \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java index f62867add1c..f245c05a02e 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java @@ -169,6 +169,39 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo doTest(fileName); } + @TestMetadata("compiler/testData/codegen/boxInline/anonymousObject/enumWhen") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class EnumWhen extends AbstractBlackBoxInlineCodegenTest { + public void testAllFilesPresentInEnumWhen() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/anonymousObject/enumWhen"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("callSite.kt") + public void testCallSite() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/enumWhen/callSite.kt"); + doTest(fileName); + } + + @TestMetadata("declSite.kt") + public void testDeclSite() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/enumWhen/declSite.kt"); + doTest(fileName); + } + + @TestMetadata("declSiteSeveralMappings.kt") + public void testDeclSiteSeveralMappings() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/enumWhen/declSiteSeveralMappings.kt"); + doTest(fileName); + } + + @TestMetadata("declSiteSeveralMappingsDifOrder.kt") + public void testDeclSiteSeveralMappingsDifOrder() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/enumWhen/declSiteSeveralMappingsDifOrder.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/codegen/boxInline/anonymousObject/properRecapturing") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index c3fb80bb835..64274044652 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -888,6 +888,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inline/splitedExceptionTable.kt"); doTest(fileName); } + + @TestMetadata("whenMappingOnCallSite.kt") + public void testWhenMappingOnCallSite() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inline/whenMappingOnCallSite.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/codegen/bytecodeText/interfaces") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java index 3617cd1483c..c45cdde00dd 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -169,6 +169,39 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi doTest(fileName); } + @TestMetadata("compiler/testData/codegen/boxInline/anonymousObject/enumWhen") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class EnumWhen extends AbstractCompileKotlinAgainstInlineKotlinTest { + public void testAllFilesPresentInEnumWhen() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/anonymousObject/enumWhen"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("callSite.kt") + public void testCallSite() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/enumWhen/callSite.kt"); + doTest(fileName); + } + + @TestMetadata("declSite.kt") + public void testDeclSite() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/enumWhen/declSite.kt"); + doTest(fileName); + } + + @TestMetadata("declSiteSeveralMappings.kt") + public void testDeclSiteSeveralMappings() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/enumWhen/declSiteSeveralMappings.kt"); + doTest(fileName); + } + + @TestMetadata("declSiteSeveralMappingsDifOrder.kt") + public void testDeclSiteSeveralMappingsDifOrder() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/anonymousObject/enumWhen/declSiteSeveralMappingsDifOrder.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/codegen/boxInline/anonymousObject/properRecapturing") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)