From 9b0e37f62778575081b5c713d6d8bfb9d87db470 Mon Sep 17 00:00:00 2001 From: Vladimir Ilmov Date: Wed, 22 Apr 2020 13:56:36 +0200 Subject: [PATCH] (CoroutineDebugger) Minor issued fixed, log level adjusted for missing classes in JVM. --- .../CoroutineDebugConfigurationExtension.java | 3 +- .../coroutine/CoroutineDebuggerContentInfo.kt | 6 +- .../CoroutineStackFrameInterceptor.kt | 4 - .../debugger/coroutine/DebuggerConnection.kt | 21 +- .../coroutine/command/CoroutineDumpAction.kt | 4 +- .../data/ContinuationValueDescriptorImpl.kt | 3 +- .../coroutine/data/CoroutineInfoData.kt | 6 +- .../coroutine/data/TreeNodeDescriptorImpl.kt | 5 +- .../coroutine/data/coroutineStackFrames.kt | 13 +- .../coroutine/proxy/ContinuationHolder.kt | 13 +- .../proxy/CoroutineDebugProbesProxy.kt | 1 - .../proxy/CoroutineLibraryAgent2Proxy.kt | 27 +-- .../proxy/CoroutineLibraryAgentProxy.kt | 190 ------------------ .../proxy/CoroutineNoLibraryProxy.kt | 15 +- .../coroutine/proxy/ManagerThreadExecutor.kt | 8 - ...kt => SkipCoroutineStackFrameProxyImpl.kt} | 10 - .../proxy/mirror/baseDynamicMirror.kt | 18 +- .../proxy/mirror/coroutinesContextMirror.kt | 26 ++- .../proxy/mirror/coroutinesDebugMirror.kt | 56 +++--- .../proxy/mirror/coroutinesMirror.kt | 44 ++-- .../coroutine/proxy/mirror/debugMetadata.kt | 7 +- .../coroutine/proxy/mirror/javaLangMirror.kt | 13 +- .../coroutine/util/CoroutineFrameBuilder.kt | 14 +- .../debugger/coroutine/util/CoroutineUtils.kt | 15 +- .../idea/debugger/coroutine/util/KUtils.kt | 25 +-- .../idea/debugger/coroutine/util/Providers.kt | 16 +- .../coroutine/view/CoroutineDumpPanel.kt | 19 +- .../view/CoroutineViewDebugSessionListener.kt | 2 +- .../coroutine/view/SimpleColoredTextIcon.kt | 23 +-- .../debugger/coroutine/view/XCoroutineView.kt | 26 +-- .../AbstractPrimitiveRangeToInspection.kt | 5 +- 31 files changed, 191 insertions(+), 447 deletions(-) delete mode 100644 idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/CoroutineLibraryAgentProxy.kt rename idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/{LocationStackFrameProxyImpl.kt => SkipCoroutineStackFrameProxyImpl.kt} (56%) diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/CoroutineDebugConfigurationExtension.java b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/CoroutineDebugConfigurationExtension.java index e7a50b7e63f..23a7d8ea818 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/CoroutineDebugConfigurationExtension.java +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/CoroutineDebugConfigurationExtension.java @@ -4,7 +4,6 @@ */ package org.jetbrains.kotlin.idea.debugger.coroutine; -import com.intellij.execution.ExecutionException; import com.intellij.execution.RunConfigurationExtension; import com.intellij.execution.configurations.JavaParameters; import com.intellij.execution.configurations.RunConfigurationBase; @@ -19,7 +18,7 @@ public class CoroutineDebugConfigurationExtension extends RunConfigurationExtens @Override public void updateJavaParameters( - @NotNull T configuration, @NotNull JavaParameters params, RunnerSettings runnerSettings + T configuration, @NotNull JavaParameters params, RunnerSettings runnerSettings ) { if (configuration != null) { Project project = configuration.getProject(); diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/CoroutineDebuggerContentInfo.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/CoroutineDebuggerContentInfo.kt index 92ebfc5f850..6573c727e59 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/CoroutineDebuggerContentInfo.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/CoroutineDebuggerContentInfo.kt @@ -5,11 +5,9 @@ package org.jetbrains.kotlin.idea.debugger.coroutine -import org.jetbrains.annotations.NonNls - class CoroutineDebuggerContentInfo { companion object { - val XCOROUTINE_THREADS_CONTENT = "XCoroutineThreadsContent" - val XCOROUTINE_POPUP_ACTION_GROUP = "Kotlin.XDebugger.Actions" + const val XCOROUTINE_THREADS_CONTENT = "XCoroutineThreadsContent" + const val XCOROUTINE_POPUP_ACTION_GROUP = "Kotlin.XDebugger.Actions" } } diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/CoroutineStackFrameInterceptor.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/CoroutineStackFrameInterceptor.kt index 65c70eb44e9..75da2436a26 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/CoroutineStackFrameInterceptor.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/CoroutineStackFrameInterceptor.kt @@ -7,16 +7,12 @@ package org.jetbrains.kotlin.idea.debugger.coroutine import com.intellij.debugger.actions.AsyncStacksToggleAction import com.intellij.debugger.engine.DebugProcessImpl -import com.intellij.debugger.engine.SuspendContextImpl import com.intellij.debugger.jdi.StackFrameProxyImpl -import com.intellij.openapi.application.Application -import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.project.Project import com.intellij.xdebugger.frame.XStackFrame import com.intellij.xdebugger.impl.XDebugSessionImpl import com.sun.jdi.Location import org.jetbrains.kotlin.idea.debugger.StackFrameInterceptor -import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.ContinuationHolder import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.SkipCoroutineStackFrameProxyImpl import org.jetbrains.kotlin.idea.debugger.coroutine.util.CoroutineFrameBuilder import org.jetbrains.kotlin.idea.debugger.coroutine.util.isInUnitTest diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/DebuggerConnection.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/DebuggerConnection.kt index 4ab9752384a..34716d9c503 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/DebuggerConnection.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/DebuggerConnection.kt @@ -45,12 +45,15 @@ class DebuggerConnection( val kotlinxCoroutinesCore = params.classPath?.pathList?.firstOrNull { it.contains("kotlinx-coroutines-core") } val kotlinxCoroutinesDebug = params.classPath?.pathList?.firstOrNull { it.contains("kotlinx-coroutines-debug") } - val mode = if (kotlinxCoroutinesDebug != null) { - CoroutineDebuggerMode.VERSION_UP_TO_1_3_5 - } else if (kotlinxCoroutinesCore != null) { - determineCoreVersionMode(kotlinxCoroutinesCore) - } else - CoroutineDebuggerMode.DISABLED + val mode = when { + kotlinxCoroutinesDebug != null -> { + CoroutineDebuggerMode.VERSION_UP_TO_1_3_5 + } + kotlinxCoroutinesCore != null -> { + determineCoreVersionMode(kotlinxCoroutinesCore) + } + else -> CoroutineDebuggerMode.DISABLED + } when (mode) { CoroutineDebuggerMode.VERSION_1_3_6_AND_UP -> initializeCoroutineAgent(params, kotlinxCoroutinesCore) @@ -62,12 +65,12 @@ class DebuggerConnection( } private fun determineCoreVersionMode(kotlinxCoroutinesCore: String): CoroutineDebuggerMode { - val regex = Regex(""".+\Wkotlinx\-coroutines\-core\-(.+)?\.jar""") + val regex = Regex(""".+\Wkotlinx-coroutines-core-(.+)?\.jar""") val matchResult = regex.matchEntire(kotlinxCoroutinesCore) ?: return CoroutineDebuggerMode.DISABLED - val coroutinesCoreVersion = DefaultArtifactVersion(matchResult.groupValues.get(1)) + val coroutinesCoreVersion = DefaultArtifactVersion(matchResult.groupValues[1]) val versionToCompareTo = DefaultArtifactVersion("1.3.5") - return if (versionToCompareTo.compareTo(coroutinesCoreVersion) < 0) + return if (versionToCompareTo < coroutinesCoreVersion) CoroutineDebuggerMode.VERSION_1_3_6_AND_UP else CoroutineDebuggerMode.DISABLED diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/command/CoroutineDumpAction.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/command/CoroutineDumpAction.kt index 4fb618fbc34..2ea58a48203 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/command/CoroutineDumpAction.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/command/CoroutineDumpAction.kt @@ -24,9 +24,9 @@ import com.intellij.psi.search.GlobalSearchScope import com.intellij.util.text.DateFormatUtil import com.intellij.xdebugger.impl.XDebuggerManagerImpl import org.jetbrains.kotlin.idea.debugger.coroutine.KotlinDebuggerCoroutinesBundle -import org.jetbrains.kotlin.idea.debugger.coroutine.view.CoroutineDumpPanel import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutineInfoData import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.CoroutineDebugProbesProxy +import org.jetbrains.kotlin.idea.debugger.coroutine.view.CoroutineDumpPanel @Suppress("ComponentNotRegistered") class CoroutineDumpAction : AnAction(), AnAction.TransparentUpdate { @@ -49,7 +49,7 @@ class CoroutineDumpAction : AnAction(), AnAction.TransparentUpdate { ApplicationManager.getApplication().invokeLater(f, ModalityState.NON_MODAL) } else { val message = KotlinDebuggerCoroutinesBundle.message("coroutine.dump.failed") - XDebuggerManagerImpl.NOTIFICATION_GROUP.createNotification(message,MessageType.ERROR).notify(project) + XDebuggerManagerImpl.NOTIFICATION_GROUP.createNotification(message, MessageType.ERROR).notify(project) } } }) diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/ContinuationValueDescriptorImpl.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/ContinuationValueDescriptorImpl.kt index 4fe5d861009..4e637482913 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/ContinuationValueDescriptorImpl.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/ContinuationValueDescriptorImpl.kt @@ -12,13 +12,12 @@ import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl import com.intellij.openapi.project.Project import com.sun.jdi.ObjectReference import com.sun.jdi.Value -import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.ContinuationHolder class ContinuationValueDescriptorImpl( project: Project, val continuation: ObjectReference, val fieldName: String, - val variableName: String + private val variableName: String ) : ValueDescriptorImpl(project) { override fun calcValueName() = variableName diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/CoroutineInfoData.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/CoroutineInfoData.kt index f95ac49cba2..f03417f3fad 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/CoroutineInfoData.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/CoroutineInfoData.kt @@ -9,7 +9,7 @@ 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.proxy.mirror.MirrorOfCoroutineInfo import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger /** @@ -31,9 +31,9 @@ data class CoroutineInfoData( fun isRunning() = key.state == State.RUNNING - fun topRestoredFrame() = stackTrace.firstOrNull() + private fun topRestoredFrame() = stackTrace.firstOrNull() - fun topFrameVariables() = stackTrace.firstOrNull()?.spilledVariables ?: emptyList() + fun topFrameVariables() = topRestoredFrame()?.spilledVariables ?: emptyList() fun restoredStackTrace(mode: SuspendExitMode): List = if (stackTrace.isNotEmpty() && stackTrace.first().isInvokeSuspend()) diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/TreeNodeDescriptorImpl.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/TreeNodeDescriptorImpl.kt index c349d8f44e9..44384d5f2cd 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/TreeNodeDescriptorImpl.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/TreeNodeDescriptorImpl.kt @@ -21,7 +21,7 @@ import org.jetbrains.kotlin.idea.debugger.coroutine.KotlinDebuggerCoroutinesBund import javax.swing.Icon @Deprecated("moved to XCoroutineView") -class CoroutineDescriptorImpl(val infoData: CoroutineInfoData) : NodeDescriptorImpl() { +class CoroutineDescriptorImpl(private val infoData: CoroutineInfoData) : NodeDescriptorImpl() { lateinit var icon: Icon override fun getName() = infoData.key.name @@ -74,10 +74,9 @@ class SuspendStackFrameDescriptor( } } - override fun getName() : String? = frame.methodName + override fun getName(): String? = frame.methodName } - /** * For the case when no data inside frame is available */ diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/coroutineStackFrames.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/coroutineStackFrames.kt index 17ca75b2283..8e476b5686b 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/coroutineStackFrames.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/data/coroutineStackFrames.kt @@ -10,16 +10,11 @@ import com.intellij.debugger.jdi.LocalVariableProxyImpl import com.intellij.debugger.jdi.StackFrameProxyImpl import com.intellij.debugger.memory.utils.StackFrameItem import com.intellij.debugger.ui.impl.watch.StackFrameDescriptorImpl -import com.intellij.ui.ColoredTextContainer -import com.intellij.ui.SimpleTextAttributes import com.intellij.xdebugger.frame.XCompositeNode import com.intellij.xdebugger.frame.XNamedValue import com.intellij.xdebugger.frame.XStackFrame import com.intellij.xdebugger.frame.XValueChildrenList import org.jetbrains.kotlin.idea.debugger.coroutine.KotlinDebuggerCoroutinesBundle -import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.SkipCoroutineStackFrameProxyImpl -import org.jetbrains.kotlin.idea.debugger.coroutine.util.coroutineDebuggerTraceEnabled -import org.jetbrains.kotlin.idea.debugger.invokeInManagerThread import org.jetbrains.kotlin.idea.debugger.stackFrame.KotlinStackFrame @@ -32,10 +27,10 @@ import org.jetbrains.kotlin.idea.debugger.stackFrame.KotlinStackFrame class CoroutinePreflightStackFrame( val coroutineInfoData: CoroutineInfoData, - val stackFrameDescriptorImpl: StackFrameDescriptorImpl, + private val stackFrameDescriptorImpl: StackFrameDescriptorImpl, val threadPreCoroutineFrames: List, val mode: SuspendExitMode, - val firstFrameVariables: List = coroutineInfoData.topFrameVariables() + private val firstFrameVariables: List = coroutineInfoData.topFrameVariables() ) : KotlinStackFrame(stackFrameDescriptorImpl), JVMStackFrameInfoProvider { override fun computeChildren(node: XCompositeNode) { @@ -49,7 +44,7 @@ class CoroutinePreflightStackFrame( override fun getVisibleVariables(): List { // skip restored variables - return super.getVisibleVariables().filter { v -> ! firstFrameVariables.any { it.name == v.name() } } + return super.getVisibleVariables().filter { v -> !firstFrameVariables.any { it.name == v.name() } } } override fun isInLibraryContent() = false @@ -77,7 +72,7 @@ class CreationCoroutineStackFrame(debugProcess: DebugProcessImpl, item: StackFra true } -open class CoroutineStackFrame(debugProcess: DebugProcessImpl, val item: StackFrameItem, val realStackFrame: XStackFrame? = null) : +open class CoroutineStackFrame(debugProcess: DebugProcessImpl, val item: StackFrameItem, private val realStackFrame: XStackFrame? = null) : StackFrameItem.CapturedStackFrame(debugProcess, item) { override fun computeChildren(node: XCompositeNode) { diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/ContinuationHolder.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/ContinuationHolder.kt index c2edeb35719..2d71bd79876 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/ContinuationHolder.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/ContinuationHolder.kt @@ -6,10 +6,11 @@ package org.jetbrains.kotlin.idea.debugger.coroutine.proxy import com.intellij.debugger.engine.JavaValue -import com.sun.jdi.* +import com.sun.jdi.ObjectReference import org.jetbrains.kotlin.idea.debugger.coroutine.data.* import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.mirror.* -import org.jetbrains.kotlin.idea.debugger.coroutine.util.* +import org.jetbrains.kotlin.idea.debugger.coroutine.util.isAbstractCoroutine +import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext class ContinuationHolder private constructor(val context: DefaultExecutionContext) { @@ -46,8 +47,8 @@ class ContinuationHolder private constructor(val context: DefaultExecutionContex val ci = debugProbesImpl?.getCoroutineInfo(input, context) if (ci != null) { if (ci.creationStackTrace != null) - for (index in 0 until ci.creationStackTrace.size) { - val frame = ci.creationStackTrace.get(index) + for (index in ci.creationStackTrace.indices) { + val frame = ci.creationStackTrace[index] val ste = frame.stackTraceElement() val location = locationCache.createLocation(ste) creationStackTrace.add(CreationCoroutineStackFrameItem(ste, location, index == 0)) @@ -64,14 +65,14 @@ class ContinuationHolder private constructor(val context: DefaultExecutionContex fun state(value: ObjectReference?): CoroutineNameIdState? { value ?: return null val reference = JavaLangMirror(context) - val standaloneCoroutine = StandaloneCoroutine(context) + val standaloneCoroutine = StandaloneCoroutine.instance(context) ?: return null val standAloneCoroutineMirror = standaloneCoroutine.mirror(value, context) if (standAloneCoroutineMirror?.context is MirrorOfCoroutineContext) { 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 r = """\w+\{(\w+)}@([\w\d]+)""".toRegex() val matcher = r.toPattern().matcher(toString) if (matcher.matches()) { val state = stateOf(matcher.group(1)) diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/CoroutineDebugProbesProxy.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/CoroutineDebugProbesProxy.kt index cb1d20b8e17..c0b299b7a5e 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/CoroutineDebugProbesProxy.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/CoroutineDebugProbesProxy.kt @@ -7,7 +7,6 @@ package org.jetbrains.kotlin.idea.debugger.coroutine.proxy import com.intellij.debugger.engine.DebuggerManagerThreadImpl import com.intellij.debugger.engine.SuspendContextImpl import com.intellij.openapi.util.registry.Registry -import org.jetbrains.kotlin.idea.debugger.coroutine.util.CoroutineFrameBuilder import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutineInfoCache import org.jetbrains.kotlin.idea.debugger.coroutine.util.executionContext import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/CoroutineLibraryAgent2Proxy.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/CoroutineLibraryAgent2Proxy.kt index 895f68a2962..a7f23dd5edf 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/CoroutineLibraryAgent2Proxy.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/CoroutineLibraryAgent2Proxy.kt @@ -6,7 +6,10 @@ package org.jetbrains.kotlin.idea.debugger.coroutine.proxy import com.intellij.xdebugger.frame.XNamedValue -import org.jetbrains.kotlin.idea.debugger.coroutine.data.* +import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutineInfoData +import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutineNameIdState +import org.jetbrains.kotlin.idea.debugger.coroutine.data.CreationCoroutineStackFrameItem +import org.jetbrains.kotlin.idea.debugger.coroutine.data.SuspendCoroutineStackFrameItem import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.mirror.DebugMetadata import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.mirror.DebugProbesImpl import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.mirror.MirrorOfCoroutineInfo @@ -26,16 +29,16 @@ class CoroutineLibraryAgent2Proxy(private val executionContext: DefaultExecution return result.mapNotNull { mapToCoroutineInfoData(it) } } - fun mapToCoroutineInfoData(mirror: MirrorOfCoroutineInfo): CoroutineInfoData? { - val cnis = CoroutineNameIdState.instance(mirror) - val stackTrace = mirror.enchancedStackTrace?.mapNotNull { it.stackTraceElement() } ?: emptyList() + private fun mapToCoroutineInfoData(mirror: MirrorOfCoroutineInfo): CoroutineInfoData? { + val coroutineNameIdState = CoroutineNameIdState.instance(mirror) + val stackTrace = mirror.enhancedStackTrace?.mapNotNull { it.stackTraceElement() } ?: emptyList() val variables: List = mirror.lastObservedFrame?.let { val spilledVariables = debugMetadata?.baseContinuationImpl?.mirror(it, executionContext) spilledVariables?.spilledValues(executionContext) } ?: emptyList() - var stackFrames = findStackFrames(stackTrace, variables) + val stackFrames = findStackFrames(stackTrace, variables) return CoroutineInfoData( - cnis, + coroutineNameIdState, stackFrames.restoredStackFrames, stackFrames.creationStackFrames, mirror.lastObservedThread, @@ -44,11 +47,11 @@ class CoroutineLibraryAgent2Proxy(private val executionContext: DefaultExecution } fun isInstalled(): Boolean { - try { - return debugProbesImpl?.isInstalledValue ?: false + return try { + debugProbesImpl?.isInstalledValue ?: false } catch (e: Exception) { log.error("Exception happened while checking agent status.", e) - return false + false } } @@ -74,10 +77,10 @@ class CoroutineLibraryAgent2Proxy(private val executionContext: DefaultExecution companion object { fun instance(executionContext: DefaultExecutionContext): CoroutineLibraryAgent2Proxy? { val agentProxy = CoroutineLibraryAgent2Proxy(executionContext) - if (agentProxy.isInstalled()) - return agentProxy + return if (agentProxy.isInstalled()) + agentProxy else - return null + null } } diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/CoroutineLibraryAgentProxy.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/CoroutineLibraryAgentProxy.kt deleted file mode 100644 index eccd96ec88b..00000000000 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/CoroutineLibraryAgentProxy.kt +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package org.jetbrains.kotlin.idea.debugger.coroutine.proxy - -import com.intellij.debugger.engine.evaluation.EvaluateException -import com.sun.jdi.* -import org.jetbrains.kotlin.idea.debugger.coroutine.data.* -import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.mirror.CoroutineContext -import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.mirror.JavaLangMirror -import org.jetbrains.kotlin.idea.debugger.coroutine.util.isCreationSeparatorFrame -import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext - -class CoroutineLibraryAgentProxy(private val debugProbesClsRef: ClassType, private val executionContext: DefaultExecutionContext) : - CoroutineInfoProvider { - private val coroutineContextReference: JavaLangMirror = JavaLangMirror(executionContext) - - private val debugProbesImplClsRef = executionContext.findClass("$DEBUG_PACKAGE.internal.DebugProbesImpl") as ClassType - private val debugProbesImplInstance = with(debugProbesImplClsRef) { getValue(fieldByName("INSTANCE")) as ObjectReference } - private val enhanceStackTraceWithThreadDumpRef: Method = debugProbesImplClsRef - .methodsByName("enhanceStackTraceWithThreadDump").single() - - private val dumpMethod: Method = debugProbesClsRef.concreteMethodByName("dumpCoroutinesInfo", "()Ljava/util/List;") - val instance = with(debugProbesClsRef) { getValue(fieldByName("INSTANCE")) as ObjectReference } - - // CoroutineInfo - private val coroutineInfoClsRef = executionContext.findClass("$DEBUG_PACKAGE.CoroutineInfo") as ClassType - - private val getStateRef: Method = coroutineInfoClsRef.concreteMethodByName("getState", "()Lkotlinx/coroutines/debug/State;") - private val getContextRef: Method = coroutineInfoClsRef.concreteMethodByName("getContext", "()Lkotlin/coroutines/CoroutineContext;") - private val lastObservedStackTraceRef: Method = coroutineInfoClsRef.methodsByName("lastObservedStackTrace").single() - - private val sequenceNumberFieldRef: Field = coroutineInfoClsRef.fieldByName("sequenceNumber") - private val lastObservedThreadFieldRef: Field = coroutineInfoClsRef.fieldByName("lastObservedThread") - private val lastObservedFrameFieldRef: Field = coroutineInfoClsRef.fieldByName("lastObservedFrame") // continuation - - // value - private val vm = executionContext.vm - private val locationCache = LocationCache(executionContext) - - private val coroutineContext: CoroutineContext = CoroutineContext(executionContext) - - @Synchronized - @Suppress("unused") - fun install() = - executionContext.invokeMethodAsVoid(instance, "install") - - @Synchronized - @Suppress("unused") - fun uninstall() = - executionContext.invokeMethodAsVoid(instance, "uninstall") - - override fun dumpCoroutinesInfo(): List { - val coroutinesInfo = executionContext.invokeMethodAsObject(instance, dumpMethod) ?: return emptyList() - executionContext.keepReference(coroutinesInfo) - val size = coroutineContextReference.sizeOf(coroutinesInfo, executionContext) - - return MutableList(size) { - val elem = coroutineContextReference.elementFromList(coroutinesInfo, it, executionContext) - fetchCoroutineState(elem) - } - } - - private fun fetchCoroutineState(instance: ObjectReference): CoroutineInfoData { - val name = getName(instance) - val state = getState(instance) - val thread = getLastObservedThread(instance, lastObservedThreadFieldRef) - val lastObservedFrameFieldRef = instance.getValue(lastObservedFrameFieldRef) as? ObjectReference - val stackTrace = getStackTrace(instance) - val creationFrameSeparatorIndex = findCreationFrameIndex(stackTrace) - val coroutineStackTrace = stackTrace.take(creationFrameSeparatorIndex) - - val coroutineStackTraceFrameItems = coroutineStackTrace.map { - SuspendCoroutineStackFrameItem(it, locationCache.createLocation(it)) - } - val creationStackTrace = stackTrace.subList(creationFrameSeparatorIndex + 1, stackTrace.size) - val creationStackTraceFrameItems = creationStackTrace.mapIndexed { index, stackTraceElement -> - CreationCoroutineStackFrameItem(stackTraceElement, locationCache.createLocation(stackTraceElement), index == 0) - } - val key = CoroutineNameIdState(name, "", State.valueOf(state), "") - - return CoroutineInfoData( - key, - coroutineStackTraceFrameItems.toMutableList(), - creationStackTraceFrameItems, - thread, - lastObservedFrameFieldRef - ) - } - - /** - * Tries to find creation frame separator if any, returns last index if none found - */ - private fun findCreationFrameIndex(frames: List): Int { - val index = frames.indexOfFirst { it.isCreationSeparatorFrame() } - return if (index < 0) - frames.lastIndex - else - index - } - - private fun getName( - info: ObjectReference // CoroutineInfo instance - ): String { - // equals to `coroutineInfo.context.get(CoroutineName).name` - val coroutineContextInst = executionContext.invokeMethod( - info, - getContextRef, - emptyList() - ) as? ObjectReference ?: throw IllegalArgumentException("Coroutine context must not be null") - val context = coroutineContext.mirror(coroutineContextInst, executionContext) - val name = context?.name ?: "coroutine" - val id = (info.getValue(sequenceNumberFieldRef) as LongValue).value() - return "$name#$id" - } - - private fun getState( - info: ObjectReference // CoroutineInfo instance - ): String { - // equals to `stringState = coroutineInfo.state.toString()` - val state = executionContext.invokeMethod(info, getStateRef, emptyList()) as ObjectReference - return coroutineContextReference.string(state, executionContext) - } - - private fun getLastObservedThread( - info: ObjectReference, // CoroutineInfo instance - threadRef: Field // reference to lastObservedThread - ): ThreadReference? = info.getValue(threadRef) as? ThreadReference - - /** - * Returns list of stackTraceElements for the given CoroutineInfo's [ObjectReference] - */ - private fun getStackTrace( - info: ObjectReference - ): List { - val frameList = lastObservedStackTrace(info) -// val tmpList = mutableListOf() -// val sizeOfFrameList = coroutineContextReference.sizeOf(frameList, executionContext) -// for (it in 0 until sizeOfFrameList) { -// val frame = coroutineContextReference.elementFromList(frameList, it, executionContext) -// val ste = coroutineContextReference.stackTraceElement(frame) -// tmpList.add(ste) -// } - val mergedFrameList = enhanceStackTraceWithThreadDump(listOf(info, frameList)) - val sizeOfMergedFrameList = coroutineContextReference.sizeOf(mergedFrameList, executionContext) - - val list = mutableListOf() - - for (it in 0 until sizeOfMergedFrameList) { - val frame = coroutineContextReference.elementFromList(mergedFrameList, it, executionContext) - val ste = coroutineContextReference.stackTraceElement(frame) - list.add(// 0, // add in the beginning // @TODO what's the point? - ste - ) - } - return list - } - - private fun lastObservedStackTrace(instance: ObjectReference) = - executionContext.invokeMethod(instance, lastObservedStackTraceRef, emptyList()) as ObjectReference - - private fun enhanceStackTraceWithThreadDump(args: List) = - executionContext.invokeMethod( - debugProbesImplInstance, - enhanceStackTraceWithThreadDumpRef, args - ) as ObjectReference - - companion object { - private const val DEBUG_PACKAGE = "kotlinx.coroutines.debug" - - fun instance(executionContext: DefaultExecutionContext): CoroutineLibraryAgentProxy? { - try { - val debugProbesClsRef = executionContext.findClass("$DEBUG_PACKAGE.DebugProbes") ?: return null - if (debugProbesClsRef is ClassType) { - val instanceField = debugProbesClsRef.fieldByName("INSTANCE") - val debugProbes = debugProbesClsRef.getValue(instanceField) as ObjectReference - val f = debugProbes.referenceType().fieldByName("isInstalled") - val debugProbesActivated = if (f != null) (debugProbes.getValue(f) as BooleanValue).value() else true - if (debugProbesActivated) - return CoroutineLibraryAgentProxy(debugProbesClsRef, executionContext) - } - } catch (e: EvaluateException) { - } - return null - } - } - -} diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/CoroutineNoLibraryProxy.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/CoroutineNoLibraryProxy.kt index 54be3fe0aa9..bffbf0ef5c6 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/CoroutineNoLibraryProxy.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/CoroutineNoLibraryProxy.kt @@ -6,7 +6,8 @@ package org.jetbrains.kotlin.idea.debugger.coroutine.proxy import com.intellij.openapi.util.registry.Registry -import com.sun.jdi.* +import com.sun.jdi.Field +import com.sun.jdi.ObjectReference import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutineInfoData import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.mirror.CancellableContinuationImpl import org.jetbrains.kotlin.idea.debugger.coroutine.util.findCancellableContinuationImplReferenceType @@ -15,10 +16,10 @@ import org.jetbrains.kotlin.idea.debugger.coroutine.util.findDispatchedContinuat import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext -class CoroutineNoLibraryProxy(val executionContext: DefaultExecutionContext) : CoroutineInfoProvider { +class CoroutineNoLibraryProxy(private val executionContext: DefaultExecutionContext) : CoroutineInfoProvider { val log by logger - val debugMetadataKtType = executionContext.findCoroutineMetadataType() - val holder = ContinuationHolder.instance(executionContext) + private val debugMetadataKtType = executionContext.findCoroutineMetadataType() + private val holder = ContinuationHolder.instance(executionContext) override fun dumpCoroutinesInfo(): List { val vm = executionContext.vm @@ -49,13 +50,13 @@ class CoroutineNoLibraryProxy(val executionContext: DefaultExecutionContext) : C return false } - fun extractCancellableContinuation( + private fun extractCancellableContinuation( dispatchedContinuation: ObjectReference, ccMirrorProvider: CancellableContinuationImpl ): 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): Boolean { @@ -75,7 +76,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) } } diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/ManagerThreadExecutor.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/ManagerThreadExecutor.kt index 52988f40d9d..c21ff62666a 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/ManagerThreadExecutor.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/ManagerThreadExecutor.kt @@ -50,15 +50,7 @@ class ManagerThreadExecutor(val debugProcess: DebugProcessImpl) { } class ApplicationThreadExecutor { - fun readAction(f: () -> T): T { - return ApplicationManager.getApplication().runReadAction(Computable(f)) - } - fun schedule(f: () -> Unit, component: Component) { return ApplicationManager.getApplication().invokeLater({ f() }, ModalityState.stateForComponent(component)) } - - fun schedule(f: () -> Unit) { - return ApplicationManager.getApplication().invokeLater { f() } - } } diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/LocationStackFrameProxyImpl.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/SkipCoroutineStackFrameProxyImpl.kt similarity index 56% rename from idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/LocationStackFrameProxyImpl.kt rename to idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/SkipCoroutineStackFrameProxyImpl.kt index f322598cf49..1af450f2091 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/LocationStackFrameProxyImpl.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/SkipCoroutineStackFrameProxyImpl.kt @@ -6,16 +6,6 @@ package org.jetbrains.kotlin.idea.debugger.coroutine.proxy import com.intellij.debugger.jdi.StackFrameProxyImpl -import com.intellij.debugger.jdi.ThreadReferenceProxyImpl -import com.sun.jdi.Location -import com.sun.jdi.StackFrame - -class LocationStackFrameProxyImpl(val location: Location, frame: StackFrameProxyImpl) : - StackFrameProxyImpl(frame.threadProxy(), frame.stackFrame, frame.indexFromBottom) { - override fun location(): Location { - return location - } -} class SkipCoroutineStackFrameProxyImpl(frame: StackFrameProxyImpl) : StackFrameProxyImpl(frame.threadProxy(), frame.stackFrame, frame.indexFromBottom) diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/baseDynamicMirror.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/baseDynamicMirror.kt index 1b5cf52d891..06a0d5e5269 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/baseDynamicMirror.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/baseDynamicMirror.kt @@ -13,26 +13,26 @@ import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext abstract class BaseDynamicMirror(val value: ObjectReference, val name: String, val context: DefaultExecutionContext) { val log by logger - val cls: ReferenceType? = value.referenceType() + private val cls: ReferenceType? = value.referenceType() - fun makeField(fieldName: String): Field? = - cls?.let { it.fieldByName(fieldName) } + private fun makeField(fieldName: String): Field? = + cls?.fieldByName(fieldName) fun findMethod(methodName: String): Method? = - cls?.let { it.methodsByName(methodName).single() } + cls?.methodsByName(methodName)?.single() fun findMethod(methodName: String, signature: String): Method? = - cls?.let { it.methodsByName(methodName, signature).single() } + cls?.methodsByName(methodName, signature)?.single() fun isCompatible(value: ObjectReference?) = - value?.let { it.referenceType().isSubTypeOrSame(name) } ?: false + value?.referenceType()?.isSubTypeOrSame(name) ?: false fun mirror(): T? { - if (!isCompatible(value)) { + return if (!isCompatible(value)) { log.trace("Value ${value.referenceType()} is not compatible with $name.") - return null + null } else - return fetchMirror(value, context) + fetchMirror(value, context) } fun staticObjectValue(fieldName: String): ObjectReference? { diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/coroutinesContextMirror.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/coroutinesContextMirror.kt index 3749e821e32..f2467813f06 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/coroutinesContextMirror.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/coroutinesContextMirror.kt @@ -5,18 +5,16 @@ package org.jetbrains.kotlin.idea.debugger.coroutine.proxy.mirror -import com.sun.jdi.Method import com.sun.jdi.ObjectReference import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext -import java.lang.StackTraceElement class CoroutineContext(context: DefaultExecutionContext) : BaseMirror("kotlin.coroutines.CombinedContext", context) { - val coroutineNameRef = CoroutineName(context) - val coroutineIdRef = CoroutineId(context) - val jobRef = Job(context) - val dispatcherRef = CoroutineDispatcher(context) - val getContextElement = makeMethod("get") + private val coroutineNameRef = CoroutineName(context) + private val coroutineIdRef = CoroutineId(context) + private val jobRef = Job(context) + private val dispatcherRef = CoroutineDispatcher(context) + private val getContextElement = makeMethod("get") override fun fetchMirror(value: ObjectReference, context: DefaultExecutionContext): MirrorOfCoroutineContext? { val coroutineName = getElementValue(value, context, coroutineNameRef) @@ -26,7 +24,7 @@ class CoroutineContext(context: DefaultExecutionContext) : return MirrorOfCoroutineContext(value, coroutineName, coroutineId, dispatcher, job) } - fun getElementValue(value: ObjectReference, context: DefaultExecutionContext, keyProvider: ContextKey): T? { + private fun getElementValue(value: ObjectReference, context: DefaultExecutionContext, keyProvider: ContextKey): T? { val key = keyProvider.key() ?: return null val elementValue = objectValue(value, getContextElement, context, key) ?: return null return keyProvider.mirror(elementValue, context) @@ -42,12 +40,12 @@ data class MirrorOfCoroutineContext( ) abstract class ContextKey(name: String, context: DefaultExecutionContext) : BaseMirror(name, context) { - abstract fun key() : ObjectReference? + abstract fun key(): ObjectReference? } class CoroutineName(context: DefaultExecutionContext) : ContextKey("kotlinx.coroutines.CoroutineName", context) { val key = staticObjectValue("Key") - val getNameRef = makeMethod("getName") + private val getNameRef = makeMethod("getName") override fun fetchMirror(value: ObjectReference, context: DefaultExecutionContext): String? { return stringValue(value, getNameRef, context) @@ -57,8 +55,8 @@ class CoroutineName(context: DefaultExecutionContext) : ContextKey("kotl } class CoroutineId(context: DefaultExecutionContext) : ContextKey("kotlinx.coroutines.CoroutineId", context) { - val key = staticObjectValue("Key") - val getIdRef = makeMethod("getId") + private val key = staticObjectValue("Key") + private val getIdRef = makeMethod("getId") override fun fetchMirror(value: ObjectReference, context: DefaultExecutionContext): Long? { return longValue(value, getIdRef, context) @@ -79,8 +77,8 @@ class Job(context: DefaultExecutionContext) : ContextKey("kotli class CoroutineDispatcher(context: DefaultExecutionContext) : ContextKey("kotlinx.coroutines.CoroutineDispatcher", context) { - val key = staticObjectValue("Key") - val jlm = JavaLangMirror(context) + private val key = staticObjectValue("Key") + private val jlm = JavaLangMirror(context) override fun fetchMirror(value: ObjectReference, context: DefaultExecutionContext): String? { return jlm.string(value, context) diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/coroutinesDebugMirror.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/coroutinesDebugMirror.kt index 8d199e457d6..9fb37f4f693 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/coroutinesDebugMirror.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/coroutinesDebugMirror.kt @@ -5,29 +5,31 @@ package org.jetbrains.kotlin.idea.debugger.coroutine.proxy.mirror -import com.sun.jdi.* +import com.sun.jdi.ObjectReference +import com.sun.jdi.ThreadReference import org.jetbrains.kotlin.idea.debugger.coroutine.util.isSubTypeOrSame import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext class DebugProbesImpl private constructor(context: DefaultExecutionContext) : BaseMirror("kotlinx.coroutines.debug.internal.DebugProbesImpl", context) { - val javaLangListMirror = JavaUtilAbstractCollection(context) - val stackTraceElement = StackTraceElement(context) - val coroutineInfo = CoroutineInfo.instance(this, context) ?: throw IllegalStateException("CoroutineInfo implementation not found.") - val debugProbesCoroutineOwner = DebugProbesImpl_CoroutineOwner(coroutineInfo, context) - val instance = staticObjectValue("INSTANCE") - val isInstalledMethod = makeMethod("isInstalled\$kotlinx_coroutines_debug", "()Z") + private val javaLangListMirror = JavaUtilAbstractCollection(context) + private val stackTraceElement = StackTraceElement(context) + private val coroutineInfo = + CoroutineInfo.instance(this, context) ?: throw IllegalStateException("CoroutineInfo implementation not found.") + private val debugProbesCoroutineOwner = DebugProbesImplCoroutineOwner(coroutineInfo, context) + private val instance = staticObjectValue("INSTANCE") + private val isInstalledMethod = makeMethod("isInstalled\$kotlinx_coroutines_debug", "()Z") ?: makeMethod("isInstalled\$kotlinx_coroutines_core", "()Z") ?: throw IllegalStateException("isInstalledMethod not found") val isInstalledValue = booleanValue(instance, isInstalledMethod, context) - val enhanceStackTraceWithThreadDumpMethod = makeMethod("enhanceStackTraceWithThreadDump") - val dumpMethod = makeMethod("dumpCoroutinesInfo", "()Ljava/util/List;") + private val enhanceStackTraceWithThreadDumpMethod = makeMethod("enhanceStackTraceWithThreadDump") + private val dumpMethod = makeMethod("dumpCoroutinesInfo", "()Ljava/util/List;") override fun fetchMirror(value: ObjectReference, context: DefaultExecutionContext): MirrorOfDebugProbesImpl? { return MirrorOfDebugProbesImpl(value, instance, isInstalledValue) } - fun enchanceStackTraceWithThreadDump( + fun enhanceStackTraceWithThreadDump( context: DefaultExecutionContext, coroutineInfo: ObjectReference, lastObservedStackTrace: ObjectReference @@ -57,12 +59,13 @@ class DebugProbesImpl private constructor(context: DefaultExecutionContext) : try { DebugProbesImpl(context) } catch (e: IllegalStateException) { + log.debug("Attempt to access DebugProbesImpl but none found.", e) null } } } -class DebugProbesImpl_CoroutineOwner(val coroutineInfo: CoroutineInfo, context: DefaultExecutionContext) : +class DebugProbesImplCoroutineOwner(private val coroutineInfo: CoroutineInfo, context: DefaultExecutionContext) : BaseMirror(COROUTINE_OWNER_CLASS_NAME, context) { private val infoField = makeField("info") @@ -75,7 +78,7 @@ class DebugProbesImpl_CoroutineOwner(val coroutineInfo: CoroutineInfo, context: const val COROUTINE_OWNER_CLASS_NAME = "kotlinx.coroutines.debug.internal.DebugProbesImpl\$CoroutineOwner" fun instanceOf(value: ObjectReference?) = - value?.let { it.referenceType().isSubTypeOrSame(COROUTINE_OWNER_CLASS_NAME) } ?: false + value?.referenceType()?.isSubTypeOrSame(COROUTINE_OWNER_CLASS_NAME) ?: false } } @@ -84,13 +87,13 @@ data class MirrorOfCoroutineOwner(val that: ObjectReference, val coroutineInfo: data class MirrorOfDebugProbesImpl(val that: ObjectReference, val instance: ObjectReference?, val isInstalled: Boolean?) class CoroutineInfo private constructor( - val debugProbesImplMirror: DebugProbesImpl, + private val debugProbesImplMirror: DebugProbesImpl, context: DefaultExecutionContext, val className: String = AGENT_134_CLASS_NAME ) : BaseMirror(className, context) { - val javaLangMirror = JavaLangMirror(context) - val javaLangListMirror = JavaUtilAbstractCollection(context) + private val javaLangMirror = JavaLangMirror(context) + private val javaLangListMirror = JavaUtilAbstractCollection(context) private val coroutineContextMirror = CoroutineContext(context) private val stackTraceElement = StackTraceElement(context) private val contextFieldRef = makeField("context") @@ -105,16 +108,16 @@ class CoroutineInfo private constructor( companion object { val log by logger - const val AGENT_134_CLASS_NAME = "kotlinx.coroutines.debug.CoroutineInfo" - const val AGENT_135_AND_UP_CLASS_NAME = "kotlinx.coroutines.debug.internal.DebugCoroutineInfo" + private const val AGENT_134_CLASS_NAME = "kotlinx.coroutines.debug.CoroutineInfo" + private const val AGENT_135_AND_UP_CLASS_NAME = "kotlinx.coroutines.debug.internal.DebugCoroutineInfo" fun instance(debugProbesImplMirror: DebugProbesImpl, context: DefaultExecutionContext): CoroutineInfo? { val classType = context.findClassSafe(AGENT_134_CLASS_NAME) ?: context.findClassSafe(AGENT_135_AND_UP_CLASS_NAME) ?: return null - try { - return CoroutineInfo(debugProbesImplMirror, context, classType.name()) + return try { + CoroutineInfo(debugProbesImplMirror, context, classType.name()) } catch (e: IllegalStateException) { log.warn("coroutine-debugger: $classType not found", e) - return null + null } } } @@ -133,9 +136,9 @@ class CoroutineInfo private constructor( val creationStackTrace = creationStackTraceMirror?.values?.mapNotNull { stackTraceElement.mirror(it, context) } val lastObservedStackTrace = objectValue(value, lastObservedStackTraceMethod, context) - val enchancedList = + val enhancedList = if (lastObservedStackTrace != null) - debugProbesImplMirror.enchanceStackTraceWithThreadDump(context, value, lastObservedStackTrace) + debugProbesImplMirror.enhanceStackTraceWithThreadDump(context, value, lastObservedStackTrace) else emptyList() val lastObservedThread = threadValue(value, lastObservedThreadField) val lastObservedFrame = threadValue(value, lastObservedFrameField) @@ -144,7 +147,7 @@ class CoroutineInfo private constructor( coroutineContext, creationStackBottom, sequenceNumber, - enchancedList, + enhancedList, creationStackTrace, state, lastObservedThread, @@ -159,7 +162,7 @@ data class MirrorOfCoroutineInfo( val context: MirrorOfCoroutineContext?, val creationStackBottom: MirrorOfCoroutineStackFrame?, val sequenceNumber: Long?, - val enchancedStackTrace: List?, + val enhancedStackTrace: List?, val creationStackTrace: List?, val state: String?, val lastObservedThread: ThreadReference?, @@ -234,11 +237,8 @@ data class MirrorOfStackTraceElement( val lineNumber: Int?, val format: Byte? ) { - fun isInvokeSuspend() = - "invokeSuspend" == methodName - fun stackTraceElement() = - java.lang.StackTraceElement( + StackTraceElement( declaringClass, methodName, fileName, diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/coroutinesMirror.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/coroutinesMirror.kt index 2c37f29ebf3..d1d44a5a3cf 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/coroutinesMirror.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/coroutinesMirror.kt @@ -9,36 +9,35 @@ import com.sun.jdi.* import org.jetbrains.kotlin.idea.debugger.coroutine.util.isSubTypeOrSame import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext -import java.lang.IllegalStateException abstract class BaseMirror(val name: String, context: DefaultExecutionContext) { val log by logger protected val cls = context.findClassSafe(name) ?: throw IllegalStateException("coroutine-debugger: class $name not found.") fun makeField(fieldName: String): Field? = - cls?.let { it.fieldByName(fieldName) } + cls.fieldByName(fieldName) fun makeMethod(methodName: String): Method? = - cls?.let { it.methodsByName(methodName).singleOrNull() } + cls.methodsByName(methodName).singleOrNull() fun makeMethod(methodName: String, signature: String): Method? = - cls?.let { it.methodsByName(methodName, signature).singleOrNull() } + cls.methodsByName(methodName, signature).singleOrNull() fun isCompatible(value: ObjectReference?) = - value?.let { it.referenceType().isSubTypeOrSame(name) } ?: false + value?.referenceType()?.isSubTypeOrSame(name) ?: false fun mirror(value: ObjectReference?, context: DefaultExecutionContext): T? { value ?: return null - if (!isCompatible(value)) { + return if (!isCompatible(value)) { log.trace("Value ${value.referenceType()} is not compatible with $name.") - return null + null } else - return fetchMirror(value, context) + fetchMirror(value, context) } fun staticObjectValue(fieldName: String): ObjectReference? { val keyFieldRef = makeField(fieldName) - return cls?.let { it.getValue(keyFieldRef) as? ObjectReference } + return cls.let { it.getValue(keyFieldRef) as? ObjectReference } } fun staticMethodValue(instance: ObjectReference?, method: Method?, context: DefaultExecutionContext, vararg values: Value?) = @@ -49,7 +48,7 @@ abstract class BaseMirror(val name: String, context: DefaultExecutionContext) } fun staticMethodValue(method: Method?, context: DefaultExecutionContext, vararg values: Value?) = - cls?.let { + cls.let { method?.let { context.invokeMethodSafe(cls, method, values.asList()) as? ObjectReference } @@ -109,7 +108,7 @@ abstract class BaseMirror(val name: String, context: DefaultExecutionContext) protected abstract fun fetchMirror(value: ObjectReference, context: DefaultExecutionContext): T? } -class StandaloneCoroutine(context: DefaultExecutionContext) : +class StandaloneCoroutine private constructor(context: DefaultExecutionContext) : BaseMirror("kotlinx.coroutines.StandaloneCoroutine", context) { private val coroutineContextMirror = CoroutineContext(context) private val childContinuationMirror = ChildContinuation(context) @@ -118,19 +117,22 @@ class StandaloneCoroutine(context: DefaultExecutionContext) : override fun fetchMirror(value: ObjectReference, context: DefaultExecutionContext): MirrorOfStandaloneCoroutine { val state = objectValue(value, stateFieldRef) - val childcontinuation = childContinuationMirror.mirror(state, context) + val childContinuation = childContinuationMirror.mirror(state, context) val cc = objectValue(value, contextFieldRef) val coroutineContext = coroutineContextMirror.mirror(cc, context) - return MirrorOfStandaloneCoroutine(value, childcontinuation, coroutineContext) + return MirrorOfStandaloneCoroutine(value, childContinuation, coroutineContext) } companion object { + val log by logger + fun instance(context: DefaultExecutionContext): StandaloneCoroutine? { - val sc = StandaloneCoroutine(context) - if (sc.cls == null) - return null - else - return sc + return try { + StandaloneCoroutine(context) + } catch (e: IllegalStateException) { + log.debug("Attempt to access DebugProbesImpl but none found.", e) + null + } } } } @@ -160,7 +162,7 @@ data class MirrorOfChildContinuation( class CancellableContinuationImpl(context: DefaultExecutionContext) : BaseMirror("kotlinx.coroutines.CancellableContinuationImpl", context) { private val coroutineContextMirror = CoroutineContext(context) - private val dispatchedContinuationtMirror = DispatchedContinuation(context) + private val dispatchedContinuationMirror = DispatchedContinuation(context) private val decisionFieldRef = makeField("_decision") private val delegateFieldRef = makeField("delegate") // DispatchedContinuation private val resumeModeFieldRef = makeField("resumeMode") @@ -169,7 +171,7 @@ class CancellableContinuationImpl(context: DefaultExecutionContext) : override fun fetchMirror(value: ObjectReference, context: DefaultExecutionContext): MirrorOfCancellableContinuationImpl? { val decision = intValue(value, decisionFieldRef) - val dispatchedContinuation = dispatchedContinuationtMirror.mirror(objectValue(value, delegateFieldRef), context) + val dispatchedContinuation = dispatchedContinuationMirror.mirror(objectValue(value, delegateFieldRef), context) val submissionTime = longValue(value, submissionTimeFieldRef) val resumeMode = intValue(value, resumeModeFieldRef) val coroutineContext = objectValue(value, contextFieldRef) @@ -183,7 +185,7 @@ data class MirrorOfCancellableContinuationImpl( val decision: Int?, val delegate: MirrorOfDispatchedContinuation?, val resumeMode: Int?, - val submissionTyme: Long?, + val submissionTime: Long?, val jobContext: MirrorOfCoroutineContext? ) diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/debugMetadata.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/debugMetadata.kt index 3650fa4134b..a33538366db 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/debugMetadata.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/debugMetadata.kt @@ -45,7 +45,7 @@ class DebugMetadata private constructor(context: DefaultExecutionContext) : try { return DebugMetadata(context) } catch (e: IllegalStateException) { - log.warn("Attempt to access DebugMetadata", e) + log.debug("Attempt to access DebugMetadata but none found.", e) } return null } @@ -73,7 +73,8 @@ class BaseContinuationImpl(context: DefaultExecutionContext, private val debugMe val fieldVariables = getSpilledVariableFieldMapping(value, context) val completionValue = objectValue(value, getCompletion, context) val completion = if (completionValue != null && isCompatible(completionValue)) completionValue else null - val coroutineOwner = if (completionValue != null && DebugProbesImpl_CoroutineOwner.instanceOf(completionValue)) completionValue else null + val coroutineOwner = + if (completionValue != null && DebugProbesImplCoroutineOwner.instanceOf(completionValue)) completionValue else null return MirrorOfBaseContinuationImpl(value, stackTraceElementMirror, fieldVariables, completion, coroutineOwner) } @@ -84,7 +85,7 @@ class BaseContinuationImpl(context: DefaultExecutionContext, private val debugMe val length = getSpilledVariableFieldMappingReference.length() / 2 val fieldVariables = ArrayList() for (index in 0 until length) { - var fieldVariable = getFieldVariableName(getSpilledVariableFieldMappingReference, index) ?: continue + val fieldVariable = getFieldVariableName(getSpilledVariableFieldMappingReference, index) ?: continue fieldVariables.add(fieldVariable) } return fieldVariables diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/javaLangMirror.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/javaLangMirror.kt index a528ec0c62b..badc27efdbc 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/javaLangMirror.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/mirror/javaLangMirror.kt @@ -10,7 +10,7 @@ import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext class JavaLangMirror(context: DefaultExecutionContext) { // java.lang.Object - val classClsRef = context.findClass("java.lang.Object") as ClassType + private val classClsRef = context.findClass("java.lang.Object") as ClassType val toString: Method = classClsRef.concreteMethodByName("toString", "()Ljava/lang/String;") // java.util.List @@ -25,9 +25,6 @@ class JavaLangMirror(context: DefaultExecutionContext) { private val fileNameFieldRef: Field = stackTraceElementClsRef.fieldByName("fileName") private val lineNumberFieldRef: Field = stackTraceElementClsRef.fieldByName("lineNumber") - // java.lang.Class - val classType = context.findClass("java.lang.Class") as ClassType - fun string(state: ObjectReference, context: DefaultExecutionContext): String = (context.invokeMethod(state, toString, emptyList()) as StringReference).value() @@ -63,14 +60,14 @@ class JavaLangMirror(context: DefaultExecutionContext) { class JavaUtilAbstractCollection(context: DefaultExecutionContext) : BaseMirror("java.util.AbstractCollection", context) { - val abstractList = JavaUtilAbstractList(context) - val sizeMethod = makeMethod("size") + private val abstractList = JavaUtilAbstractList(context) + private val sizeMethod = makeMethod("size") override fun fetchMirror(value: ObjectReference, context: DefaultExecutionContext): MirrorOfJavaLangAbstractCollection? { val list = mutableListOf() val size = intValue(value, sizeMethod, context) ?: 0 for (index in 0 until size) { - val reference = abstractList.get(value, index, context) ?: continue + val reference = abstractList.get(value, index, context) ?: continue list.add(reference) } return MirrorOfJavaLangAbstractCollection(value, list) @@ -81,7 +78,7 @@ class JavaUtilAbstractList(context: DefaultExecutionContext) : BaseMirror("java.util.AbstractList", context) { val getMethod = makeMethod("get") - override fun fetchMirror(value: ObjectReference, context: DefaultExecutionContext) = + override fun fetchMirror(value: ObjectReference, context: DefaultExecutionContext): Nothing? = null fun get(value: ObjectReference, index: Int, context: DefaultExecutionContext): ObjectReference? = diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/CoroutineFrameBuilder.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/CoroutineFrameBuilder.kt index df62b999c31..f3e32ad88d2 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/CoroutineFrameBuilder.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/CoroutineFrameBuilder.kt @@ -20,7 +20,7 @@ class CoroutineFrameBuilder { companion object { val log by logger - const val PRE_FETCH_FRAME_COUNT = 5 + private const val PRE_FETCH_FRAME_COUNT = 5 fun build(coroutine: CoroutineInfoData, suspendContext: SuspendContextImpl): DoubleFrameList? = when { @@ -81,10 +81,10 @@ class CoroutineFrameBuilder { frame: StackFrameProxyImpl ): RunningCoroutineStackFrameItem? { val location = frame.location() - if (!location.safeCoroutineExitPointLineNumber()) - return RunningCoroutineStackFrameItem(frame, location) + return if (!location.safeCoroutineExitPointLineNumber()) + RunningCoroutineStackFrameItem(frame, location) else - return null + null } /** @@ -130,7 +130,7 @@ class CoroutineFrameBuilder { else -> null } ?: return null - val continuationHolder = ContinuationHolder.instance(context) ?: return null + val continuationHolder = ContinuationHolder.instance(context) val coroutineInfo = continuationHolder.extractCoroutineInfoData(continuation) ?: return null return preflight(frame, theFollowingFrames, coroutineInfo, mode) } @@ -139,7 +139,7 @@ class CoroutineFrameBuilder { private fun lookForTheFollowingFrame(theFollowingFrames: List): StackFrameProxyImpl? { for (i in 0 until min(PRE_FETCH_FRAME_COUNT, theFollowingFrames.size)) { // pre-scan PRE_FETCH_FRAME_COUNT frames - val nextFrame = theFollowingFrames.get(i) + val nextFrame = theFollowingFrames[i] if (nextFrame.location().isPreFlight() == SuspendExitMode.SUSPEND_METHOD) { return nextFrame } @@ -168,7 +168,7 @@ class CoroutineFrameBuilder { private fun getThisContinuation(frame: StackFrameProxyImpl?): ObjectReference? = frame?.thisVariableValue() - fun theFollowingFrames(frame: StackFrameProxyImpl): List? { + private fun theFollowingFrames(frame: StackFrameProxyImpl): List? { val frames = frame.threadProxy().frames() val indexOfCurrentFrame = frames.indexOf(frame) if (indexOfCurrentFrame >= 0) { diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/CoroutineUtils.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/CoroutineUtils.kt index 093a5b1ac81..e54aaf33411 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/CoroutineUtils.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/CoroutineUtils.kt @@ -30,9 +30,6 @@ fun Method.isInvokeSuspend(): Boolean = fun Method.isInvoke(): Boolean = name() == "invoke" && signature().contains("Ljava/lang/Object;)Ljava/lang/Object;") -fun Method.isContinuation() = - isInvokeSuspend() && declaringType().isContinuation() /* Perhaps need to check for "Lkotlin/coroutines/Continuation;)" in signature() ? */ - fun Method.isSuspendLambda() = isInvokeSuspend() && declaringType().isSuspendLambda() @@ -79,16 +76,13 @@ fun StackFrameProxyImpl.variableValue(variableName: String): ObjectReference? { return getValue(continuationVariable) as? ObjectReference ?: return null } -fun StackFrameProxyImpl.completionVariableValue(): ObjectReference? = - variableValue("completion") - fun StackFrameProxyImpl.continuationVariableValue(): ObjectReference? = variableValue("\$continuation") fun StackFrameProxyImpl.thisVariableValue(): ObjectReference? = this.thisObject() -private fun Method.isGetCOROUTINE_SUSPENDED() = +private fun Method.isGetCoroutineSuspended() = signature() == "()Ljava/lang/Object;" && name() == "getCOROUTINE_SUSPENDED" && declaringType().name() == "kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsKt" fun DefaultExecutionContext.findCoroutineMetadataType() = @@ -101,7 +95,7 @@ fun DefaultExecutionContext.findCancellableContinuationImplReferenceType(): List vm.classesByName("kotlinx.coroutines.CancellableContinuationImpl") fun hasGetCoroutineSuspended(frames: List) = - frames.indexOfFirst { it.safeLocation()?.safeMethod()?.isGetCOROUTINE_SUSPENDED() == true } + frames.indexOfFirst { it.safeLocation()?.safeMethod()?.isGetCoroutineSuspended() == true } fun StackTraceElement.isCreationSeparatorFrame() = className.startsWith(CREATION_STACK_TRACE_SEPARATOR) @@ -112,9 +106,6 @@ fun StackTraceElement.findPosition(project: Project): XSourcePosition? = fun Location.findPosition(project: Project) = getPosition(project, declaringType().name(), lineNumber()) -fun ClassType.completionField() = - fieldByName("completion") - private fun getPosition(project: Project, className: String, lineNumber: Int): XSourcePosition? { val psiFacade = JavaPsiFacade.getInstance(project) val psiClass = psiFacade.findClass( @@ -130,7 +121,7 @@ private fun getPosition(project: Project, className: String, lineNumber: Int): X fun SuspendContextImpl.executionContext() = invokeInManagerThread { DefaultExecutionContext(EvaluationContextImpl(this, this.frameProxy)) } -fun SuspendContextImpl.invokeInManagerThread(f: () -> T?) : T? = +fun SuspendContextImpl.invokeInManagerThread(f: () -> T?): T? = debugProcess.invokeInManagerThread { f() } fun ThreadReferenceProxyImpl.supportsEvaluation(): Boolean = diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/KUtils.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/KUtils.kt index 497131db0d3..79a33f88d1a 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/KUtils.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/KUtils.kt @@ -10,37 +10,16 @@ import com.intellij.debugger.jdi.StackFrameProxyImpl import com.intellij.debugger.memory.utils.StackFrameItem import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.project.Project -import com.intellij.openapi.ui.MessageType -import com.intellij.openapi.util.registry.Registry import com.intellij.psi.JavaPsiFacade import com.intellij.psi.search.GlobalSearchScope import com.intellij.xdebugger.XDebuggerUtil import com.intellij.xdebugger.XSourcePosition -import com.intellij.xdebugger.frame.XStackFrame -import com.intellij.xdebugger.impl.XDebuggerManagerImpl import com.sun.jdi.Location import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.ApplicationThreadExecutor import org.jetbrains.kotlin.idea.debugger.safeLineNumber import org.jetbrains.kotlin.idea.debugger.safeLocation import org.jetbrains.kotlin.idea.debugger.safeMethod -fun getPosition(stackTraceElement: StackTraceElement, project: Project): XSourcePosition? { - val psiFacade = JavaPsiFacade.getInstance(project) - - val psiClass = ApplicationThreadExecutor().readAction { - @Suppress("DEPRECATION") - psiFacade.findClass( - stackTraceElement.className.substringBefore("$"), // find outer class, for which psi exists TODO - GlobalSearchScope.everythingScope(project) - ) - } - - val classFile = psiClass?.containingFile?.virtualFile - // to convert to 0-based line number or '-1' to do not move - val lineNumber = if (stackTraceElement.lineNumber > 0) stackTraceElement.lineNumber - 1 else return null - return XDebuggerUtil.getInstance().createPosition(classFile, lineNumber) -} - fun Location.format(): String { val method = safeMethod() return "${method?.name() ?: "noname"}:${safeLineNumber()}, ${method?.declaringType()?.name() ?: "empty"}" @@ -48,7 +27,7 @@ fun Location.format(): String { fun JavaStackFrame.format(): String { val location = descriptor.location - return location?.let { it.format() } ?: "emptyLocation" + return location?.format() ?: "emptyLocation" } fun StackFrameItem.format(): String { @@ -63,5 +42,3 @@ fun StackFrameProxyImpl.format(): String { } fun isInUnitTest() = ApplicationManager.getApplication().isUnitTestMode - -fun coroutineDebuggerTraceEnabled() = Registry.`is`("kotlin.debugger.coroutines.trace") || isInUnitTest() diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/Providers.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/Providers.kt index 8f5d5bed4f7..f5e3d7efa5b 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/Providers.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/util/Providers.kt @@ -5,27 +5,29 @@ package org.jetbrains.kotlin.idea.debugger.coroutine.util -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.diagnostic.DefaultLogger import com.intellij.openapi.diagnostic.Logger import com.intellij.xdebugger.XDebugSession import com.intellij.xdebugger.XDebugSessionListener -import org.apache.log4j.Level -import org.jetbrains.kotlin.idea.util.application.isUnitTestMode import javax.swing.Icon import javax.swing.JComponent import kotlin.properties.ReadOnlyProperty import kotlin.reflect.KProperty interface CreateContentParamsProvider { - fun createContentParams() : CreateContentParams + fun createContentParams(): CreateContentParams } -data class CreateContentParams(val id: String, val component: JComponent, val displayName: String, val icon: Icon?, val parentComponent: JComponent) +data class CreateContentParams( + val id: String, + val component: JComponent, + val displayName: String, + val icon: Icon?, + val parentComponent: JComponent +) interface XDebugSessionListenerProvider { - fun debugSessionListener(session: XDebugSession) : XDebugSessionListener + fun debugSessionListener(session: XDebugSession): XDebugSessionListener } /** diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/view/CoroutineDumpPanel.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/view/CoroutineDumpPanel.kt index 09a754bc42a..8d7b6dcfe09 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/view/CoroutineDumpPanel.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/view/CoroutineDumpPanel.kt @@ -45,7 +45,12 @@ import javax.swing.event.DocumentEvent /** * Panel with dump of coroutines */ -class CoroutineDumpPanel(project: Project, consoleView: ConsoleView, toolbarActions: DefaultActionGroup, val dump: List) : +class CoroutineDumpPanel( + project: Project, + consoleView: ConsoleView, + toolbarActions: DefaultActionGroup, + val dump: List +) : JPanel(BorderLayout()), DataProvider { private var exporterToTextFile: ExporterToTextFile private var mergedDump = ArrayList() @@ -180,14 +185,6 @@ class CoroutineDumpPanel(project: Project, consoleView: ConsoleView, toolbarActi override fun getData(dataId: String): Any? = if (PlatformDataKeys.EXPORTER_TO_TEXT_FILE.`is`(dataId)) exporterToTextFile else null - private fun getCoroutineStateIcon(infoData: CoroutineInfoData): Icon { - return when (infoData.key.state) { - State.RUNNING -> LayeredIcon(AllIcons.Actions.Resume, Daemon_sign) - State.SUSPENDED -> AllIcons.Actions.Pause - else -> EmptyIcon.create(6) - } - } - private fun getAttributes(infoData: CoroutineInfoData): SimpleTextAttributes { return when { infoData.isSuspended() -> SimpleTextAttributes.GRAY_ATTRIBUTES @@ -296,9 +293,9 @@ class CoroutineDumpPanel(project: Project, consoleView: ConsoleView, toolbarActi private fun stringStackTrace(info: CoroutineInfoData) = buildString { - appendln("\"${info.key.name}\", state: ${info.key.state}") + appendLine("\"${info.key.name}\", state: ${info.key.state}") info.stackTrace.forEach { - appendln("\t$it") + appendLine("\t$it") } } diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/view/CoroutineViewDebugSessionListener.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/view/CoroutineViewDebugSessionListener.kt index 7bfe98215ae..a7010f135db 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/view/CoroutineViewDebugSessionListener.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/view/CoroutineViewDebugSessionListener.kt @@ -48,7 +48,7 @@ class CoroutineViewDebugSessionListener( renew(suspendContext) } - fun renew(suspendContext: XSuspendContext) { + private fun renew(suspendContext: XSuspendContext) { if (suspendContext is SuspendContextImpl) { DebuggerUIUtil.invokeLater { xCoroutineView.renewRoot(suspendContext) diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/view/SimpleColoredTextIcon.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/view/SimpleColoredTextIcon.kt index 64e7fd3cffb..1f499f0d88e 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/view/SimpleColoredTextIcon.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/view/SimpleColoredTextIcon.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.idea.debugger.coroutine.view import com.intellij.debugger.impl.DebuggerUtilsEx import com.intellij.debugger.settings.ThreadsViewSettings import com.intellij.icons.AllIcons -import com.intellij.icons.AllIcons.General.Information import com.intellij.openapi.editor.HighlighterColors import com.intellij.openapi.editor.colors.TextAttributesKey import com.intellij.ui.ColoredTextContainer @@ -25,11 +24,11 @@ import org.jetbrains.kotlin.idea.debugger.coroutine.data.State import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger import javax.swing.Icon -class SimpleColoredTextIcon(val icon: Icon?, val hasChildrens: Boolean) { - val texts = mutableListOf() - val textKeyAttributes = mutableListOf() +class SimpleColoredTextIcon(val icon: Icon?, val hasChildren: Boolean) { + private val texts = mutableListOf() + private val textKeyAttributes = mutableListOf() - constructor(icon: Icon?, hasChildrens: Boolean, text: String) : this(icon, hasChildrens) { + constructor(icon: Icon?, hasChildren: Boolean, text: String) : this(icon, hasChildren) { append(text) } @@ -43,14 +42,14 @@ class SimpleColoredTextIcon(val icon: Icon?, val hasChildrens: Boolean) { textKeyAttributes.add(CoroutineDebuggerColors.VALUE_ATTRIBUTES) } - fun appendToComponent(component: ColoredTextContainer) { + private fun appendToComponent(component: ColoredTextContainer) { val size: Int = texts.size for (i in 0 until size) { - val text: String = texts.get(i) - val attribute: TextAttributesKey = textKeyAttributes.get(i) - val simpleTextAttrinbute = toSimpleTextAttribute(attribute) + val text: String = texts[i] + val attribute: TextAttributesKey = textKeyAttributes[i] + val simpleTextAttribute = toSimpleTextAttribute(attribute) - component.append(text, simpleTextAttrinbute) + component.append(text, simpleTextAttribute) } } @@ -90,7 +89,7 @@ class SimpleColoredTextIcon(val icon: Icon?, val hasChildrens: Boolean) { interface CoroutineDebuggerColors { companion object { - val REGULAR_ATTRIBUTES = HighlighterColors.TEXT + val REGULAR_ATTRIBUTES: TextAttributesKey = HighlighterColors.TEXT val VALUE_ATTRIBUTES = TextAttributesKey.createTextAttributesKey("KOTLIN_COROUTINE_DEBUGGER_VALUE", HighlighterColors.TEXT) } } @@ -185,7 +184,7 @@ class SimpleColoredTextIconPresentationRenderer { ) fun renderErrorNode(error: String) = - SimpleColoredTextIcon(AllIcons.Actions.Lightning,false, KotlinDebuggerCoroutinesBundle.message(error)) + SimpleColoredTextIcon(AllIcons.Actions.Lightning, false, KotlinDebuggerCoroutinesBundle.message(error)) fun renderInfoNode(text: String) = SimpleColoredTextIcon(AllIcons.General.Information, false, KotlinDebuggerCoroutinesBundle.message(text)) diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/view/XCoroutineView.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/view/XCoroutineView.kt index 1197cdf009b..5a924f01ed4 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/view/XCoroutineView.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/view/XCoroutineView.kt @@ -32,16 +32,12 @@ import org.jetbrains.kotlin.idea.debugger.coroutine.CoroutineDebuggerContentInfo import org.jetbrains.kotlin.idea.debugger.coroutine.CoroutineDebuggerContentInfo.Companion.XCOROUTINE_POPUP_ACTION_GROUP import org.jetbrains.kotlin.idea.debugger.coroutine.KotlinDebuggerCoroutinesBundle import org.jetbrains.kotlin.idea.debugger.coroutine.VersionedImplementationProvider -import org.jetbrains.kotlin.idea.debugger.coroutine.util.CoroutineFrameBuilder import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutineInfoData import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutineStackFrameItem import org.jetbrains.kotlin.idea.debugger.coroutine.data.CreationCoroutineStackFrameItem import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.CoroutineDebugProbesProxy import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.ManagerThreadExecutor -import org.jetbrains.kotlin.idea.debugger.coroutine.util.CreateContentParams -import org.jetbrains.kotlin.idea.debugger.coroutine.util.CreateContentParamsProvider -import org.jetbrains.kotlin.idea.debugger.coroutine.util.XDebugSessionListenerProvider -import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger +import org.jetbrains.kotlin.idea.debugger.coroutine.util.* import java.awt.BorderLayout import javax.swing.JPanel @@ -49,20 +45,20 @@ import javax.swing.JPanel class XCoroutineView(val project: Project, val session: XDebugSession) : Disposable, XDebugSessionListenerProvider, CreateContentParamsProvider { val log by logger - val versionedImplementationProvider = VersionedImplementationProvider() + private val versionedImplementationProvider = VersionedImplementationProvider() val mainPanel = JPanel(BorderLayout()) val someCombobox = ComboBox() val panel = XDebuggerTreePanel(project, session.debugProcess.editorsProvider, this, null, XCOROUTINE_POPUP_ACTION_GROUP, null) - val alarm = SingleAlarm(Runnable { resetRoot() }, VIEW_CLEAR_DELAY, this) + val alarm = SingleAlarm({ resetRoot() }, VIEW_CLEAR_DELAY, this) val renderer = SimpleColoredTextIconPresentationRenderer() val managerThreadExecutor = ManagerThreadExecutor(session) - var treeState: XDebuggerTreeState? = null + private var treeState: XDebuggerTreeState? = null private var restorer: XDebuggerTreeRestorer? = null private var selectedNodeListener: XDebuggerTreeSelectedNodeListener? = null companion object { - private val VIEW_CLEAR_DELAY = 100 //ms + private const val VIEW_CLEAR_DELAY = 100 //ms } init { @@ -97,7 +93,7 @@ class XCoroutineView(val project: Project, val session: XDebugSession) : fun saveState() { DebuggerUIUtil.invokeLater { - if (!(panel.tree.root is EmptyNode)) { + if (panel.tree.root !is EmptyNode) { treeState = XDebuggerTreeState.saveState(panel.tree) } } @@ -124,10 +120,6 @@ class XCoroutineView(val project: Project, val session: XDebugSession) : } } - fun forceClear() { - alarm.cancel() - } - override fun debugSessionListener(session: XDebugSession) = CoroutineViewDebugSessionListener(session, this) @@ -155,10 +147,10 @@ class XCoroutineView(val project: Project, val session: XDebugSession) : val debugProbesProxy = CoroutineDebugProbesProxy(suspendContext) val emptyDispatcherName = KotlinDebuggerCoroutinesBundle.message("coroutine.view.dispatcher.empty") - var coroutineCache = debugProbesProxy.dumpCoroutines() + val coroutineCache = debugProbesProxy.dumpCoroutines() if (coroutineCache.isOk()) { val children = XValueChildrenList() - var groups = coroutineCache.cache.groupBy { it.key.dispatcher } + val groups = coroutineCache.cache.groupBy { it.key.dispatcher } for (dispatcher in groups.keys) { children.add(CoroutineContainer(suspendContext, dispatcher ?: emptyDispatcherName, groups[dispatcher])) } @@ -248,7 +240,7 @@ class XCoroutineView(val project: Project, val session: XDebugSession) : } private fun applyRenderer(node: XValueNode, presentation: SimpleColoredTextIcon) = - node.setPresentation(presentation.icon, presentation.valuePresentation(), presentation.hasChildrens) + node.setPresentation(presentation.icon, presentation.valuePresentation(), presentation.hasChildren) open inner class RendererContainer(val presentation: SimpleColoredTextIcon) : XNamedValue(presentation.simpleString()) { override fun computePresentation(node: XValueNode, place: XValuePlace) = diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/AbstractPrimitiveRangeToInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/AbstractPrimitiveRangeToInspection.kt index 537038c54b5..4752a892fe6 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/AbstractPrimitiveRangeToInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/AbstractPrimitiveRangeToInspection.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.inspections import com.intellij.codeInspection.ProblemsHolder import com.intellij.psi.PsiElementVisitor import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall import org.jetbrains.kotlin.idea.intentions.getCallableDescriptor import org.jetbrains.kotlin.psi.KtBinaryExpression import org.jetbrains.kotlin.psi.KtDotQualifiedExpression @@ -46,4 +47,6 @@ abstract class AbstractPrimitiveRangeToInspection : AbstractKotlinInspection() { return constant.toConstantValue(getType(c) ?: return null) } } -} \ No newline at end of file +} + +var q = 12 \ No newline at end of file