Switch to 201 platform
This commit is contained in:
+80
-54
@@ -6,20 +6,22 @@
|
||||
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.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.isFilteredInvokeSuspend
|
||||
import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger
|
||||
import org.jetbrains.kotlin.idea.debugger.stackFrame.KotlinStackFrame
|
||||
|
||||
@@ -32,12 +34,12 @@ class CreationCoroutineStackFrameItem(
|
||||
val first: Boolean
|
||||
) : CoroutineStackFrameItem(location, emptyList()) {
|
||||
|
||||
override fun createFrame(debugProcess: DebugProcessImpl): CoroutineGeneratedFrame? {
|
||||
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(debugProcess, this, first)
|
||||
CreationCoroutineStackFrame(locationFrame, position, first)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,18 +53,19 @@ class SuspendCoroutineStackFrameItem(
|
||||
spilledVariables: List<XNamedValue> = emptyList()
|
||||
) : CoroutineStackFrameItem(location, spilledVariables)
|
||||
|
||||
|
||||
/**
|
||||
* Restored from memory dump
|
||||
*/
|
||||
class DefaultCoroutineStackFrameItem(location: Location, spilledVariables: List<XNamedValue>) :
|
||||
CoroutineStackFrameItem(location, spilledVariables) {
|
||||
|
||||
override fun createFrame(debugProcess: DebugProcessImpl): CoroutineGeneratedFrame? {
|
||||
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(debugProcess, this)
|
||||
CoroutineStackFrame(locationStackFrameProxyImpl, position, spilledVariables, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,24 +85,25 @@ class DefaultCoroutineStackFrameItem(location: Location, spilledVariables: List<
|
||||
open class RunningCoroutineStackFrameItem(
|
||||
val frame: StackFrameProxyImpl,
|
||||
spilledVariables: List<XNamedValue> = emptyList()
|
||||
) : CoroutineStackFrameItem(frame.location(), spilledVariables), FrameProvider {
|
||||
override fun createFrame(debugProcess: DebugProcessImpl): CoroutineGeneratedFrame? {
|
||||
) : CoroutineStackFrameItem(frame.location(), spilledVariables) {
|
||||
override fun createFrame(debugProcess: DebugProcessImpl): XStackFrame? {
|
||||
return debugProcess.invokeInManagerThread {
|
||||
CoroutineStackFrame(debugProcess, this)
|
||||
val position = frame.location().findPosition(debugProcess.project)
|
||||
CoroutineStackFrame(frame, position)
|
||||
}
|
||||
}
|
||||
|
||||
override fun provideFrame(debugProcess: DebugProcessImpl): XStackFrame? =
|
||||
debugProcess.invokeInManagerThread { KotlinStackFrame(frame) }
|
||||
}
|
||||
|
||||
sealed class CoroutineStackFrameItem(val location: Location, val spilledVariables: List<XNamedValue>) :
|
||||
StackFrameItem(location, spilledVariables) {
|
||||
val log by logger
|
||||
|
||||
override fun createFrame(debugProcess: DebugProcessImpl): CoroutineGeneratedFrame? {
|
||||
override fun createFrame(debugProcess: DebugProcessImpl): XStackFrame? {
|
||||
return debugProcess.invokeInManagerThread {
|
||||
CoroutineStackFrame(debugProcess, this)
|
||||
val frame = debugProcess.findFirstFrame() ?: return@invokeInManagerThread null
|
||||
val locationFrame = LocationStackFrameProxyImpl(location, frame)
|
||||
val position = location.findPosition(debugProcess.project)
|
||||
CoroutineStackFrame(locationFrame, position)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,10 +112,6 @@ sealed class CoroutineStackFrameItem(val location: Location, val spilledVariable
|
||||
location.safeLineNumber() + ":" + location.safeKotlinPreferredLineNumber()
|
||||
}
|
||||
|
||||
interface FrameProvider {
|
||||
fun provideFrame(debugProcess: DebugProcessImpl): XStackFrame?
|
||||
}
|
||||
|
||||
fun DebugProcessImpl.findFirstFrame(): StackFrameProxyImpl? =
|
||||
suspendManager.pausedContext.thread?.forceFrames()?.firstOrNull()
|
||||
|
||||
@@ -123,19 +123,71 @@ fun DebugProcessImpl.findFirstFrame(): StackFrameProxyImpl? =
|
||||
*/
|
||||
class CoroutinePreflightFrame(
|
||||
val coroutineInfoData: CoroutineInfoData,
|
||||
private val frame: StackFrameProxyImpl,
|
||||
val frame: StackFrameProxyImpl,
|
||||
val threadPreCoroutineFrames: List<StackFrameProxyImpl>,
|
||||
val mode: SuspendExitMode
|
||||
) : KotlinStackFrame(frame), JVMStackFrameInfoProvider {
|
||||
val mode: SuspendExitMode,
|
||||
private val firstFrameVariables: List<XNamedValue> = 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<XNamedValue>? = 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)
|
||||
val topRestoredFrame = coroutineInfoData.stackTrace.firstOrNull()
|
||||
if (topRestoredFrame != null && topRestoredFrame.location.isFilteredInvokeSuspend()) {
|
||||
val firstFrameVariables: List<XNamedValue> = topRestoredFrame.spilledVariables
|
||||
if (spilledVariables != null) {
|
||||
children.let {
|
||||
val varNames = (0 until children.size()).map { children.getName(it) }.toSet()
|
||||
firstFrameVariables.forEach {
|
||||
spilledVariables.forEach {
|
||||
if (!varNames.contains(it.name))
|
||||
children.add(it)
|
||||
}
|
||||
@@ -143,32 +195,6 @@ class CoroutinePreflightFrame(
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
override fun getSourcePosition() =
|
||||
position ?: super.getSourcePosition()
|
||||
}
|
||||
+54
-80
@@ -6,22 +6,20 @@
|
||||
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.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.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.isFilteredInvokeSuspend
|
||||
import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger
|
||||
import org.jetbrains.kotlin.idea.debugger.stackFrame.KotlinStackFrame
|
||||
|
||||
@@ -34,12 +32,12 @@ class CreationCoroutineStackFrameItem(
|
||||
val first: Boolean
|
||||
) : CoroutineStackFrameItem(location, emptyList()) {
|
||||
|
||||
override fun createFrame(debugProcess: DebugProcessImpl): XStackFrame? {
|
||||
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(locationFrame, position, first)
|
||||
CreationCoroutineStackFrame(debugProcess, this, first)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,19 +51,18 @@ class SuspendCoroutineStackFrameItem(
|
||||
spilledVariables: List<XNamedValue> = emptyList()
|
||||
) : CoroutineStackFrameItem(location, spilledVariables)
|
||||
|
||||
|
||||
/**
|
||||
* Restored from memory dump
|
||||
*/
|
||||
class DefaultCoroutineStackFrameItem(location: Location, spilledVariables: List<XNamedValue>) :
|
||||
CoroutineStackFrameItem(location, spilledVariables) {
|
||||
|
||||
override fun createFrame(debugProcess: DebugProcessImpl): XStackFrame? {
|
||||
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(locationStackFrameProxyImpl, position, spilledVariables, false)
|
||||
CoroutineStackFrame(debugProcess, this)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,25 +82,24 @@ class DefaultCoroutineStackFrameItem(location: Location, spilledVariables: List<
|
||||
open class RunningCoroutineStackFrameItem(
|
||||
val frame: StackFrameProxyImpl,
|
||||
spilledVariables: List<XNamedValue> = emptyList()
|
||||
) : CoroutineStackFrameItem(frame.location(), spilledVariables) {
|
||||
override fun createFrame(debugProcess: DebugProcessImpl): XStackFrame? {
|
||||
) : CoroutineStackFrameItem(frame.location(), spilledVariables), FrameProvider {
|
||||
override fun createFrame(debugProcess: DebugProcessImpl): CoroutineGeneratedFrame? {
|
||||
return debugProcess.invokeInManagerThread {
|
||||
val position = frame.location().findPosition(debugProcess.project)
|
||||
CoroutineStackFrame(frame, position)
|
||||
CoroutineStackFrame(debugProcess, this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun provideFrame(debugProcess: DebugProcessImpl): XStackFrame? =
|
||||
debugProcess.invokeInManagerThread { KotlinStackFrame(frame) }
|
||||
}
|
||||
|
||||
sealed class CoroutineStackFrameItem(val location: Location, val spilledVariables: List<XNamedValue>) :
|
||||
StackFrameItem(location, spilledVariables) {
|
||||
val log by logger
|
||||
|
||||
override fun createFrame(debugProcess: DebugProcessImpl): XStackFrame? {
|
||||
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)
|
||||
CoroutineStackFrame(locationFrame, position)
|
||||
CoroutineStackFrame(debugProcess, this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +108,10 @@ sealed class CoroutineStackFrameItem(val location: Location, val spilledVariable
|
||||
location.safeLineNumber() + ":" + location.safeKotlinPreferredLineNumber()
|
||||
}
|
||||
|
||||
interface FrameProvider {
|
||||
fun provideFrame(debugProcess: DebugProcessImpl): XStackFrame?
|
||||
}
|
||||
|
||||
fun DebugProcessImpl.findFirstFrame(): StackFrameProxyImpl? =
|
||||
suspendManager.pausedContext.thread?.forceFrames()?.firstOrNull()
|
||||
|
||||
@@ -123,71 +123,19 @@ fun DebugProcessImpl.findFirstFrame(): StackFrameProxyImpl? =
|
||||
*/
|
||||
class CoroutinePreflightFrame(
|
||||
val coroutineInfoData: CoroutineInfoData,
|
||||
val frame: StackFrameProxyImpl,
|
||||
private val frame: StackFrameProxyImpl,
|
||||
val threadPreCoroutineFrames: List<StackFrameProxyImpl>,
|
||||
val mode: SuspendExitMode,
|
||||
private val firstFrameVariables: List<XNamedValue> = 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<XNamedValue>? = 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)
|
||||
}
|
||||
}
|
||||
val mode: SuspendExitMode
|
||||
) : KotlinStackFrame(frame), JVMStackFrameInfoProvider {
|
||||
|
||||
override fun superBuildVariables(evaluationContext: EvaluationContextImpl, children: XValueChildrenList) {
|
||||
super.superBuildVariables(evaluationContext, children)
|
||||
if (spilledVariables != null) {
|
||||
val topRestoredFrame = coroutineInfoData.stackTrace.firstOrNull()
|
||||
if (topRestoredFrame != null && topRestoredFrame.location.isFilteredInvokeSuspend()) {
|
||||
val firstFrameVariables: List<XNamedValue> = topRestoredFrame.spilledVariables
|
||||
children.let {
|
||||
val varNames = (0 until children.size()).map { children.getName(it) }.toSet()
|
||||
spilledVariables.forEach {
|
||||
firstFrameVariables.forEach {
|
||||
if (!varNames.contains(it.name))
|
||||
children.add(it)
|
||||
}
|
||||
@@ -195,6 +143,32 @@ open class CoroutineStackFrame(
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSourcePosition() =
|
||||
position ?: super.getSourcePosition()
|
||||
}
|
||||
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
|
||||
Reference in New Issue
Block a user