diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/ReadMe.md b/idea/jvm-debugger/jvm-debugger-coroutine/ReadMe.md new file mode 100644 index 00000000000..93602fe010d --- /dev/null +++ b/idea/jvm-debugger/jvm-debugger-coroutine/ReadMe.md @@ -0,0 +1,16 @@ +# Coroutine Debugger support + +## Java thread stack with coroutine information +1. Real frames +1. Coroutine 'preflight' frame: [SuspendExitMode](src/org/jetbrains/kotlin/idea/debugger/coroutine/data/SuspendExitMode.kt) +is `SUSPEND_LAMBDA` or `SUSPEND_METHOD_PARAMETER`. [Location.isPreflight](org/jetbrains/kotlin/idea/debugger/coroutine/util/CoroutineUtils.kt) +1. One or more frames (skipped in debugger) +1. Coroutine 'starting' frame: [SuspendExitMode](src/org/jetbrains/kotlin/idea/debugger/coroutine/data/SuspendExitMode.kt) `SUSPEND_METHOD` frame +1. Restored from coroutine information frames +1. Real frames after the 'starting' frame +1. Creation frames (only exists if coroutine agent enabled) + +## Debugger interface +Debugger works as a combination of PositionManager and AsyncStackTraceProvider. +Once the 'preflight' signature frame found PositionManager forms a 'preflight' frame with coroutine information which gets +processed with AsyncStackTraceProvider. \ No newline at end of file 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 99f9795779e..d547c8fa500 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 @@ -9,7 +9,7 @@ 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 org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutinePreflightStackFrame +import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutinePreflightFrame import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutineStackFrameItem import org.jetbrains.kotlin.idea.debugger.coroutine.util.CoroutineFrameBuilder import org.jetbrains.kotlin.idea.debugger.coroutine.util.threadAndContextSupportsEvaluation @@ -19,18 +19,19 @@ class CoroutineAsyncStackTraceProvider : AsyncStackTraceProvider { override fun getAsyncStackTrace(stackFrame: JavaStackFrame, suspendContext: SuspendContextImpl): List? { val stackFrameList = hopelessAware { - if (stackFrame is CoroutinePreflightStackFrame) + if (stackFrame is CoroutinePreflightFrame) processPreflight(stackFrame, suspendContext) else null } return if (stackFrameList == null || stackFrameList.isEmpty()) null - else stackFrameList + else + stackFrameList } private fun processPreflight( - preflightFrame: CoroutinePreflightStackFrame, + preflightFrame: CoroutinePreflightFrame, suspendContext: SuspendContextImpl ): List? { val resumeWithFrame = preflightFrame.threadPreCoroutineFrames.firstOrNull() @@ -41,15 +42,8 @@ class CoroutineAsyncStackTraceProvider : AsyncStackTraceProvider { ) ) { val doubleFrameList = CoroutineFrameBuilder.build(preflightFrame, suspendContext) - val resultList = doubleFrameList.stackTrace + doubleFrameList.creationStackTrace - return PreflightProvider(preflightFrame, resultList) + return doubleFrameList.allFrames() } 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-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/ContinuationValueDescriptorImpl.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/ContinuationVariableValueDescriptorImpl.kt similarity index 100% rename from idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/ContinuationValueDescriptorImpl.kt rename to idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/ContinuationVariableValueDescriptorImpl.kt diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/CoroutineAsyncStackFrameItem.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/CoroutineAsyncStackFrameItem.kt deleted file mode 100644 index 96bdb851e07..00000000000 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/CoroutineAsyncStackFrameItem.kt +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.idea.debugger.coroutine.data - -import com.intellij.debugger.engine.DebugProcessImpl -import com.intellij.debugger.jdi.StackFrameProxyImpl -import com.intellij.debugger.memory.utils.StackFrameItem -import com.intellij.debugger.ui.impl.watch.MethodsTracker -import com.intellij.debugger.ui.impl.watch.StackFrameDescriptorImpl -import com.intellij.xdebugger.frame.XNamedValue -import com.sun.jdi.Location -import org.jetbrains.kotlin.idea.debugger.* -import org.jetbrains.kotlin.idea.debugger.coroutine.util.isInvokeSuspend -import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger - -/** - * Creation frame of coroutine either in RUNNING or SUSPENDED state. - */ -class CreationCoroutineStackFrameItem( - val stackTraceElement: StackTraceElement, - location: Location, - val first: Boolean -) : CoroutineStackFrameItem(location, emptyList()) { - fun descriptor(frame: StackFrameProxyImpl) = - RestoredStackFrameDescriptor(stackTraceElement, frame) - - override fun createFrame(debugProcess: DebugProcessImpl): CapturedStackFrame { - return if (first) - CreationCoroutineStackFrame(debugProcess, this) - else - super.createFrame(debugProcess) - } -} - -/** - * Restored frame in SUSPENDED coroutine, not attached to any thread. - */ -class SuspendCoroutineStackFrameItem( - val stackTraceElement: StackTraceElement, - location: Location, - spilledVariables: List = emptyList() -) : CoroutineStackFrameItem(location, spilledVariables) { - - fun descriptor(frame: StackFrameProxyImpl) = - RestoredStackFrameDescriptor(stackTraceElement, frame) -} - -/** - * Restored frame in RUNNING coroutine, attached to running thread. Frame references a 'preflight' or 'exit' frame. - */ -class RestoredCoroutineStackFrameItem( - val frame: StackFrameProxyImpl, - location: Location, - spilledVariables: List -) : CoroutineStackFrameItem(location, spilledVariables) { - - fun descriptor() = - StackFrameDescriptorImpl(frame, MethodsTracker()) -} - -/** - * Restored from memory dump - */ -class DefaultCoroutineStackFrameItem(location: Location, spilledVariables: List) : - CoroutineStackFrameItem(location, spilledVariables) { - - fun descriptor(frame: StackFrameProxyImpl) = - StackFrameDescriptorImpl(frame, MethodsTracker()) -} - -/** - * Original frame appeared before resumeWith call. - * - * Sequence is the following - * - * - KotlinStackFrame - * - invokeSuspend(KotlinStackFrame) -| - * | replaced with CoroutinePreflightStackFrame - * - resumeWith(KotlinStackFrame) ----| - * - Kotlin/JavaStackFrame -> PreCoroutineStackFrameItem : CoroutinePreflightStackFrame.threadPreCoroutineFrames - * - */ - -class RunningCoroutineStackFrameItem( - val frame: StackFrameProxyImpl, - location: Location, - spilledVariables: List = emptyList() -) : CoroutineStackFrameItem(location, spilledVariables) { - override fun createFrame(debugProcess: DebugProcessImpl): CapturedStackFrame { - val realStackFrame = debugProcess.invokeInManagerThread { - debugProcess.positionManager.createStackFrame(frame, debugProcess, location) - } - return CoroutineStackFrame(debugProcess, this, realStackFrame) - } -} - -sealed class CoroutineStackFrameItem(val location: Location, val spilledVariables: List) : - StackFrameItem(location, spilledVariables) { - val log by logger - - override fun createFrame(debugProcess: DebugProcessImpl): CapturedStackFrame = - CoroutineStackFrame(debugProcess, this) - - fun uniqueId(): String { - return location.safeSourceName() + ":" + location.safeMethod().toString() + ":" + - location.safeLineNumber() + ":" + location.safeKotlinPreferredLineNumber() - } - - fun isInvokeSuspend(): Boolean = - location.isInvokeSuspend() -} - -class RestoredStackFrameDescriptor(val frame: StackTraceElement, proxy: StackFrameProxyImpl) : - StackFrameDescriptorImpl(proxy, MethodsTracker()) diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/CoroutineInfoData.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/CoroutineInfoData.kt index f03417f3fad..d92f439a02a 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/CoroutineInfoData.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/CoroutineInfoData.kt @@ -35,14 +35,6 @@ data class CoroutineInfoData( fun topFrameVariables() = topRestoredFrame()?.spilledVariables ?: emptyList() - fun restoredStackTrace(mode: SuspendExitMode): List = - if (stackTrace.isNotEmpty() && stackTrace.first().isInvokeSuspend()) - stackTrace.drop(1) - else if (mode == SuspendExitMode.SUSPEND_METHOD_PARAMETER) - stackTrace.drop(1) - else - stackTrace - companion object { val log by logger const val DEFAULT_COROUTINE_NAME = "coroutine" diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/SuspendExitMode.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/SuspendExitMode.kt new file mode 100644 index 00000000000..68093b8cfaf --- /dev/null +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/SuspendExitMode.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.debugger.coroutine.data; + +enum class SuspendExitMode { + SUSPEND_LAMBDA, SUSPEND_METHOD_PARAMETER, SUSPEND_METHOD, UNKNOWN, NONE; + + fun isCoroutineFound() = + this == SUSPEND_LAMBDA || this == SUSPEND_METHOD_PARAMETER + + fun isSuspendMethodParameter() = + this == SUSPEND_METHOD_PARAMETER +} \ No newline at end of file diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/SyntheticStackFrame.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/SyntheticStackFrame.kt deleted file mode 100644 index d14f8ec5429..00000000000 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/SyntheticStackFrame.kt +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.idea.debugger.coroutine.data - -import com.intellij.debugger.engine.JavaStackFrame -import com.intellij.debugger.ui.impl.watch.StackFrameDescriptorImpl -import com.intellij.xdebugger.XSourcePosition -import com.intellij.xdebugger.frame.XCompositeNode -import com.intellij.xdebugger.frame.XNamedValue -import com.intellij.xdebugger.frame.XValueChildrenList - -/** - * Puts the frameProxy into JavaStackFrame just to instantiate. SyntheticStackFrame provides it's own data for variables view. - */ -class SyntheticStackFrame( - descriptor: StackFrameDescriptorImpl, - private val vars: List, - private val position: XSourcePosition -) : - JavaStackFrame(descriptor, true) { - - override fun computeChildren(node: XCompositeNode) { - val list = XValueChildrenList() - vars.forEach { list.add(it) } - node.addChildren(list, true) - } - - override fun getSourcePosition(): XSourcePosition? { - return position - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - - val frame = other as? JavaStackFrame ?: return false - - return descriptor.frameProxy == frame.descriptor.frameProxy - } - - override fun hashCode(): Int { - return descriptor.frameProxy.hashCode() - } -} \ No newline at end of file diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/TreeNodeDescriptorImpl.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/TreeNodeDescriptorImpl.kt deleted file mode 100644 index 44384d5f2cd..00000000000 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/TreeNodeDescriptorImpl.kt +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.idea.debugger.coroutine.data - -import com.intellij.debugger.engine.evaluation.EvaluateException -import com.intellij.debugger.engine.evaluation.EvaluationContextImpl -import com.intellij.debugger.impl.DebuggerUtilsEx -import com.intellij.debugger.jdi.StackFrameProxyImpl -import com.intellij.debugger.memory.utils.StackFrameItem -import com.intellij.debugger.ui.impl.watch.MessageDescriptor -import com.intellij.debugger.ui.impl.watch.MethodsTracker -import com.intellij.debugger.ui.impl.watch.NodeDescriptorImpl -import com.intellij.debugger.ui.impl.watch.StackFrameDescriptorImpl -import com.intellij.debugger.ui.tree.render.DescriptorLabelListener -import com.intellij.icons.AllIcons -import com.sun.jdi.ObjectReference -import org.jetbrains.kotlin.idea.debugger.coroutine.KotlinDebuggerCoroutinesBundle -import javax.swing.Icon - -@Deprecated("moved to XCoroutineView") -class CoroutineDescriptorImpl(private val infoData: CoroutineInfoData) : NodeDescriptorImpl() { - lateinit var icon: Icon - - override fun getName() = infoData.key.name - - @Throws(EvaluateException::class) - override fun calcRepresentation(context: EvaluationContextImpl?, labelListener: DescriptorLabelListener): String { - val thread = infoData.activeThread - val name = thread?.name()?.substringBefore(" @${infoData.key.name}") ?: "" - val threadState = if (thread != null) DebuggerUtilsEx.getThreadStatusText(thread.status()) else "" - val threadName = if (name.isNotEmpty()) " on thread \"$name\":$threadState" else "" - return "${infoData.key.name}: ${infoData.key.state} $threadName" - } - - override fun isExpandable() = infoData.key.state != State.CREATED - - private fun calcIcon() = when { - infoData.isSuspended() -> AllIcons.Debugger.ThreadSuspended - infoData.isCreated() -> AllIcons.Debugger.ThreadStates.Idle - else -> AllIcons.Debugger.ThreadRunning - } - - override fun setContext(context: EvaluationContextImpl?) { - icon = calcIcon() - } -} - -@Deprecated("moved to XCoroutineView") -class CreationFramesDescriptor(val frames: List) : - MessageDescriptor(KotlinDebuggerCoroutinesBundle.message("coroutine.dump.creation.trace"), INFORMATION) { - - override fun isExpandable() = true -} - -/** - * Descriptor for suspend functions - */ -@Deprecated("moved to XCoroutineView") -class SuspendStackFrameDescriptor( - val infoData: CoroutineInfoData, - val frame: StackTraceElement, - proxy: StackFrameProxyImpl, - val continuation: ObjectReference -) : - CoroutineStackFrameDescriptor(proxy) { - override fun calcRepresentation(context: EvaluationContextImpl?, labelListener: DescriptorLabelListener?): String { - return with(frame) { - val pack = className.substringBeforeLast(".", "") - val packDisplay = if (pack.isNotEmpty()) "{$pack}" else "" - "$methodName:$lineNumber, ${className.substringAfterLast(".")} $packDisplay" - } - } - - override fun getName(): String? = frame.methodName -} - -/** - * For the case when no data inside frame is available - */ -@Deprecated("moved to XCoroutineView") -class CoroutineCreatedStackFrameDescriptor(val frame: StackTraceElement, proxy: StackFrameProxyImpl) : - CoroutineStackFrameDescriptor(proxy) { - override fun calcRepresentation(context: EvaluationContextImpl?, labelListener: DescriptorLabelListener?): String { - return with(frame) { - val pack = className.substringBeforeLast(".", "") - val packDisplay = if (pack.isNotEmpty()) "{$pack}" else "" - "$methodName:$lineNumber, ${className.substringAfterLast(".")} $packDisplay" - } - } - - override fun getName() = null -} - -@Deprecated("moved to XCoroutineView") -class AsyncStackFrameDescriptor(val infoData: CoroutineInfoData, val frame: StackFrameItem, proxy: StackFrameProxyImpl) : - CoroutineStackFrameDescriptor(proxy) { - override fun calcRepresentation(context: EvaluationContextImpl?, labelListener: DescriptorLabelListener?): String { - return with(frame) { - val pack = path().substringBeforeLast(".", "") - val packDisplay = if (pack.isNotEmpty()) "{$pack}" else "" - "${method()}:${line()}, ${path().substringAfterLast(".")} $packDisplay" - } - } - - override fun getName() = frame.method() -} - -@Deprecated("moved to XCoroutineView") -open class CoroutineStackFrameDescriptor(proxy: StackFrameProxyImpl) : StackFrameDescriptorImpl(proxy, MethodsTracker()) { - override fun isExpandable() = false -} diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/coroutineStackFrameItems.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/coroutineStackFrameItems.kt new file mode 100644 index 00000000000..e7796e3b3cf --- /dev/null +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/coroutineStackFrameItems.kt @@ -0,0 +1,174 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.debugger.coroutine.data + +import com.intellij.debugger.engine.DebugProcessImpl +import com.intellij.debugger.engine.JVMStackFrameInfoProvider +import com.intellij.debugger.engine.evaluation.EvaluationContextImpl +import com.intellij.debugger.jdi.StackFrameProxyImpl +import com.intellij.debugger.memory.utils.StackFrameItem +import com.intellij.xdebugger.frame.XCompositeNode +import com.intellij.xdebugger.frame.XNamedValue +import com.intellij.xdebugger.frame.XStackFrame +import com.intellij.xdebugger.frame.XValueChildrenList +import com.sun.jdi.Location +import org.jetbrains.kotlin.idea.debugger.* +import org.jetbrains.kotlin.idea.debugger.coroutine.KotlinDebuggerCoroutinesBundle +import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.LocationStackFrameProxyImpl +import org.jetbrains.kotlin.idea.debugger.coroutine.util.findPosition +import org.jetbrains.kotlin.idea.debugger.coroutine.util.isFilteredInvokeSuspend +import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger +import org.jetbrains.kotlin.idea.debugger.stackFrame.KotlinStackFrame + +/** + * Creation frame of coroutine either in RUNNING or SUSPENDED state. + */ +class CreationCoroutineStackFrameItem( + val stackTraceElement: StackTraceElement, + location: Location, + val first: Boolean +) : CoroutineStackFrameItem(location, emptyList()) { + + override fun createFrame(debugProcess: DebugProcessImpl): CoroutineGeneratedFrame? { + return debugProcess.invokeInManagerThread { + val frame = debugProcess.findFirstFrame() ?: return@invokeInManagerThread null + val locationFrame = LocationStackFrameProxyImpl(location, frame) + val position = location.findPosition(debugProcess.project) + CreationCoroutineStackFrame(debugProcess, this, first) + } + } +} + +/** + * Restored frame in SUSPENDED coroutine, not attached to any thread. + */ +class SuspendCoroutineStackFrameItem( + val stackTraceElement: StackTraceElement, + location: Location, + spilledVariables: List = emptyList() +) : CoroutineStackFrameItem(location, spilledVariables) + +/** + * Restored from memory dump + */ +class DefaultCoroutineStackFrameItem(location: Location, spilledVariables: List) : + CoroutineStackFrameItem(location, spilledVariables) { + + override fun createFrame(debugProcess: DebugProcessImpl): CoroutineGeneratedFrame? { + return debugProcess.invokeInManagerThread { + val frame = debugProcess.findFirstFrame() ?: return@invokeInManagerThread null + val locationStackFrameProxyImpl = LocationStackFrameProxyImpl(location, frame) + val position = location.findPosition(debugProcess.project) ?: return@invokeInManagerThread null + CoroutineStackFrame(debugProcess, this) + } + } +} + +/** + * Original frame appeared before resumeWith call. + * + * Sequence is the following + * + * - KotlinStackFrame + * - invokeSuspend(KotlinStackFrame) -| + * | replaced with CoroutinePreflightStackFrame + * - resumeWith(KotlinStackFrame) ----| + * - Kotlin/JavaStackFrame -> PreCoroutineStackFrameItem : CoroutinePreflightStackFrame.threadPreCoroutineFrames + * + */ +open class RunningCoroutineStackFrameItem( + val frame: StackFrameProxyImpl, + spilledVariables: List = emptyList() +) : CoroutineStackFrameItem(frame.location(), spilledVariables), FrameProvider { + override fun createFrame(debugProcess: DebugProcessImpl): CoroutineGeneratedFrame? { + return debugProcess.invokeInManagerThread { + CoroutineStackFrame(debugProcess, this) + } + } + + override fun provideFrame(debugProcess: DebugProcessImpl): XStackFrame? = + debugProcess.invokeInManagerThread { KotlinStackFrame(frame) } +} + +sealed class CoroutineStackFrameItem(val location: Location, val spilledVariables: List) : + StackFrameItem(location, spilledVariables) { + val log by logger + + override fun createFrame(debugProcess: DebugProcessImpl): CoroutineGeneratedFrame? { + return debugProcess.invokeInManagerThread { + CoroutineStackFrame(debugProcess, this) + } + } + + fun uniqueId() = + location.safeSourceName() + ":" + location.safeMethod().toString() + ":" + + location.safeLineNumber() + ":" + location.safeKotlinPreferredLineNumber() +} + +interface FrameProvider { + fun provideFrame(debugProcess: DebugProcessImpl): XStackFrame? +} + +fun DebugProcessImpl.findFirstFrame(): StackFrameProxyImpl? = + suspendManager.pausedContext.thread?.forceFrames()?.firstOrNull() + +/** + * Coroutine exit frame represented by a stack frames + * invokeSuspend():-1 + * resumeWith() + * + */ +class CoroutinePreflightFrame( + val coroutineInfoData: CoroutineInfoData, + private val frame: StackFrameProxyImpl, + val threadPreCoroutineFrames: List, + val mode: SuspendExitMode +) : KotlinStackFrame(frame), JVMStackFrameInfoProvider { + + override fun superBuildVariables(evaluationContext: EvaluationContextImpl, children: XValueChildrenList) { + super.superBuildVariables(evaluationContext, children) + val topRestoredFrame = coroutineInfoData.stackTrace.firstOrNull() + if (topRestoredFrame != null && topRestoredFrame.location.isFilteredInvokeSuspend()) { + val firstFrameVariables: List = topRestoredFrame.spilledVariables + children.let { + val varNames = (0 until children.size()).map { children.getName(it) }.toSet() + firstFrameVariables.forEach { + if (!varNames.contains(it.name)) + children.add(it) + } + } + } + } + + override fun isInLibraryContent() = false + + override fun isSynthetic() = false +} + +class CreationCoroutineStackFrame(debugProcess: DebugProcessImpl, item: CoroutineStackFrameItem, val first: Boolean) : CoroutineStackFrame(debugProcess, item) { + override fun getCaptionAboveOf() = KotlinDebuggerCoroutinesBundle.message("coroutine.dump.creation.trace") + + override fun hasSeparatorAbove(): Boolean = + first +} + +open class CoroutineStackFrame(val debugProcess: DebugProcessImpl, val item: CoroutineStackFrameItem) : + StackFrameItem.CapturedStackFrame(debugProcess, item) { + + override fun computeChildren(node: XCompositeNode) { + if (item is FrameProvider) + item.provideFrame(debugProcess)?.computeChildren(node) + else + super.computeChildren(node) + } + + override fun getCaptionAboveOf() = "CoroutineExit" + + override fun hasSeparatorAbove(): Boolean = + false +} + +typealias CoroutineGeneratedFrame = StackFrameItem.CapturedStackFrame \ No newline at end of file diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/coroutineStackFrameItems.kt.201 b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/coroutineStackFrameItems.kt.201 new file mode 100644 index 00000000000..d69db4cc07d --- /dev/null +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/coroutineStackFrameItems.kt.201 @@ -0,0 +1,200 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.debugger.coroutine.data + +import com.intellij.debugger.engine.DebugProcessImpl +import com.intellij.debugger.engine.JavaStackFrame +import com.intellij.debugger.engine.evaluation.EvaluationContextImpl +import com.intellij.debugger.jdi.StackFrameProxyImpl +import com.intellij.debugger.memory.utils.StackFrameItem +import com.intellij.debugger.ui.tree.render.DescriptorLabelListener +import com.intellij.xdebugger.XSourcePosition +import com.intellij.xdebugger.frame.XCompositeNode +import com.intellij.xdebugger.frame.XNamedValue +import com.intellij.xdebugger.frame.XStackFrame +import com.intellij.xdebugger.frame.XValueChildrenList +import com.intellij.xdebugger.impl.frame.XDebuggerFramesList +import com.sun.jdi.Location +import org.jetbrains.kotlin.idea.debugger.* +import org.jetbrains.kotlin.idea.debugger.coroutine.KotlinDebuggerCoroutinesBundle +import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.LocationStackFrameProxyImpl +import org.jetbrains.kotlin.idea.debugger.coroutine.util.findPosition +import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger +import org.jetbrains.kotlin.idea.debugger.stackFrame.KotlinStackFrame + +/** + * Creation frame of coroutine either in RUNNING or SUSPENDED state. + */ +class CreationCoroutineStackFrameItem( + val stackTraceElement: StackTraceElement, + location: Location, + val first: Boolean +) : CoroutineStackFrameItem(location, emptyList()) { + + override fun createFrame(debugProcess: DebugProcessImpl): XStackFrame? { + return debugProcess.invokeInManagerThread { + val frame = debugProcess.findFirstFrame() ?: return@invokeInManagerThread null + val locationFrame = LocationStackFrameProxyImpl(location, frame) + val position = location.findPosition(debugProcess.project) + CreationCoroutineStackFrame(locationFrame, position, first) + } + } +} + +/** + * Restored frame in SUSPENDED coroutine, not attached to any thread. + */ +class SuspendCoroutineStackFrameItem( + val stackTraceElement: StackTraceElement, + location: Location, + spilledVariables: List = emptyList() +) : CoroutineStackFrameItem(location, spilledVariables) + + +/** + * Restored from memory dump + */ +class DefaultCoroutineStackFrameItem(location: Location, spilledVariables: List) : + CoroutineStackFrameItem(location, spilledVariables) { + + override fun createFrame(debugProcess: DebugProcessImpl): XStackFrame? { + return debugProcess.invokeInManagerThread { + val frame = debugProcess.findFirstFrame() ?: return@invokeInManagerThread null + val locationStackFrameProxyImpl = LocationStackFrameProxyImpl(location, frame) + val position = location.findPosition(debugProcess.project) ?: return@invokeInManagerThread null + CoroutineStackFrame(locationStackFrameProxyImpl, position, spilledVariables, false) + } + } +} + +/** + * Original frame appeared before resumeWith call. + * + * Sequence is the following + * + * - KotlinStackFrame + * - invokeSuspend(KotlinStackFrame) -| + * | replaced with CoroutinePreflightStackFrame + * - resumeWith(KotlinStackFrame) ----| + * - Kotlin/JavaStackFrame -> PreCoroutineStackFrameItem : CoroutinePreflightStackFrame.threadPreCoroutineFrames + * + */ +open class RunningCoroutineStackFrameItem( + val frame: StackFrameProxyImpl, + spilledVariables: List = emptyList() +) : CoroutineStackFrameItem(frame.location(), spilledVariables) { + override fun createFrame(debugProcess: DebugProcessImpl): XStackFrame? { + return debugProcess.invokeInManagerThread { + val position = frame.location().findPosition(debugProcess.project) + CoroutineStackFrame(frame, position) + } + } +} + +sealed class CoroutineStackFrameItem(val location: Location, val spilledVariables: List) : + StackFrameItem(location, spilledVariables) { + val log by logger + + override fun createFrame(debugProcess: DebugProcessImpl): XStackFrame? { + return debugProcess.invokeInManagerThread { + val frame = debugProcess.findFirstFrame() ?: return@invokeInManagerThread null + val locationFrame = LocationStackFrameProxyImpl(location, frame) + val position = location.findPosition(debugProcess.project) + CoroutineStackFrame(locationFrame, position) + } + } + + fun uniqueId() = + location.safeSourceName() + ":" + location.safeMethod().toString() + ":" + + location.safeLineNumber() + ":" + location.safeKotlinPreferredLineNumber() +} + +fun DebugProcessImpl.findFirstFrame(): StackFrameProxyImpl? = + suspendManager.pausedContext.thread?.forceFrames()?.firstOrNull() + +/** + * Coroutine exit frame represented by a stack frames + * invokeSuspend():-1 + * resumeWith() + * + */ +class CoroutinePreflightFrame( + val coroutineInfoData: CoroutineInfoData, + val frame: StackFrameProxyImpl, + val threadPreCoroutineFrames: List, + val mode: SuspendExitMode, + private val firstFrameVariables: List = coroutineInfoData.topFrameVariables() +) : CoroutineStackFrame(frame, null, firstFrameVariables) { + + override fun isInLibraryContent() = false + + override fun isSynthetic() = false + +} + +class CreationCoroutineStackFrame( + frame: StackFrameProxyImpl, + sourcePosition: XSourcePosition?, + val first: Boolean +) : CoroutineStackFrame(frame, sourcePosition, emptyList(), false), XDebuggerFramesList.ItemWithSeparatorAbove { + + override fun getCaptionAboveOf() = + KotlinDebuggerCoroutinesBundle.message("coroutine.dump.creation.trace") + + override fun hasSeparatorAbove() = + first +} + +open class CoroutineStackFrame( + frame: StackFrameProxyImpl, + val position: XSourcePosition?, + private val spilledVariables: List? = null, + private val includeFrameVariables: Boolean = true, +) : KotlinStackFrame(frame) { + + init { + descriptor.updateRepresentation(null, DescriptorLabelListener.DUMMY_LISTENER) + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + + val frame = other as? JavaStackFrame ?: return false + + return descriptor.frameProxy == frame.descriptor.frameProxy + } + + override fun hashCode(): Int { + return descriptor.frameProxy.hashCode() + } + + override fun computeChildren(node: XCompositeNode) { + if (includeFrameVariables || spilledVariables == null) { + super.computeChildren(node) + } else { + // ignore original frame variables + val list = XValueChildrenList() + spilledVariables.forEach { list.add(it) } + node.addChildren(list, true) + } + } + + override fun superBuildVariables(evaluationContext: EvaluationContextImpl, children: XValueChildrenList) { + super.superBuildVariables(evaluationContext, children) + if (spilledVariables != null) { + children.let { + val varNames = (0 until children.size()).map { children.getName(it) }.toSet() + spilledVariables.forEach { + if (!varNames.contains(it.name)) + children.add(it) + } + } + } + } + + override fun getSourcePosition() = + position ?: super.getSourcePosition() +} \ No newline at end of file diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/coroutineStackFrames.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/coroutineStackFrames.kt deleted file mode 100644 index 0b862a7d78b..00000000000 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/coroutineStackFrames.kt +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ -package org.jetbrains.kotlin.idea.debugger.coroutine.data - -import com.intellij.debugger.engine.DebugProcessImpl -import com.intellij.debugger.engine.JVMStackFrameInfoProvider -import com.intellij.debugger.engine.evaluation.EvaluationContextImpl -import com.intellij.debugger.jdi.StackFrameProxyImpl -import com.intellij.debugger.memory.utils.StackFrameItem -import com.intellij.debugger.ui.impl.watch.StackFrameDescriptorImpl -import com.intellij.xdebugger.frame.XCompositeNode -import com.intellij.xdebugger.frame.XNamedValue -import com.intellij.xdebugger.frame.XStackFrame -import com.intellij.xdebugger.frame.XValueChildrenList -import org.jetbrains.kotlin.idea.debugger.coroutine.KotlinDebuggerCoroutinesBundle -import org.jetbrains.kotlin.idea.debugger.stackFrame.KotlinStackFrame - - -/** - * Coroutine exit frame represented by a stack frames - * invokeSuspend():-1 - * resumeWith() - * - */ - -class CoroutinePreflightStackFrame( - val coroutineInfoData: CoroutineInfoData, - private val stackFrameDescriptorImpl: StackFrameDescriptorImpl, - val threadPreCoroutineFrames: List, - val mode: SuspendExitMode, - private val firstFrameVariables: List = coroutineInfoData.topFrameVariables() -) : KotlinStackFrame(stackFrameDescriptorImpl), JVMStackFrameInfoProvider { - - override fun superBuildVariables(evaluationContext: EvaluationContextImpl, children: XValueChildrenList) { - super.superBuildVariables(evaluationContext, children) - children.let { - val varNames = (0 until children.size()).map { children.getName(it) }.toSet() - firstFrameVariables.forEach { - if (!varNames.contains(it.name)) - children.add(it) - } - } - } - - override fun isInLibraryContent() = false - - override fun isSynthetic() = false - - fun restoredStackTrace() = - coroutineInfoData.restoredStackTrace(mode) -} - -enum class SuspendExitMode { - SUSPEND_LAMBDA, SUSPEND_METHOD_PARAMETER, SUSPEND_METHOD, UNKNOWN, NONE; - - fun isCoroutineFound() = - this == SUSPEND_LAMBDA || this == SUSPEND_METHOD_PARAMETER - - fun isSuspendMethodParameter() = - this == SUSPEND_METHOD_PARAMETER -} - -class CreationCoroutineStackFrame(debugProcess: DebugProcessImpl, item: StackFrameItem) : CoroutineStackFrame(debugProcess, item) { - override fun getCaptionAboveOf() = KotlinDebuggerCoroutinesBundle.message("coroutine.dump.creation.trace") - - override fun hasSeparatorAbove(): Boolean = - true -} - -open class CoroutineStackFrame(debugProcess: DebugProcessImpl, val item: StackFrameItem, private val realStackFrame: XStackFrame? = null) : - StackFrameItem.CapturedStackFrame(debugProcess, item) { - - override fun computeChildren(node: XCompositeNode) { - if (realStackFrame != null) - realStackFrame.computeChildren(node) - else - super.computeChildren(node) - } - - override fun getCaptionAboveOf() = "CoroutineExit" - - override fun hasSeparatorAbove(): Boolean = - false -} diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/ManagerThreadExecutor.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/ManagerThreadExecutor.kt index c21ff62666a..0fda565e60e 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/ManagerThreadExecutor.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/ManagerThreadExecutor.kt @@ -49,8 +49,5 @@ class ManagerThreadExecutor(val debugProcess: DebugProcessImpl) { } } -class ApplicationThreadExecutor { - fun schedule(f: () -> Unit, component: Component) { - return ApplicationManager.getApplication().invokeLater({ f() }, ModalityState.stateForComponent(component)) - } -} +fun invokeLater(component: Component, f: () -> Unit) = + ApplicationManager.getApplication().invokeLater({ f() }, ModalityState.stateForComponent(component)) diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/SkipCoroutineStackFrameProxyImpl.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/SkipCoroutineStackFrameProxyImpl.kt index 1af450f2091..bc500528fb4 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/SkipCoroutineStackFrameProxyImpl.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/SkipCoroutineStackFrameProxyImpl.kt @@ -6,6 +6,14 @@ package org.jetbrains.kotlin.idea.debugger.coroutine.proxy import com.intellij.debugger.jdi.StackFrameProxyImpl +import com.sun.jdi.Location class SkipCoroutineStackFrameProxyImpl(frame: StackFrameProxyImpl) : StackFrameProxyImpl(frame.threadProxy(), frame.stackFrame, frame.indexFromBottom) + +class LocationStackFrameProxyImpl(val location: Location, frame: StackFrameProxyImpl) : + StackFrameProxyImpl(frame.threadProxy(), frame.stackFrame, frame.indexFromBottom) { + + override fun location(): Location = + location +} diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/CoroutineFrameBuilder.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/CoroutineFrameBuilder.kt index 1311f7d491a..90b78c5b007 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/CoroutineFrameBuilder.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/CoroutineFrameBuilder.kt @@ -8,8 +8,7 @@ package org.jetbrains.kotlin.idea.debugger.coroutine.util import com.intellij.debugger.engine.SuspendContextImpl import com.intellij.debugger.jdi.StackFrameProxyImpl import com.intellij.debugger.jdi.ThreadReferenceProxyImpl -import com.intellij.debugger.ui.impl.watch.MethodsTracker -import com.intellij.debugger.ui.impl.watch.StackFrameDescriptorImpl +import com.intellij.xdebugger.frame.XNamedValue import com.sun.jdi.ObjectReference import org.jetbrains.kotlin.idea.debugger.coroutine.data.* import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.ContinuationHolder @@ -23,14 +22,14 @@ class CoroutineFrameBuilder { val log by logger private const val PRE_FETCH_FRAME_COUNT = 5 - fun build(coroutine: CoroutineInfoData, suspendContext: SuspendContextImpl): DoubleFrameList? = + fun build(coroutine: CoroutineInfoData, suspendContext: SuspendContextImpl): CoroutineFrameItemLists? = when { coroutine.isRunning() -> buildStackFrameForActive(coroutine, suspendContext) - coroutine.isSuspended() -> DoubleFrameList(coroutine.stackTrace, coroutine.creationStackTrace) + coroutine.isSuspended() -> CoroutineFrameItemLists(coroutine.stackTrace, coroutine.creationStackTrace) else -> null } - private fun buildStackFrameForActive(coroutine: CoroutineInfoData, suspendContext: SuspendContextImpl): DoubleFrameList? { + private fun buildStackFrameForActive(coroutine: CoroutineInfoData, suspendContext: SuspendContextImpl): CoroutineFrameItemLists? { val activeThread = coroutine.activeThread ?: return null val coroutineStackFrameList = mutableListOf() @@ -43,47 +42,77 @@ class CoroutineFrameBuilder { coroutineStackFrameList.add(it) } - val doubleFrameList = build(preflightStackFrame, suspendContext) - coroutineStackFrameList.addAll(doubleFrameList.stackTrace) - return DoubleFrameList(coroutineStackFrameList, doubleFrameList.creationStackTrace) + val coroutineFrameLists = build(preflightStackFrame, suspendContext) + coroutineStackFrameList.addAll(coroutineFrameLists.frames) + return CoroutineFrameItemLists(coroutineStackFrameList, coroutineFrameLists.creationFrames) } else { buildRealStackFrameItem(runningStackFrameProxy)?.let { coroutineStackFrameList.add(it) } } } - return DoubleFrameList(coroutineStackFrameList, emptyList()) + return CoroutineFrameItemLists(coroutineStackFrameList, emptyList()) } /** * Used by CoroutineAsyncStackTraceProvider to build XFramesView */ - fun build(preflightFrame: CoroutinePreflightStackFrame, suspendContext: SuspendContextImpl): DoubleFrameList { + fun build(preflightFrame: CoroutinePreflightFrame, suspendContext: SuspendContextImpl): CoroutineFrameItemLists { val stackFrames = mutableListOf() - stackFrames.addAll(preflightFrame.restoredStackTrace()) + val (restoredStackTrace, variablesRemovedFromBottomRestoredFrame) = restoredStackTrace( + preflightFrame + ) + stackFrames.addAll(restoredStackTrace) - // rest of the stack - // @TODO perhaps we need to merge the dropped frame below with the last restored (at least variables). - val framesLeft = preflightFrame.threadPreCoroutineFrames.drop(1) + // @TODO perhaps we need to merge the dropped variables with the frame below... + val framesLeft = preflightFrame.threadPreCoroutineFrames stackFrames.addAll(framesLeft.mapIndexedNotNull { index, stackFrameProxyImpl -> suspendContext.invokeInManagerThread { buildRealStackFrameItem(stackFrameProxyImpl) } }) - return DoubleFrameList(stackFrames, preflightFrame.coroutineInfoData.creationStackTrace) + return CoroutineFrameItemLists(stackFrames, preflightFrame.coroutineInfoData.creationStackTrace) } - data class DoubleFrameList( - val stackTrace: List, - val creationStackTrace: List - ) + fun restoredStackTrace(preflightFrame: CoroutinePreflightFrame): Pair, List> { + val preflightFrameLocation = preflightFrame.stackFrameProxy.location() + val coroutineStackFrame = preflightFrame.coroutineInfoData.stackTrace + val preCoroutineTopFrameLocation = preflightFrame.threadPreCoroutineFrames.firstOrNull()?.location() + + val variablesRemovedFromTopRestoredFrame = mutableListOf() + val stripTopStackTrace = coroutineStackFrame.dropWhile { + it.location.isFilterFromTop(preflightFrameLocation).apply { + if (this) + variablesRemovedFromTopRestoredFrame.addAll(it.spilledVariables) + } + } + // @TODO Need to merge variablesRemovedFromTopRestoredFrame into stripTopStackTrace.firstOrNull().spilledVariables + val variablesRemovedFromBottomRestoredFrame = mutableListOf() + val restoredFrames = when (preCoroutineTopFrameLocation) { + null -> stripTopStackTrace + else -> + stripTopStackTrace.dropLastWhile { + it.location.isFilterFromBottom(preCoroutineTopFrameLocation) + .apply { variablesRemovedFromBottomRestoredFrame.addAll(it.spilledVariables) } + } + } + return Pair(restoredFrames, variablesRemovedFromBottomRestoredFrame) + } + + data class CoroutineFrameItemLists( + val frames: List, + val creationFrames: List + ) { + fun allFrames() = + frames + creationFrames + } private fun buildRealStackFrameItem( frame: StackFrameProxyImpl ): RunningCoroutineStackFrameItem? { - val location = frame.location() + val location = frame.location() ?: return null return if (!location.safeCoroutineExitPointLineNumber()) - RunningCoroutineStackFrameItem(SkipCoroutineStackFrameProxyImpl(frame), location) + RunningCoroutineStackFrameItem(SkipCoroutineStackFrameProxyImpl(frame)) else null } @@ -94,14 +123,14 @@ class CoroutineFrameBuilder { fun coroutineExitFrame( frame: StackFrameProxyImpl, suspendContext: SuspendContextImpl - ): CoroutinePreflightStackFrame? { + ): CoroutinePreflightFrame? { return suspendContext.invokeInManagerThread { val sem = frame.location().isPreFlight() - if (sem.isCoroutineFound()) { + val preflightStackFrame = if (sem.isCoroutineFound()) { lookupContinuation(suspendContext, frame, sem) } else null - + preflightStackFrame } } @@ -109,7 +138,7 @@ class CoroutineFrameBuilder { suspendContext: SuspendContextImpl, frame: StackFrameProxyImpl, mode: SuspendExitMode - ): CoroutinePreflightStackFrame? { + ): CoroutinePreflightFrame? { if (!mode.isCoroutineFound()) return null @@ -133,10 +162,9 @@ class CoroutineFrameBuilder { val continuationHolder = ContinuationHolder.instance(context) val coroutineInfo = continuationHolder.extractCoroutineInfoData(continuation) ?: return null - val descriptor = StackFrameDescriptorImpl(frame, MethodsTracker()) - return CoroutinePreflightStackFrame( + return CoroutinePreflightFrame( coroutineInfo, - descriptor, + frame, theFollowingFrames, mode ) @@ -174,4 +202,4 @@ class CoroutineFrameBuilder { return null } } -} \ No newline at end of file +} diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/CoroutineUtils.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/CoroutineUtils.kt index e54aaf33411..eb2731a5e27 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/CoroutineUtils.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/CoroutineUtils.kt @@ -19,6 +19,7 @@ import com.intellij.xdebugger.XSourcePosition import com.sun.jdi.* import org.jetbrains.kotlin.idea.debugger.* import org.jetbrains.kotlin.idea.debugger.coroutine.data.SuspendExitMode +import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.invokeLater import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext import org.jetbrains.kotlin.idea.util.application.isUnitTestMode @@ -71,6 +72,12 @@ fun ReferenceType.isSuspendLambda() = fun Location.isInvokeSuspend() = safeMethod()?.isInvokeSuspend() ?: false +fun Location.isInvokeSuspendWithNegativeLineNumber() = + isInvokeSuspend() && safeLineNumber() < 0 + +fun Location.isFilteredInvokeSuspend() = + isInvokeSuspend() || isInvokeSuspendWithNegativeLineNumber() + fun StackFrameProxyImpl.variableValue(variableName: String): ObjectReference? { val continuationVariable = safeVisibleVariableByName(variableName) ?: return null return getValue(continuationVariable) as? ObjectReference ?: return null @@ -104,7 +111,9 @@ fun StackTraceElement.findPosition(project: Project): XSourcePosition? = getPosition(project, className, lineNumber) fun Location.findPosition(project: Project) = - getPosition(project, declaringType().name(), lineNumber()) + readAction { + getPosition(project, declaringType().name(), lineNumber()) + } private fun getPosition(project: Project, className: String, lineNumber: Int): XSourcePosition? { val psiFacade = JavaPsiFacade.getInstance(project) @@ -137,3 +146,13 @@ fun threadAndContextSupportsEvaluation(suspendContext: SuspendContextImpl, frame suspendContext.invokeInManagerThread { suspendContext.supportsEvaluation() && frameProxy?.threadProxy()?.supportsEvaluation() ?: false } ?: false + + +fun Location.sameLineAndMethod(location: Location?): Boolean = + location != null && location.safeMethod() == safeMethod() && location.safeLineNumber() == safeLineNumber() + +fun Location.isFilterFromTop(location: Location?): Boolean = + isFilteredInvokeSuspend() || sameLineAndMethod(location) || location?.safeMethod() == safeMethod() + +fun Location.isFilterFromBottom(location: Location?): Boolean = + sameLineAndMethod(location) \ No newline at end of file diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/KUtils.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/KUtils.kt index 79a33f88d1a..1871c140043 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/KUtils.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/KUtils.kt @@ -9,13 +9,7 @@ import com.intellij.debugger.engine.JavaStackFrame import com.intellij.debugger.jdi.StackFrameProxyImpl import com.intellij.debugger.memory.utils.StackFrameItem import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.project.Project -import com.intellij.psi.JavaPsiFacade -import com.intellij.psi.search.GlobalSearchScope -import com.intellij.xdebugger.XDebuggerUtil -import com.intellij.xdebugger.XSourcePosition import com.sun.jdi.Location -import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.ApplicationThreadExecutor import org.jetbrains.kotlin.idea.debugger.safeLineNumber import org.jetbrains.kotlin.idea.debugger.safeLocation import org.jetbrains.kotlin.idea.debugger.safeMethod diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/view/XCoroutineView.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/view/XCoroutineView.kt index 5a924f01ed4..300cd034792 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/view/XCoroutineView.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/view/XCoroutineView.kt @@ -205,10 +205,10 @@ class XCoroutineView(val project: Project, val session: XDebugSession) : managerThreadExecutor.on(suspendContext).invoke { val children = XValueChildrenList() val doubleFrameList = CoroutineFrameBuilder.build(infoData, suspendContext) - doubleFrameList?.stackTrace?.forEach { + doubleFrameList?.frames?.forEach { children.add(CoroutineFrameValue(infoData, it)) } - doubleFrameList?.creationStackTrace?.let { + doubleFrameList?.creationFrames?.let { children.add(CreationFramesContainer(infoData, it)) } node.addChildren(children, true) diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/view/XDebuggerTreeSelectedNodeListener.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/view/XDebuggerTreeSelectedNodeListener.kt index c395807da60..ea713b51eda 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/view/XDebuggerTreeSelectedNodeListener.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/view/XDebuggerTreeSelectedNodeListener.kt @@ -16,9 +16,7 @@ import com.intellij.xdebugger.frame.XStackFrame import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl import org.jetbrains.kotlin.idea.debugger.coroutine.data.* -import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.ApplicationThreadExecutor -import org.jetbrains.kotlin.idea.debugger.coroutine.util.findPosition -import org.jetbrains.kotlin.idea.debugger.coroutine.util.invokeInManagerThread +import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.invokeLater import org.jetbrains.kotlin.idea.debugger.coroutine.util.suspendContextImpl import org.jetbrains.kotlin.idea.debugger.invokeInManagerThread import java.awt.event.KeyAdapter @@ -26,7 +24,6 @@ import java.awt.event.KeyEvent import java.awt.event.MouseEvent class XDebuggerTreeSelectedNodeListener(val session: XDebugSession, val tree: XDebuggerTree) { - val applicationThreadExecutor = ApplicationThreadExecutor() val javaDebugProcess = session.debugProcess as JavaDebugProcess val debugProcess: DebugProcessImpl = javaDebugProcess.debuggerSession.process @@ -54,90 +51,38 @@ class XDebuggerTreeSelectedNodeListener(val session: XDebugSession, val tree: XD val valueContainer = node.valueContainer val suspendContext = session.suspendContextImpl() if (valueContainer is XCoroutineView.CoroutineFrameValue) { - when (val stackFrameItem = valueContainer.frameItem) { - is RunningCoroutineStackFrameItem -> { - val threadProxy = stackFrameItem.frame.threadProxy() - val isCurrentContext = suspendContext.thread == threadProxy - createStackAndSetFrame(threadProxy, { it.createStackFrame(stackFrameItem.frame) }, isCurrentContext) - } - is CreationCoroutineStackFrameItem -> { - val position = stackFrameItem.stackTraceElement.findPosition(session.project) ?: return false - val threadProxy = suspendContext.thread ?: return false - createStackAndSetFrame(threadProxy, { - val realFrame = threadProxy.forceFrames().first() ?: return@createStackAndSetFrame null - SyntheticStackFrame(stackFrameItem.descriptor(realFrame), emptyList(), position) - }) - } - is SuspendCoroutineStackFrameItem -> { - val threadProxy = suspendContext.thread ?: return false - val position = stackFrameItem.location.findPosition(session.project) - ?: return false + val frameItem = valueContainer.frameItem + val frame = frameItem.createFrame(debugProcess) ?: return false + + val executionStack = + if (frameItem is RunningCoroutineStackFrameItem) + createExecutionStack(frameItem.frame.threadProxy(), debugProcess) + else + suspendContext.thread?.let { + createExecutionStack(it, debugProcess) + } + + if (executionStack != null) + setCurrentStackFrame(executionStack, frame) - createStackAndSetFrame(threadProxy, { - val realFrame = threadProxy.forceFrames().first() ?: return@createStackAndSetFrame null - SyntheticStackFrame(stackFrameItem.descriptor(realFrame), stackFrameItem.spilledVariables, position) - }) - } - is RestoredCoroutineStackFrameItem -> { - val threadProxy = stackFrameItem.frame.threadProxy() - val position = stackFrameItem.location.findPosition(session.project) - ?: return false - createStackAndSetFrame(threadProxy, { - SyntheticStackFrame(stackFrameItem.descriptor(), stackFrameItem.spilledVariables, position) - }) - } - is DefaultCoroutineStackFrameItem, is SuspendCoroutineStackFrameItem -> { - val threadProxy = suspendContext.thread ?: return false - val position = stackFrameItem.location.findPosition(session.project) - ?: return false - createStackAndSetFrame(threadProxy, { - val realFrame = threadProxy.forceFrames().first() ?: return@createStackAndSetFrame null - val descriptor = when (stackFrameItem) { - is DefaultCoroutineStackFrameItem -> stackFrameItem.descriptor(realFrame) - is SuspendCoroutineStackFrameItem -> stackFrameItem.descriptor(realFrame) - else -> null - } ?: return@createStackAndSetFrame null - SyntheticStackFrame(descriptor, stackFrameItem.spilledVariables, position) - }) - } - else -> { - } - } } } return false } - fun createStackAndSetFrame( - threadReferenceProxy: ThreadReferenceProxyImpl, - stackFrameProvider: (executionStack: JavaExecutionStack) -> XStackFrame?, - isCurrentContext: Boolean = false - ) { - val stackFrameStack = debugProcess.invokeInManagerThread { - val executionStack = createExecutionStack(threadReferenceProxy, isCurrentContext); - val stackFrame = stackFrameProvider.invoke(executionStack) ?: return@invokeInManagerThread null - XStackFrameStack(stackFrame, executionStack) - } ?: return - setCurrentStackFrame(stackFrameStack) - } - - fun setCurrentStackFrame(stackFrameStack: XStackFrameStack) { - applicationThreadExecutor.schedule( - { - session.setCurrentStackFrame(stackFrameStack.executionStack, stackFrameStack.stackFrame, false) - }, tree - ) - } - - data class XStackFrameStack(val stackFrame: XStackFrame, val executionStack: XExecutionStack) - - private fun createExecutionStack(proxy: ThreadReferenceProxyImpl, isCurrentContext: Boolean = false): JavaExecutionStack { - val executionStack = JavaExecutionStack(proxy, debugProcess, isCurrentContext) - executionStack.initTopFrame() - return executionStack - } + fun setCurrentStackFrame(executionStack: XExecutionStack, stackFrame: XStackFrame) = + invokeLater(tree) { + session.setCurrentStackFrame(executionStack, stackFrame, false) + } } +fun createExecutionStack(threadReference: ThreadReferenceProxyImpl, debugProcess: DebugProcessImpl): JavaExecutionStack? = + debugProcess.invokeInManagerThread { + val executionStack = JavaExecutionStack(threadReference, debugProcess, debugProcess.isSameContext(threadReference)) + executionStack.initTopFrame() + executionStack + } + data class KeyMouseEvent(val keyEvent: KeyEvent?, val mouseEvent: MouseEvent?) { constructor(keyEvent: KeyEvent) : this(keyEvent, null) constructor(mouseEvent: MouseEvent) : this(null, mouseEvent) @@ -145,4 +90,7 @@ data class KeyMouseEvent(val keyEvent: KeyEvent?, val mouseEvent: MouseEvent?) { fun isKeyEvent() = keyEvent != null fun isMouseEvent() = mouseEvent != null -} \ No newline at end of file +} + +fun DebugProcessImpl.isSameContext(threadReference: ThreadReferenceProxyImpl): Boolean = + suspendManager.pausedContext.thread == threadReference \ No newline at end of file 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 d7011602bb2..e799ee5ab16 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 @@ -5,13 +5,7 @@ package org.jetbrains.kotlin.idea.debugger.test -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) { diff --git a/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/ContinuationStackTraceTestGenerated.java b/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/ContinuationStackTraceTestGenerated.java index b2ea65b1527..9112c7bc424 100644 --- a/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/ContinuationStackTraceTestGenerated.java +++ b/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/ContinuationStackTraceTestGenerated.java @@ -33,6 +33,11 @@ public class ContinuationStackTraceTestGenerated extends AbstractContinuationSta runTest("idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFun.kt"); } + @TestMetadata("suspendFunWithInner.kt") + public void testSuspendFunWithInner() throws Exception { + runTest("idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFunWithInner.kt"); + } + @TestMetadata("suspendLambda.kt") public void testSuspendLambda() throws Exception { runTest("idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendLambda.kt"); diff --git a/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/CoroutineDebuggerTestSuite.kt b/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/CoroutineDebuggerTestSuite.kt new file mode 100644 index 00000000000..3e2ee22f393 --- /dev/null +++ b/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/CoroutineDebuggerTestSuite.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.debugger.test + +import org.junit.runner.RunWith +import org.junit.runners.Suite + +@Suite.SuiteClasses( + ContinuationStackTraceTestGenerated::class, + XCoroutinesStackTraceTestGenerated::class +) +@RunWith(Suite::class) +class CoroutineDebuggerTestSuite \ No newline at end of file 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 d72abecfbb2..7e3944ab793 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 @@ -19,10 +19,11 @@ import com.intellij.openapi.roots.ui.configuration.libraryEditor.NewLibraryEdito import com.intellij.testFramework.EdtTestUtil import com.intellij.xdebugger.frame.XNamedValue import com.intellij.xdebugger.frame.XStackFrame +import com.intellij.xdebugger.impl.frame.XDebuggerFramesList 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.CoroutinePreflightFrame import org.jetbrains.kotlin.idea.debugger.coroutine.data.CreationCoroutineStackFrameItem import org.jetbrains.kotlin.idea.debugger.invokeInSuspendManagerThread import org.jetbrains.kotlin.idea.debugger.test.preference.DebuggerPreferences @@ -44,7 +45,7 @@ abstract class KotlinDescriptorTestCaseWithStackFrames() : KotlinDescriptorTestC val classPath = mutableListOf() protected fun out(frame: XStackFrame) { - out(INDENT_FRAME, XDebuggerTestUtil.getFramePresentation(frame)) + out(INDENT_FRAME, frame.javaClass.simpleName + " FRAME:" + XDebuggerTestUtil.getFramePresentation(frame)) outVariables(frame) } @@ -84,32 +85,28 @@ abstract class KotlinDescriptorTestCaseWithStackFrames() : KotlinDescriptorTestC out("Thread stack trace:") val stackFrames: List = XDebuggerTestUtil.collectFrames(executionStack) val suspendContextImpl = suspendContext as SuspendContextImpl - suspendContextImpl.runActionInSuspendCommand { - for (frame in stackFrames) { - if (frame is JavaStackFrame) { - out(frame) - val stackFrames = suspendContext.invokeInSuspendManagerThread(debugProcess) { - asyncStackTraceProvider?.getAsyncStackTrace(frame, suspendContextImpl) - } - if (stackFrames != null) { - if (stackFrames is PreflightProvider) { - val preflightFrame = stackFrames.getPreflight() - out(0, preflightFrame.coroutineInfoData.key.toString()) - } - for (frameItem in stackFrames) { - if (frameItem is CreationCoroutineStackFrameItem && frameItem.first) - out(0, "Creation stack frame") - - val frame: XStackFrame? = suspendContext.invokeInSuspendManagerThread(debugProcess) { - frameItem.createFrame(debugProcess) - } - frame?.let { - out(frame) - } + for (frame in stackFrames) { + if (frame is JavaStackFrame) { + out(frame) + if (frame is CoroutinePreflightFrame) { + val key = frame.coroutineInfoData.key + out(0, "CoroutineInfo: ${key.id} ${key.name} ${key.state}") + } + val stackFrames = suspendContext.invokeInSuspendManagerThread(debugProcess) { + asyncStackTraceProvider?.getAsyncStackTrace(frame, suspendContextImpl) + } + if (stackFrames != null) { + for (frameItem in stackFrames) { + val frame: XStackFrame? = + frameItem.createFrame(debugProcess) + if (frame is XDebuggerFramesList.ItemWithSeparatorAbove && frame.hasSeparatorAbove()) + out(0, frame.captionAboveOf) + frame?.let { + out(frame) } - return@runActionInSuspendCommand } + return@doWhenXSessionPausedThenResume } } } diff --git a/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/util/FramePrinter.kt b/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/util/FramePrinter.kt index e6df068568f..fac0b1b4bd4 100644 --- a/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/util/FramePrinter.kt +++ b/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/util/FramePrinter.kt @@ -31,7 +31,7 @@ import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree import com.intellij.xdebugger.impl.ui.tree.nodes.* import org.jetbrains.kotlin.idea.debugger.KotlinFrameExtraVariablesProvider -import org.jetbrains.kotlin.idea.debugger.coroutine.data.ContinuationValueDescriptorImpl +import org.jetbrains.kotlin.idea.debugger.coroutine.data.ContinuationVariableValueDescriptorImpl import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinCodeFragmentFactory import org.jetbrains.kotlin.idea.debugger.invokeInManagerThread import org.jetbrains.kotlin.idea.debugger.test.KOTLIN_LIBRARY_NAME @@ -275,7 +275,7 @@ private class Printer(private val delegate: FramePrinterDelegate, private val co is ThisDescriptorImpl -> "this" is FieldDescriptor -> "field" is ArrayElementDescriptor -> "element" - is ContinuationValueDescriptorImpl -> "cont" + is ContinuationVariableValueDescriptorImpl -> "cont" is MessageDescriptor -> "" else -> "unknown" } diff --git a/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/util/KotlinOutputChecker.kt b/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/util/KotlinOutputChecker.kt index a2842cc68ae..02f126a0785 100644 --- a/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/util/KotlinOutputChecker.kt +++ b/idea/jvm-debugger/jvm-debugger-test/test/org/jetbrains/kotlin/idea/debugger/test/util/KotlinOutputChecker.kt @@ -109,9 +109,10 @@ internal class KotlinOutputChecker( val disconnectedIndex = lines.indexOfFirst { it.startsWith(DISCONNECT_PREFIX) } lines[disconnectedIndex] = DISCONNECT_PREFIX - return lines.filter { - !(it.matches(JDI_BUG_OUTPUT_PATTERN_1) || it.matches(JDI_BUG_OUTPUT_PATTERN_2)) - }.joinToString("\n") + return lines + .map { it.replace("FRAME:(.*):\\d+".toRegex(), "$1:!LINE_NUMBER!") } + .filter { !(it.matches(JDI_BUG_OUTPUT_PATTERN_1) || it.matches(JDI_BUG_OUTPUT_PATTERN_2)) } + .joinToString("\n") } private fun buildOutputString(): String { diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFun.out b/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFun.out index 1680e7541a6..07a5035567a 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFun.out +++ b/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFun.out @@ -3,22 +3,22 @@ Run Java Connected to the target VM suspendFun.kt:28 Thread stack trace: - b:28, SuspendFunKt (coroutine1) + KotlinStackFrame b:!LINE_NUMBER!, SuspendFunKt (coroutine1) ($completion, b, bParam) - a:21, SuspendFunKt (coroutine1) + CoroutinePreflightFrame a:!LINE_NUMBER!, SuspendFunKt (coroutine1) ($completion, $continuation, $result, a, aParam) -CoroutineNameIdState(name=coroutine, id=-1, state=UNKNOWN, dispatcher=null) - test1:15, SuspendFunKt (coroutine1) - (i, test1) - invoke:9, SuspendFunKt$main$result$1 (coroutine1) +CoroutineInfo: -1 coroutine UNKNOWN + CoroutineStackFrame test1:!LINE_NUMBER!, SuspendFunKt (coroutine1) + ($completion, $continuation, $result, i, test1) + CoroutineStackFrame invoke:!LINE_NUMBER!, SuspendFunKt$main$result$1 (coroutine1) (continuation, p1, this) - invokeSuspend:121, IntrinsicsKt__IntrinsicsJvmKt$createCoroutineUnintercepted$$inlined$createCoroutineFromSuspendFunction$IntrinsicsKt__IntrinsicsJvmKt$3 (kotlin.coroutines.intrinsics) + CoroutineStackFrame invokeSuspend:!LINE_NUMBER!, 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) + CoroutineStackFrame resumeWith:!LINE_NUMBER!, BaseContinuationImpl (kotlin.coroutines.jvm.internal) ($i$a$-with-BaseContinuationImpl$resumeWith$1, $this$with, completion, current, param, result, this) - startCoroutine:128, ContinuationKt (kotlin.coroutines) + CoroutineStackFrame startCoroutine:!LINE_NUMBER!, ContinuationKt (kotlin.coroutines) ($this$startCoroutine, completion, receiver) - main:9, SuspendFunKt (coroutine1) + CoroutineStackFrame main:!LINE_NUMBER!, SuspendFunKt (coroutine1) (cnt) Disconnected from the target VM diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFunWithInner.kt b/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFunWithInner.kt new file mode 100644 index 00000000000..57bd5e161b0 --- /dev/null +++ b/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFunWithInner.kt @@ -0,0 +1,44 @@ +package continuation +// ATTACH_LIBRARY: maven(org.jetbrains.kotlinx:kotlinx-coroutines-debug:1.3.5)-javaagent + +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.yield + +fun main() { + val mainTestVal = "" + runBlocking { + val rootCoroutineVal = mainTestVal + TestSuspendA().a() + print("") + } +} + +class TestSuspendA { + val classField = "" + suspend fun a() { + val methodVal = "" + InClassB().b() + print("") + } + + class InClassB { + val inClassBField = "" + + suspend fun b() { + val inClassBMethodVal = "" + InClassC().c() + print("") + } + + inner class InClassC { + val inClassCField = inClassBField + + suspend fun c() { + yield() + val inClassCMethodVal = "" + //Breakpoint! + print("") + } + } + } +} \ No newline at end of file diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFunWithInner.out b/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFunWithInner.out new file mode 100644 index 00000000000..71db26183cf --- /dev/null +++ b/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendFunWithInner.out @@ -0,0 +1,46 @@ +LineBreakpoint created at suspendFunWithInner.kt:40 +Run Java +Connected to the target VM +suspendFunWithInner.kt:40 +Thread stack trace: + CoroutinePreflightFrame c:!LINE_NUMBER!, TestSuspendA$InClassB$InClassC (continuation) + ($completion, $continuation, $result, inClassCMethodVal, this) +CoroutineInfo: 1 coroutine RUNNING + CoroutineStackFrame b:!LINE_NUMBER!, TestSuspendA$InClassB (continuation) + (inClassBMethodVal, this) + CoroutineStackFrame a:!LINE_NUMBER!, TestSuspendA (continuation) + (methodVal, this) + CoroutineStackFrame invokeSuspend:!LINE_NUMBER!, SuspendFunWithInnerKt$main$1 (continuation) + ($this$runBlocking, rootCoroutineVal) + CoroutineStackFrame resumeWith:!LINE_NUMBER!, BaseContinuationImpl (kotlin.coroutines.jvm.internal) + ($i$a$-with-BaseContinuationImpl$resumeWith$1, $this$with, completion, current, param, result, this) + CoroutineStackFrame run:!LINE_NUMBER!, DispatchedTask (kotlinx.coroutines) + ($i$a$-withCoroutineContext-DispatchedTask$run$1, $i$f$withCoroutineContext, context, continuation, countOrElement$iv, delegate, exception, fatalException, job, oldValue$iv, state, taskContext, this) + CoroutineStackFrame processNextEvent:!LINE_NUMBER!, EventLoopImplBase (kotlinx.coroutines) + (delayed, this) + CoroutineStackFrame joinBlocking:!LINE_NUMBER!, BlockingCoroutine (kotlinx.coroutines) + (this) + CoroutineStackFrame runBlocking:!LINE_NUMBER!, BuildersKt__BuildersKt (kotlinx.coroutines) + (block, context, contextInterceptor, coroutine, currentThread, eventLoop, newContext) + CoroutineStackFrame runBlocking:!LINE_NUMBER!, BuildersKt (kotlinx.coroutines) + (block, context) + CoroutineStackFrame runBlocking$default:!LINE_NUMBER!, BuildersKt__BuildersKt (kotlinx.coroutines) + () + CoroutineStackFrame runBlocking$default:!LINE_NUMBER!, BuildersKt (kotlinx.coroutines) + () + CoroutineStackFrame main:!LINE_NUMBER!, SuspendFunWithInnerKt (continuation) + (mainTestVal) +Coroutine creation stack trace + CreationCoroutineStackFrame createCoroutineUnintercepted:!LINE_NUMBER!, IntrinsicsKt__IntrinsicsJvmKt (kotlin.coroutines.intrinsics) + () + CreationCoroutineStackFrame startCoroutineCancellable:!LINE_NUMBER!, CancellableKt (kotlinx.coroutines.intrinsics) + () + CreationCoroutineStackFrame runBlocking$default:!LINE_NUMBER!, BuildersKt (kotlinx.coroutines) + () + CreationCoroutineStackFrame main:!LINE_NUMBER!, SuspendFunWithInnerKt (continuation) + () + CreationCoroutineStackFrame FRAME:main:-1, SuspendFunWithInnerKt (continuation) + () +Disconnected from the target VM + +Process finished with exit code 0 \ No newline at end of file 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 fc8f0fea5fc..3e0b17a6199 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendLambda.out +++ b/idea/jvm-debugger/jvm-debugger-test/testData/continuation/suspendLambda.out @@ -3,24 +3,24 @@ Run Java Connected to the target VM suspendLambda.kt:12 Thread stack trace: - nextSequence:12, SuspendLambdaKt (continuation) + KotlinStackFrame nextSequence:!LINE_NUMBER!, SuspendLambdaKt (continuation) (terms, terms1) - invokeSuspend:23, SuspendLambdaKt$fibonacci$1 (continuation) + CoroutinePreflightFrame invokeSuspend:!LINE_NUMBER!, 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 +CoroutineInfo: -1 coroutine UNKNOWN + CoroutineStackFrame resumeWith:!LINE_NUMBER!, BaseContinuationImpl (kotlin.coroutines.jvm.internal) ($i$a$-with-BaseContinuationImpl$resumeWith$1, $this$with, completion, current, param, result, this) - hasNext:140, kotlin.sequences.SequenceBuilderIterator + CoroutineStackFrame hasNext:!LINE_NUMBER!, SequenceBuilderIterator (kotlin.sequences) (step, this) - hasNext:406, kotlin.sequences.TakeSequence$iterator$1 + CoroutineStackFrame hasNext:!LINE_NUMBER!, TakeSequence$iterator$1 (kotlin.sequences) (this) - toCollection:722, kotlin.sequences.SequencesKt___SequencesKt + CoroutineStackFrame toCollection:!LINE_NUMBER!, SequencesKt___SequencesKt (kotlin.sequences) ($this$toCollection, destination) - toMutableList:752, kotlin.sequences.SequencesKt___SequencesKt + CoroutineStackFrame toMutableList:!LINE_NUMBER!, SequencesKt___SequencesKt (kotlin.sequences) ($this$toMutableList) - toList:743, kotlin.sequences.SequencesKt___SequencesKt + CoroutineStackFrame toList:!LINE_NUMBER!, SequencesKt___SequencesKt (kotlin.sequences) ($this$toList) - main:5, continuation.SuspendLambdaKt + CoroutineStackFrame main:!LINE_NUMBER!, SuspendLambdaKt (continuation) (a) 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 f8b776007d1..b226e88e1bd 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun.out +++ b/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun.out @@ -3,43 +3,43 @@ Run Java Connected to the target VM coroutineSuspendFun.kt:29 Thread stack trace: - c:29, CoroutineSuspendFunKt (continuation) + KotlinStackFrame c:!LINE_NUMBER!, CoroutineSuspendFunKt (continuation) ($completion, c, paramB) - b:23, CoroutineSuspendFunKt (continuation) + CoroutinePreflightFrame b:!LINE_NUMBER!, CoroutineSuspendFunKt (continuation) ($completion, $continuation, $result, b, paramA) -CoroutineNameIdState(name=coroutine, id=1, state=RUNNING, dispatcher=BlockingEventLoop@6f45df59) - a:16, CoroutineSuspendFunKt (continuation) +CoroutineInfo: 1 coroutine RUNNING + CoroutineStackFrame a:!LINE_NUMBER!, CoroutineSuspendFunKt (continuation) (a) - invokeSuspend:10, CoroutineSuspendFunKt$main$1 (continuation) + CoroutineStackFrame invokeSuspend:!LINE_NUMBER!, CoroutineSuspendFunKt$main$1 (continuation) ($this$runBlocking) - resumeWith:33, BaseContinuationImpl (kotlin.coroutines.jvm.internal) + CoroutineStackFrame resumeWith:!LINE_NUMBER!, BaseContinuationImpl (kotlin.coroutines.jvm.internal) ($i$a$-with-BaseContinuationImpl$resumeWith$1, $this$with, completion, current, param, result, this) - run:56, DispatchedTask (kotlinx.coroutines) + CoroutineStackFrame run:!LINE_NUMBER!, DispatchedTask (kotlinx.coroutines) ($i$a$-withCoroutineContext-DispatchedTask$run$1, $i$f$withCoroutineContext, context, continuation, countOrElement$iv, delegate, exception, fatalException, job, oldValue$iv, state, taskContext, this) - processNextEvent:272, EventLoopImplBase (kotlinx.coroutines) + CoroutineStackFrame processNextEvent:!LINE_NUMBER!, EventLoopImplBase (kotlinx.coroutines) (delayed, this) - joinBlocking:79, BlockingCoroutine (kotlinx.coroutines) + CoroutineStackFrame joinBlocking:!LINE_NUMBER!, BlockingCoroutine (kotlinx.coroutines) (this) - runBlocking:54, BuildersKt__BuildersKt (kotlinx.coroutines) + CoroutineStackFrame runBlocking:!LINE_NUMBER!, BuildersKt__BuildersKt (kotlinx.coroutines) (block, context, contextInterceptor, coroutine, currentThread, eventLoop, newContext) - runBlocking:1, BuildersKt (kotlinx.coroutines) + CoroutineStackFrame runBlocking:!LINE_NUMBER!, BuildersKt (kotlinx.coroutines) + (block, context) + CoroutineStackFrame runBlocking$default:!LINE_NUMBER!, BuildersKt__BuildersKt (kotlinx.coroutines) () - runBlocking$default:36, BuildersKt__BuildersKt (kotlinx.coroutines) + CoroutineStackFrame runBlocking$default:!LINE_NUMBER!, BuildersKt (kotlinx.coroutines) () - runBlocking$default:1, BuildersKt (kotlinx.coroutines) - () - main:9, CoroutineSuspendFunKt (continuation) + CoroutineStackFrame main:!LINE_NUMBER!, CoroutineSuspendFunKt (continuation) (main) -Creation stack frame - createCoroutineUnintercepted:116, IntrinsicsKt__IntrinsicsJvmKt (kotlin.coroutines.intrinsics) +Coroutine creation stack trace + CreationCoroutineStackFrame createCoroutineUnintercepted:!LINE_NUMBER!, IntrinsicsKt__IntrinsicsJvmKt (kotlin.coroutines.intrinsics) () - startCoroutineCancellable:26, CancellableKt (kotlinx.coroutines.intrinsics) + CreationCoroutineStackFrame startCoroutineCancellable:!LINE_NUMBER!, CancellableKt (kotlinx.coroutines.intrinsics) () - runBlocking$default:1, BuildersKt (kotlinx.coroutines) + CreationCoroutineStackFrame runBlocking$default:!LINE_NUMBER!, BuildersKt (kotlinx.coroutines) () - main:9, CoroutineSuspendFunKt (continuation) + CreationCoroutineStackFrame main:!LINE_NUMBER!, CoroutineSuspendFunKt (continuation) () - main:-1, CoroutineSuspendFunKt (continuation) + CreationCoroutineStackFrame FRAME:main:-1, CoroutineSuspendFunKt (continuation) () Disconnected from the target VM diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun136.kt b/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun136.kt index e355828a724..b5a7796e728 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun136.kt +++ b/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun136.kt @@ -1,5 +1,5 @@ package continuation -// ATTACH_LIBRARY: maven(org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.5-SNAPSHOT)-javaagent +// ATTACH_LIBRARY: maven(org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.6)-javaagent import kotlinx.coroutines.runBlocking import kotlinx.coroutines.yield diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun136.out b/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun136.out index a7b51ff002b..4dbe765424e 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun136.out +++ b/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun136.out @@ -3,43 +3,43 @@ Run Java Connected to the target VM coroutineSuspendFun136.kt:29 Thread stack trace: - c:29, CoroutineSuspendFun136Kt (continuation) + KotlinStackFrame c:!LINE_NUMBER!, CoroutineSuspendFun136Kt (continuation) ($completion, c, paramB) - b:23, CoroutineSuspendFun136Kt (continuation) + CoroutinePreflightFrame b:!LINE_NUMBER!, CoroutineSuspendFun136Kt (continuation) ($completion, $continuation, $result, b, paramA) -CoroutineNameIdState(name=coroutine, id=1, state=RUNNING, dispatcher=BlockingEventLoop@305fd85d) - a:16, CoroutineSuspendFun136Kt (continuation) +CoroutineInfo: 1 coroutine RUNNING + CoroutineStackFrame a:!LINE_NUMBER!, CoroutineSuspendFun136Kt (continuation) (a) - invokeSuspend:10, CoroutineSuspendFun136Kt$main$1 (continuation) + CoroutineStackFrame invokeSuspend:!LINE_NUMBER!, CoroutineSuspendFun136Kt$main$1 (continuation) ($this$runBlocking) - resumeWith:33, BaseContinuationImpl (kotlin.coroutines.jvm.internal) + CoroutineStackFrame resumeWith:!LINE_NUMBER!, BaseContinuationImpl (kotlin.coroutines.jvm.internal) ($i$a$-with-BaseContinuationImpl$resumeWith$1, $this$with, completion, current, param, result, this) - run:56, DispatchedTask (kotlinx.coroutines) + CoroutineStackFrame run:!LINE_NUMBER!, DispatchedTask (kotlinx.coroutines) ($i$a$-withCoroutineContext-DispatchedTask$run$1, $i$f$withCoroutineContext, context, continuation, countOrElement$iv, delegate, exception, fatalException, job, oldValue$iv, state, taskContext, this) - processNextEvent:274, EventLoopImplBase (kotlinx.coroutines) + CoroutineStackFrame processNextEvent:!LINE_NUMBER!, EventLoopImplBase (kotlinx.coroutines) (delayed, task, this) - joinBlocking:79, BlockingCoroutine (kotlinx.coroutines) + CoroutineStackFrame joinBlocking:!LINE_NUMBER!, BlockingCoroutine (kotlinx.coroutines) (this) - runBlocking:54, BuildersKt__BuildersKt (kotlinx.coroutines) + CoroutineStackFrame runBlocking:!LINE_NUMBER!, BuildersKt__BuildersKt (kotlinx.coroutines) (block, context, contextInterceptor, coroutine, currentThread, eventLoop, newContext) - runBlocking:1, BuildersKt (kotlinx.coroutines) + CoroutineStackFrame runBlocking:!LINE_NUMBER!, BuildersKt (kotlinx.coroutines) + (block, context) + CoroutineStackFrame runBlocking$default:!LINE_NUMBER!, BuildersKt__BuildersKt (kotlinx.coroutines) () - runBlocking$default:36, BuildersKt__BuildersKt (kotlinx.coroutines) + CoroutineStackFrame runBlocking$default:!LINE_NUMBER!, BuildersKt (kotlinx.coroutines) () - runBlocking$default:1, BuildersKt (kotlinx.coroutines) - () - main:9, CoroutineSuspendFun136Kt (continuation) + CoroutineStackFrame main:!LINE_NUMBER!, CoroutineSuspendFun136Kt (continuation) (main) -Creation stack frame - createCoroutineUnintercepted:116, IntrinsicsKt__IntrinsicsJvmKt (kotlin.coroutines.intrinsics) +Coroutine creation stack trace + CreationCoroutineStackFrame createCoroutineUnintercepted:!LINE_NUMBER!, IntrinsicsKt__IntrinsicsJvmKt (kotlin.coroutines.intrinsics) () - startCoroutineCancellable:26, CancellableKt (kotlinx.coroutines.intrinsics) + CreationCoroutineStackFrame startCoroutineCancellable:!LINE_NUMBER!, CancellableKt (kotlinx.coroutines.intrinsics) () - runBlocking$default:1, BuildersKt (kotlinx.coroutines) + CreationCoroutineStackFrame runBlocking$default:!LINE_NUMBER!, BuildersKt (kotlinx.coroutines) () - main:9, CoroutineSuspendFun136Kt (continuation) + CreationCoroutineStackFrame main:!LINE_NUMBER!, CoroutineSuspendFun136Kt (continuation) () - main:-1, CoroutineSuspendFun136Kt (continuation) + CreationCoroutineStackFrame FRAME:main:-1, CoroutineSuspendFun136Kt (continuation) () Disconnected from the target VM diff --git a/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/suspendMain.out b/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/suspendMain.out index 792ce207276..8d7b6f38697 100644 --- a/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/suspendMain.out +++ b/idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/suspendMain.out @@ -3,22 +3,22 @@ Run Java Connected to the target VM suspendMain.kt:15 Thread stack trace: - invokeSuspend:15, SuspendMainKt$main$2 (continuation) + CoroutinePreflightFrame invokeSuspend:!LINE_NUMBER!, SuspendMainKt$main$2 (continuation) ($result, $this$coroutineScope, this) -CoroutineNameIdState(name=coroutine, id=-1, state=UNKNOWN, dispatcher=null) - startUndispatchedOrReturn:91, UndispatchedKt (kotlinx.coroutines.intrinsics) +CoroutineInfo: -1 coroutine UNKNOWN + CoroutineStackFrame startUndispatchedOrReturn:!LINE_NUMBER!, UndispatchedKt (kotlinx.coroutines.intrinsics) ($i$a$-undispatchedResult-UndispatchedKt$startUndispatchedOrReturn$2, $i$f$undispatchedResult, $this$startUndispatchedOrReturn, $this$undispatchedResult$iv, block, receiver) - coroutineScope:177, CoroutineScopeKt (kotlinx.coroutines) + CoroutineStackFrame coroutineScope:!LINE_NUMBER!, CoroutineScopeKt (kotlinx.coroutines) ($completion, $i$a$-suspendCoroutineUninterceptedOrReturn-CoroutineScopeKt$coroutineScope$2, block, coroutine, uCont) - main:9, SuspendMainKt (continuation) + CoroutineStackFrame main:!LINE_NUMBER!, SuspendMainKt (continuation) ($completion) - invokeSuspend:86, IntrinsicsKt__IntrinsicsJvmKt$createCoroutineUnintercepted$$inlined$createCoroutineFromSuspendFunction$IntrinsicsKt__IntrinsicsJvmKt$1 (kotlin.coroutines.intrinsics) + CoroutineStackFrame invokeSuspend:!LINE_NUMBER!, IntrinsicsKt__IntrinsicsJvmKt$createCoroutineUnintercepted$$inlined$createCoroutineFromSuspendFunction$IntrinsicsKt__IntrinsicsJvmKt$1 (kotlin.coroutines.intrinsics) ($i$a$-createCoroutineFromSuspendFunction-IntrinsicsKt__IntrinsicsJvmKt$createCoroutineUnintercepted$1, it, result, this) - resumeWith:33, BaseContinuationImpl (kotlin.coroutines.jvm.internal) + CoroutineStackFrame resumeWith:!LINE_NUMBER!, BaseContinuationImpl (kotlin.coroutines.jvm.internal) ($i$a$-with-BaseContinuationImpl$resumeWith$1, $this$with, completion, current, param, result, this) - startCoroutine:114, ContinuationKt (kotlin.coroutines) + CoroutineStackFrame startCoroutine:!LINE_NUMBER!, ContinuationKt (kotlin.coroutines) ($this$startCoroutine, completion) - runSuspend:19, RunSuspendKt (kotlin.coroutines.jvm.internal) + CoroutineStackFrame runSuspend:!LINE_NUMBER!, RunSuspendKt (kotlin.coroutines.jvm.internal) (block, run) Disconnected from the target VM diff --git a/tests/mute-common.csv b/tests/mute-common.csv index 8e982c34253..535de205ac6 100644 --- a/tests/mute-common.csv +++ b/tests/mute-common.csv @@ -67,8 +67,3 @@ org.jetbrains.kotlin.idea.debugger.test.AsyncStackTraceTestGenerated.testAsyncLa org.jetbrains.kotlin.idea.debugger.test.AsyncStackTraceTestGenerated.testAsyncSimple, redesign test AsyncStackTraces,, org.jetbrains.kotlin.idea.debugger.test.KotlinSteppingTestGenerated.StepOver.testStepOverInlinedLambdaStdlib, fails after advancing bootstrap KT-37879,, org.jetbrains.kotlin.incremental.IncrementalJsKlibCompilerRunnerTestGenerated.ClassHierarchyAffected.testMethodRemoved, FO in klib required,, -org.jetbrains.kotlin.idea.debugger.test.XCoroutinesStackTraceTestGenerated.testCoroutineSuspendFun136, running test on SNAPSHOT version,, -org.jetbrains.kotlin.idea.debugger.test.XCoroutinesStackTraceTestGenerated.testCoroutineSuspendFun, unstable,, -org.jetbrains.kotlin.idea.debugger.test.XCoroutinesStackTraceTestGenerated.testSuspendMain, unstable,, -org.jetbrains.kotlin.idea.debugger.test.ContinuationStackTraceTestGenerated.testSuspendLambda, unstable,, -org.jetbrains.kotlin.idea.debugger.test.ContinuationStackTraceTestGenerated.testSuspendFun, unstable in 201/202,, \ No newline at end of file