Debugger: Support coroutineContext for suspend functions without suspend calls (KT-24829)

This commit is contained in:
Yan Zhulanow
2019-04-19 23:45:12 +03:00
parent b5f5149fc0
commit 35c63db9bc
5 changed files with 36 additions and 2 deletions
@@ -333,7 +333,9 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, val sourcePosition: Sour
return method.name().endsWith("\$default") && DEFAULT_METHOD_MARKERS.any { desc.contains("I${it.descriptor})") }
}
if (parameter in compiledData.crossingBounds) {
if (parameter.kind == CodeFragmentParameter.Kind.COROUTINE_CONTEXT) {
evaluationException("'coroutineContext' is not available")
} else if (parameter in compiledData.crossingBounds) {
evaluationException("'$name' is not captured")
} else if (parameter.kind == CodeFragmentParameter.Kind.FIELD_VAR) {
evaluationException("Cannot find the backing field '${parameter.name}'")
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.AsmUtil.getCapturedFieldName
import org.jetbrains.kotlin.codegen.AsmUtil.getLabeledThisName
import org.jetbrains.kotlin.codegen.coroutines.CONTINUATION_VARIABLE_NAME
import org.jetbrains.kotlin.codegen.coroutines.SUSPEND_FUNCTION_CONTINUATION_PARAMETER
import org.jetbrains.kotlin.codegen.inline.INLINE_FUN_VAR_SUFFIX
import org.jetbrains.kotlin.codegen.inline.INLINE_TRANSFORMATION_SUFFIX
import org.jetbrains.kotlin.idea.core.util.mergeAttachments
@@ -370,7 +371,10 @@ class VariableFinder(val context: ExecutionContext) {
return null
}
val continuationVariable = frameProxy.safeVisibleVariableByName(CONTINUATION_VARIABLE_NAME) ?: return null
val continuationVariable = frameProxy.safeVisibleVariableByName(CONTINUATION_VARIABLE_NAME)
?: frameProxy.safeVisibleVariableByName(SUSPEND_FUNCTION_CONTINUATION_PARAMETER)
?: return null
val continuation = frameProxy.getValue(continuationVariable) as? ObjectReference ?: return null
return findCoroutineContextForContinuation(continuation)
}
@@ -0,0 +1,15 @@
package coroutineContextWithoutSuspend
import kotlin.coroutines.coroutineContext
suspend fun main() {
foo()
}
private suspend fun foo() {
//Breakpoint!
val a = 5
}
// EXPRESSION: coroutineContext
// RESULT: instance of kotlin.coroutines.EmptyCoroutineContext(id=ID): Lkotlin/coroutines/EmptyCoroutineContext;
@@ -0,0 +1,8 @@
LineBreakpoint created at coroutineContextWithoutSuspend.kt:11
Run Java
Connected to the target VM
coroutineContextWithoutSuspend.kt:11
Compile bytecode for coroutineContext
Disconnected from the target VM
Process finished with exit code 0
@@ -700,6 +700,11 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/coroutineContextLambda.kt");
}
@TestMetadata("coroutineContextWithoutSuspend.kt")
public void testCoroutineContextWithoutSuspend() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/coroutineContextWithoutSuspend.kt");
}
@TestMetadata("defaultImplsMangling.kt")
public void testDefaultImplsMangling() throws Exception {
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/frame/defaultImplsMangling.kt");