From 9904304e07151ed199c6a9cd52c041d6f595d50c Mon Sep 17 00:00:00 2001 From: Vladimir Ilmov Date: Mon, 9 Mar 2020 13:23:39 +0100 Subject: [PATCH] (CoroutineDebugger) StackFrameInterceptor service added to KotlinPositionManager, dependency cleanup --- .../idea/debugger/KotlinPositionManager.kt | 9 ++-- .../idea/debugger/StackFrameInterceptor.kt | 20 ++++++++ .../debugger/stackFrame/KotlinStackFrame.kt | 4 +- .../jvm-debugger-coroutine/build.gradle.kts | 2 +- .../CoroutineAsyncStackTraceProvider.kt | 5 +- .../CoroutineStackFrameInterceptor.kt | 21 ++++++++ .../coroutine/data/CoroutineInfoData.kt | 3 +- .../coroutine/proxy/AsyncStackTraceContext.kt | 10 ++-- .../proxy/CoroutineDebugProbesProxy.kt | 10 ++-- .../coroutine/proxy/LookupContinuation.kt | 11 ++-- .../idea/debugger/coroutine/util/KUtils.kt | 3 +- .../idea/debugger/coroutine/util/Providers.kt | 2 +- .../debugger/coroutine/view/XCoroutineView.kt | 15 +++--- .../kotlin/idea/debugger/CoroutineUtils.kt | 12 ++++- .../debugger/evaluate/ExecutionContext.kt | 51 ++++++++++++++++--- idea/resources/META-INF/plugin-common.xml | 3 ++ idea/resources/META-INF/plugin-common.xml.191 | 3 ++ idea/resources/META-INF/plugin-common.xml.192 | 3 ++ 18 files changed, 146 insertions(+), 41 deletions(-) create mode 100644 idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/StackFrameInterceptor.kt create mode 100644 idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/CoroutineStackFrameInterceptor.kt diff --git a/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/KotlinPositionManager.kt b/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/KotlinPositionManager.kt index 7ec4781cd9a..a45d0e1593a 100644 --- a/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/KotlinPositionManager.kt +++ b/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/KotlinPositionManager.kt @@ -36,7 +36,6 @@ import org.jetbrains.kotlin.codegen.inline.KOTLIN_STRATA_NAME import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil import org.jetbrains.kotlin.idea.core.KotlinFileTypeFactory import org.jetbrains.kotlin.idea.core.util.CodeInsightUtils -import org.jetbrains.kotlin.idea.core.util.getLineCount import org.jetbrains.kotlin.idea.core.util.getLineStartOffset import org.jetbrains.kotlin.idea.debugger.breakpoints.getLambdasAtLineIfAny import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches @@ -53,6 +52,8 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil import org.jetbrains.kotlin.resolve.jvm.JvmClassName class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiRequestPositionManager, PositionManagerEx() { + private val stackFrameInterceptor: StackFrameInterceptor = myDebugProcess.project.getService() + private val allKotlinFilesScope = object : DelegatingGlobalSearchScope( KotlinSourceFilterScope.projectAndLibrariesSources(GlobalSearchScope.allScope(myDebugProcess.project), myDebugProcess.project) ) { @@ -80,9 +81,9 @@ class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiReq } override fun createStackFrame(frame: StackFrameProxyImpl, debugProcess: DebugProcessImpl, location: Location): XStackFrame? = - if (location.isInKotlinSources()) - KotlinStackFrame(frame) - else + if (location.isInKotlinSources()) { + stackFrameInterceptor.createStackFrame(frame, debugProcess, location) ?: KotlinStackFrame(frame) + } else null override fun getSourcePosition(location: Location?): SourcePosition? { diff --git a/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/StackFrameInterceptor.kt b/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/StackFrameInterceptor.kt new file mode 100644 index 00000000000..1a892285f00 --- /dev/null +++ b/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/StackFrameInterceptor.kt @@ -0,0 +1,20 @@ +/* + * 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; + +import com.intellij.debugger.engine.DebugProcessImpl; +import com.intellij.debugger.jdi.StackFrameProxyImpl; +import com.intellij.xdebugger.frame.XStackFrame +import com.sun.jdi.Location; +import org.jetbrains.kotlin.idea.debugger.stackFrame.KotlinStackFrame; + +interface StackFrameInterceptor { + fun createStackFrame( + frame: StackFrameProxyImpl, + debugProcess: DebugProcessImpl, + location: Location + ): XStackFrame? +} diff --git a/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/stackFrame/KotlinStackFrame.kt b/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/stackFrame/KotlinStackFrame.kt index f7d94c30470..5b6b336e77b 100644 --- a/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/stackFrame/KotlinStackFrame.kt +++ b/idea/jvm-debugger/jvm-debugger-core/src/org/jetbrains/kotlin/idea/debugger/stackFrame/KotlinStackFrame.kt @@ -24,9 +24,11 @@ import org.jetbrains.kotlin.codegen.inline.isFakeLocalVariableForInline import org.jetbrains.kotlin.idea.debugger.* import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerEvaluator -class KotlinStackFrame(frame: StackFrameProxyImpl) : JavaStackFrame(StackFrameDescriptorImpl(frame, MethodsTracker()), true) { +open class KotlinStackFrame(stackFrameDescriptorImpl: StackFrameDescriptorImpl) : JavaStackFrame(stackFrameDescriptorImpl, true) { private val kotlinVariableViewService = ToggleKotlinVariablesState.getService() + constructor(frame: StackFrameProxyImpl) : this(StackFrameDescriptorImpl(frame, MethodsTracker())) + private val kotlinEvaluator by lazy { val debugProcess = descriptor.debugProcess as DebugProcessImpl // Cast as in JavaStackFrame KotlinDebuggerEvaluator(debugProcess, this@KotlinStackFrame) diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/build.gradle.kts b/idea/jvm-debugger/jvm-debugger-coroutine/build.gradle.kts index cfd818bed9d..c4ded1cde71 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/build.gradle.kts +++ b/idea/jvm-debugger/jvm-debugger-coroutine/build.gradle.kts @@ -4,7 +4,7 @@ plugins { } dependencies { - compile(project(":idea:jvm-debugger:jvm-debugger-core")) + implementation(project(":idea:jvm-debugger:jvm-debugger-core")) compileOnly(toolsJarApi()) compileOnly(intellijDep()) diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/CoroutineAsyncStackTraceProvider.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/CoroutineAsyncStackTraceProvider.kt index 290c09d892b..80266162aaf 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/CoroutineAsyncStackTraceProvider.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/CoroutineAsyncStackTraceProvider.kt @@ -13,6 +13,8 @@ import com.sun.jdi.* import org.jetbrains.kotlin.idea.debugger.* import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutineStackFrameItem import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.AsyncStackTraceContext +import org.jetbrains.kotlin.idea.debugger.evaluate.BaseExecutionContext +import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext import org.jetbrains.kotlin.idea.debugger.evaluate.ExecutionContext class CoroutineAsyncStackTraceProvider : AsyncStackTraceProvider { @@ -38,8 +40,7 @@ class CoroutineAsyncStackTraceProvider : AsyncStackTraceProvider { if (threadReference == null || !threadReference.isSuspended || !canRunEvaluation(suspendContext)) return defaultResult - val evaluationContext = EvaluationContextImpl(suspendContext as SuspendContextImpl, frameProxy) - val context = ExecutionContext(evaluationContext, frameProxy) + val context = DefaultExecutionContext(suspendContext as SuspendContextImpl, frameProxy) val astContext = AsyncStackTraceContext(context, method) return astContext.getAsyncStackTraceIfAny() } 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 new file mode 100644 index 00000000000..4cf8d339729 --- /dev/null +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/CoroutineStackFrameInterceptor.kt @@ -0,0 +1,21 @@ +/* + * 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 + +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.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 + +class CoroutineStackFrameInterceptor(val project: Project) : StackFrameInterceptor { + override fun createStackFrame(frame: StackFrameProxyImpl, debugProcess: DebugProcessImpl, location: Location): XStackFrame? = + null +} \ No newline at end of file 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 34df3615fc6..c0bd4041f65 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 @@ -5,7 +5,8 @@ package org.jetbrains.kotlin.idea.debugger.coroutine.data -import com.sun.jdi.* +import com.sun.jdi.ObjectReference +import com.sun.jdi.ThreadReference /** * Represents state of a coroutine. diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/AsyncStackTraceContext.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/AsyncStackTraceContext.kt index acec453b978..4ae43df50c0 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/AsyncStackTraceContext.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/AsyncStackTraceContext.kt @@ -19,11 +19,12 @@ import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger import org.jetbrains.kotlin.idea.debugger.SUSPEND_LAMBDA_CLASSES import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutineStackFrameItem import org.jetbrains.kotlin.idea.debugger.coroutine.data.DefaultCoroutineStackFrameItem +import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext import org.jetbrains.kotlin.idea.debugger.isSubtype import org.jetbrains.kotlin.idea.debugger.safeVisibleVariableByName class AsyncStackTraceContext( - val context: ExecutionContext, + val context: DefaultExecutionContext, val method: Method ) { val log by logger @@ -46,13 +47,12 @@ class AsyncStackTraceContext( private fun locateContinuation(): ObjectReference? { val continuation: ObjectReference? if (isInvokeSuspendMethod(method)) { - continuation = context.frameProxy.thisObject() ?: return null + continuation = context.frameProxy?.thisObject() ?: return null if (!isSuspendLambda(continuation.referenceType())) return null } else if (isContinuationProvider(method)) { - val frameProxy = context.frameProxy - val continuationVariable = frameProxy.safeVisibleVariableByName(CONTINUATION_VARIABLE_NAME) ?: return null - continuation = frameProxy.getValue(continuationVariable) as? ObjectReference ?: return null + val continuationVariable = context.frameProxy?.safeVisibleVariableByName(CONTINUATION_VARIABLE_NAME) ?: return null + continuation = context.frameProxy?.getValue(continuationVariable) as? ObjectReference ?: return null context.keepReference(continuation) } else { continuation = null 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 99e613c0b39..ad7ec3d20e7 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 @@ -13,12 +13,13 @@ import org.jetbrains.kotlin.idea.debugger.coroutine.command.CoroutineBuilder import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutineInfoCache import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutineInfoData import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger +import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext import org.jetbrains.kotlin.idea.debugger.evaluate.ExecutionContext class CoroutineDebugProbesProxy(val suspendContext: XSuspendContext) { private val log by logger - private var executionContext: ExecutionContext = executionContext() + private var executionContext: DefaultExecutionContext = executionContext() // might want to use inner class but also having to monitor order of fields private var refs: ProcessReferences = ProcessReferences(executionContext) @@ -185,16 +186,15 @@ class CoroutineDebugProbesProxy(val suspendContext: XSuspendContext) { private fun sizeOf(args: ObjectReference): Int = (executionContext.invokeMethod(args, refs.sizeRef, emptyList()) as IntegerValue).value() - private fun executionContext() : ExecutionContext { - val evaluationContextImpl = EvaluationContextImpl(suspendContext as SuspendContextImpl, suspendContext.frameProxy) - return ExecutionContext(evaluationContextImpl, suspendContext.frameProxy as StackFrameProxyImpl) + private fun executionContext() : DefaultExecutionContext { + return DefaultExecutionContext(suspendContext as SuspendContextImpl, suspendContext.frameProxy) } /** * @TODO refactor later * Holds ClassTypes, Methods, ObjectReferences and Fields for a particular jvm */ - class ProcessReferences(executionContext: ExecutionContext) { + class ProcessReferences(executionContext: DefaultExecutionContext) { // kotlinx.coroutines.debug.DebugProbes instance and methods val debugProbesClsRef = executionContext.findClass("$DEBUG_PACKAGE.DebugProbes") as ClassType val debugProbesImplClsRef = executionContext.findClass("$DEBUG_PACKAGE.internal.DebugProbesImpl") as ClassType diff --git a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/LookupContinuation.kt b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/LookupContinuation.kt index 683f71880bc..6f38b73e040 100644 --- a/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/LookupContinuation.kt +++ b/idea/jvm-debugger/jvm-debugger-coroutine/src/org/jetbrains/kotlin/idea/debugger/coroutine/proxy/LookupContinuation.kt @@ -6,17 +6,16 @@ package org.jetbrains.kotlin.idea.debugger.coroutine.proxy import com.sun.jdi.* -import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutineInfoData -import org.jetbrains.kotlin.idea.debugger.evaluate.ExecutionContext +import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext import org.jetbrains.kotlin.idea.debugger.isSubtype -class LookupContinuation(val context: ExecutionContext, val frame: StackTraceElement) { +class LookupContinuation(val context: DefaultExecutionContext, val frame: StackTraceElement) { private fun suspendOrInvokeSuspend(method: Method): Boolean = "Lkotlin/coroutines/Continuation;)" in method.signature() || - (method.name() == "invokeSuspend" && method.signature() == "(Ljava/lang/Object;)Ljava/lang/Object;") // suspend fun or invokeSuspend + (method.name() == "invokeSuspend" && method.signature() == "(Ljava/lang/Object;)Ljava/lang/Object;") // suspend fun or invokeSuspend - private fun findMethod() : Method { + private fun findMethod(): Method { val clazz = context.findClass(frame.className) as ClassType val method = clazz.methodsByName(frame.methodName).last { val loc = it.location().lineNumber() @@ -75,7 +74,7 @@ class LookupContinuation(val context: ExecutionContext, val frame: StackTraceEle * Finds previous Continuation for this Continuation (completion field in BaseContinuationImpl) * @return null if given ObjectReference is not a BaseContinuationImpl instance or completion is null */ - private fun getNextFrame(continuation: ObjectReference, context: ExecutionContext): ObjectReference? { + private fun getNextFrame(continuation: ObjectReference, context: DefaultExecutionContext): ObjectReference? { val type = continuation.type() as ClassType if (!type.isSubtype("kotlin.coroutines.jvm.internal.BaseContinuationImpl")) return null val next = type.concreteMethodByName("getCompletion", "()Lkotlin/coroutines/Continuation;") 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 062da87bc73..e64a14119a2 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 @@ -24,7 +24,8 @@ fun getPosition(stackTraceElement: StackTraceElement, project: Project): XSource @Suppress("DEPRECATION") psiFacade.findClass( stackTraceElement.className.substringBefore("$"), // find outer class, for which psi exists TODO - GlobalSearchScope.everythingScope(project)) + GlobalSearchScope.everythingScope(project) + ) } val classFile = psiClass?.containingFile?.virtualFile 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 4c96a449f7b..38e4d1304fd 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 @@ -25,7 +25,7 @@ interface XDebugSessionListenerProvider { } /** - * Logger instantiation sample: 'val log by logger' + * Logger instantiation: 'val log by logger' */ val logger: ReadOnlyProperty get() = LoggerDelegate() 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 ecb98b49c46..3f194c8b43f 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 @@ -9,7 +9,6 @@ import com.intellij.debugger.engine.DebugProcessImpl import com.intellij.debugger.engine.JavaDebugProcess import com.intellij.debugger.engine.JavaExecutionStack import com.intellij.debugger.engine.SuspendContextImpl -import com.intellij.debugger.engine.evaluation.EvaluationContextImpl import com.intellij.debugger.jdi.StackFrameProxyImpl import com.intellij.debugger.jdi.ThreadReferenceProxyImpl import com.intellij.ide.CommonActionsManager @@ -46,12 +45,15 @@ 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.VersionedImplementationProvider import org.jetbrains.kotlin.idea.debugger.coroutine.data.* -import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.* +import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.ApplicationThreadExecutor +import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.CoroutineDebugProbesProxy +import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.LookupContinuation +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.evaluate.ExecutionContext +import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext import java.awt.BorderLayout import java.awt.event.KeyAdapter import java.awt.event.KeyEvent @@ -363,13 +365,12 @@ class XCoroutineView(val project: Project, val session: XDebugSession) : return XDebuggerUtil.getInstance().createPosition(classFile, lineNumber) } - private fun executionContext(suspendContext: SuspendContextImpl, frameProxy: StackFrameProxyImpl): ExecutionContext { - val evaluationContextImpl = EvaluationContextImpl(suspendContext, frameProxy) - return ExecutionContext(evaluationContextImpl, frameProxy) + private fun executionContext(suspendContext: SuspendContextImpl, frameProxy: StackFrameProxyImpl): DefaultExecutionContext { + return DefaultExecutionContext(suspendContext, frameProxy) } private fun createSyntheticStackFrame( - executionContext: ExecutionContext, + executionContext: DefaultExecutionContext, frame: SuspendCoroutineStackFrameItem ): SyntheticStackFrame? { diff --git a/idea/jvm-debugger/jvm-debugger-util/src/org/jetbrains/kotlin/idea/debugger/CoroutineUtils.kt b/idea/jvm-debugger/jvm-debugger-util/src/org/jetbrains/kotlin/idea/debugger/CoroutineUtils.kt index 70913d6dcd0..17efb59aef6 100644 --- a/idea/jvm-debugger/jvm-debugger-util/src/org/jetbrains/kotlin/idea/debugger/CoroutineUtils.kt +++ b/idea/jvm-debugger/jvm-debugger-util/src/org/jetbrains/kotlin/idea/debugger/CoroutineUtils.kt @@ -5,6 +5,8 @@ package org.jetbrains.kotlin.idea.debugger +import com.intellij.openapi.components.ServiceManager +import com.intellij.openapi.project.Project import kotlin.coroutines.Continuation import org.jetbrains.org.objectweb.asm.Type as AsmType @@ -13,4 +15,12 @@ val CONTINUATION_TYPE: AsmType = AsmType.getType(Continuation::class.java) val SUSPEND_LAMBDA_CLASSES: List = listOf( "kotlin.coroutines.jvm.internal.SuspendLambda", "kotlin.coroutines.jvm.internal.RestrictedSuspendLambda" -) \ No newline at end of file +) + +inline fun Project.getService(): T { + val service = ServiceManager.getService(this, T::class.java) + if (service == null) + throw IllegalStateException("Instance of service type ${T::class.java} can't be found. Check if service has been registered.") + else + return service +} diff --git a/idea/jvm-debugger/jvm-debugger-util/src/org/jetbrains/kotlin/idea/debugger/evaluate/ExecutionContext.kt b/idea/jvm-debugger/jvm-debugger-util/src/org/jetbrains/kotlin/idea/debugger/evaluate/ExecutionContext.kt index a4ed3e1c8a3..b64437eb1f2 100644 --- a/idea/jvm-debugger/jvm-debugger-util/src/org/jetbrains/kotlin/idea/debugger/evaluate/ExecutionContext.kt +++ b/idea/jvm-debugger/jvm-debugger-util/src/org/jetbrains/kotlin/idea/debugger/evaluate/ExecutionContext.kt @@ -6,12 +6,10 @@ package org.jetbrains.kotlin.idea.debugger.evaluate import com.intellij.debugger.engine.DebugProcessImpl -import com.intellij.debugger.engine.DebuggerManagerThreadImpl import com.intellij.debugger.engine.SuspendContextImpl import com.intellij.debugger.engine.evaluation.EvaluateException import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil import com.intellij.debugger.engine.evaluation.EvaluationContextImpl -import com.intellij.debugger.impl.DebuggerContextImpl import com.intellij.debugger.impl.DebuggerUtilsEx import com.intellij.debugger.jdi.StackFrameProxyImpl import com.intellij.debugger.jdi.VirtualMachineProxyImpl @@ -21,7 +19,32 @@ import com.sun.jdi.request.EventRequest import org.jetbrains.kotlin.idea.debugger.hopelessAware import org.jetbrains.org.objectweb.asm.Type -class ExecutionContext(val evaluationContext: EvaluationContextImpl, val frameProxy: StackFrameProxyImpl) { +class ExecutionContext(evaluationContext: EvaluationContextImpl, val frameProxy: StackFrameProxyImpl) : + BaseExecutionContext(evaluationContext) { +} + +class DefaultExecutionContext(evaluationContext: EvaluationContextImpl) : BaseExecutionContext(evaluationContext) { + + constructor(suspendContext: SuspendContextImpl) : this( + EvaluationContextImpl( + suspendContext, + null + ) + ) + + constructor(suspendContext: SuspendContextImpl, frameProxy: StackFrameProxyImpl?) : this( + EvaluationContextImpl( + suspendContext, + frameProxy + ) + ) + + val frameProxy: StackFrameProxyImpl? + get() = + evaluationContext.frameProxy +} + +sealed class BaseExecutionContext(val evaluationContext: EvaluationContextImpl) { val vm: VirtualMachineProxyImpl get() = evaluationContext.debugProcess.virtualMachineProxy @@ -121,7 +144,12 @@ class ExecutionContext(val evaluationContext: EvaluationContextImpl, val framePr fun invokeMethodAsObject(instance: ObjectReference, methodName: String, vararg params: Value): ObjectReference? = invokeMethodAsObject(instance, methodName, null, *params) - fun invokeMethodAsObject(instance: ObjectReference, methodName: String, methodSignature: String?, vararg params: Value): ObjectReference? = + fun invokeMethodAsObject( + instance: ObjectReference, + methodName: String, + methodSignature: String?, + vararg params: Value + ): ObjectReference? = findAndInvoke(instance, methodName, methodSignature, *params) as? ObjectReference fun invokeMethodAsObject(instance: ObjectReference, method: Method, vararg params: Value): ObjectReference? = @@ -130,13 +158,24 @@ class ExecutionContext(val evaluationContext: EvaluationContextImpl, val framePr fun invokeMethodAsVoid(type: ClassType, methodName: String, methodSignature: String? = null, vararg params: Value = emptyArray()) = findAndInvoke(type, methodName, methodSignature, *params) - fun invokeMethodAsVoid(instance: ObjectReference, methodName: String, methodSignature: String? = null, vararg params: Value = emptyArray()) = + fun invokeMethodAsVoid( + instance: ObjectReference, + methodName: String, + methodSignature: String? = null, + vararg params: Value = emptyArray() + ) = findAndInvoke(instance, methodName, methodSignature, *params) fun invokeMethodAsArray(instance: ClassType, methodName: String, methodSignature: String, vararg params: Value): ArrayReference? = findAndInvoke(instance, methodName, methodSignature, *params) as? ArrayReference - private fun findAndInvoke(ref: ObjectReference, type: ReferenceType, name: String, methodSignature: String, vararg params: Value): Value? { + private fun findAndInvoke( + ref: ObjectReference, + type: ReferenceType, + name: String, + methodSignature: String, + vararg params: Value + ): Value? { val method = type.methodsByName(name, methodSignature).single() return invokeMethod(ref, method, params.asList()) } diff --git a/idea/resources/META-INF/plugin-common.xml b/idea/resources/META-INF/plugin-common.xml index 4470e47ac4f..ca7628e9522 100644 --- a/idea/resources/META-INF/plugin-common.xml +++ b/idea/resources/META-INF/plugin-common.xml @@ -385,6 +385,9 @@ + + + + + +