Special enum function support; Fix for KT-10569: Cannot iterate over values of an enum class when it is used as a generic parameter

#KT-10569 Fixed
This commit is contained in:
Michael Bogdanov
2016-11-02 12:32:47 +03:00
parent 6a3597fa0f
commit fd6d4c352c
28 changed files with 547 additions and 4 deletions
@@ -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<TypeParameterDescriptor, ReificationArgument> typeParameterAndReificationArgument = extractReificationArgument(type);
if (typeParameterAndReificationArgument != null && typeParameterAndReificationArgument.getFirst().isReified()) {
@@ -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<TypeParameterDescriptor, KotlinType> 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
@@ -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
@@ -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<ValueParameterDescriptor> 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() + ";";
}
}
@@ -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?
+2
View File
@@ -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 </*0*/ reified @kotlin.internal.PureReifiable T> emptyArray(): kotlin.Array<T>
public inline fun </*0*/ reified T : kotlin.Enum<T>> enumValueOf(/*0*/ name: kotlin.String): T
public inline fun </*0*/ reified T : kotlin.Enum<T>> enumValues(): kotlin.Array<T>
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
+2
View File
@@ -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 </*0*/ reified @kotlin.internal.PureReifiable T> emptyArray(): kotlin.Array<T>
public inline fun </*0*/ reified T : kotlin.Enum<T>> enumValueOf(/*0*/ name: kotlin.String): T
public inline fun </*0*/ reified T : kotlin.Enum<T>> enumValues(): kotlin.Array<T>
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
+2
View File
@@ -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 </*0*/ reified @kotlin.internal.PureReifiable T> emptyArray(): kotlin.Array<T>
public inline fun </*0*/ reified T : kotlin.Enum<T>> enumValueOf(/*0*/ name: kotlin.String): T
public inline fun </*0*/ reified T : kotlin.Enum<T>> enumValues(): kotlin.Array<T>
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
@@ -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 </*0*/ reified @kotlin.internal.PureReifiable T> emptyArray(): kotlin.Array<T>
public inline fun </*0*/ reified T : kotlin.Enum<T>> enumValueOf(/*0*/ name: kotlin.String): T
public inline fun </*0*/ reified T : kotlin.Enum<T>> enumValues(): kotlin.Array<T>
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
+31
View File
@@ -0,0 +1,31 @@
// FILE: 1.kt
// WITH_RUNTIME
package test
var result = ""
inline fun <reified T : Enum<T>> renderOptions(render: (T) -> String) {
val values = enumValues<T>()
for (v in values) {
result += render(v)
}
}
enum class Z {
O, K;
val myParam = name
}
// FILE: 2.kt
import test.*
fun box(): String {
renderOptions<Z> {
it.myParam
}
return result
}
+20
View File
@@ -0,0 +1,20 @@
// FILE: 1.kt
// WITH_RUNTIME
package test
inline fun <reified T : Enum<T>> myValueOf(): String {
return enumValueOf<T>("OK").name
}
enum class Z {
OK
}
// FILE: 2.kt
import test.*
fun box(): String {
return myValueOf<Z>()
}
@@ -0,0 +1,20 @@
// FILE: 1.kt
// WITH_RUNTIME
package test
inline fun <reified T : Enum<T>> myValueOf(): String {
return { enumValueOf<T>("OK") }().name
}
enum class Z {
OK
}
// FILE: 2.kt
import test.*
fun box(): String {
return myValueOf<Z>()
}
@@ -0,0 +1,25 @@
// FILE: 1.kt
// WITH_RUNTIME
package test
inline fun <reified T : Enum<T>> myValueOf(): String {
return myValueOf2<T>()
}
inline fun <reified Y : Enum<Y>> myValueOf2(): String {
return enumValueOf<Y>("OK").name
}
enum class Z {
OK
}
// FILE: 2.kt
import test.*
fun box(): String {
return myValueOf<Z>()
}
@@ -0,0 +1,25 @@
// FILE: 1.kt
// WITH_RUNTIME
package test
inline fun <reified T : Enum<T>> myValueOf(): String {
return myValueOf2<T>()
}
inline fun <reified Y : Enum<Y>> myValueOf2(): String {
return { enumValueOf<Y>("OK").name }()
}
enum class Z {
OK
}
// FILE: 2.kt
import test.*
fun box(): String {
return myValueOf<Z>()
}
@@ -0,0 +1,20 @@
// FILE: 1.kt
// WITH_RUNTIME
package test
inline fun myValueOf(): String {
return enumValueOf<Z>("OK").name
}
enum class Z {
OK
}
// FILE: 2.kt
import test.*
fun box(): String {
return myValueOf()
}
+21
View File
@@ -0,0 +1,21 @@
// FILE: 1.kt
// WITH_RUNTIME
package test
inline fun <reified T : Enum<T>> myValues(): String {
val values = enumValues<T>()
return values.joinToString("")
}
enum class Z {
O, K
}
// FILE: 2.kt
import test.*
fun box(): String {
return myValues<Z>()
}
@@ -0,0 +1,26 @@
// FILE: 1.kt
// WITH_RUNTIME
package test
inline fun <reified T : Enum<T>> myValues(): Array<T> {
return enumValues<T>()
}
enum class Z {
O, K;
val myParam = name
}
// FILE: 2.kt
import test.*
fun box(): String {
return test(myValues<Z>())
}
fun test(myValues: Array<Z>): String {
return myValues.map { it.myParam }.joinToString ("");
}
@@ -0,0 +1,21 @@
// FILE: 1.kt
// WITH_RUNTIME
package test
inline fun <reified T : Enum<T>> myValues(): String {
val values = { enumValues<T>() }()
return values.joinToString("")
}
enum class Z {
O, K
}
// FILE: 2.kt
import test.*
fun box(): String {
return myValues<Z>()
}
+25
View File
@@ -0,0 +1,25 @@
// FILE: 1.kt
// WITH_RUNTIME
package test
inline fun <reified Y : Enum<Y>> myValues2(): String {
val values = enumValues<Y>()
return values.joinToString("")
}
inline fun <reified T : Enum<T>> myValues(): String {
return myValues2<T>()
}
enum class Z {
O, K
}
// FILE: 2.kt
import test.*
fun box(): String {
return myValues<Z>()
}
@@ -0,0 +1,25 @@
// FILE: 1.kt
// WITH_RUNTIME
package test
inline fun <reified Y : Enum<Y>> myValues2(): String {
val values = { enumValues<Y>() }()
return values.joinToString("")
}
inline fun <reified T : Enum<T>> myValues(): String {
return myValues2<T>()
}
enum class Z {
O, K
}
// FILE: 2.kt
import test.*
fun box(): String {
return myValues<Z>()
}
@@ -0,0 +1,21 @@
// FILE: 1.kt
// WITH_RUNTIME
package test
inline fun myValues(): String {
val values = enumValues<Z>()
return values.joinToString("")
}
enum class Z {
O, K
}
// FILE: 2.kt
import test.*
fun box(): String {
return myValues()
}
@@ -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)
@@ -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)
+10
View File
@@ -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 <reified T : Enum<T>> enumValues(): Array<T>
/**
* Returns an enum entry with specified name.
*/
public inline fun <reified T : Enum<T>> enumValueOf(name: String): T
@@ -14,4 +14,5 @@ fun bar() {
// EXIST: { itemText: "object: C1<...>(){...}" }
// EXIST: { itemText: "object: C2(){...}" }
// EXIST: { itemText: "object: C3(){...}" }
// EXIST: { itemText: "enumValueOf" }
// NOTHING_ELSE
@@ -15,4 +15,5 @@ fun bar() {
// EXIST: { itemText: "object: C1<...>(){...}" }
// EXIST: { itemText: "object: C2(){...}" }
// EXIST: { itemText: "object: C4<String>(){...}" }
// EXIST: { itemText: "enumValueOf" }
// NOTHING_ELSE
@@ -10,4 +10,5 @@ fun bar() {
// EXIST: { itemText: "object: I<...>{...}" }
// EXIST: { itemText: "object: C<...>(){...}" }
// EXIST: { itemText: "enumValueOf" }
// NOTHING_ELSE
@@ -17,4 +17,5 @@ fun bar() {
// EXIST: { itemText: "object: I<...>{...}" }
// EXIST: { itemText: "object: C1<X>(){...}" }
// EXIST: { itemText: "object: C2(){...}" }
// EXIST: { itemText: "enumValueOf" }
// NOTHING_ELSE