(CoroutineDebugger) Minor fixes, kotlinx.coroutines version fix

This commit is contained in:
Vladimir Ilmov
2020-04-20 16:32:29 +02:00
parent 0ce8ca7bcd
commit 73f5e48518
22 changed files with 197 additions and 179 deletions
@@ -7,7 +7,9 @@ package org.jetbrains.kotlin.idea.debugger
import com.intellij.debugger.engine.DebugProcessImpl
import com.intellij.debugger.engine.DebuggerManagerThreadImpl
import com.intellij.debugger.engine.SuspendContextImpl
import com.intellij.debugger.engine.events.DebuggerCommandImpl
import com.intellij.debugger.engine.events.SuspendContextCommandImpl
import com.intellij.debugger.impl.DebuggerContextImpl
import com.intellij.psi.PsiElement
import com.sun.jdi.*
@@ -84,6 +86,24 @@ fun <T : Any> DebugProcessImpl.invokeInManagerThread(f: (DebuggerContextImpl) ->
return result
}
fun <T : Any> SuspendContextImpl.invokeInSuspendManagerThread(debugProcessImpl: DebugProcessImpl, f: (SuspendContextImpl) -> T?): T? {
var result: T? = null
val command: SuspendContextCommandImpl = object : SuspendContextCommandImpl(this) {
override fun contextAction() {
result = runReadAction { f(this@invokeInSuspendManagerThread) }
}
}
when {
DebuggerManagerThreadImpl.isManagerThread() ->
debugProcessImpl.managerThread.invoke(command)
else ->
debugProcessImpl.managerThread.invokeAndWait(command)
}
return result
}
private fun lambdaOrdinalByArgument(elementAt: KtFunction, context: BindingContext): Int {
val type = asmTypeForAnonymousClass(context, elementAt)
return type.className.substringAfterLast("$").toInt()
@@ -6,10 +6,8 @@
package org.jetbrains.kotlin.idea.debugger.coroutine
import com.intellij.debugger.DebuggerInvocationUtil
import com.intellij.debugger.engine.DebugProcessImpl
import com.intellij.debugger.engine.JavaDebugProcess
import com.intellij.debugger.engine.SuspendContextImpl
import com.intellij.debugger.impl.PrioritizedTask
import com.intellij.execution.configurations.DebuggingRunnerData
import com.intellij.execution.configurations.JavaParameters
import com.intellij.execution.configurations.RunConfigurationBase
@@ -18,7 +16,6 @@ import com.intellij.execution.ui.layout.PlaceInGrid
import com.intellij.openapi.Disposable
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.registry.Registry
import com.intellij.ui.content.Content
import com.intellij.util.messages.MessageBusConnection
import com.intellij.xdebugger.XDebugProcess
@@ -49,15 +46,15 @@ class DebuggerConnection(
val kotlinxCoroutinesDebug = params.classPath?.pathList?.firstOrNull { it.contains("kotlinx-coroutines-debug") }
val mode = if (kotlinxCoroutinesDebug != null) {
CoroutineDebuggerMode.VERSION_UP_TO_1_3_4
CoroutineDebuggerMode.VERSION_UP_TO_1_3_5
} else if (kotlinxCoroutinesCore != null) {
determineCoreVersionMode(kotlinxCoroutinesCore)
} else
CoroutineDebuggerMode.DISABLED
when (mode) {
CoroutineDebuggerMode.VERSION_1_3_5_AND_UP -> initializeCoroutineAgent(params, kotlinxCoroutinesCore)
CoroutineDebuggerMode.VERSION_UP_TO_1_3_4 -> initializeCoroutineAgent(params, kotlinxCoroutinesDebug)
CoroutineDebuggerMode.VERSION_1_3_6_AND_UP -> initializeCoroutineAgent(params, kotlinxCoroutinesCore)
CoroutineDebuggerMode.VERSION_UP_TO_1_3_5 -> initializeCoroutineAgent(params, kotlinxCoroutinesDebug)
else -> log.debug("CoroutineDebugger disabled.")
}
}
@@ -69,9 +66,9 @@ class DebuggerConnection(
val matchResult = regex.matchEntire(kotlinxCoroutinesCore) ?: return CoroutineDebuggerMode.DISABLED
val coroutinesCoreVersion = DefaultArtifactVersion(matchResult.groupValues.get(1))
val versionToCompareTo = DefaultArtifactVersion("1.3.4")
val versionToCompareTo = DefaultArtifactVersion("1.3.5")
return if (versionToCompareTo.compareTo(coroutinesCoreVersion) < 0)
CoroutineDebuggerMode.VERSION_1_3_5_AND_UP
CoroutineDebuggerMode.VERSION_1_3_6_AND_UP
else
CoroutineDebuggerMode.DISABLED
}
@@ -96,7 +93,7 @@ class DebuggerConnection(
override fun processStopped(debugProcess: XDebugProcess) {
val rootDisposable = disposable
if (rootDisposable is Disposable && debugProcess is JavaDebugProcess && debugProcess.session.suspendContext is SuspendContextImpl) {
ManagerThreadExecutor(debugProcess).on(debugProcess.session.suspendContext).schedule {
ManagerThreadExecutor(debugProcess).on(debugProcess.session.suspendContext).invoke {
Disposer.dispose(rootDisposable)
disposable = null
}
@@ -124,6 +121,6 @@ class DebuggerConnection(
enum class CoroutineDebuggerMode {
DISABLED,
VERSION_UP_TO_1_3_4,
VERSION_1_3_5_AND_UP
VERSION_UP_TO_1_3_5,
VERSION_1_3_6_AND_UP
}
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.idea.debugger.coroutine.data
import com.sun.jdi.ObjectReference
import com.sun.jdi.ThreadReference
import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutineInfoData.Companion.DEFAULT_COROUTINE_NAME
import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutineInfoData.Companion.DEFAULT_COROUTINE_STATE
import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.mirror.*
import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger
@@ -56,9 +58,9 @@ data class CoroutineNameIdState(val name: String, val id: String, val state: Sta
companion object {
fun instance(mirror: MirrorOfCoroutineInfo): CoroutineNameIdState =
CoroutineNameIdState(
mirror.context?.name ?: "coroutine",
mirror.context?.name ?: DEFAULT_COROUTINE_NAME,
"${mirror.sequenceNumber}",
State.valueOf(mirror.state ?: "UNKNOWN"),
State.valueOf(mirror.state ?: DEFAULT_COROUTINE_STATE),
mirror.context?.dispatcher
)
}
@@ -49,14 +49,12 @@ class CoroutinePreflightStackFrame(
override fun getVisibleVariables(): List<LocalVariableProxyImpl> {
// skip restored variables
return super.getVisibleVariables().filter { v -> firstFrameVariables.find { it.name == v.name() } == null }
return super.getVisibleVariables().filter { v -> ! firstFrameVariables.any { it.name == v.name() } }
}
override fun isInLibraryContent() =
false
override fun isInLibraryContent() = false
override fun isSynthetic() =
false
override fun isSynthetic() = false
fun restoredStackTrace() =
coroutineInfoData.restoredStackTrace(mode)
@@ -69,7 +67,7 @@ enum class SuspendExitMode {
this == SUSPEND_LAMBDA || this == SUSPEND_METHOD_PARAMETER
fun isSuspendMethodParameter() =
this == SuspendExitMode.SUSPEND_METHOD_PARAMETER
this == SUSPEND_METHOD_PARAMETER
}
class CreationCoroutineStackFrame(debugProcess: DebugProcessImpl, item: StackFrameItem) : CoroutineStackFrame(debugProcess, item) {
@@ -81,11 +79,7 @@ class CreationCoroutineStackFrame(debugProcess: DebugProcessImpl, item: StackFra
open class CoroutineStackFrame(debugProcess: DebugProcessImpl, val item: StackFrameItem, val realStackFrame: XStackFrame? = null) :
StackFrameItem.CapturedStackFrame(debugProcess, item) {
override fun customizePresentation(component: ColoredTextContainer) {
if (coroutineDebuggerTraceEnabled())
component.append("${item.javaClass.simpleName} / ${this.javaClass.simpleName} ", SimpleTextAttributes.GRAYED_ATTRIBUTES)
super.customizePresentation(component)
}
override fun computeChildren(node: XCompositeNode) {
if (realStackFrame != null)
realStackFrame.computeChildren(node)
@@ -93,7 +87,6 @@ open class CoroutineStackFrame(debugProcess: DebugProcessImpl, val item: StackFr
super.computeChildren(node)
}
override fun getCaptionAboveOf() = "CoroutineExit"
override fun hasSeparatorAbove(): Boolean =
@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.mirror.*
import org.jetbrains.kotlin.idea.debugger.coroutine.util.*
import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext
class ContinuationHolder(val context: DefaultExecutionContext) {
class ContinuationHolder private constructor(val context: DefaultExecutionContext) {
private val debugMetadata: DebugMetadata? = DebugMetadata.instance(context)
private val locationCache = LocationCache(context)
private val debugProbesImpl = DebugProbesImpl.instance(context)
@@ -70,6 +70,7 @@ class ContinuationHolder(val context: DefaultExecutionContext) {
val id = standAloneCoroutineMirror.context.id
val name = standAloneCoroutineMirror.context.name ?: CoroutineInfoData.DEFAULT_COROUTINE_NAME
val toString = reference.string(value, context)
// trying to get coroutine information by calling JobSupport.toString(), ${nameString()}{${stateString(state)}}@$hexAddress
val r = """\w+\{(\w+)\}\@([\w\d]+)""".toRegex()
val matcher = r.toPattern().matcher(toString)
if (matcher.matches()) {
@@ -94,6 +95,9 @@ class ContinuationHolder(val context: DefaultExecutionContext) {
companion object {
val log by logger
fun instance(context: DefaultExecutionContext) =
ContinuationHolder(context)
private fun stateOf(state: String?): State =
when (state) {
"Active" -> State.RUNNING
@@ -104,8 +108,6 @@ class ContinuationHolder(val context: DefaultExecutionContext) {
"New" -> State.NEW
else -> State.UNKNOWN
}
}
}
@@ -129,5 +131,4 @@ fun FieldVariable.toJavaValue(continuation: ObjectReference, context: DefaultExe
context.debugProcess.xdebugProcess!!.nodeManager,
false
)
}
@@ -18,7 +18,7 @@ import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext
class CoroutineNoLibraryProxy(val executionContext: DefaultExecutionContext) : CoroutineInfoProvider {
val log by logger
val debugMetadataKtType = executionContext.findCoroutineMetadataType()
val holder = ContinuationHolder(executionContext)
val holder = ContinuationHolder.instance(executionContext)
override fun dumpCoroutinesInfo(): List<CoroutineInfoData> {
val vm = executionContext.vm
@@ -55,7 +55,7 @@ class CoroutineNoLibraryProxy(val executionContext: DefaultExecutionContext) : C
): CoroutineInfoData? {
val mirror = ccMirrorProvider.mirror(dispatchedContinuation, executionContext) ?: return null
val continuation = mirror.delegate?.continuation ?: return null
return holder.extractCoroutineInfoData(continuation)
return holder?.extractCoroutineInfoData(continuation)
}
private fun dispatchedContinuation(resultList: MutableList<CoroutineInfoData>): Boolean {
@@ -75,7 +75,7 @@ class CoroutineNoLibraryProxy(val executionContext: DefaultExecutionContext) : C
private fun extractDispatchedContinuation(dispatchedContinuation: ObjectReference, continuation: Field): CoroutineInfoData? {
debugMetadataKtType ?: return null
val initialContinuation = dispatchedContinuation.getValue(continuation) as ObjectReference
return holder.extractCoroutineInfoData(initialContinuation)
return holder?.extractCoroutineInfoData(initialContinuation)
}
}
@@ -34,16 +34,18 @@ class ManagerThreadExecutor(val debugProcess: DebugProcessImpl) {
constructor(sc: XSuspendContext, priority: PrioritizedTask.Priority) : this(sc as SuspendContextImpl, priority)
fun schedule(f: (SuspendContextImpl) -> Unit) {
val suspendContextCommand = object : SuspendContextCommandImpl(suspendContext) {
fun invoke(f: (SuspendContextImpl) -> Unit) {
debugProcess.managerThread.invoke(makeCommand(f))
}
private fun makeCommand(f: (SuspendContextImpl) -> Unit) =
object : SuspendContextCommandImpl(suspendContext) {
override fun getPriority() = this@ManagerThreadExecutorInstance.priority
override fun contextAction(suspendContext: SuspendContextImpl) {
f(suspendContext)
}
}
debugProcess.managerThread.invoke(suspendContextCommand)
}
}
}
@@ -53,7 +55,7 @@ class ApplicationThreadExecutor {
}
fun schedule(f: () -> Unit, component: Component) {
return ApplicationManager.getApplication().invokeLater( { f() }, ModalityState.stateForComponent(component))
return ApplicationManager.getApplication().invokeLater({ f() }, ModalityState.stateForComponent(component))
}
fun schedule(f: () -> Unit) {
@@ -18,10 +18,10 @@ abstract class BaseDynamicMirror<T>(val value: ObjectReference, val name: String
fun makeField(fieldName: String): Field? =
cls?.let { it.fieldByName(fieldName) }
fun makeMethod(methodName: String): Method? =
fun findMethod(methodName: String): Method? =
cls?.let { it.methodsByName(methodName).single() }
fun makeMethod(methodName: String, signature: String): Method? =
fun findMethod(methodName: String, signature: String): Method? =
cls?.let { it.methodsByName(methodName, signature).single() }
fun isCompatible(value: ObjectReference?) =
@@ -170,8 +170,8 @@ data class MirrorOfCoroutineInfo(
class CoroutineStackFrame(value: ObjectReference, context: DefaultExecutionContext) :
BaseDynamicMirror<MirrorOfCoroutineStackFrame>(value, "kotlin.coroutines.jvm.internal.CoroutineStackFrame", context) {
private val stackTraceElementMirror = StackTraceElement(context)
private val callerFrameMethod = makeMethod("getCallerFrame")
private val getStackTraceElementMethod = makeMethod("getStackTraceElement")
private val callerFrameMethod = findMethod("getCallerFrame")
private val getStackTraceElementMethod = findMethod("getStackTraceElement")
override fun fetchMirror(value: ObjectReference, context: DefaultExecutionContext): MirrorOfCoroutineStackFrame? {
val objectReference = objectValue(value, callerFrameMethod, context)
@@ -6,10 +6,8 @@
package org.jetbrains.kotlin.idea.debugger.coroutine.proxy.mirror
import com.sun.jdi.ArrayReference
import com.sun.jdi.ClassType
import com.sun.jdi.ObjectReference
import com.sun.jdi.StringReference
import org.jetbrains.kotlin.idea.debugger.coroutine.util.isBaseContinuationImpl
import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger
import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext
@@ -20,10 +18,8 @@ class DebugMetadata private constructor(context: DefaultExecutionContext) :
makeMethod("getSpilledVariableFieldMapping", "(Lkotlin/coroutines/jvm/internal/BaseContinuationImpl;)[Ljava/lang/String;")
val baseContinuationImpl = BaseContinuationImpl(context, this)
override fun fetchMirror(value: ObjectReference, context: DefaultExecutionContext): MirrorOfDebugProbesImpl? {
// @TODO fix this
return null
}
override fun fetchMirror(value: ObjectReference, context: DefaultExecutionContext): MirrorOfDebugProbesImpl? =
throw IllegalStateException("Not meant to be mirrored.")
fun fetchContinuationStack(continuation: ObjectReference, context: DefaultExecutionContext): MirrorOfContinuationStack {
val coroutineStack = mutableListOf<MirrorOfStackFrame>()
@@ -45,13 +41,14 @@ class DebugMetadata private constructor(context: DefaultExecutionContext) :
companion object {
val log by logger
fun instance(context: DefaultExecutionContext) =
fun instance(context: DefaultExecutionContext): DebugMetadata? {
try {
DebugMetadata(context)
return DebugMetadata(context)
} catch (e: IllegalStateException) {
log.warn("Attempt to access DebugMetadata", e)
null
}
return null
}
}
}
@@ -87,7 +84,8 @@ class BaseContinuationImpl(context: DefaultExecutionContext, private val debugMe
val length = getSpilledVariableFieldMappingReference.length() / 2
val fieldVariables = ArrayList<FieldVariable>()
for (index in 0 until length) {
fieldVariables.add(getFieldVariableName(getSpilledVariableFieldMappingReference, index) ?: continue)
var fieldVariable = getFieldVariableName(getSpilledVariableFieldMappingReference, index) ?: continue
fieldVariables.add(fieldVariable)
}
return fieldVariables
}
@@ -10,13 +10,9 @@ 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.util.containers.addIfNotNull
import com.sun.jdi.ObjectReference
import org.jetbrains.kotlin.idea.debugger.coroutine.data.*
import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.ContinuationHolder
import org.jetbrains.kotlin.idea.debugger.safeLineNumber
import org.jetbrains.kotlin.idea.debugger.safeLocation
import org.jetbrains.kotlin.idea.debugger.safeMethod
import java.lang.Integer.min
@@ -42,12 +38,17 @@ class CoroutineFrameBuilder {
for (runningStackFrameProxy in realFrames) {
val preflightStackFrame = coroutineExitFrame(runningStackFrameProxy, suspendContext)
if (preflightStackFrame != null) {
coroutineStackFrameList.addIfNotNull(buildRealStackFrameItem(preflightStackFrame.stackFrameProxy))
buildRealStackFrameItem(preflightStackFrame.stackFrameProxy)?.let {
coroutineStackFrameList.add(it)
}
val doubleFrameList = build(preflightStackFrame, suspendContext)
coroutineStackFrameList.addAll(doubleFrameList.stackTrace)
return DoubleFrameList(coroutineStackFrameList, doubleFrameList.creationStackTrace)
} else {
coroutineStackFrameList.addIfNotNull(buildRealStackFrameItem(runningStackFrameProxy))
buildRealStackFrameItem(runningStackFrameProxy)?.let {
coroutineStackFrameList.add(it)
}
}
}
return DoubleFrameList(coroutineStackFrameList, emptyList())
@@ -62,6 +63,7 @@ class CoroutineFrameBuilder {
stackFrames.addAll(preflightFrame.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)
stackFrames.addAll(framesLeft.mapIndexedNotNull { index, stackFrameProxyImpl ->
suspendContext.invokeInManagerThread { buildRealStackFrameItem(stackFrameProxyImpl) }
@@ -95,17 +97,11 @@ class CoroutineFrameBuilder {
return suspendContext.invokeInManagerThread {
val sem = frame.location().isPreFlight()
if (sem.isCoroutineFound()) {
if (coroutineDebuggerTraceEnabled())
ContinuationHolder.log.debug("Entry frame found: ${frame.format()}")
lookupContinuation(suspendContext, frame, sem)
} else
null
}
}
private fun filterNegativeLineNumberInvokeSuspendFrames(frame: StackFrameProxyImpl): Boolean {
val method = frame.safeLocation()?.safeMethod() ?: return false
return method.isInvokeSuspend() && frame.safeLocation()?.safeLineNumber() ?: 0 < 0
}
}
fun lookupContinuation(
@@ -117,13 +113,14 @@ class CoroutineFrameBuilder {
return null
val theFollowingFrames = theFollowingFrames(frame) ?: emptyList()
if (mode.isSuspendMethodParameter()) {
val suspendParameterFrame = if (mode.isSuspendMethodParameter()) {
if (theFollowingFrames.isNotEmpty()) {
// have to check next frame if that's invokeSuspend:-1 before proceed, otherwise skip
val invokeSuspendFrame = lookForTheFollowingFrame(theFollowingFrames) ?: return null
lookForTheFollowingFrame(theFollowingFrames) ?: return null
} else
return null
}
} else
null
if (threadAndContextSupportsEvaluation(suspendContext, frame)) {
val context = suspendContext.executionContext() ?: return null
@@ -133,7 +130,8 @@ class CoroutineFrameBuilder {
else -> null
} ?: return null
val coroutineInfo = ContinuationHolder(context).extractCoroutineInfoData(continuation) ?: return null
val continuationHolder = ContinuationHolder.instance(context) ?: return null
val coroutineInfo = continuationHolder.extractCoroutineInfoData(continuation) ?: return null
return preflight(frame, theFollowingFrames, coroutineInfo, mode)
}
return null
@@ -151,7 +151,7 @@ class XCoroutineView(val project: Project, val session: XDebugSession) :
inner class CoroutineGroupContainer(val suspendContext: SuspendContextImpl) : XValueContainer() {
override fun computeChildren(node: XCompositeNode) {
if (suspendContext.suspendPolicy == EventRequest.SUSPEND_ALL) {
managerThreadExecutor.on(suspendContext).schedule {
managerThreadExecutor.on(suspendContext).invoke {
val debugProbesProxy = CoroutineDebugProbesProxy(suspendContext)
val emptyDispatcherName = KotlinDebuggerCoroutinesBundle.message("coroutine.view.dispatcher.empty")
@@ -210,7 +210,7 @@ class XCoroutineView(val project: Project, val session: XDebugSession) :
) : RendererContainer(renderer.render(infoData)) {
override fun computeChildren(node: XCompositeNode) {
managerThreadExecutor.on(suspendContext).schedule {
managerThreadExecutor.on(suspendContext).invoke {
val children = XValueChildrenList()
val doubleFrameList = CoroutineFrameBuilder.build(infoData, suspendContext)
doubleFrameList?.stackTrace?.forEach {
@@ -211,21 +211,6 @@ abstract class AbstractKotlinEvaluateExpressionTest : KotlinDescriptorTestCaseWi
super.expandAll(tree, runnable, HashSet(), filter, suspendContext)
}
private fun SuspendContextImpl.runActionInSuspendCommand(action: SuspendContextImpl.() -> Unit) {
if (myInProgress) {
action()
} else {
val command = object : SuspendContextCommandImpl(this) {
override fun contextAction(suspendContext: SuspendContextImpl) {
action(suspendContext)
}
}
// Try to execute the action inside a command if we aren't already inside it.
debuggerSession.process.managerThread?.invoke(command) ?: command.contextAction(this)
}
}
private fun mayThrow(collector: MutableMap<String, Throwable>, expression: String, f: () -> Unit) {
try {
f()
@@ -8,7 +8,6 @@ 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
import com.intellij.jarRepository.JarRepositoryManager
@@ -25,8 +24,7 @@ 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.invokeInSuspendManagerThread
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
@@ -45,14 +43,7 @@ abstract class KotlinDescriptorTestCaseWithStackFrames() : KotlinDescriptorTestC
val agentList = mutableListOf<JpsMavenRepositoryLibraryDescriptor>()
val classPath = mutableListOf<String>()
protected fun out(stackFrame: StackFrameItem) {
if (stackFrame is CreationCoroutineStackFrameItem && stackFrame.first)
out(0, "Creation stack frame")
out(INDENT_FRAME, stackFrame.format())
outVariables(debugProcess.invokeInManagerThread { stackFrame.createFrame(debugProcess) } ?: return)
}
protected fun out(frame: JavaStackFrame) {
protected fun out(frame: XStackFrame) {
out(INDENT_FRAME, XDebuggerTestUtil.getFramePresentation(frame))
outVariables(frame)
}
@@ -92,18 +83,33 @@ abstract class KotlinDescriptorTestCaseWithStackFrames() : KotlinDescriptorTestC
try {
out("Thread stack trace:")
val stackFrames: List<XStackFrame> = 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())
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)
}
}
return@runActionInSuspendCommand
}
for (frameItem in stackFrames)
out(frameItem)
return@doWhenXSessionPausedThenResume
}
}
}
@@ -118,7 +124,6 @@ abstract class KotlinDescriptorTestCaseWithStackFrames() : KotlinDescriptorTestC
}
}
protected fun getAsyncStackTraceProvider(): CoroutineAsyncStackTraceProvider? {
val area = Extensions.getArea(null)
if (!area.hasExtensionPoint(ASYNC_STACKTRACE_EP_NAME)) {
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.debugger.test
import com.intellij.debugger.actions.MethodSmartStepTarget
import com.intellij.debugger.engine.*
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
import com.intellij.debugger.engine.events.SuspendContextCommandImpl
import com.intellij.debugger.impl.DebuggerContextImpl
import com.intellij.debugger.impl.JvmSteppingCommandProvider
import com.intellij.debugger.impl.PositionUtil
@@ -157,4 +158,19 @@ abstract class KotlinDescriptorTestCaseWithStepping : KotlinDescriptorTestCase()
}
}
}
protected fun SuspendContextImpl.runActionInSuspendCommand(action: SuspendContextImpl.() -> Unit) {
if (myInProgress) {
action()
} else {
val command = object : SuspendContextCommandImpl(this) {
override fun contextAction(suspendContext: SuspendContextImpl) {
action(suspendContext)
}
}
// Try to execute the action inside a command if we aren't already inside it.
debuggerSession.process.managerThread?.invoke(command) ?: command.contextAction(this)
}
}
}
@@ -33,8 +33,8 @@ public class XCoroutinesStackTraceTestGenerated extends AbstractXCoroutinesStack
runTest("idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun.kt");
}
@TestMetadata("coroutineSuspendFun135.kt")
public void testCoroutineSuspendFun135() throws Exception {
runTest("idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun135.kt");
@TestMetadata("coroutineSuspendFun136.kt")
public void testCoroutineSuspendFun136() throws Exception {
runTest("idea/jvm-debugger/jvm-debugger-test/testData/xcoroutines/coroutineSuspendFun136.kt");
}
}
@@ -8,17 +8,17 @@ Thread stack trace:
a:21, SuspendFunKt (coroutine1)
($completion, $continuation, $result, a, aParam)
CoroutineNameIdState(name=coroutine, id=-1, state=UNKNOWN, dispatcher=null)
test1:15, coroutine1.SuspendFunKt
test1:15, SuspendFunKt (coroutine1)
(i, test1)
invoke:9, coroutine1.SuspendFunKt$main$result$1
invoke:9, SuspendFunKt$main$result$1 (coroutine1)
(continuation, p1, this)
invokeSuspend:121, kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt$createCoroutineUnintercepted$$inlined$createCoroutineFromSuspendFunction$IntrinsicsKt__IntrinsicsJvmKt$3
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, kotlin.coroutines.jvm.internal.BaseContinuationImpl
resumeWith:33, BaseContinuationImpl (kotlin.coroutines.jvm.internal)
($i$a$-with-BaseContinuationImpl$resumeWith$1, $this$with, completion, current, param, result, this)
startCoroutine:128, kotlin.coroutines.ContinuationKt
startCoroutine:128, ContinuationKt (kotlin.coroutines)
($this$startCoroutine, completion, receiver)
main:9, coroutine1.SuspendFunKt
main:9, SuspendFunKt (coroutine1)
(cnt)
Disconnected from the target VM
@@ -8,38 +8,38 @@ Thread stack trace:
b:23, CoroutineSuspendFunKt (continuation)
($completion, $continuation, $result, b, paramA)
CoroutineNameIdState(name=coroutine, id=1, state=RUNNING, dispatcher=BlockingEventLoop@6f45df59)
a:16, continuation.CoroutineSuspendFunKt
a:16, CoroutineSuspendFunKt (continuation)
(a)
invokeSuspend:10, continuation.CoroutineSuspendFunKt$main$1
invokeSuspend:10, CoroutineSuspendFunKt$main$1 (continuation)
($this$runBlocking)
resumeWith:33, kotlin.coroutines.jvm.internal.BaseContinuationImpl
resumeWith:33, BaseContinuationImpl (kotlin.coroutines.jvm.internal)
($i$a$-with-BaseContinuationImpl$resumeWith$1, $this$with, completion, current, param, result, this)
run:56, kotlinx.coroutines.DispatchedTask
run:56, 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, kotlinx.coroutines.EventLoopImplBase
processNextEvent:272, EventLoopImplBase (kotlinx.coroutines)
(delayed, this)
joinBlocking:79, kotlinx.coroutines.BlockingCoroutine
joinBlocking:79, BlockingCoroutine (kotlinx.coroutines)
(this)
runBlocking:54, kotlinx.coroutines.BuildersKt__BuildersKt
runBlocking:54, BuildersKt__BuildersKt (kotlinx.coroutines)
(block, context, contextInterceptor, coroutine, currentThread, eventLoop, newContext)
runBlocking:1, kotlinx.coroutines.BuildersKt
runBlocking:1, BuildersKt (kotlinx.coroutines)
()
runBlocking$default:36, kotlinx.coroutines.BuildersKt__BuildersKt
runBlocking$default:36, BuildersKt__BuildersKt (kotlinx.coroutines)
()
runBlocking$default:1, kotlinx.coroutines.BuildersKt
runBlocking$default:1, BuildersKt (kotlinx.coroutines)
()
main:9, continuation.CoroutineSuspendFunKt
main:9, CoroutineSuspendFunKt (continuation)
(main)
Creation stack frame
createCoroutineUnintercepted:116, kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt
createCoroutineUnintercepted:116, IntrinsicsKt__IntrinsicsJvmKt (kotlin.coroutines.intrinsics)
()
startCoroutineCancellable:26, kotlinx.coroutines.intrinsics.CancellableKt
startCoroutineCancellable:26, CancellableKt (kotlinx.coroutines.intrinsics)
()
runBlocking$default:1, kotlinx.coroutines.BuildersKt
runBlocking$default:1, BuildersKt (kotlinx.coroutines)
()
main:9, continuation.CoroutineSuspendFunKt
main:9, CoroutineSuspendFunKt (continuation)
()
main:-1, continuation.CoroutineSuspendFunKt
main:-1, CoroutineSuspendFunKt (continuation)
()
Disconnected from the target VM
@@ -1,46 +0,0 @@
LineBreakpoint created at coroutineSuspendFun135.kt:29
Run Java
Connected to the target VM
coroutineSuspendFun135.kt:29
Thread stack trace:
c:29, CoroutineSuspendFun135Kt (continuation)
($completion, c, paramB)
b:23, CoroutineSuspendFun135Kt (continuation)
($completion, $continuation, $result, b, paramA)
CoroutineNameIdState(name=coroutine, id=1, state=RUNNING, dispatcher=BlockingEventLoop@305fd85d)
a:16, continuation.CoroutineSuspendFun135Kt
(a)
invokeSuspend:10, continuation.CoroutineSuspendFun135Kt$main$1
($this$runBlocking)
resumeWith:33, kotlin.coroutines.jvm.internal.BaseContinuationImpl
($i$a$-with-BaseContinuationImpl$resumeWith$1, $this$with, completion, current, param, result, this)
run:56, kotlinx.coroutines.DispatchedTask
($i$a$-withCoroutineContext-DispatchedTask$run$1, $i$f$withCoroutineContext, context, continuation, countOrElement$iv, delegate, exception, fatalException, job, oldValue$iv, state, taskContext, this)
processNextEvent:274, kotlinx.coroutines.EventLoopImplBase
(delayed, task, this)
joinBlocking:79, kotlinx.coroutines.BlockingCoroutine
(this)
runBlocking:54, kotlinx.coroutines.BuildersKt__BuildersKt
(block, context, contextInterceptor, coroutine, currentThread, eventLoop, newContext)
runBlocking:1, kotlinx.coroutines.BuildersKt
()
runBlocking$default:36, kotlinx.coroutines.BuildersKt__BuildersKt
()
runBlocking$default:1, kotlinx.coroutines.BuildersKt
()
main:9, continuation.CoroutineSuspendFun135Kt
(main)
Creation stack frame
createCoroutineUnintercepted:116, kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt
()
startCoroutineCancellable:26, kotlinx.coroutines.intrinsics.CancellableKt
()
runBlocking$default:1, kotlinx.coroutines.BuildersKt
()
main:9, continuation.CoroutineSuspendFun135Kt
()
main:-1, continuation.CoroutineSuspendFun135Kt
()
Disconnected from the target VM
Process finished with exit code 0
@@ -0,0 +1,46 @@
LineBreakpoint created at coroutineSuspendFun136.kt:29
Run Java
Connected to the target VM
coroutineSuspendFun136.kt:29
Thread stack trace:
c:29, CoroutineSuspendFun136Kt (continuation)
($completion, c, paramB)
b:23, CoroutineSuspendFun136Kt (continuation)
($completion, $continuation, $result, b, paramA)
CoroutineNameIdState(name=coroutine, id=1, state=RUNNING, dispatcher=BlockingEventLoop@305fd85d)
a:16, CoroutineSuspendFun136Kt (continuation)
(a)
invokeSuspend:10, CoroutineSuspendFun136Kt$main$1 (continuation)
($this$runBlocking)
resumeWith:33, BaseContinuationImpl (kotlin.coroutines.jvm.internal)
($i$a$-with-BaseContinuationImpl$resumeWith$1, $this$with, completion, current, param, result, this)
run:56, 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)
(delayed, task, this)
joinBlocking:79, BlockingCoroutine (kotlinx.coroutines)
(this)
runBlocking:54, BuildersKt__BuildersKt (kotlinx.coroutines)
(block, context, contextInterceptor, coroutine, currentThread, eventLoop, newContext)
runBlocking:1, BuildersKt (kotlinx.coroutines)
()
runBlocking$default:36, BuildersKt__BuildersKt (kotlinx.coroutines)
()
runBlocking$default:1, BuildersKt (kotlinx.coroutines)
()
main:9, CoroutineSuspendFun136Kt (continuation)
(main)
Creation stack frame
createCoroutineUnintercepted:116, IntrinsicsKt__IntrinsicsJvmKt (kotlin.coroutines.intrinsics)
()
startCoroutineCancellable:26, CancellableKt (kotlinx.coroutines.intrinsics)
()
runBlocking$default:1, BuildersKt (kotlinx.coroutines)
()
main:9, CoroutineSuspendFun136Kt (continuation)
()
main:-1, CoroutineSuspendFun136Kt (continuation)
()
Disconnected from the target VM
Process finished with exit code 0
+1
View File
@@ -61,3 +61,4 @@ 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.testCoroutineSuspendFun135, running test on SNAPSHOT version
Can't render this file because it contains an unexpected character in line 12 and column 132.