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:
@@ -4445,6 +4445,12 @@ The "returned" value of try expression with no finally is either the last expres
|
|||||||
|
|
||||||
public void putReifiedOperationMarkerIfTypeIsReifiedParameter(
|
public void putReifiedOperationMarkerIfTypeIsReifiedParameter(
|
||||||
@NotNull KotlinType type, @NotNull ReifiedTypeInliner.OperationKind operationKind
|
@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);
|
Pair<TypeParameterDescriptor, ReificationArgument> typeParameterAndReificationArgument = extractReificationArgument(type);
|
||||||
if (typeParameterAndReificationArgument != null && typeParameterAndReificationArgument.getFirst().isReified()) {
|
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.jvm.jvmSignature.JvmMethodSignature;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
|
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.DoubleColonLHS;
|
||||||
import org.jetbrains.kotlin.types.expressions.LabelResolver;
|
import org.jetbrains.kotlin.types.expressions.LabelResolver;
|
||||||
import org.jetbrains.org.objectweb.asm.Label;
|
import org.jetbrains.org.objectweb.asm.Label;
|
||||||
@@ -171,7 +172,7 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
|
|
||||||
SMAPAndMethodNode nodeAndSmap = null;
|
SMAPAndMethodNode nodeAndSmap = null;
|
||||||
try {
|
try {
|
||||||
nodeAndSmap = createMethodNode(functionDescriptor, jvmSignature, codegen, context, callDefault);
|
nodeAndSmap = createMethodNode(functionDescriptor, jvmSignature, codegen, context, callDefault, resolvedCall);
|
||||||
endCall(inlineCall(nodeAndSmap));
|
endCall(inlineCall(nodeAndSmap));
|
||||||
}
|
}
|
||||||
catch (CompilationException e) {
|
catch (CompilationException e) {
|
||||||
@@ -227,8 +228,24 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
@NotNull JvmMethodSignature jvmSignature,
|
@NotNull JvmMethodSignature jvmSignature,
|
||||||
@NotNull ExpressionCodegen codegen,
|
@NotNull ExpressionCodegen codegen,
|
||||||
@NotNull CodegenContext context,
|
@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 GenerationState state = codegen.getState();
|
||||||
final Method asmMethod =
|
final Method asmMethod =
|
||||||
callDefault
|
callDefault
|
||||||
|
|||||||
+1
-1
@@ -65,7 +65,7 @@ class InlineCodegenForDefaultBody(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun genCallInner(callableMethod: Callable, resolvedCall: ResolvedCall<*>?, callDefault: Boolean, codegen: ExpressionCodegen) {
|
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 childSourceMapper = InlineCodegen.createNestedSourceMapper(nodeAndSmap, sourceMapper)
|
||||||
|
|
||||||
val node = nodeAndSmap.node
|
val node = nodeAndSmap.node
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import kotlin.text.StringsKt;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.backend.common.output.OutputFile;
|
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.MemberCodegen;
|
||||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
||||||
import org.jetbrains.kotlin.codegen.context.CodegenContext;
|
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.DescriptorToSourceUtils;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
|
import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions;
|
import org.jetbrains.kotlin.util.OperatorNameConventions;
|
||||||
import org.jetbrains.org.objectweb.asm.*;
|
import org.jetbrains.org.objectweb.asm.*;
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
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.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
|
import java.util.List;
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
|
||||||
public class InlineCodegenUtil {
|
public class InlineCodegenUtil {
|
||||||
@@ -509,4 +513,47 @@ public class InlineCodegenUtil {
|
|||||||
public static boolean isThis0(@NotNull String name) {
|
public static boolean isThis0(@NotNull String name) {
|
||||||
return THIS$0.equals(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?) {
|
class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?) {
|
||||||
enum class OperationKind {
|
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
|
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.SAFE_AS -> processAs(insn, instructions, kotlinType, asmType, safe = true)
|
||||||
OperationKind.IS -> processIs(insn, instructions, kotlinType, asmType)
|
OperationKind.IS -> processIs(insn, instructions, kotlinType, asmType)
|
||||||
OperationKind.JAVA_CLASS -> processJavaClass(insn, 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.previous!!) // PUSH operation ID
|
||||||
instructions.remove(insn.previous!!) // PUSH type parameter
|
instructions.remove(insn.previous!!) // PUSH type parameter
|
||||||
@@ -219,6 +220,14 @@ class ReifiedTypeInliner(private val parametersMapping: TypeParameterMappings?)
|
|||||||
next.cst = parameter
|
next.cst = parameter
|
||||||
return true
|
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?
|
private val MethodInsnNode.reificationArgument: ReificationArgument?
|
||||||
|
|||||||
@@ -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 charArrayOf(/*0*/ vararg elements: kotlin.Char /*kotlin.CharArray*/): kotlin.CharArray
|
||||||
public fun doubleArrayOf(/*0*/ vararg elements: kotlin.Double /*kotlin.DoubleArray*/): kotlin.DoubleArray
|
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 @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 floatArrayOf(/*0*/ vararg elements: kotlin.Float /*kotlin.FloatArray*/): kotlin.FloatArray
|
||||||
public fun intArrayOf(/*0*/ vararg elements: kotlin.Int /*kotlin.IntArray*/): kotlin.IntArray
|
public fun intArrayOf(/*0*/ vararg elements: kotlin.Int /*kotlin.IntArray*/): kotlin.IntArray
|
||||||
public fun longArrayOf(/*0*/ vararg elements: kotlin.Long /*kotlin.LongArray*/): kotlin.LongArray
|
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 charArrayOf(/*0*/ vararg elements: kotlin.Char /*kotlin.CharArray*/): kotlin.CharArray
|
||||||
public fun doubleArrayOf(/*0*/ vararg elements: kotlin.Double /*kotlin.DoubleArray*/): kotlin.DoubleArray
|
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 @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 floatArrayOf(/*0*/ vararg elements: kotlin.Float /*kotlin.FloatArray*/): kotlin.FloatArray
|
||||||
public fun intArrayOf(/*0*/ vararg elements: kotlin.Int /*kotlin.IntArray*/): kotlin.IntArray
|
public fun intArrayOf(/*0*/ vararg elements: kotlin.Int /*kotlin.IntArray*/): kotlin.IntArray
|
||||||
public fun longArrayOf(/*0*/ vararg elements: kotlin.Long /*kotlin.LongArray*/): kotlin.LongArray
|
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 charArrayOf(/*0*/ vararg elements: kotlin.Char /*kotlin.CharArray*/): kotlin.CharArray
|
||||||
public fun doubleArrayOf(/*0*/ vararg elements: kotlin.Double /*kotlin.DoubleArray*/): kotlin.DoubleArray
|
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 @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 floatArrayOf(/*0*/ vararg elements: kotlin.Float /*kotlin.FloatArray*/): kotlin.FloatArray
|
||||||
public fun intArrayOf(/*0*/ vararg elements: kotlin.Int /*kotlin.IntArray*/): kotlin.IntArray
|
public fun intArrayOf(/*0*/ vararg elements: kotlin.Int /*kotlin.IntArray*/): kotlin.IntArray
|
||||||
public fun longArrayOf(/*0*/ vararg elements: kotlin.Long /*kotlin.LongArray*/): kotlin.LongArray
|
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 charArrayOf(/*0*/ vararg elements: kotlin.Char /*kotlin.CharArray*/): kotlin.CharArray
|
||||||
public fun doubleArrayOf(/*0*/ vararg elements: kotlin.Double /*kotlin.DoubleArray*/): kotlin.DoubleArray
|
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 @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 floatArrayOf(/*0*/ vararg elements: kotlin.Float /*kotlin.FloatArray*/): kotlin.FloatArray
|
||||||
public fun intArrayOf(/*0*/ vararg elements: kotlin.Int /*kotlin.IntArray*/): kotlin.IntArray
|
public fun intArrayOf(/*0*/ vararg elements: kotlin.Int /*kotlin.IntArray*/): kotlin.IntArray
|
||||||
public fun longArrayOf(/*0*/ vararg elements: kotlin.Long /*kotlin.LongArray*/): kotlin.LongArray
|
public fun longArrayOf(/*0*/ vararg elements: kotlin.Long /*kotlin.LongArray*/): kotlin.LongArray
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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()
|
||||||
|
}
|
||||||
@@ -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>()
|
||||||
|
}
|
||||||
@@ -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")
|
@TestMetadata("compiler/testData/codegen/boxInline/functionExpression")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+81
@@ -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")
|
@TestMetadata("compiler/testData/codegen/boxInline/functionExpression")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
@@ -79,3 +79,13 @@ public fun byteArrayOf(vararg elements: Byte): ByteArray
|
|||||||
* Returns an array containing the specified boolean values.
|
* Returns an array containing the specified boolean values.
|
||||||
*/
|
*/
|
||||||
public fun booleanArrayOf(vararg elements: Boolean): BooleanArray
|
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: C1<...>(){...}" }
|
||||||
// EXIST: { itemText: "object: C2(){...}" }
|
// EXIST: { itemText: "object: C2(){...}" }
|
||||||
// EXIST: { itemText: "object: C3(){...}" }
|
// EXIST: { itemText: "object: C3(){...}" }
|
||||||
|
// EXIST: { itemText: "enumValueOf" }
|
||||||
// NOTHING_ELSE
|
// NOTHING_ELSE
|
||||||
|
|||||||
@@ -15,4 +15,5 @@ fun bar() {
|
|||||||
// EXIST: { itemText: "object: C1<...>(){...}" }
|
// EXIST: { itemText: "object: C1<...>(){...}" }
|
||||||
// EXIST: { itemText: "object: C2(){...}" }
|
// EXIST: { itemText: "object: C2(){...}" }
|
||||||
// EXIST: { itemText: "object: C4<String>(){...}" }
|
// EXIST: { itemText: "object: C4<String>(){...}" }
|
||||||
|
// EXIST: { itemText: "enumValueOf" }
|
||||||
// NOTHING_ELSE
|
// NOTHING_ELSE
|
||||||
|
|||||||
@@ -10,4 +10,5 @@ fun bar() {
|
|||||||
|
|
||||||
// EXIST: { itemText: "object: I<...>{...}" }
|
// EXIST: { itemText: "object: I<...>{...}" }
|
||||||
// EXIST: { itemText: "object: C<...>(){...}" }
|
// EXIST: { itemText: "object: C<...>(){...}" }
|
||||||
|
// EXIST: { itemText: "enumValueOf" }
|
||||||
// NOTHING_ELSE
|
// NOTHING_ELSE
|
||||||
|
|||||||
@@ -17,4 +17,5 @@ fun bar() {
|
|||||||
// EXIST: { itemText: "object: I<...>{...}" }
|
// EXIST: { itemText: "object: I<...>{...}" }
|
||||||
// EXIST: { itemText: "object: C1<X>(){...}" }
|
// EXIST: { itemText: "object: C1<X>(){...}" }
|
||||||
// EXIST: { itemText: "object: C2(){...}" }
|
// EXIST: { itemText: "object: C2(){...}" }
|
||||||
|
// EXIST: { itemText: "enumValueOf" }
|
||||||
// NOTHING_ELSE
|
// NOTHING_ELSE
|
||||||
|
|||||||
Reference in New Issue
Block a user