(CoroutineDebugger) StackFrameInterceptor service added to KotlinPositionManager, dependency cleanup

This commit is contained in:
Vladimir Ilmov
2020-03-09 13:23:39 +01:00
parent 0af61293d5
commit 9904304e07
18 changed files with 146 additions and 41 deletions
@@ -36,7 +36,6 @@ import org.jetbrains.kotlin.codegen.inline.KOTLIN_STRATA_NAME
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
import org.jetbrains.kotlin.idea.core.KotlinFileTypeFactory import org.jetbrains.kotlin.idea.core.KotlinFileTypeFactory
import org.jetbrains.kotlin.idea.core.util.CodeInsightUtils 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.core.util.getLineStartOffset
import org.jetbrains.kotlin.idea.debugger.breakpoints.getLambdasAtLineIfAny import org.jetbrains.kotlin.idea.debugger.breakpoints.getLambdasAtLineIfAny
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches 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 import org.jetbrains.kotlin.resolve.jvm.JvmClassName
class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiRequestPositionManager, PositionManagerEx() { class KotlinPositionManager(private val myDebugProcess: DebugProcess) : MultiRequestPositionManager, PositionManagerEx() {
private val stackFrameInterceptor: StackFrameInterceptor = myDebugProcess.project.getService()
private val allKotlinFilesScope = object : DelegatingGlobalSearchScope( private val allKotlinFilesScope = object : DelegatingGlobalSearchScope(
KotlinSourceFilterScope.projectAndLibrariesSources(GlobalSearchScope.allScope(myDebugProcess.project), myDebugProcess.project) 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? = override fun createStackFrame(frame: StackFrameProxyImpl, debugProcess: DebugProcessImpl, location: Location): XStackFrame? =
if (location.isInKotlinSources()) if (location.isInKotlinSources()) {
KotlinStackFrame(frame) stackFrameInterceptor.createStackFrame(frame, debugProcess, location) ?: KotlinStackFrame(frame)
else } else
null null
override fun getSourcePosition(location: Location?): SourcePosition? { override fun getSourcePosition(location: Location?): SourcePosition? {
@@ -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?
}
@@ -24,9 +24,11 @@ import org.jetbrains.kotlin.codegen.inline.isFakeLocalVariableForInline
import org.jetbrains.kotlin.idea.debugger.* import org.jetbrains.kotlin.idea.debugger.*
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerEvaluator 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() private val kotlinVariableViewService = ToggleKotlinVariablesState.getService()
constructor(frame: StackFrameProxyImpl) : this(StackFrameDescriptorImpl(frame, MethodsTracker()))
private val kotlinEvaluator by lazy { private val kotlinEvaluator by lazy {
val debugProcess = descriptor.debugProcess as DebugProcessImpl // Cast as in JavaStackFrame val debugProcess = descriptor.debugProcess as DebugProcessImpl // Cast as in JavaStackFrame
KotlinDebuggerEvaluator(debugProcess, this@KotlinStackFrame) KotlinDebuggerEvaluator(debugProcess, this@KotlinStackFrame)
@@ -4,7 +4,7 @@ plugins {
} }
dependencies { dependencies {
compile(project(":idea:jvm-debugger:jvm-debugger-core")) implementation(project(":idea:jvm-debugger:jvm-debugger-core"))
compileOnly(toolsJarApi()) compileOnly(toolsJarApi())
compileOnly(intellijDep()) compileOnly(intellijDep())
@@ -13,6 +13,8 @@ import com.sun.jdi.*
import org.jetbrains.kotlin.idea.debugger.* import org.jetbrains.kotlin.idea.debugger.*
import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutineStackFrameItem import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutineStackFrameItem
import org.jetbrains.kotlin.idea.debugger.coroutine.proxy.AsyncStackTraceContext 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 import org.jetbrains.kotlin.idea.debugger.evaluate.ExecutionContext
class CoroutineAsyncStackTraceProvider : AsyncStackTraceProvider { class CoroutineAsyncStackTraceProvider : AsyncStackTraceProvider {
@@ -38,8 +40,7 @@ class CoroutineAsyncStackTraceProvider : AsyncStackTraceProvider {
if (threadReference == null || !threadReference.isSuspended || !canRunEvaluation(suspendContext)) if (threadReference == null || !threadReference.isSuspended || !canRunEvaluation(suspendContext))
return defaultResult return defaultResult
val evaluationContext = EvaluationContextImpl(suspendContext as SuspendContextImpl, frameProxy) val context = DefaultExecutionContext(suspendContext as SuspendContextImpl, frameProxy)
val context = ExecutionContext(evaluationContext, frameProxy)
val astContext = AsyncStackTraceContext(context, method) val astContext = AsyncStackTraceContext(context, method)
return astContext.getAsyncStackTraceIfAny() return astContext.getAsyncStackTraceIfAny()
} }
@@ -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
}
@@ -5,7 +5,8 @@
package org.jetbrains.kotlin.idea.debugger.coroutine.data 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. * Represents state of a coroutine.
@@ -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.SUSPEND_LAMBDA_CLASSES
import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutineStackFrameItem import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutineStackFrameItem
import org.jetbrains.kotlin.idea.debugger.coroutine.data.DefaultCoroutineStackFrameItem 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.isSubtype
import org.jetbrains.kotlin.idea.debugger.safeVisibleVariableByName import org.jetbrains.kotlin.idea.debugger.safeVisibleVariableByName
class AsyncStackTraceContext( class AsyncStackTraceContext(
val context: ExecutionContext, val context: DefaultExecutionContext,
val method: Method val method: Method
) { ) {
val log by logger val log by logger
@@ -46,13 +47,12 @@ class AsyncStackTraceContext(
private fun locateContinuation(): ObjectReference? { private fun locateContinuation(): ObjectReference? {
val continuation: ObjectReference? val continuation: ObjectReference?
if (isInvokeSuspendMethod(method)) { if (isInvokeSuspendMethod(method)) {
continuation = context.frameProxy.thisObject() ?: return null continuation = context.frameProxy?.thisObject() ?: return null
if (!isSuspendLambda(continuation.referenceType())) if (!isSuspendLambda(continuation.referenceType()))
return null return null
} else if (isContinuationProvider(method)) { } else if (isContinuationProvider(method)) {
val frameProxy = context.frameProxy val continuationVariable = context.frameProxy?.safeVisibleVariableByName(CONTINUATION_VARIABLE_NAME) ?: return null
val continuationVariable = frameProxy.safeVisibleVariableByName(CONTINUATION_VARIABLE_NAME) ?: return null continuation = context.frameProxy?.getValue(continuationVariable) as? ObjectReference ?: return null
continuation = frameProxy.getValue(continuationVariable) as? ObjectReference ?: return null
context.keepReference(continuation) context.keepReference(continuation)
} else { } else {
continuation = null continuation = null
@@ -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.CoroutineInfoCache
import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutineInfoData import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutineInfoData
import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger 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 import org.jetbrains.kotlin.idea.debugger.evaluate.ExecutionContext
class CoroutineDebugProbesProxy(val suspendContext: XSuspendContext) { class CoroutineDebugProbesProxy(val suspendContext: XSuspendContext) {
private val log by logger 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 // might want to use inner class but also having to monitor order of fields
private var refs: ProcessReferences = ProcessReferences(executionContext) private var refs: ProcessReferences = ProcessReferences(executionContext)
@@ -185,16 +186,15 @@ class CoroutineDebugProbesProxy(val suspendContext: XSuspendContext) {
private fun sizeOf(args: ObjectReference): Int = private fun sizeOf(args: ObjectReference): Int =
(executionContext.invokeMethod(args, refs.sizeRef, emptyList()) as IntegerValue).value() (executionContext.invokeMethod(args, refs.sizeRef, emptyList()) as IntegerValue).value()
private fun executionContext() : ExecutionContext { private fun executionContext() : DefaultExecutionContext {
val evaluationContextImpl = EvaluationContextImpl(suspendContext as SuspendContextImpl, suspendContext.frameProxy) return DefaultExecutionContext(suspendContext as SuspendContextImpl, suspendContext.frameProxy)
return ExecutionContext(evaluationContextImpl, suspendContext.frameProxy as StackFrameProxyImpl)
} }
/** /**
* @TODO refactor later * @TODO refactor later
* Holds ClassTypes, Methods, ObjectReferences and Fields for a particular jvm * 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 // kotlinx.coroutines.debug.DebugProbes instance and methods
val debugProbesClsRef = executionContext.findClass("$DEBUG_PACKAGE.DebugProbes") as ClassType val debugProbesClsRef = executionContext.findClass("$DEBUG_PACKAGE.DebugProbes") as ClassType
val debugProbesImplClsRef = executionContext.findClass("$DEBUG_PACKAGE.internal.DebugProbesImpl") as ClassType val debugProbesImplClsRef = executionContext.findClass("$DEBUG_PACKAGE.internal.DebugProbesImpl") as ClassType
@@ -6,17 +6,16 @@
package org.jetbrains.kotlin.idea.debugger.coroutine.proxy package org.jetbrains.kotlin.idea.debugger.coroutine.proxy
import com.sun.jdi.* import com.sun.jdi.*
import org.jetbrains.kotlin.idea.debugger.coroutine.data.CoroutineInfoData import org.jetbrains.kotlin.idea.debugger.evaluate.DefaultExecutionContext
import org.jetbrains.kotlin.idea.debugger.evaluate.ExecutionContext
import org.jetbrains.kotlin.idea.debugger.isSubtype 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 = private fun suspendOrInvokeSuspend(method: Method): Boolean =
"Lkotlin/coroutines/Continuation;)" in method.signature() || "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 clazz = context.findClass(frame.className) as ClassType
val method = clazz.methodsByName(frame.methodName).last { val method = clazz.methodsByName(frame.methodName).last {
val loc = it.location().lineNumber() 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) * Finds previous Continuation for this Continuation (completion field in BaseContinuationImpl)
* @return null if given ObjectReference is not a BaseContinuationImpl instance or completion is null * @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 val type = continuation.type() as ClassType
if (!type.isSubtype("kotlin.coroutines.jvm.internal.BaseContinuationImpl")) return null if (!type.isSubtype("kotlin.coroutines.jvm.internal.BaseContinuationImpl")) return null
val next = type.concreteMethodByName("getCompletion", "()Lkotlin/coroutines/Continuation;") val next = type.concreteMethodByName("getCompletion", "()Lkotlin/coroutines/Continuation;")
@@ -24,7 +24,8 @@ fun getPosition(stackTraceElement: StackTraceElement, project: Project): XSource
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
psiFacade.findClass( psiFacade.findClass(
stackTraceElement.className.substringBefore("$"), // find outer class, for which psi exists TODO stackTraceElement.className.substringBefore("$"), // find outer class, for which psi exists TODO
GlobalSearchScope.everythingScope(project)) GlobalSearchScope.everythingScope(project)
)
} }
val classFile = psiClass?.containingFile?.virtualFile val classFile = psiClass?.containingFile?.virtualFile
@@ -25,7 +25,7 @@ interface XDebugSessionListenerProvider {
} }
/** /**
* Logger instantiation sample: 'val log by logger' * Logger instantiation: 'val log by logger'
*/ */
val logger: ReadOnlyProperty<Any, Logger> get() = LoggerDelegate() val logger: ReadOnlyProperty<Any, Logger> get() = LoggerDelegate()
@@ -9,7 +9,6 @@ import com.intellij.debugger.engine.DebugProcessImpl
import com.intellij.debugger.engine.JavaDebugProcess import com.intellij.debugger.engine.JavaDebugProcess
import com.intellij.debugger.engine.JavaExecutionStack import com.intellij.debugger.engine.JavaExecutionStack
import com.intellij.debugger.engine.SuspendContextImpl import com.intellij.debugger.engine.SuspendContextImpl
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
import com.intellij.debugger.jdi.StackFrameProxyImpl import com.intellij.debugger.jdi.StackFrameProxyImpl
import com.intellij.debugger.jdi.ThreadReferenceProxyImpl import com.intellij.debugger.jdi.ThreadReferenceProxyImpl
import com.intellij.ide.CommonActionsManager 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.CoroutineDebuggerContentInfo.Companion.XCOROUTINE_POPUP_ACTION_GROUP
import org.jetbrains.kotlin.idea.debugger.coroutine.VersionedImplementationProvider import org.jetbrains.kotlin.idea.debugger.coroutine.VersionedImplementationProvider
import org.jetbrains.kotlin.idea.debugger.coroutine.data.* 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.CreateContentParams
import org.jetbrains.kotlin.idea.debugger.coroutine.util.CreateContentParamsProvider 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.XDebugSessionListenerProvider
import org.jetbrains.kotlin.idea.debugger.coroutine.util.logger 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.BorderLayout
import java.awt.event.KeyAdapter import java.awt.event.KeyAdapter
import java.awt.event.KeyEvent import java.awt.event.KeyEvent
@@ -363,13 +365,12 @@ class XCoroutineView(val project: Project, val session: XDebugSession) :
return XDebuggerUtil.getInstance().createPosition(classFile, lineNumber) return XDebuggerUtil.getInstance().createPosition(classFile, lineNumber)
} }
private fun executionContext(suspendContext: SuspendContextImpl, frameProxy: StackFrameProxyImpl): ExecutionContext { private fun executionContext(suspendContext: SuspendContextImpl, frameProxy: StackFrameProxyImpl): DefaultExecutionContext {
val evaluationContextImpl = EvaluationContextImpl(suspendContext, frameProxy) return DefaultExecutionContext(suspendContext, frameProxy)
return ExecutionContext(evaluationContextImpl, frameProxy)
} }
private fun createSyntheticStackFrame( private fun createSyntheticStackFrame(
executionContext: ExecutionContext, executionContext: DefaultExecutionContext,
frame: SuspendCoroutineStackFrameItem frame: SuspendCoroutineStackFrameItem
): SyntheticStackFrame? { ): SyntheticStackFrame? {
@@ -5,6 +5,8 @@
package org.jetbrains.kotlin.idea.debugger package org.jetbrains.kotlin.idea.debugger
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.project.Project
import kotlin.coroutines.Continuation import kotlin.coroutines.Continuation
import org.jetbrains.org.objectweb.asm.Type as AsmType 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<String> = listOf( val SUSPEND_LAMBDA_CLASSES: List<String> = listOf(
"kotlin.coroutines.jvm.internal.SuspendLambda", "kotlin.coroutines.jvm.internal.SuspendLambda",
"kotlin.coroutines.jvm.internal.RestrictedSuspendLambda" "kotlin.coroutines.jvm.internal.RestrictedSuspendLambda"
) )
inline fun <reified T> 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
}
@@ -6,12 +6,10 @@
package org.jetbrains.kotlin.idea.debugger.evaluate package org.jetbrains.kotlin.idea.debugger.evaluate
import com.intellij.debugger.engine.DebugProcessImpl import com.intellij.debugger.engine.DebugProcessImpl
import com.intellij.debugger.engine.DebuggerManagerThreadImpl
import com.intellij.debugger.engine.SuspendContextImpl import com.intellij.debugger.engine.SuspendContextImpl
import com.intellij.debugger.engine.evaluation.EvaluateException import com.intellij.debugger.engine.evaluation.EvaluateException
import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
import com.intellij.debugger.impl.DebuggerContextImpl
import com.intellij.debugger.impl.DebuggerUtilsEx import com.intellij.debugger.impl.DebuggerUtilsEx
import com.intellij.debugger.jdi.StackFrameProxyImpl import com.intellij.debugger.jdi.StackFrameProxyImpl
import com.intellij.debugger.jdi.VirtualMachineProxyImpl 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.kotlin.idea.debugger.hopelessAware
import org.jetbrains.org.objectweb.asm.Type 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 val vm: VirtualMachineProxyImpl
get() = evaluationContext.debugProcess.virtualMachineProxy 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? = fun invokeMethodAsObject(instance: ObjectReference, methodName: String, vararg params: Value): ObjectReference? =
invokeMethodAsObject(instance, methodName, null, *params) 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 findAndInvoke(instance, methodName, methodSignature, *params) as? ObjectReference
fun invokeMethodAsObject(instance: ObjectReference, method: Method, vararg params: Value): 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()) = fun invokeMethodAsVoid(type: ClassType, methodName: String, methodSignature: String? = null, vararg params: Value = emptyArray()) =
findAndInvoke(type, methodName, methodSignature, *params) 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) findAndInvoke(instance, methodName, methodSignature, *params)
fun invokeMethodAsArray(instance: ClassType, methodName: String, methodSignature: String, vararg params: Value): ArrayReference? = fun invokeMethodAsArray(instance: ClassType, methodName: String, methodSignature: String, vararg params: Value): ArrayReference? =
findAndInvoke(instance, methodName, methodSignature, *params) as? 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() val method = type.methodsByName(name, methodSignature).single()
return invokeMethod(ref, method, params.asList()) return invokeMethod(ref, method, params.asList())
} }
@@ -385,6 +385,9 @@
<projectService serviceInterface="org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings" <projectService serviceInterface="org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings"
serviceImplementation="org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings"/> serviceImplementation="org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings"/>
<projectService serviceInterface="org.jetbrains.kotlin.idea.debugger.StackFrameInterceptor"
serviceImplementation="org.jetbrains.kotlin.idea.debugger.coroutine.CoroutineStackFrameInterceptor"/>
<errorHandler implementation="org.jetbrains.kotlin.idea.reporter.KotlinReportSubmitter"/> <errorHandler implementation="org.jetbrains.kotlin.idea.reporter.KotlinReportSubmitter"/>
<registryKey <registryKey
@@ -386,6 +386,9 @@
<projectService serviceInterface="org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings" <projectService serviceInterface="org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings"
serviceImplementation="org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings"/> serviceImplementation="org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings"/>
<projectService serviceInterface="org.jetbrains.kotlin.idea.debugger.StackFrameInterceptor"
serviceImplementation="org.jetbrains.kotlin.idea.debugger.coroutine.CoroutineStackFrameInterceptor"/>
<errorHandler implementation="org.jetbrains.kotlin.idea.reporter.KotlinReportSubmitter"/> <errorHandler implementation="org.jetbrains.kotlin.idea.reporter.KotlinReportSubmitter"/>
<registryKey <registryKey
@@ -386,6 +386,9 @@
<projectService serviceInterface="org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings" <projectService serviceInterface="org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings"
serviceImplementation="org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings"/> serviceImplementation="org.jetbrains.kotlin.idea.core.script.settings.KotlinScriptingSettings"/>
<projectService serviceInterface="org.jetbrains.kotlin.idea.debugger.StackFrameInterceptor"
serviceImplementation="org.jetbrains.kotlin.idea.debugger.coroutine.CoroutineStackFrameInterceptor"/>
<errorHandler implementation="org.jetbrains.kotlin.idea.reporter.KotlinReportSubmitter"/> <errorHandler implementation="org.jetbrains.kotlin.idea.reporter.KotlinReportSubmitter"/>
<registryKey <registryKey