diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index f08d659dbf9..7f47def8f83 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -4445,6 +4445,12 @@ The "returned" value of try expression with no finally is either the last expres public void putReifiedOperationMarkerIfTypeIsReifiedParameter( @NotNull KotlinType type, @NotNull ReifiedTypeInliner.OperationKind operationKind + ) { + putReifiedOperationMarkerIfTypeIsReifiedParameter(type, operationKind, v); + } + + public void putReifiedOperationMarkerIfTypeIsReifiedParameter( + @NotNull KotlinType type, @NotNull ReifiedTypeInliner.OperationKind operationKind, @NotNull InstructionAdapter v ) { Pair typeParameterAndReificationArgument = extractReificationArgument(type); if (typeParameterAndReificationArgument != null && typeParameterAndReificationArgument.getFirst().isReified()) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java index 464798ae3ca..5d26992e04c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegen.java @@ -50,6 +50,7 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature; import org.jetbrains.kotlin.resolve.scopes.MemberScope; import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor; +import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.types.expressions.DoubleColonLHS; import org.jetbrains.kotlin.types.expressions.LabelResolver; import org.jetbrains.org.objectweb.asm.Label; @@ -171,7 +172,7 @@ public class InlineCodegen extends CallGenerator { SMAPAndMethodNode nodeAndSmap = null; try { - nodeAndSmap = createMethodNode(functionDescriptor, jvmSignature, codegen, context, callDefault); + nodeAndSmap = createMethodNode(functionDescriptor, jvmSignature, codegen, context, callDefault, resolvedCall); endCall(inlineCall(nodeAndSmap)); } catch (CompilationException e) { @@ -227,8 +228,24 @@ public class InlineCodegen extends CallGenerator { @NotNull JvmMethodSignature jvmSignature, @NotNull ExpressionCodegen codegen, @NotNull CodegenContext context, - boolean callDefault + boolean callDefault, + @Nullable ResolvedCall resolvedCall ) { + if (InlineCodegenUtil.isSpecialEnumMethod(functionDescriptor)) { + assert resolvedCall != null : "Resolved call for " + functionDescriptor + " should be not null"; + Map arguments = resolvedCall.getTypeArguments(); + assert arguments.size() == 1 : "Resolved call for " + functionDescriptor + " should have 1 type argument"; + KotlinType type = arguments.values().iterator().next(); + MethodNode node = + InlineCodegenUtil.createSpecialEnumMethodBody( + codegen, + functionDescriptor.getName().asString(), + type, + codegen.getState().getTypeMapper() + ); + return new SMAPAndMethodNode(node, SMAPParser.parseOrCreateDefault(null, null, "fake", -1, -1)); + } + final GenerationState state = codegen.getState(); final Method asmMethod = callDefault diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt index 1835d00e9ae..97cb7eb1253 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenForDefaultBody.kt @@ -65,7 +65,7 @@ class InlineCodegenForDefaultBody( } override fun genCallInner(callableMethod: Callable, resolvedCall: ResolvedCall<*>?, callDefault: Boolean, codegen: ExpressionCodegen) { - val nodeAndSmap = InlineCodegen.createMethodNode(functionDescriptor, jvmSignature, codegen, context, callDefault) + val nodeAndSmap = InlineCodegen.createMethodNode(functionDescriptor, jvmSignature, codegen, context, callDefault, null) val childSourceMapper = InlineCodegen.createNestedSourceMapper(nodeAndSmap, sourceMapper) val node = nodeAndSmap.node diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java index 0330c9c599b..400e18669df 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/InlineCodegenUtil.java @@ -22,6 +22,8 @@ import kotlin.text.StringsKt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.backend.common.output.OutputFile; +import org.jetbrains.kotlin.builtins.KotlinBuiltIns; +import org.jetbrains.kotlin.codegen.ExpressionCodegen; import org.jetbrains.kotlin.codegen.MemberCodegen; import org.jetbrains.kotlin.codegen.binding.CodegenBinding; import org.jetbrains.kotlin.codegen.context.CodegenContext; @@ -44,6 +46,7 @@ import org.jetbrains.kotlin.psi.KtFile; import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; import org.jetbrains.kotlin.resolve.jvm.AsmTypes; import org.jetbrains.kotlin.resolve.jvm.JvmClassName; +import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.kotlin.util.OperatorNameConventions; import org.jetbrains.org.objectweb.asm.*; import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; @@ -54,6 +57,7 @@ import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; +import java.util.List; import java.util.ListIterator; public class InlineCodegenUtil { @@ -509,4 +513,47 @@ public class InlineCodegenUtil { public static boolean isThis0(@NotNull String name) { return THIS$0.equals(name); } + + public static boolean isSpecialEnumMethod(@NotNull FunctionDescriptor functionDescriptor) { + DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration(); + if (!(containingDeclaration instanceof PackageFragmentDescriptor)) { + return false; + } + if (!containingDeclaration.getName().equals(KotlinBuiltIns.BUILT_INS_PACKAGE_NAME)) { + return false; + } + if (functionDescriptor.getTypeParameters().size() != 1) { + return false; + } + String name = functionDescriptor.getName().asString(); + List parameters = functionDescriptor.getValueParameters(); + return "enumValues".equals(name) && parameters.size() == 0 || + "enumValueOf".equals(name) && parameters.size() == 1 && KotlinBuiltIns.isString(parameters.get(0).getType()); + } + + public static MethodNode createSpecialEnumMethodBody( + @NotNull ExpressionCodegen codegen, + @NotNull String name, + @NotNull KotlinType type, + @NotNull KotlinTypeMapper typeMapper + ) { + boolean isEnumValues = "enumValues".equals(name); + Type invokeType = typeMapper.mapType(type); + String desc = getSpecialEnumFunDescriptor(invokeType, isEnumValues); + + MethodNode node = new MethodNode(API, Opcodes.ACC_STATIC, "fake", desc, null, null); + if (!isEnumValues) { + node.visitVarInsn(Opcodes.ALOAD, 0); + } + codegen.putReifiedOperationMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.OperationKind.ENUM_REIFIED, new InstructionAdapter(node)); + node.visitMethodInsn(Opcodes.INVOKESTATIC, invokeType.getInternalName(), isEnumValues ? "values" : "valueOf", desc, false); + node.visitInsn(Opcodes.ARETURN); + node.visitMaxs(isEnumValues ? 2 : 3, isEnumValues ? 0 : 1); + return node; + } + + public static String getSpecialEnumFunDescriptor(@NotNull Type type, boolean isEnumValues) { + return (isEnumValues ? "()[" : "(Ljava/lang/String;)") + "L" + type.getInternalName() + ";"; + } } + diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt index 7245cb07755..4bf53467b17 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/inline/ReifiedTypeInliner.kt @@ -59,7 +59,7 @@ class ReificationArgument( class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?) { enum class OperationKind { - NEW_ARRAY, AS, SAFE_AS, IS, JAVA_CLASS; + NEW_ARRAY, AS, SAFE_AS, IS, JAVA_CLASS, ENUM_REIFIED; val id: Int get() = ordinal } @@ -139,6 +139,7 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?) OperationKind.SAFE_AS -> processAs(insn, instructions, kotlinType, asmType, safe = true) OperationKind.IS -> processIs(insn, instructions, kotlinType, asmType) OperationKind.JAVA_CLASS -> processJavaClass(insn, asmType) + OperationKind.ENUM_REIFIED -> processSpecialEnumFunction(insn, asmType) }) { instructions.remove(insn.previous.previous!!) // PUSH operation ID instructions.remove(insn.previous!!) // PUSH type parameter @@ -219,6 +220,14 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?) next.cst = parameter return true } + + private fun processSpecialEnumFunction(insn: MethodInsnNode, parameter: Type): Boolean { + val next = insn.next + if (next !is MethodInsnNode) return false + next.owner = parameter.internalName + next.desc = InlineCodegenUtil.getSpecialEnumFunDescriptor(parameter, "values" == next.name) + return true + } } private val MethodInsnNode.reificationArgument: ReificationArgument? diff --git a/compiler/testData/builtin-classes/default/kotlin.txt b/compiler/testData/builtin-classes/default/kotlin.txt index 52dca4cbff2..5ff6b533aca 100644 --- a/compiler/testData/builtin-classes/default/kotlin.txt +++ b/compiler/testData/builtin-classes/default/kotlin.txt @@ -7,6 +7,8 @@ public fun byteArrayOf(/*0*/ vararg elements: kotlin.Byte /*kotlin.ByteArray*/): public fun charArrayOf(/*0*/ vararg elements: kotlin.Char /*kotlin.CharArray*/): kotlin.CharArray public fun doubleArrayOf(/*0*/ vararg elements: kotlin.Double /*kotlin.DoubleArray*/): kotlin.DoubleArray public inline fun emptyArray(): kotlin.Array +public inline fun > enumValueOf(/*0*/ name: kotlin.String): T +public inline fun > enumValues(): kotlin.Array public fun floatArrayOf(/*0*/ vararg elements: kotlin.Float /*kotlin.FloatArray*/): kotlin.FloatArray public fun intArrayOf(/*0*/ vararg elements: kotlin.Int /*kotlin.IntArray*/): kotlin.IntArray public fun longArrayOf(/*0*/ vararg elements: kotlin.Long /*kotlin.LongArray*/): kotlin.LongArray diff --git a/compiler/testData/builtin-classes/java6/kotlin.txt b/compiler/testData/builtin-classes/java6/kotlin.txt index ad41027ce95..eab25fd4a1d 100644 --- a/compiler/testData/builtin-classes/java6/kotlin.txt +++ b/compiler/testData/builtin-classes/java6/kotlin.txt @@ -7,6 +7,8 @@ public fun byteArrayOf(/*0*/ vararg elements: kotlin.Byte /*kotlin.ByteArray*/): public fun charArrayOf(/*0*/ vararg elements: kotlin.Char /*kotlin.CharArray*/): kotlin.CharArray public fun doubleArrayOf(/*0*/ vararg elements: kotlin.Double /*kotlin.DoubleArray*/): kotlin.DoubleArray public inline fun emptyArray(): kotlin.Array +public inline fun > enumValueOf(/*0*/ name: kotlin.String): T +public inline fun > enumValues(): kotlin.Array public fun floatArrayOf(/*0*/ vararg elements: kotlin.Float /*kotlin.FloatArray*/): kotlin.FloatArray public fun intArrayOf(/*0*/ vararg elements: kotlin.Int /*kotlin.IntArray*/): kotlin.IntArray public fun longArrayOf(/*0*/ vararg elements: kotlin.Long /*kotlin.LongArray*/): kotlin.LongArray diff --git a/compiler/testData/builtin-classes/java8/kotlin.txt b/compiler/testData/builtin-classes/java8/kotlin.txt index 47e38fd486e..15f38268f88 100644 --- a/compiler/testData/builtin-classes/java8/kotlin.txt +++ b/compiler/testData/builtin-classes/java8/kotlin.txt @@ -7,6 +7,8 @@ public fun byteArrayOf(/*0*/ vararg elements: kotlin.Byte /*kotlin.ByteArray*/): public fun charArrayOf(/*0*/ vararg elements: kotlin.Char /*kotlin.CharArray*/): kotlin.CharArray public fun doubleArrayOf(/*0*/ vararg elements: kotlin.Double /*kotlin.DoubleArray*/): kotlin.DoubleArray public inline fun emptyArray(): kotlin.Array +public inline fun > enumValueOf(/*0*/ name: kotlin.String): T +public inline fun > enumValues(): kotlin.Array public fun floatArrayOf(/*0*/ vararg elements: kotlin.Float /*kotlin.FloatArray*/): kotlin.FloatArray public fun intArrayOf(/*0*/ vararg elements: kotlin.Int /*kotlin.IntArray*/): kotlin.IntArray public fun longArrayOf(/*0*/ vararg elements: kotlin.Long /*kotlin.LongArray*/): kotlin.LongArray diff --git a/compiler/testData/builtin-classes/newMethods/kotlin.txt b/compiler/testData/builtin-classes/newMethods/kotlin.txt index c4b21cfe85b..1d375089109 100644 --- a/compiler/testData/builtin-classes/newMethods/kotlin.txt +++ b/compiler/testData/builtin-classes/newMethods/kotlin.txt @@ -7,6 +7,8 @@ public fun byteArrayOf(/*0*/ vararg elements: kotlin.Byte /*kotlin.ByteArray*/): public fun charArrayOf(/*0*/ vararg elements: kotlin.Char /*kotlin.CharArray*/): kotlin.CharArray public fun doubleArrayOf(/*0*/ vararg elements: kotlin.Double /*kotlin.DoubleArray*/): kotlin.DoubleArray public inline fun emptyArray(): kotlin.Array +public inline fun > enumValueOf(/*0*/ name: kotlin.String): T +public inline fun > enumValues(): kotlin.Array public fun floatArrayOf(/*0*/ vararg elements: kotlin.Float /*kotlin.FloatArray*/): kotlin.FloatArray public fun intArrayOf(/*0*/ vararg elements: kotlin.Int /*kotlin.IntArray*/): kotlin.IntArray public fun longArrayOf(/*0*/ vararg elements: kotlin.Long /*kotlin.LongArray*/): kotlin.LongArray diff --git a/compiler/testData/codegen/boxInline/enum/kt10569.kt b/compiler/testData/codegen/boxInline/enum/kt10569.kt new file mode 100644 index 00000000000..2ffd30c8ad8 --- /dev/null +++ b/compiler/testData/codegen/boxInline/enum/kt10569.kt @@ -0,0 +1,31 @@ +// FILE: 1.kt +// WITH_RUNTIME +package test + +var result = "" + +inline fun > renderOptions(render: (T) -> String) { + val values = enumValues() + for (v in values) { + result += render(v) + } +} + +enum class Z { + O, K; + + val myParam = name +} + + +// FILE: 2.kt + +import test.* + +fun box(): String { + renderOptions { + it.myParam + } + return result +} + diff --git a/compiler/testData/codegen/boxInline/enum/valueOf.kt b/compiler/testData/codegen/boxInline/enum/valueOf.kt new file mode 100644 index 00000000000..85d4e64100b --- /dev/null +++ b/compiler/testData/codegen/boxInline/enum/valueOf.kt @@ -0,0 +1,20 @@ +// FILE: 1.kt +// WITH_RUNTIME +package test + +inline fun > myValueOf(): String { + return enumValueOf("OK").name +} + +enum class Z { + OK +} + + +// FILE: 2.kt + +import test.* + +fun box(): String { + return myValueOf() +} diff --git a/compiler/testData/codegen/boxInline/enum/valueOfCapturedType.kt b/compiler/testData/codegen/boxInline/enum/valueOfCapturedType.kt new file mode 100644 index 00000000000..c0519a81e3e --- /dev/null +++ b/compiler/testData/codegen/boxInline/enum/valueOfCapturedType.kt @@ -0,0 +1,20 @@ +// FILE: 1.kt +// WITH_RUNTIME +package test + +inline fun > myValueOf(): String { + return { enumValueOf("OK") }().name +} + +enum class Z { + OK +} + + +// FILE: 2.kt + +import test.* + +fun box(): String { + return myValueOf() +} diff --git a/compiler/testData/codegen/boxInline/enum/valueOfChain.kt b/compiler/testData/codegen/boxInline/enum/valueOfChain.kt new file mode 100644 index 00000000000..15d240b28c5 --- /dev/null +++ b/compiler/testData/codegen/boxInline/enum/valueOfChain.kt @@ -0,0 +1,25 @@ +// FILE: 1.kt +// WITH_RUNTIME +package test + +inline fun > myValueOf(): String { + return myValueOf2() +} + +inline fun > myValueOf2(): String { + return enumValueOf("OK").name +} + + +enum class Z { + OK +} + + +// FILE: 2.kt + +import test.* + +fun box(): String { + return myValueOf() +} diff --git a/compiler/testData/codegen/boxInline/enum/valueOfChainCapturedType.kt b/compiler/testData/codegen/boxInline/enum/valueOfChainCapturedType.kt new file mode 100644 index 00000000000..48e1b314d51 --- /dev/null +++ b/compiler/testData/codegen/boxInline/enum/valueOfChainCapturedType.kt @@ -0,0 +1,25 @@ +// FILE: 1.kt +// WITH_RUNTIME +package test + +inline fun > myValueOf(): String { + return myValueOf2() +} + +inline fun > myValueOf2(): String { + return { enumValueOf("OK").name }() +} + + +enum class Z { + OK +} + + +// FILE: 2.kt + +import test.* + +fun box(): String { + return myValueOf() +} diff --git a/compiler/testData/codegen/boxInline/enum/valueOfNonReified.kt b/compiler/testData/codegen/boxInline/enum/valueOfNonReified.kt new file mode 100644 index 00000000000..761813faec2 --- /dev/null +++ b/compiler/testData/codegen/boxInline/enum/valueOfNonReified.kt @@ -0,0 +1,20 @@ +// FILE: 1.kt +// WITH_RUNTIME +package test + +inline fun myValueOf(): String { + return enumValueOf("OK").name +} + +enum class Z { + OK +} + + +// FILE: 2.kt + +import test.* + +fun box(): String { + return myValueOf() +} diff --git a/compiler/testData/codegen/boxInline/enum/values.kt b/compiler/testData/codegen/boxInline/enum/values.kt new file mode 100644 index 00000000000..b0f397f5a1a --- /dev/null +++ b/compiler/testData/codegen/boxInline/enum/values.kt @@ -0,0 +1,21 @@ +// FILE: 1.kt +// WITH_RUNTIME +package test + +inline fun > myValues(): String { + val values = enumValues() + return values.joinToString("") +} + +enum class Z { + O, K +} + + +// FILE: 2.kt + +import test.* + +fun box(): String { + return myValues() +} diff --git a/compiler/testData/codegen/boxInline/enum/valuesAsArray.kt b/compiler/testData/codegen/boxInline/enum/valuesAsArray.kt new file mode 100644 index 00000000000..027b228d6be --- /dev/null +++ b/compiler/testData/codegen/boxInline/enum/valuesAsArray.kt @@ -0,0 +1,26 @@ +// FILE: 1.kt +// WITH_RUNTIME +package test + +inline fun > myValues(): Array { + return enumValues() +} + +enum class Z { + O, K; + + val myParam = name +} + + +// FILE: 2.kt + +import test.* + +fun box(): String { + return test(myValues()) +} + +fun test(myValues: Array): String { + return myValues.map { it.myParam }.joinToString (""); +} diff --git a/compiler/testData/codegen/boxInline/enum/valuesCapturedType.kt b/compiler/testData/codegen/boxInline/enum/valuesCapturedType.kt new file mode 100644 index 00000000000..99ce9e279c1 --- /dev/null +++ b/compiler/testData/codegen/boxInline/enum/valuesCapturedType.kt @@ -0,0 +1,21 @@ +// FILE: 1.kt +// WITH_RUNTIME +package test + +inline fun > myValues(): String { + val values = { enumValues() }() + return values.joinToString("") +} + +enum class Z { + O, K +} + + +// FILE: 2.kt + +import test.* + +fun box(): String { + return myValues() +} diff --git a/compiler/testData/codegen/boxInline/enum/valuesChain.kt b/compiler/testData/codegen/boxInline/enum/valuesChain.kt new file mode 100644 index 00000000000..2207e07e806 --- /dev/null +++ b/compiler/testData/codegen/boxInline/enum/valuesChain.kt @@ -0,0 +1,25 @@ +// FILE: 1.kt +// WITH_RUNTIME +package test + +inline fun > myValues2(): String { + val values = enumValues() + return values.joinToString("") +} + +inline fun > myValues(): String { + return myValues2() +} + +enum class Z { + O, K +} + + +// FILE: 2.kt + +import test.* + +fun box(): String { + return myValues() +} diff --git a/compiler/testData/codegen/boxInline/enum/valuesChainCapturedType.kt b/compiler/testData/codegen/boxInline/enum/valuesChainCapturedType.kt new file mode 100644 index 00000000000..12436f80868 --- /dev/null +++ b/compiler/testData/codegen/boxInline/enum/valuesChainCapturedType.kt @@ -0,0 +1,25 @@ +// FILE: 1.kt +// WITH_RUNTIME +package test + +inline fun > myValues2(): String { + val values = { enumValues() }() + return values.joinToString("") +} + +inline fun > myValues(): String { + return myValues2() +} + +enum class Z { + O, K +} + + +// FILE: 2.kt + +import test.* + +fun box(): String { + return myValues() +} diff --git a/compiler/testData/codegen/boxInline/enum/valuesNonReified.kt b/compiler/testData/codegen/boxInline/enum/valuesNonReified.kt new file mode 100644 index 00000000000..fee857c2c3c --- /dev/null +++ b/compiler/testData/codegen/boxInline/enum/valuesNonReified.kt @@ -0,0 +1,21 @@ +// FILE: 1.kt +// WITH_RUNTIME +package test + +inline fun myValues(): String { + val values = enumValues() + return values.joinToString("") +} + +enum class Z { + O, K +} + + +// FILE: 2.kt + +import test.* + +fun box(): String { + return myValues() +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java index dc70c94557d..22cd70cee1e 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxInlineCodegenTestGenerated.java @@ -941,6 +941,87 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo } } + @TestMetadata("compiler/testData/codegen/boxInline/enum") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Enum extends AbstractBlackBoxInlineCodegenTest { + public void testAllFilesPresentInEnum() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/enum"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("kt10569.kt") + public void testKt10569() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/kt10569.kt"); + doTest(fileName); + } + + @TestMetadata("valueOf.kt") + public void testValueOf() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valueOf.kt"); + doTest(fileName); + } + + @TestMetadata("valueOfCapturedType.kt") + public void testValueOfCapturedType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valueOfCapturedType.kt"); + doTest(fileName); + } + + @TestMetadata("valueOfChain.kt") + public void testValueOfChain() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valueOfChain.kt"); + doTest(fileName); + } + + @TestMetadata("valueOfChainCapturedType.kt") + public void testValueOfChainCapturedType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valueOfChainCapturedType.kt"); + doTest(fileName); + } + + @TestMetadata("valueOfNonReified.kt") + public void testValueOfNonReified() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valueOfNonReified.kt"); + doTest(fileName); + } + + @TestMetadata("values.kt") + public void testValues() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/values.kt"); + doTest(fileName); + } + + @TestMetadata("valuesAsArray.kt") + public void testValuesAsArray() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valuesAsArray.kt"); + doTest(fileName); + } + + @TestMetadata("valuesCapturedType.kt") + public void testValuesCapturedType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valuesCapturedType.kt"); + doTest(fileName); + } + + @TestMetadata("valuesChain.kt") + public void testValuesChain() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valuesChain.kt"); + doTest(fileName); + } + + @TestMetadata("valuesChainCapturedType.kt") + public void testValuesChainCapturedType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valuesChainCapturedType.kt"); + doTest(fileName); + } + + @TestMetadata("valuesNonReified.kt") + public void testValuesNonReified() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valuesNonReified.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/codegen/boxInline/functionExpression") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java index 1dd1f19ad1a..84c9af6cc4e 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/CompileKotlinAgainstInlineKotlinTestGenerated.java @@ -941,6 +941,87 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi } } + @TestMetadata("compiler/testData/codegen/boxInline/enum") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Enum extends AbstractCompileKotlinAgainstInlineKotlinTest { + public void testAllFilesPresentInEnum() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/enum"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("kt10569.kt") + public void testKt10569() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/kt10569.kt"); + doTest(fileName); + } + + @TestMetadata("valueOf.kt") + public void testValueOf() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valueOf.kt"); + doTest(fileName); + } + + @TestMetadata("valueOfCapturedType.kt") + public void testValueOfCapturedType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valueOfCapturedType.kt"); + doTest(fileName); + } + + @TestMetadata("valueOfChain.kt") + public void testValueOfChain() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valueOfChain.kt"); + doTest(fileName); + } + + @TestMetadata("valueOfChainCapturedType.kt") + public void testValueOfChainCapturedType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valueOfChainCapturedType.kt"); + doTest(fileName); + } + + @TestMetadata("valueOfNonReified.kt") + public void testValueOfNonReified() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valueOfNonReified.kt"); + doTest(fileName); + } + + @TestMetadata("values.kt") + public void testValues() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/values.kt"); + doTest(fileName); + } + + @TestMetadata("valuesAsArray.kt") + public void testValuesAsArray() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valuesAsArray.kt"); + doTest(fileName); + } + + @TestMetadata("valuesCapturedType.kt") + public void testValuesCapturedType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valuesCapturedType.kt"); + doTest(fileName); + } + + @TestMetadata("valuesChain.kt") + public void testValuesChain() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valuesChain.kt"); + doTest(fileName); + } + + @TestMetadata("valuesChainCapturedType.kt") + public void testValuesChainCapturedType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valuesChainCapturedType.kt"); + doTest(fileName); + } + + @TestMetadata("valuesNonReified.kt") + public void testValuesNonReified() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/enum/valuesNonReified.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/codegen/boxInline/functionExpression") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/core/builtins/native/kotlin/Library.kt b/core/builtins/native/kotlin/Library.kt index cef523a7b19..cfd8c47a60c 100644 --- a/core/builtins/native/kotlin/Library.kt +++ b/core/builtins/native/kotlin/Library.kt @@ -79,3 +79,13 @@ public fun byteArrayOf(vararg elements: Byte): ByteArray * Returns an array containing the specified boolean values. */ public fun booleanArrayOf(vararg elements: Boolean): BooleanArray + +/** + * Returns an array containing enum T entries. + */ +public inline fun > enumValues(): Array + +/** + * Returns an enum entry with specified name. + */ +public inline fun > enumValueOf(name: String): T \ No newline at end of file diff --git a/idea/idea-completion/testData/smart/inheritors/GenericClass2.kt b/idea/idea-completion/testData/smart/inheritors/GenericClass2.kt index 9608f802d6b..c84b4963942 100644 --- a/idea/idea-completion/testData/smart/inheritors/GenericClass2.kt +++ b/idea/idea-completion/testData/smart/inheritors/GenericClass2.kt @@ -14,4 +14,5 @@ fun bar() { // EXIST: { itemText: "object: C1<...>(){...}" } // EXIST: { itemText: "object: C2(){...}" } // EXIST: { itemText: "object: C3(){...}" } +// EXIST: { itemText: "enumValueOf" } // NOTHING_ELSE diff --git a/idea/idea-completion/testData/smart/inheritors/GenericClass3.kt b/idea/idea-completion/testData/smart/inheritors/GenericClass3.kt index a60379a6999..52036982ef3 100644 --- a/idea/idea-completion/testData/smart/inheritors/GenericClass3.kt +++ b/idea/idea-completion/testData/smart/inheritors/GenericClass3.kt @@ -15,4 +15,5 @@ fun bar() { // EXIST: { itemText: "object: C1<...>(){...}" } // EXIST: { itemText: "object: C2(){...}" } // EXIST: { itemText: "object: C4(){...}" } +// EXIST: { itemText: "enumValueOf" } // NOTHING_ELSE diff --git a/idea/idea-completion/testData/smart/inheritors/GenericClass4.kt b/idea/idea-completion/testData/smart/inheritors/GenericClass4.kt index cbd89805067..3a24b32c87e 100644 --- a/idea/idea-completion/testData/smart/inheritors/GenericClass4.kt +++ b/idea/idea-completion/testData/smart/inheritors/GenericClass4.kt @@ -10,4 +10,5 @@ fun bar() { // EXIST: { itemText: "object: I<...>{...}" } // EXIST: { itemText: "object: C<...>(){...}" } +// EXIST: { itemText: "enumValueOf" } // NOTHING_ELSE diff --git a/idea/idea-completion/testData/smart/inheritors/GenericClass6.kt b/idea/idea-completion/testData/smart/inheritors/GenericClass6.kt index 8e6e9a4ffe3..7fa7aa17423 100644 --- a/idea/idea-completion/testData/smart/inheritors/GenericClass6.kt +++ b/idea/idea-completion/testData/smart/inheritors/GenericClass6.kt @@ -17,4 +17,5 @@ fun bar() { // EXIST: { itemText: "object: I<...>{...}" } // EXIST: { itemText: "object: C1(){...}" } // EXIST: { itemText: "object: C2(){...}" } +// EXIST: { itemText: "enumValueOf" } // NOTHING_ELSE