diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/CoroutineAsyncStackTraceProvider.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/CoroutineAsyncStackTraceProvider.kt index 6ccdceecb2c..99f9795779e 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/CoroutineAsyncStackTraceProvider.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/CoroutineAsyncStackTraceProvider.kt @@ -41,9 +41,15 @@ class CoroutineAsyncStackTraceProvider : AsyncStackTraceProvider { ) ) { val doubleFrameList = CoroutineFrameBuilder.build(preflightFrame, suspendContext) - return doubleFrameList.stackTrace + doubleFrameList.creationStackTrace + val resultList = doubleFrameList.stackTrace + doubleFrameList.creationStackTrace + return PreflightProvider(preflightFrame, resultList) } return null } } +class PreflightProvider(private val preflight: CoroutinePreflightStackFrame, stackFrames: List) : + List by stackFrames { + fun getPreflight() = + preflight +} \ No newline at end of file diff --git a/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/AbstractContinuationStackTraceTest.kt b/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/AbstractContinuationStackTraceTest.kt index 6096a5ad39a..f9ab288d338 100644 --- a/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/AbstractContinuationStackTraceTest.kt +++ b/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/AbstractContinuationStackTraceTest.kt @@ -25,34 +25,6 @@ import java.io.StringWriter abstract class AbstractContinuationStackTraceTest : KotlinDescriptorTestCaseWithStackFrames() { override fun doMultiFileTest(files: TestFiles, preferences: DebuggerPreferences) { - val asyncStackTraceProvider = getAsyncStackTraceProvider() - - doWhenXSessionPausedThenResume { - printContext(debugProcess.debuggerContext) - val suspendContext = debuggerSession.xDebugSession?.getSuspendContext() - var executionStack = suspendContext?.getActiveExecutionStack() - if (executionStack != null) { - try { - out("Thread stack trace:") - val stackFrames: List = XDebuggerTestUtil.collectFrames(executionStack) - for (frame in stackFrames) { - if (frame is JavaStackFrame) { - out(frame) - asyncStackTraceProvider?.getAsyncStackTrace(frame, suspendContext as SuspendContextImpl)?.let { - for (frameItem in it) - out(frameItem) - return@doWhenXSessionPausedThenResume - } - } - } - } catch (e: Throwable) { - val stackTrace = e.stackTraceAsString() - System.err.println("Exception occurred on calculating async stack traces: $stackTrace") - throw e - } - } else { - println("FrameProxy is 'null', can't calculate async stack trace", ProcessOutputTypes.SYSTEM) - } - } + printStackFrame(files, preferences) } } diff --git a/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/AbstractXCoroutinesStackTraceTest.kt b/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/AbstractXCoroutinesStackTraceTest.kt index 7f930080a73..d7011602bb2 100644 --- a/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/AbstractXCoroutinesStackTraceTest.kt +++ b/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/AbstractXCoroutinesStackTraceTest.kt @@ -9,39 +9,12 @@ import com.intellij.debugger.engine.JavaStackFrame import com.intellij.debugger.engine.SuspendContextImpl import com.intellij.execution.process.ProcessOutputTypes import com.intellij.xdebugger.frame.XStackFrame +import org.jetbrains.kotlin.idea.debugger.coroutine.PreflightProvider import org.jetbrains.kotlin.idea.debugger.test.preference.DebuggerPreferences import org.jetbrains.kotlin.idea.debugger.test.util.XDebuggerTestUtil abstract class AbstractXCoroutinesStackTraceTest : KotlinDescriptorTestCaseWithStackFrames() { override fun doMultiFileTest(files: TestFiles, preferences: DebuggerPreferences) { - val asyncStackTraceProvider = getAsyncStackTraceProvider() - - doWhenXSessionPausedThenResume { - printContext(debugProcess.debuggerContext) - val suspendContext = debuggerSession.xDebugSession?.getSuspendContext() - var executionStack = suspendContext?.getActiveExecutionStack() - if (executionStack != null) { - try { - out("Thread stack trace:") - val stackFrames: List = XDebuggerTestUtil.collectFrames(executionStack) - for (frame in stackFrames) { - if (frame is JavaStackFrame) { - out(frame) - asyncStackTraceProvider?.getAsyncStackTrace(frame, suspendContext as SuspendContextImpl)?.let { - for (frameItem in it) - out(frameItem) - return@doWhenXSessionPausedThenResume - } - } - } - } catch (e: Throwable) { - val stackTrace = e.stackTraceAsString() - System.err.println("Exception occurred on calculating async stack traces: $stackTrace") - throw e - } - } else { - println("FrameProxy is 'null', can't calculate async stack trace", ProcessOutputTypes.SYSTEM) - } - } + printStackFrame(files, preferences) } } diff --git a/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/KotlinDescriptorTestCaseWithStackFrames.kt b/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/KotlinDescriptorTestCaseWithStackFrames.kt index e399e850599..a737575fd19 100644 --- a/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/KotlinDescriptorTestCaseWithStackFrames.kt +++ b/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/KotlinDescriptorTestCaseWithStackFrames.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.idea.debugger.test import com.intellij.debugger.engine.AsyncStackTraceProvider import com.intellij.debugger.engine.JavaStackFrame +import com.intellij.debugger.engine.SuspendContextImpl import com.intellij.debugger.memory.utils.StackFrameItem import com.intellij.execution.configurations.JavaParameters import com.intellij.execution.process.ProcessOutputTypes @@ -22,9 +23,11 @@ import com.intellij.xdebugger.frame.XStackFrame import org.jetbrains.idea.maven.aether.ArtifactKind import org.jetbrains.jps.model.library.JpsMavenRepositoryLibraryDescriptor import org.jetbrains.kotlin.idea.debugger.coroutine.CoroutineAsyncStackTraceProvider +import org.jetbrains.kotlin.idea.debugger.coroutine.PreflightProvider import org.jetbrains.kotlin.idea.debugger.coroutine.data.CreationCoroutineStackFrameItem import org.jetbrains.kotlin.idea.debugger.coroutine.util.format import org.jetbrains.kotlin.idea.debugger.invokeInManagerThread +import org.jetbrains.kotlin.idea.debugger.test.preference.DebuggerPreferences import org.jetbrains.kotlin.idea.debugger.test.util.XDebuggerTestUtil import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil import org.jetbrains.kotlin.test.testFramework.runWriteAction @@ -78,6 +81,44 @@ abstract class KotlinDescriptorTestCaseWithStackFrames() : KotlinDescriptorTestC return writer.toString() } + fun printStackFrame(files: TestFiles, preferences: DebuggerPreferences) { + val asyncStackTraceProvider = getAsyncStackTraceProvider() + + doWhenXSessionPausedThenResume { + printContext(debugProcess.debuggerContext) + val suspendContext = debuggerSession.xDebugSession?.getSuspendContext() + var executionStack = suspendContext?.getActiveExecutionStack() + if (executionStack != null) { + try { + out("Thread stack trace:") + val stackFrames: List = XDebuggerTestUtil.collectFrames(executionStack) + for (frame in stackFrames) { + if (frame is JavaStackFrame) { + out(frame) + val stackFrames = asyncStackTraceProvider?.getAsyncStackTrace(frame, suspendContext as SuspendContextImpl) + if (stackFrames != null) { + if (stackFrames is PreflightProvider) { + val preflightFrame = stackFrames.getPreflight() + out(0, preflightFrame.coroutineInfoData.key.toString()) + } + for (frameItem in stackFrames) + out(frameItem) + return@doWhenXSessionPausedThenResume + } + } + } + } catch (e: Throwable) { + val stackTrace = e.stackTraceAsString() + System.err.println("Exception occurred on calculating async stack traces: $stackTrace") + throw e + } + } else { + println("FrameProxy is 'null', can't calculate async stack trace", ProcessOutputTypes.SYSTEM) + } + } + } + + protected fun getAsyncStackTraceProvider(): CoroutineAsyncStackTraceProvider? { val area = Extensions.getArea(null) if (!area.hasExtensionPoint(ASYNC_STACKTRACE_EP_NAME)) { diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFun.kt b/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFun.kt index 00bd1928d30..a42ae359594 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFun.kt +++ b/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFun.kt @@ -13,18 +13,17 @@ fun main() { suspend fun test1(i: Int): Int { val test1 = "a" a(test1) - println(test1) return i } suspend fun a(aParam: String) { val a = "a" b(a) - println(a) + a + 1 } suspend fun b(bParam: String) { val b = "b" - // Breakpoint! - println(b) + //Breakpoint! + b + 1 } \ No newline at end of file diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFun.out b/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFun.out new file mode 100644 index 00000000000..7e2c80d3686 --- /dev/null +++ b/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFun.out @@ -0,0 +1,29 @@ +LineBreakpoint created at suspendFun.kt:28 +Run Java +Connected to the target VM +suspendFun.kt:28 +Thread stack trace: + b:28, SuspendFunKt (coroutine1) + ($completion, b, bParam) + a:21, SuspendFunKt (coroutine1) + ($completion, $continuation, $result, a, aParam) + test1:15, SuspendFunKt (coroutine1) + ($completion, $continuation, $result, i, test1) + invoke:9, SuspendFunKt$main$result$1 (coroutine1) + (continuation, p1, this) + invoke:-1, SuspendFunKt$main$result$1 (coroutine1) + (this) + invokeSuspend:121, IntrinsicsKt__IntrinsicsJvmKt$createCoroutineUnintercepted$$inlined$createCoroutineFromSuspendFunction$IntrinsicsKt__IntrinsicsJvmKt$3 (kotlin.coroutines.intrinsics) + ($i$a$-createCoroutineFromSuspendFunction-IntrinsicsKt__IntrinsicsJvmKt$createCoroutineUnintercepted$2, it, result, this) + resumeWith:33, BaseContinuationImpl (kotlin.coroutines.jvm.internal) + ($i$a$-with-BaseContinuationImpl$resumeWith$1, $this$with, completion, current, param, result, this) + startCoroutine:128, ContinuationKt (kotlin.coroutines) + ($this$startCoroutine, completion, receiver) + main:9, SuspendFunKt (coroutine1) + (cnt) + main:-1, SuspendFunKt (coroutine1) + () +Disconnected from the target VM + +Process finished with exit code 0 +kotlin.Unit diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendLambda.out b/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendLambda.out index 0cbe27833d3..0e094402ce5 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendLambda.out +++ b/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendLambda.out @@ -1,12 +1,13 @@ -LineBreakpoint created at sequence.kt:14 +LineBreakpoint created at suspendLambda.kt:12 Run Java Connected to the target VM -sequence.kt:12 +suspendLambda.kt:12 Thread stack trace: - nextSequence:12, SequenceKt (continuation) + nextSequence:12, SuspendLambdaKt (continuation) (terms, terms1) - invokeSuspend:23, SequenceKt$fibonacci$1 (continuation) + invokeSuspend:23, SuspendLambdaKt$fibonacci$1 (continuation) ($result, $this$sequence, step, terms, this) +CoroutineNameIdState(name=coroutine, id=-1, state=UNKNOWN, dispatcher=null) resumeWith:33, kotlin.coroutines.jvm.internal.BaseContinuationImpl ($i$a$-with-BaseContinuationImpl$resumeWith$1, $this$with, completion, current, param, result, this) hasNext:140, kotlin.sequences.SequenceBuilderIterator @@ -19,9 +20,9 @@ Thread stack trace: ($this$toMutableList) toList:743, kotlin.sequences.SequencesKt___SequencesKt ($this$toList) - main:5, continuation.SequenceKt + main:5, continuation.SuspendLambdaKt (a) - main:-1, continuation.SequenceKt + main:-1, continuation.SuspendLambdaKt () Disconnected from the target VM diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun.out b/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun.out index 41260aaa1ac..fd6bf5cf55c 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun.out +++ b/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun.out @@ -1,15 +1,16 @@ -LineBreakpoint created at coroutineSuspendFun.kt:30 +LineBreakpoint created at coroutineSuspendFun.kt:29 Run Java Connected to the target VM -coroutineSuspendFun.kt:30 +coroutineSuspendFun.kt:29 Thread stack trace: - c:30, CoroutineSuspendFunKt (continuation) + c:29, CoroutineSuspendFunKt (continuation) ($completion, c, paramB) - b:24, CoroutineSuspendFunKt (continuation) + b:23, CoroutineSuspendFunKt (continuation) ($completion, $continuation, $result, b, paramA) - a:17, continuation.CoroutineSuspendFunKt +CoroutineNameIdState(name=coroutine, id=1, state=RUNNING, dispatcher=BlockingEventLoop@6f45df59) + a:16, continuation.CoroutineSuspendFunKt (a) - invokeSuspend:11, continuation.CoroutineSuspendFunKt$main$1 + invokeSuspend:10, continuation.CoroutineSuspendFunKt$main$1 ($this$runBlocking) resumeWith:33, kotlin.coroutines.jvm.internal.BaseContinuationImpl ($i$a$-with-BaseContinuationImpl$resumeWith$1, $this$with, completion, current, param, result, this) @@ -27,7 +28,7 @@ Thread stack trace: () runBlocking$default:1, kotlinx.coroutines.BuildersKt () - main:10, continuation.CoroutineSuspendFunKt + main:9, continuation.CoroutineSuspendFunKt (main) main:-1, continuation.CoroutineSuspendFunKt () @@ -38,7 +39,7 @@ Creation stack frame () runBlocking$default:1, kotlinx.coroutines.BuildersKt () - main:10, continuation.CoroutineSuspendFunKt + main:9, continuation.CoroutineSuspendFunKt () main:-1, continuation.CoroutineSuspendFunKt ()