JS: add support of interceptResume function in coroutine controller
This commit is contained in:
committed by
Alexey Andreev
parent
9eff193ea4
commit
060f08a8dd
+6
@@ -18,9 +18,12 @@ package org.jetbrains.kotlin.backend.common
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
val SUSPEND_WITH_CURRENT_CONTINUATION_NAME = Name.identifier("suspendWithCurrentContinuation")
|
||||
|
||||
@@ -30,4 +33,7 @@ fun FunctionDescriptor.getBuiltInSuspendWithCurrentContinuation() =
|
||||
?.getContributedFunctions(SUSPEND_WITH_CURRENT_CONTINUATION_NAME, NoLookupLocation.FROM_BACKEND)
|
||||
?.singleOrNull()
|
||||
|
||||
fun KotlinType.findInterceptResume() = findOperatorInController(this, OperatorNameConventions.COROUTINE_INTERCEPT_RESUME)
|
||||
|
||||
fun findOperatorInController(controllerType: KotlinType, name: Name): SimpleFunctionDescriptor? =
|
||||
controllerType.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND).singleOrNull { it.isOperator }
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.coroutines
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.findOperatorInController
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
import org.jetbrains.kotlin.codegen.context.ClosureContext
|
||||
|
||||
+2
-8
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
@@ -240,14 +239,9 @@ private fun FunctionDescriptor.getContinuationParameterTypeOfSuspendFunction() =
|
||||
|
||||
val KotlinBuiltIns.continuationClassDescriptor get() = getBuiltInClassByFqName(DescriptorUtils.CONTINUATION_INTERFACE_FQ_NAME)
|
||||
|
||||
fun KotlinType.hasInlineInterceptResume() =
|
||||
findOperatorInController(this, OperatorNameConventions.COROUTINE_INTERCEPT_RESUME)?.isInline == true
|
||||
fun KotlinType.hasInlineInterceptResume() = findInterceptResume()?.isInline == true
|
||||
|
||||
fun KotlinType.hasNoinlineInterceptResume() =
|
||||
findOperatorInController(this, OperatorNameConventions.COROUTINE_INTERCEPT_RESUME)?.isInline == false
|
||||
|
||||
fun findOperatorInController(controllerType: KotlinType, name: Name): SimpleFunctionDescriptor? =
|
||||
controllerType.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND).singleOrNull { it.isOperator }
|
||||
fun KotlinType.hasNoinlineInterceptResume() = findInterceptResume()?.isInline == false
|
||||
|
||||
fun FunctionDescriptor.isBuiltInSuspendWithCurrentContinuation(): Boolean {
|
||||
if (name != SUSPEND_WITH_CURRENT_CONTINUATION_NAME) return false
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
// NO_INTERCEPT_RESUME_TESTS
|
||||
|
||||
class Controller {
|
||||
var log = ""
|
||||
var resumeIndex = 0
|
||||
|
||||
suspend fun <T> suspendWithValue(value: T): T = suspendWithCurrentContinuation { continuation ->
|
||||
log += "suspend($value);"
|
||||
continuation.resume(value)
|
||||
Suspend
|
||||
}
|
||||
|
||||
suspend fun suspendWithException(value: String): Unit = suspendWithCurrentContinuation { continuation ->
|
||||
log += "error($value);"
|
||||
continuation.resumeWithException(RuntimeException(value))
|
||||
Suspend
|
||||
}
|
||||
|
||||
operator fun interceptResume(block: () -> Unit) {
|
||||
var id = resumeIndex++
|
||||
log += "before $id;"
|
||||
block()
|
||||
log += "after $id;"
|
||||
}
|
||||
}
|
||||
|
||||
fun test(coroutine c: Controller.() -> Continuation<Unit>): String {
|
||||
val controller = Controller()
|
||||
c(controller).resume(Unit)
|
||||
return controller.log
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var result = test {
|
||||
val o = suspendWithValue("O")
|
||||
val k = suspendWithValue("K")
|
||||
log += "$o$k;"
|
||||
}
|
||||
if (result != "before 0;suspend(O);before 1;suspend(K);before 2;OK;after 2;after 1;after 0;") return "fail1: $result"
|
||||
|
||||
result = test {
|
||||
try {
|
||||
suspendWithException("OK")
|
||||
log += "ignore;"
|
||||
}
|
||||
catch (e: RuntimeException) {
|
||||
log += "${e.message};"
|
||||
}
|
||||
}
|
||||
if (result != "before 0;error(OK);before 1;OK;after 1;after 0;") return "fail2: $result"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+6
@@ -4595,6 +4595,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("interceptResume.kt")
|
||||
public void testInterceptResume() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/interceptResume.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("iterateOverArray.kt")
|
||||
public void testIterateOverArray() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/iterateOverArray.kt");
|
||||
|
||||
@@ -4595,6 +4595,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("interceptResume.kt")
|
||||
public void testInterceptResume() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/interceptResume.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("iterateOverArray.kt")
|
||||
public void testIterateOverArray() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/coroutines/iterateOverArray.kt");
|
||||
|
||||
Reference in New Issue
Block a user