Support coroutines stack-unwinding in JVM backend
#KT-14924 In Progress
This commit is contained in:
@@ -2810,7 +2810,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
|
|
||||||
if (CoroutineCodegenUtilKt.isSuspensionPoint(resolvedCall, bindingContext)) {
|
if (CoroutineCodegenUtilKt.isSuspensionPoint(resolvedCall, bindingContext)) {
|
||||||
// Suspension points should behave like they leave actual values on stack, while real methods return VOID
|
// Suspension points should behave like they leave actual values on stack, while real methods return VOID
|
||||||
return new OperationStackValue(getSuspensionReturnTypeByResolvedCall(resolvedCall), ((OperationStackValue) result).getLambda());
|
return new OperationStackValue(getSuspensionBoxedReturnTypeByResolvedCall(resolvedCall), ((OperationStackValue) result).getLambda());
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -2925,7 +2925,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isSuspensionPoint) {
|
if (isSuspensionPoint) {
|
||||||
v.tconst(getSuspensionReturnTypeByResolvedCall(resolvedCall));
|
v.tconst(getSuspensionBoxedReturnTypeByResolvedCall(resolvedCall));
|
||||||
v.invokestatic(
|
v.invokestatic(
|
||||||
CoroutineCodegenUtilKt.COROUTINE_MARKER_OWNER,
|
CoroutineCodegenUtilKt.COROUTINE_MARKER_OWNER,
|
||||||
CoroutineCodegenUtilKt.BEFORE_SUSPENSION_POINT_MARKER_NAME,
|
CoroutineCodegenUtilKt.BEFORE_SUSPENSION_POINT_MARKER_NAME,
|
||||||
@@ -2935,7 +2935,6 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
callGenerator.genCall(callableMethod, resolvedCall, defaultMaskWasGenerated, this);
|
callGenerator.genCall(callableMethod, resolvedCall, defaultMaskWasGenerated, this);
|
||||||
|
|
||||||
if (isSuspensionPoint) {
|
if (isSuspensionPoint) {
|
||||||
AsmUtil.pushDefaultValueOnStack(getSuspensionReturnTypeByResolvedCall(resolvedCall), v);
|
|
||||||
v.invokestatic(
|
v.invokestatic(
|
||||||
CoroutineCodegenUtilKt.COROUTINE_MARKER_OWNER,
|
CoroutineCodegenUtilKt.COROUTINE_MARKER_OWNER,
|
||||||
CoroutineCodegenUtilKt.AFTER_SUSPENSION_POINT_MARKER_NAME, "()V", false);
|
CoroutineCodegenUtilKt.AFTER_SUSPENSION_POINT_MARKER_NAME, "()V", false);
|
||||||
@@ -2950,7 +2949,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private Type getSuspensionReturnTypeByResolvedCall(@NotNull ResolvedCall<?> resolvedCall) {
|
private Type getSuspensionBoxedReturnTypeByResolvedCall(@NotNull ResolvedCall<?> resolvedCall) {
|
||||||
assert resolvedCall.getResultingDescriptor() instanceof SimpleFunctionDescriptor
|
assert resolvedCall.getResultingDescriptor() instanceof SimpleFunctionDescriptor
|
||||||
: "Suspension point resolved call should be built on SimpleFunctionDescriptor";
|
: "Suspension point resolved call should be built on SimpleFunctionDescriptor";
|
||||||
|
|
||||||
@@ -2963,7 +2962,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
|||||||
KotlinType returnType = initialSignature.getReturnType();
|
KotlinType returnType = initialSignature.getReturnType();
|
||||||
|
|
||||||
assert returnType != null : "Return type of suspension point should not be null";
|
assert returnType != null : "Return type of suspension point should not be null";
|
||||||
return typeMapper.mapType(returnType);
|
return typeMapper.mapType(TypeUtils.makeNullable(returnType));
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
+35
-19
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue
|
|||||||
import org.jetbrains.kotlin.codegen.optimization.common.analyzeLiveness
|
import org.jetbrains.kotlin.codegen.optimization.common.analyzeLiveness
|
||||||
import org.jetbrains.kotlin.codegen.optimization.common.insnListOf
|
import org.jetbrains.kotlin.codegen.optimization.common.insnListOf
|
||||||
import org.jetbrains.kotlin.codegen.optimization.common.removeEmptyCatchBlocks
|
import org.jetbrains.kotlin.codegen.optimization.common.removeEmptyCatchBlocks
|
||||||
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.utils.sure
|
import org.jetbrains.kotlin.utils.sure
|
||||||
@@ -95,8 +96,10 @@ class CoroutineTransformerMethodVisitor(
|
|||||||
|
|
||||||
spillVariables(suspensionPoints, methodNode)
|
spillVariables(suspensionPoints, methodNode)
|
||||||
|
|
||||||
|
val suspendMarkerVarIndex = methodNode.maxLocals++
|
||||||
|
|
||||||
val suspensionPointLabels = suspensionPoints.withIndex().map {
|
val suspensionPointLabels = suspensionPoints.withIndex().map {
|
||||||
transformCallAndReturnContinuationLabel(it.index + 1, it.value, methodNode)
|
transformCallAndReturnContinuationLabel(it.index + 1, it.value, methodNode, suspendMarkerVarIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
methodNode.instructions.apply {
|
methodNode.instructions.apply {
|
||||||
@@ -116,6 +119,13 @@ class CoroutineTransformerMethodVisitor(
|
|||||||
// tableswitch(this.label)
|
// tableswitch(this.label)
|
||||||
insertBefore(firstToInsertBefore,
|
insertBefore(firstToInsertBefore,
|
||||||
insnListOf(
|
insnListOf(
|
||||||
|
FieldInsnNode(
|
||||||
|
Opcodes.GETSTATIC,
|
||||||
|
AsmTypes.COROUTINES_SUSPEND.internalName,
|
||||||
|
JvmAbi.INSTANCE_FIELD,
|
||||||
|
AsmTypes.COROUTINES_SUSPEND.descriptor
|
||||||
|
),
|
||||||
|
VarInsnNode(Opcodes.ASTORE, suspendMarkerVarIndex),
|
||||||
VarInsnNode(Opcodes.ALOAD, 0),
|
VarInsnNode(Opcodes.ALOAD, 0),
|
||||||
FieldInsnNode(
|
FieldInsnNode(
|
||||||
Opcodes.GETFIELD,
|
Opcodes.GETFIELD,
|
||||||
@@ -178,20 +188,16 @@ class CoroutineTransformerMethodVisitor(
|
|||||||
methodNode.instructions.remove(beforeSuspensionPointMarker.previous)
|
methodNode.instructions.remove(beforeSuspensionPointMarker.previous)
|
||||||
beforeSuspensionPointMarker.desc = "()V"
|
beforeSuspensionPointMarker.desc = "()V"
|
||||||
|
|
||||||
if (suspensionPoint.returnType != Type.VOID_TYPE) {
|
assert(suspensionPoint.returnType != Type.VOID_TYPE) { "Suspension point can't be VOID" }
|
||||||
val previous = suspensionPoint.suspensionCallEnd.previous
|
|
||||||
assert(previous.opcode in DEFAULT_VALUE_OPCODES) {
|
|
||||||
"Expected on of default value bytecodes, but ${previous.opcode} was found"
|
|
||||||
}
|
|
||||||
fakeReturnValueInsns.add(previous)
|
|
||||||
|
|
||||||
if (previous.opcode == Opcodes.ACONST_NULL) {
|
// Checkcast only is needed to tell analyzer what type exactly should be returned from suspension point
|
||||||
// Checkcast is needed to tell analyzer what type exactly should be returned from suspension point
|
// This type is used when for restoring spilled variables into fields
|
||||||
val checkCast = TypeInsnNode(Opcodes.CHECKCAST, suspensionPoint.returnType.internalName)
|
val checkCast = TypeInsnNode(Opcodes.CHECKCAST, suspensionPoint.returnType.internalName)
|
||||||
methodNode.instructions.insert(previous, checkCast)
|
methodNode.instructions.insertBefore(
|
||||||
fakeReturnValueInsns.add(checkCast)
|
suspensionPoint.suspensionCallEnd, checkCast
|
||||||
}
|
)
|
||||||
}
|
|
||||||
|
fakeReturnValueInsns.add(checkCast)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -317,8 +323,14 @@ class CoroutineTransformerMethodVisitor(
|
|||||||
return suspensionCallEnd.next as LabelNode
|
return suspensionCallEnd.next as LabelNode
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun transformCallAndReturnContinuationLabel(id: Int, suspension: SuspensionPoint, methodNode: MethodNode): LabelNode {
|
private fun transformCallAndReturnContinuationLabel(
|
||||||
|
id: Int,
|
||||||
|
suspension: SuspensionPoint,
|
||||||
|
methodNode: MethodNode,
|
||||||
|
suspendMarkerVarIndex: Int
|
||||||
|
): LabelNode {
|
||||||
val continuationLabel = LabelNode()
|
val continuationLabel = LabelNode()
|
||||||
|
val continuationLabelAfterLoadedResult = LabelNode()
|
||||||
with(methodNode.instructions) {
|
with(methodNode.instructions) {
|
||||||
// Save state
|
// Save state
|
||||||
insertBefore(suspension.suspensionCallBegin,
|
insertBefore(suspension.suspensionCallBegin,
|
||||||
@@ -336,6 +348,10 @@ class CoroutineTransformerMethodVisitor(
|
|||||||
suspension.fakeReturnValueInsns.forEach { methodNode.instructions.remove(it) }
|
suspension.fakeReturnValueInsns.forEach { methodNode.instructions.remove(it) }
|
||||||
|
|
||||||
insert(suspension.tryCatchBlockEndLabelAfterSuspensionCall, withInstructionAdapter {
|
insert(suspension.tryCatchBlockEndLabelAfterSuspensionCall, withInstructionAdapter {
|
||||||
|
dup()
|
||||||
|
load(suspendMarkerVarIndex, AsmTypes.COROUTINES_SUSPEND)
|
||||||
|
ifacmpne(continuationLabelAfterLoadedResult.label)
|
||||||
|
|
||||||
// Exit
|
// Exit
|
||||||
areturn(Type.VOID_TYPE)
|
areturn(Type.VOID_TYPE)
|
||||||
// Mark place for continuation
|
// Mark place for continuation
|
||||||
@@ -358,6 +374,8 @@ class CoroutineTransformerMethodVisitor(
|
|||||||
|
|
||||||
// Load continuation argument just like suspending function returns it
|
// Load continuation argument just like suspending function returns it
|
||||||
load(1, AsmTypes.OBJECT_TYPE)
|
load(1, AsmTypes.OBJECT_TYPE)
|
||||||
|
|
||||||
|
visitLabel(continuationLabelAfterLoadedResult.label)
|
||||||
StackValue.coerce(AsmTypes.OBJECT_TYPE, suspension.returnType, this)
|
StackValue.coerce(AsmTypes.OBJECT_TYPE, suspension.returnType, this)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -371,8 +389,7 @@ class CoroutineTransformerMethodVisitor(
|
|||||||
// How suspension point area will look like after all transformations:
|
// How suspension point area will look like after all transformations:
|
||||||
// <spill variables>
|
// <spill variables>
|
||||||
// INVOKESTATIC beforeSuspensionMarker
|
// INVOKESTATIC beforeSuspensionMarker
|
||||||
// INVOKEVIRTUAL suspensionMethod()V
|
// INVOKEVIRTUAL suspensionMethod()Ljava/lang/Object;
|
||||||
// ACONST_NULL -- default value
|
|
||||||
// CHECKCAST SomeType
|
// CHECKCAST SomeType
|
||||||
// INVOKESTATIC afterSuspensionMarker
|
// INVOKESTATIC afterSuspensionMarker
|
||||||
// L1: -- end of all TCB's that are containing the suspension point (inserted by this method)
|
// L1: -- end of all TCB's that are containing the suspension point (inserted by this method)
|
||||||
@@ -480,8 +497,7 @@ private fun Type.normalize() =
|
|||||||
/**
|
/**
|
||||||
* Suspension call may consists of several instructions:
|
* Suspension call may consists of several instructions:
|
||||||
* INVOKESTATIC beforeSuspensionMarker
|
* INVOKESTATIC beforeSuspensionMarker
|
||||||
* INVOKEVIRTUAL suspensionMethod()V // actually it could be some inline method instead of plain call
|
* INVOKEVIRTUAL suspensionMethod()Ljava/lang/Object; // actually it could be some inline method instead of plain call
|
||||||
* ACONST_NULL // It's only needed when the suspension point returns something beside VOID
|
|
||||||
* CHECKCAST Type
|
* CHECKCAST Type
|
||||||
* INVOKESTATIC afterSuspensionMarker
|
* INVOKESTATIC afterSuspensionMarker
|
||||||
*/
|
*/
|
||||||
|
|||||||
+3
-4
@@ -189,7 +189,7 @@ fun ResolvedCall<*>.isSuspensionPoint(bindingContext: BindingContext) =
|
|||||||
bindingContext[BindingContext.COROUTINE_RECEIVER_FOR_SUSPENSION_POINT, call] != null
|
bindingContext[BindingContext.COROUTINE_RECEIVER_FOR_SUSPENSION_POINT, call] != null
|
||||||
|
|
||||||
// Suspend functions have irregular signatures on JVM, containing an additional last parameter with type `Continuation<return-type>`,
|
// Suspend functions have irregular signatures on JVM, containing an additional last parameter with type `Continuation<return-type>`,
|
||||||
// and return type Unit (later it will be replaced with 'Any?')
|
// and return type Any?
|
||||||
// This function returns a function descriptor reflecting how the suspend function looks from point of view of JVM
|
// This function returns a function descriptor reflecting how the suspend function looks from point of view of JVM
|
||||||
fun <D : FunctionDescriptor> createJvmSuspendFunctionView(function: D): D {
|
fun <D : FunctionDescriptor> createJvmSuspendFunctionView(function: D): D {
|
||||||
val continuationParameter = ValueParameterDescriptorImpl(
|
val continuationParameter = ValueParameterDescriptorImpl(
|
||||||
@@ -201,7 +201,7 @@ fun <D : FunctionDescriptor> createJvmSuspendFunctionView(function: D): D {
|
|||||||
|
|
||||||
return function.createCustomCopy {
|
return function.createCustomCopy {
|
||||||
setPreserveSourceElement()
|
setPreserveSourceElement()
|
||||||
setReturnType(function.builtIns.unitType)
|
setReturnType(function.builtIns.nullableAnyType)
|
||||||
setValueParameters(it.valueParameters + continuationParameter)
|
setValueParameters(it.valueParameters + continuationParameter)
|
||||||
putUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION, it)
|
putUserData(INITIAL_DESCRIPTOR_FOR_SUSPEND_FUNCTION, it)
|
||||||
}
|
}
|
||||||
@@ -288,8 +288,7 @@ fun createMethodNodeForSuspendWithCurrentContinuation(
|
|||||||
"(${AsmTypes.OBJECT_TYPE})${AsmTypes.OBJECT_TYPE}",
|
"(${AsmTypes.OBJECT_TYPE})${AsmTypes.OBJECT_TYPE}",
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
node.visitInsn(Opcodes.POP)
|
node.visitInsn(Opcodes.ARETURN)
|
||||||
node.visitInsn(Opcodes.RETURN)
|
|
||||||
node.visitMaxs(2, 2)
|
node.visitMaxs(2, 2)
|
||||||
|
|
||||||
return node
|
return node
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ public class AsmTypes {
|
|||||||
public static final Type MUTABLE_PROPERTY_REFERENCE1 = Type.getObjectType("kotlin/jvm/internal/MutablePropertyReference1");
|
public static final Type MUTABLE_PROPERTY_REFERENCE1 = Type.getObjectType("kotlin/jvm/internal/MutablePropertyReference1");
|
||||||
public static final Type MUTABLE_PROPERTY_REFERENCE2 = Type.getObjectType("kotlin/jvm/internal/MutablePropertyReference2");
|
public static final Type MUTABLE_PROPERTY_REFERENCE2 = Type.getObjectType("kotlin/jvm/internal/MutablePropertyReference2");
|
||||||
public static final Type COROUTINE_IMPL = Type.getObjectType("kotlin/jvm/internal/CoroutineImpl");
|
public static final Type COROUTINE_IMPL = Type.getObjectType("kotlin/jvm/internal/CoroutineImpl");
|
||||||
|
public static final Type COROUTINES_SUSPEND = Type.getObjectType("kotlin/coroutines/Suspend");
|
||||||
|
|
||||||
|
|
||||||
public static final Type[] PROPERTY_REFERENCE_IMPL = {
|
public static final Type[] PROPERTY_REFERENCE_IMPL = {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ class Controller {
|
|||||||
exception = t
|
exception = t
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun suspendHere(): Any = suspendWithCurrentContinuation { x ->}
|
suspend fun suspendHere(): Any = suspendWithCurrentContinuation { x -> }
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ class Controller {
|
|||||||
|
|
||||||
suspend fun <T> await(t: T): T = suspendWithCurrentContinuation { c ->
|
suspend fun <T> await(t: T): T = suspendWithCurrentContinuation { c ->
|
||||||
c.resume(t)
|
c.resume(t)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ class Controller {
|
|||||||
|
|
||||||
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
|
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
|
||||||
c.resume(value)
|
c.resume(value)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ class Controller {
|
|||||||
|
|
||||||
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
|
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
|
||||||
c.resume(value)
|
c.resume(value)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ class Controller {
|
|||||||
|
|
||||||
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
|
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
|
||||||
c.resume(value)
|
c.resume(value)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ class Controller {
|
|||||||
|
|
||||||
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
|
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
|
||||||
c.resume(value)
|
c.resume(value)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ class Controller {
|
|||||||
|
|
||||||
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
|
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
|
||||||
c.resume(value)
|
c.resume(value)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ class Controller {
|
|||||||
|
|
||||||
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
|
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
|
||||||
c.resume(value)
|
c.resume(value)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ class Controller {
|
|||||||
suspend fun <T> suspendAndLog(value: T): T = suspendWithCurrentContinuation { c ->
|
suspend fun <T> suspendAndLog(value: T): T = suspendWithCurrentContinuation { c ->
|
||||||
result += "suspend($value);"
|
result += "suspend($value);"
|
||||||
c.resume(value)
|
c.resume(value)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun handleResult(value: String, c: Continuation<Nothing>) {
|
operator fun handleResult(value: String, c: Continuation<Nothing>) {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ class Controller {
|
|||||||
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
|
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
|
||||||
result += "["
|
result += "["
|
||||||
c.resume(value)
|
c.resume(value)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,11 +8,13 @@ class Controller {
|
|||||||
suspend fun <T> suspendAndLog(value: T): T = suspendWithCurrentContinuation { c ->
|
suspend fun <T> suspendAndLog(value: T): T = suspendWithCurrentContinuation { c ->
|
||||||
result += "suspend($value);"
|
result += "suspend($value);"
|
||||||
c.resume(value)
|
c.resume(value)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun suspendLogAndThrow(exception: Throwable): Nothing = suspendWithCurrentContinuation { c ->
|
suspend fun suspendLogAndThrow(exception: Throwable): Nothing = suspendWithCurrentContinuation { c ->
|
||||||
result += "throw(${exception.message});"
|
result += "throw(${exception.message});"
|
||||||
c.resumeWithException(exception)
|
c.resumeWithException(exception)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun handleException(exception: Throwable, c: Continuation<Nothing>) {
|
operator fun handleException(exception: Throwable, c: Continuation<Nothing>) {
|
||||||
|
|||||||
+1
@@ -8,6 +8,7 @@ class Controller {
|
|||||||
suspend fun <T> suspendAndLog(value: T): T = suspendWithCurrentContinuation { c ->
|
suspend fun <T> suspendAndLog(value: T): T = suspendWithCurrentContinuation { c ->
|
||||||
result += "suspend($value);"
|
result += "suspend($value);"
|
||||||
c.resume(value)
|
c.resume(value)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun handleException(exception: Throwable, c: Continuation<Nothing>) {
|
operator fun handleException(exception: Throwable, c: Continuation<Nothing>) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ class Controller {
|
|||||||
|
|
||||||
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
|
suspend fun <T> suspendWithResult(value: T): T = suspendWithCurrentContinuation { c ->
|
||||||
c.resume(value)
|
c.resume(value)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ class Controller {
|
|||||||
var result = false
|
var result = false
|
||||||
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
fun foo() {
|
fun foo() {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(a: String = "abc", i: Int = 2): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(a: String = "abc", i: Int = 2): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(a + "#" + (i + 1))
|
x.resume(a + "#" + (i + 1))
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ class Controller {
|
|||||||
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
result++
|
result++
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun <T> suspendHere(v: T): T = suspendWithCurrentContinuation { x ->
|
suspend fun <T> suspendHere(v: T): T = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ class GeneratorController<T>() : AbstractIterator<T>() {
|
|||||||
suspend fun yield(value: T): Unit = suspendWithCurrentContinuation { c ->
|
suspend fun yield(value: T): Unit = suspendWithCurrentContinuation { c ->
|
||||||
setNext(value)
|
setNext(value)
|
||||||
setNextStep(c)
|
setNextStep(c)
|
||||||
|
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun handleResult(result: Unit, c: Continuation<Nothing>) {
|
operator fun handleResult(result: Unit, c: Continuation<Nothing>) {
|
||||||
|
|||||||
@@ -8,12 +8,16 @@ class Controller {
|
|||||||
postponedActions.add {
|
postponedActions.add {
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x ->
|
||||||
postponedActions.add {
|
postponedActions.add {
|
||||||
x.resumeWithException(e)
|
x.resumeWithException(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun handleException(t: Throwable, c: Continuation<Nothing>) {
|
operator fun handleException(t: Throwable, c: Continuation<Nothing>) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ class Controller {
|
|||||||
var isCompleted = false
|
var isCompleted = false
|
||||||
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun handleResult(x: Unit, y: Continuation<Nothing>) {
|
operator fun handleResult(x: Unit, y: Continuation<Nothing>) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ class Controller {
|
|||||||
suspend fun <T> suspendAndLog(value: T): T = suspendWithCurrentContinuation { x ->
|
suspend fun <T> suspendAndLog(value: T): T = suspendWithCurrentContinuation { x ->
|
||||||
log += "suspend($value);"
|
log += "suspend($value);"
|
||||||
x.resume(value)
|
x.resume(value)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun handleResult(value: String, y: Continuation<Nothing>) {
|
operator fun handleResult(value: String, y: Continuation<Nothing>) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ class Controller {
|
|||||||
|
|
||||||
suspend inline fun suspendInline(v: String): String = suspendWithCurrentContinuation { x ->
|
suspend inline fun suspendInline(v: String): String = suspendWithCurrentContinuation { x ->
|
||||||
withValue(v, x)
|
withValue(v, x)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend inline fun suspendInline(crossinline b: () -> String): String = suspendInline(b())
|
suspend inline fun suspendInline(crossinline b: () -> String): String = suspendInline(b())
|
||||||
|
|||||||
@@ -9,12 +9,16 @@ class Controller {
|
|||||||
postponedActions.add {
|
postponedActions.add {
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x ->
|
||||||
postponedActions.add {
|
postponedActions.add {
|
||||||
x.resumeWithException(e)
|
x.resumeWithException(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun handleResult(x: String, c: Continuation<Nothing>) {
|
operator fun handleResult(x: String, c: Continuation<Nothing>) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ class Controller {
|
|||||||
var i = 0
|
var i = 0
|
||||||
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume((i++).toString())
|
x.resume((i++).toString())
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
@@ -6,11 +6,13 @@ class Controller {
|
|||||||
suspend fun runInstanceOf(): Boolean = suspendWithCurrentContinuation { x ->
|
suspend fun runInstanceOf(): Boolean = suspendWithCurrentContinuation { x ->
|
||||||
val y: Any = x
|
val y: Any = x
|
||||||
x.resume(x is Continuation<*>)
|
x.resume(x is Continuation<*>)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun runCast(): Boolean = suspendWithCurrentContinuation { x ->
|
suspend fun runCast(): Boolean = suspendWithCurrentContinuation { x ->
|
||||||
val y: Any = x
|
val y: Any = x
|
||||||
x.resume(Continuation::class.isInstance(y as Continuation<*>))
|
x.resume(Continuation::class.isInstance(y as Continuation<*>))
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
+1
@@ -4,6 +4,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): Unit = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ class Controller {
|
|||||||
var result = "fail"
|
var result = "fail"
|
||||||
suspend fun <V> suspendHere(v: V): V = suspendWithCurrentContinuation { x ->
|
suspend fun <V> suspendHere(v: V): V = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun handleResult(x: String, c: Continuation<Nothing>) {
|
operator fun handleResult(x: String, c: Continuation<Nothing>) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(v: String): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(v: String): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ class Controller {
|
|||||||
suspend fun suspendHere(v: String): Unit = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(v: String): Unit = suspendWithCurrentContinuation { x ->
|
||||||
result += v
|
result += v
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun handleResult(u: Unit, v: Continuation<Nothing>) {
|
operator fun handleResult(u: Unit, v: Continuation<Nothing>) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ class Controller {
|
|||||||
var wasHandleResultCalled = false
|
var wasHandleResultCalled = false
|
||||||
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun handleResult(x: Unit, y: Continuation<Nothing>) {
|
operator fun handleResult(x: Unit, y: Continuation<Nothing>) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ class Controller {
|
|||||||
var wasHandleResultCalled = false
|
var wasHandleResultCalled = false
|
||||||
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun handleResult(x: Unit, y: Continuation<Nothing>) {
|
operator fun handleResult(x: Unit, y: Continuation<Nothing>) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ class Controller {
|
|||||||
suspend fun suspendHere(v: String): Unit = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(v: String): Unit = suspendWithCurrentContinuation { x ->
|
||||||
this.v = v
|
this.v = v
|
||||||
x.resume(Unit)
|
x.resume(Unit)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun handleResult(u: Unit, v: Continuation<Nothing>) {
|
operator fun handleResult(u: Unit, v: Continuation<Nothing>) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package lib
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ package lib
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun String.suspendHere(): String = suspendWithCurrentContinuation { x ->
|
suspend fun String.suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(this)
|
x.resume(this)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
inline suspend fun String.inlineSuspendHere(): String = suspendHere()
|
inline suspend fun String.inlineSuspendHere(): String = suspendHere()
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ class Controller {
|
|||||||
var result = "fail"
|
var result = "fail"
|
||||||
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
lastSuspension = x
|
lastSuspension = x
|
||||||
Unit
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hasNext() = lastSuspension != null
|
fun hasNext() = lastSuspension != null
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ class Controller {
|
|||||||
var result = "fail"
|
var result = "fail"
|
||||||
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
lastSuspension = x
|
lastSuspension = x
|
||||||
Unit
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hasNext() = lastSuspension != null
|
fun hasNext() = lastSuspension != null
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ class Controller {
|
|||||||
var result = "fail"
|
var result = "fail"
|
||||||
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
lastSuspension = x
|
lastSuspension = x
|
||||||
Unit
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hasNext() = lastSuspension != null
|
fun hasNext() = lastSuspension != null
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ class Controller {
|
|||||||
var result = "fail"
|
var result = "fail"
|
||||||
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
lastSuspension = x
|
lastSuspension = x
|
||||||
Unit
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hasNext() = lastSuspension != null
|
fun hasNext() = lastSuspension != null
|
||||||
|
|||||||
@@ -9,12 +9,16 @@ class Controller {
|
|||||||
postponedActions.add {
|
postponedActions.add {
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x ->
|
||||||
postponedActions.add {
|
postponedActions.add {
|
||||||
x.resumeWithException(e)
|
x.resumeWithException(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun handleResult(x: String, c: Continuation<Nothing>) {
|
operator fun handleResult(x: String, c: Continuation<Nothing>) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ class Controller {
|
|||||||
var cResult = 0
|
var cResult = 0
|
||||||
suspend fun suspendHere(v: Int): Int = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(v: Int): Int = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(v * 2)
|
x.resume(v * 2)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun handleResult(x: Int, y: Continuation<Nothing>) {
|
operator fun handleResult(x: Int, y: Continuation<Nothing>) {
|
||||||
|
|||||||
+1
@@ -5,6 +5,7 @@ class Controller {
|
|||||||
var cResult = 0
|
var cResult = 0
|
||||||
suspend fun suspendHere(v: Int): Int = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(v: Int): Int = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(v * 2)
|
x.resume(v * 2)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun handleResult(x: Int, y: Continuation<Nothing>) {
|
operator fun handleResult(x: Int, y: Continuation<Nothing>) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ class Controller {
|
|||||||
var res = 0
|
var res = 0
|
||||||
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun handleResult(x: Int, y: Continuation<Nothing>) {
|
operator fun handleResult(x: Int, y: Continuation<Nothing>) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resumeWithException(RuntimeException("OK"))
|
x.resumeWithException(RuntimeException("OK"))
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ class Controller {
|
|||||||
var res = 0
|
var res = 0
|
||||||
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun handleResult(x: Int, y: Continuation<Nothing>) {
|
operator fun handleResult(x: Int, y: Continuation<Nothing>) {
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
class Controller {
|
||||||
|
suspend fun suspendHere(): String = throw RuntimeException("OK")
|
||||||
|
|
||||||
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
}
|
||||||
|
|
||||||
|
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
|
||||||
|
c(Controller()).resume(Unit)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var result = ""
|
||||||
|
|
||||||
|
builder {
|
||||||
|
result = try { suspendHere() } catch (e: RuntimeException) { e.message!! }
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
// WITH_REFLECT
|
||||||
|
// CHECK_NOT_CALLED: suspendInline_die06n$
|
||||||
|
// CHECK_NOT_CALLED: suspendInline_nesahw$
|
||||||
|
// CHECK_NOT_CALLED: suspendInline_grpnnl$
|
||||||
|
class Controller {
|
||||||
|
suspend inline fun suspendInline(v: String): String = v
|
||||||
|
|
||||||
|
suspend inline fun suspendInline(crossinline b: () -> String): String = suspendInline(b())
|
||||||
|
|
||||||
|
suspend inline fun <reified T : Any> suspendInline(): String = suspendInline({ T::class.simpleName!! })
|
||||||
|
|
||||||
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
}
|
||||||
|
|
||||||
|
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
|
||||||
|
c(Controller()).resume(Unit)
|
||||||
|
}
|
||||||
|
|
||||||
|
class OK
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var result = ""
|
||||||
|
|
||||||
|
builder {
|
||||||
|
result = suspendInline("56")
|
||||||
|
if (result != "56") throw RuntimeException("fail 1")
|
||||||
|
|
||||||
|
result = suspendInline { "57" }
|
||||||
|
if (result != "57") throw RuntimeException("fail 2")
|
||||||
|
|
||||||
|
result = suspendInline<OK>()
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
class Controller {
|
||||||
|
suspend fun suspendHere() = "OK"
|
||||||
|
|
||||||
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
}
|
||||||
|
|
||||||
|
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
|
||||||
|
c(Controller()).resume(Unit)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var result = ""
|
||||||
|
|
||||||
|
builder {
|
||||||
|
result = suspendHere()
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
// IGNORE_BACKEND: JS
|
||||||
|
class Controller {
|
||||||
|
suspend fun suspendHere(): Int = suspendWithCurrentContinuation { x ->
|
||||||
|
1
|
||||||
|
}
|
||||||
|
suspend fun suspendThere(): String = suspendWithCurrentContinuation { x ->
|
||||||
|
"?"
|
||||||
|
}
|
||||||
|
|
||||||
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
}
|
||||||
|
|
||||||
|
fun builder(coroutine c: Controller.() -> Continuation<Unit>) {
|
||||||
|
c(Controller()).resume(Unit)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
var result = ""
|
||||||
|
|
||||||
|
builder {
|
||||||
|
result += "-"
|
||||||
|
for (i in 0..10000) {
|
||||||
|
if (i % 2 == 0) {
|
||||||
|
result += suspendHere().toString()
|
||||||
|
}
|
||||||
|
else if (i == 3) {
|
||||||
|
result += suspendThere()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result += "+"
|
||||||
|
}
|
||||||
|
|
||||||
|
var mustBe = "-"
|
||||||
|
for (i in 0..10000) {
|
||||||
|
if (i % 2 == 0) {
|
||||||
|
mustBe += "1"
|
||||||
|
}
|
||||||
|
else if (i == 3) {
|
||||||
|
mustBe += "?"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mustBe += "+"
|
||||||
|
|
||||||
|
if (result != mustBe) return "fail: $result/$mustBe"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ var globalResult = ""
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendWithValue(v: String): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendWithValue(v: String): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun handleResult(x: String, c: Continuation<Nothing>) {
|
operator fun handleResult(x: String, c: Continuation<Nothing>) {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ class Controller {
|
|||||||
|
|
||||||
suspend fun suspendThere(): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendThere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun String.suspendHere(): String = suspendWithCurrentContinuation { x ->
|
suspend fun String.suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(this)
|
x.resume(this)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
inline suspend fun String.inlineSuspendHere(): String = suspendHere()
|
inline suspend fun String.inlineSuspendHere(): String = suspendHere()
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(v: Int): Int = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(v: Int): Int = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(v * 2)
|
x.resume(v * 2)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
@@ -3,9 +3,11 @@ class Controller {
|
|||||||
var i = 0
|
var i = 0
|
||||||
suspend fun suspendHere(): Int = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): Int = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(i++)
|
x.resume(i++)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
suspend fun suspendThere(): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendThere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("?")
|
x.resume("?")
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
+3
@@ -2,14 +2,17 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("K")
|
x.resume("K")
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun suspendWithArgument(v: String): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendWithArgument(v: String): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun suspendWithDouble(v: Double): Double = suspendWithCurrentContinuation { x ->
|
suspend fun suspendWithDouble(v: Double): Double = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
@@ -9,12 +9,16 @@ class Controller {
|
|||||||
postponedActions.add {
|
postponedActions.add {
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x ->
|
||||||
postponedActions.add {
|
postponedActions.add {
|
||||||
x.resumeWithException(e)
|
x.resumeWithException(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun handleResult(x: String, c: Continuation<Nothing>) {
|
operator fun handleResult(x: String, c: Continuation<Nothing>) {
|
||||||
|
|||||||
@@ -9,12 +9,16 @@ class Controller {
|
|||||||
postponedActions.add {
|
postponedActions.add {
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x ->
|
||||||
postponedActions.add {
|
postponedActions.add {
|
||||||
x.resumeWithException(e)
|
x.resumeWithException(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun handleResult(x: String, c: Continuation<Nothing>) {
|
operator fun handleResult(x: String, c: Continuation<Nothing>) {
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(v: String): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(v: String): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
|
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
@@ -9,12 +9,16 @@ class Controller {
|
|||||||
postponedActions.add {
|
postponedActions.add {
|
||||||
x.resume(v)
|
x.resume(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendWithException(e: Exception): String = suspendWithCurrentContinuation { x ->
|
||||||
postponedActions.add {
|
postponedActions.add {
|
||||||
x.resumeWithException(e)
|
x.resumeWithException(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun handleResult(x: String, c: Continuation<Nothing>) {
|
operator fun handleResult(x: String, c: Continuation<Nothing>) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
+1
@@ -2,6 +2,7 @@
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
suspend fun suspendHere(): String = suspendWithCurrentContinuation { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
// INTERCEPT_RESUME_PLACEHOLDER
|
// INTERCEPT_RESUME_PLACEHOLDER
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
@kotlin.Metadata
|
@kotlin.Metadata
|
||||||
public final class Controller {
|
public final class Controller {
|
||||||
public method <init>(): void
|
public method <init>(): void
|
||||||
public final method suspendHere(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): void
|
public final @org.jetbrains.annotations.Nullable method suspendHere(@org.jetbrains.annotations.NotNull p0: kotlin.coroutines.Continuation): java.lang.Object
|
||||||
}
|
}
|
||||||
|
|
||||||
@kotlin.Metadata
|
@kotlin.Metadata
|
||||||
|
|||||||
@@ -19,4 +19,5 @@ fun box(): String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 1 GETSTATIC kotlin/Unit.INSTANCE : Lkotlin/Unit;
|
// 1 GETSTATIC kotlin/Unit.INSTANCE : Lkotlin/Unit;
|
||||||
// 1 GETSTATIC
|
// 1 GETSTATIC kotlin/coroutines/Suspend.INSTANCE
|
||||||
|
// 2 GETSTATIC
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ class FutureController<T> {
|
|||||||
else
|
else
|
||||||
machine.resumeWithException(throwable)
|
machine.resumeWithException(throwable)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun handleResult(value: T, c: Continuation<Nothing>) {
|
operator fun handleResult(value: T, c: Continuation<Nothing>) {
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ class FutureController<T> {
|
|||||||
else
|
else
|
||||||
machine.resumeWithException(throwable)
|
machine.resumeWithException(throwable)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun handleResult(value: T, c: Continuation<Nothing>) {
|
operator fun handleResult(value: T, c: Continuation<Nothing>) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package a
|
|||||||
class Controller {
|
class Controller {
|
||||||
suspend fun suspendHere() = suspendWithCurrentContinuation<String> { x ->
|
suspend fun suspendHere() = suspendWithCurrentContinuation<String> { x ->
|
||||||
x.resume("OK")
|
x.resume("OK")
|
||||||
|
Suspend
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+33
@@ -4945,6 +4945,39 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class StackUnwinding extends AbstractIrBlackBoxCodegenTest {
|
||||||
|
public void testAllFilesPresentInStackUnwinding() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/stackUnwinding"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("exception.kt")
|
||||||
|
public void testException() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/exception.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inlineSuspendFunction.kt")
|
||||||
|
public void testInlineSuspendFunction() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/inlineSuspendFunction.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simple.kt")
|
||||||
|
public void testSimple() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/simple.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("suspendInCycle.kt")
|
||||||
|
public void testSuspendInCycle() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/suspendInCycle.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/dataClasses")
|
@TestMetadata("compiler/testData/codegen/box/dataClasses")
|
||||||
|
|||||||
+33
@@ -423,4 +423,37 @@ public class AdditionalCoroutineBlackBoxCodegenTestGenerated extends AbstractAdd
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class StackUnwinding extends AbstractAdditionalCoroutineBlackBoxCodegenTest {
|
||||||
|
public void testAllFilesPresentInStackUnwinding() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/stackUnwinding"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("exception.kt")
|
||||||
|
public void testException() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/exception.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inlineSuspendFunction.kt")
|
||||||
|
public void testInlineSuspendFunction() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/inlineSuspendFunction.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simple.kt")
|
||||||
|
public void testSimple() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/simple.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("suspendInCycle.kt")
|
||||||
|
public void testSuspendInCycle() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/suspendInCycle.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4945,6 +4945,39 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class StackUnwinding extends AbstractBlackBoxCodegenTest {
|
||||||
|
public void testAllFilesPresentInStackUnwinding() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/stackUnwinding"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("exception.kt")
|
||||||
|
public void testException() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/exception.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inlineSuspendFunction.kt")
|
||||||
|
public void testInlineSuspendFunction() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/inlineSuspendFunction.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simple.kt")
|
||||||
|
public void testSimple() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/simple.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("suspendInCycle.kt")
|
||||||
|
public void testSuspendInCycle() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/suspendInCycle.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/dataClasses")
|
@TestMetadata("compiler/testData/codegen/box/dataClasses")
|
||||||
|
|||||||
+39
@@ -6152,6 +6152,45 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
|
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class StackUnwinding extends AbstractJsCodegenBoxTest {
|
||||||
|
public void testAllFilesPresentInStackUnwinding() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/coroutines/stackUnwinding"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("exception.kt")
|
||||||
|
public void testException() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/exception.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inlineSuspendFunction.kt")
|
||||||
|
public void testInlineSuspendFunction() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/inlineSuspendFunction.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simple.kt")
|
||||||
|
public void testSimple() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/simple.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("suspendInCycle.kt")
|
||||||
|
public void testSuspendInCycle() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/stackUnwinding/suspendInCycle.kt");
|
||||||
|
try {
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
catch (Throwable ignore) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive for that.");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/dataClasses")
|
@TestMetadata("compiler/testData/codegen/box/dataClasses")
|
||||||
|
|||||||
Reference in New Issue
Block a user