(CoroutineDebugger) Minor fixes, kotlinx.coroutines version fix
This commit is contained in:
+20
@@ -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()
|
||||
|
||||
+8
-11
@@ -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
|
||||
}
|
||||
+4
-2
@@ -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
|
||||
)
|
||||
}
|
||||
|
||||
+5
-12
@@ -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 =
|
||||
|
||||
+5
-4
@@ -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
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
+3
-3
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-5
@@ -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) {
|
||||
|
||||
+2
-2
@@ -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?) =
|
||||
|
||||
+2
-2
@@ -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)
|
||||
|
||||
+8
-10
@@ -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
|
||||
}
|
||||
|
||||
+15
-17
@@ -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
|
||||
|
||||
+2
-2
@@ -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 {
|
||||
|
||||
-15
@@ -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()
|
||||
|
||||
+28
-23
@@ -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)) {
|
||||
|
||||
+16
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -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
|
||||
|
||||
|
||||
+16
-16
@@ -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
|
||||
|
||||
|
||||
-46
@@ -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
|
||||
+46
@@ -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
|
||||
@@ -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.
|
Reference in New Issue
Block a user