mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[debugger] fallback to the direct evaluation if helper fails and report helper stack in the error message
GitOrigin-RevId: e8162cd8f310cf870b456abe2a76da043fe3b726
This commit is contained in:
committed by
intellij-monorepo-bot
parent
9477778580
commit
a8bcc8b7db
@@ -5,7 +5,6 @@ import com.intellij.Patches;
|
||||
import com.intellij.debugger.*;
|
||||
import com.intellij.debugger.actions.DebuggerAction;
|
||||
import com.intellij.debugger.engine.evaluation.*;
|
||||
import com.intellij.debugger.engine.evaluation.expression.BoxingEvaluator;
|
||||
import com.intellij.debugger.engine.evaluation.expression.RetryEvaluationException;
|
||||
import com.intellij.debugger.engine.events.DebuggerCommandImpl;
|
||||
import com.intellij.debugger.engine.events.DebuggerContextCommandImpl;
|
||||
@@ -63,11 +62,13 @@ import com.intellij.psi.CommonClassNames;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.rt.debugger.MethodInvoker;
|
||||
import com.intellij.ui.awt.AnchoredPoint;
|
||||
import com.intellij.ui.classFilter.ClassFilter;
|
||||
import com.intellij.ui.classFilter.DebuggerClassFilterProvider;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.EventDispatcher;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.SingleEdtTaskScheduler;
|
||||
import com.intellij.util.concurrency.EdtScheduler;
|
||||
import com.intellij.util.concurrency.Semaphore;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -107,6 +108,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static com.intellij.debugger.engine.MethodInvokeUtilsKt.tryInvokeWithHelper;
|
||||
|
||||
public abstract class DebugProcessImpl extends UserDataHolderBase implements DebugProcess {
|
||||
private static final Logger LOG = Logger.getInstance(DebugProcessImpl.class);
|
||||
|
||||
@@ -1483,85 +1486,26 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
|
||||
@NotNull List<? extends Value> args,
|
||||
final int invocationOptions,
|
||||
boolean internalEvaluate) throws EvaluateException {
|
||||
if (!internalEvaluate && shouldInvokeWithHelper(method, invocationOptions)) {
|
||||
return invokeWithHelper(method.declaringType(), objRef, method, args, (EvaluationContextImpl)evaluationContext);
|
||||
InvocationResult result =
|
||||
tryInvokeWithHelper(method.declaringType(), objRef, method, args, (EvaluationContextImpl)evaluationContext, invocationOptions, internalEvaluate);
|
||||
if (result.isSuccess()) {
|
||||
return result.getValue();
|
||||
}
|
||||
else {
|
||||
return new InvokeCommand<>(method, args, (EvaluationContextImpl)evaluationContext) {
|
||||
@Override
|
||||
protected Value invokeMethod(ThreadReference thread, int invokePolicy, Method method, List<? extends Value> args)
|
||||
throws InvocationException, ClassNotLoadedException, IncompatibleThreadStateException, InvalidTypeException {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Invoking " + objRef.type().name() + "." + method.name());
|
||||
}
|
||||
//noinspection SSBasedInspection
|
||||
return objRef.invokeMethod(thread, method, args, invokePolicy | invocationOptions);
|
||||
return new InvokeCommand<>(method, args, (EvaluationContextImpl)evaluationContext) {
|
||||
@Override
|
||||
protected Value invokeMethod(ThreadReference thread, int invokePolicy, Method method, List<? extends Value> args)
|
||||
throws InvocationException, ClassNotLoadedException, IncompatibleThreadStateException, InvalidTypeException {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Invoking " + objRef.type().name() + "." + method.name());
|
||||
}
|
||||
}.start(internalEvaluate);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean shouldInvokeWithHelper(@NotNull Method method, int invocationOptions) {
|
||||
return Registry.is("debugger.evaluate.method.helper") &&
|
||||
!BitUtil.isSet(invocationOptions, ObjectReference.INVOKE_NONVIRTUAL) && // TODO: support
|
||||
!DebuggerUtils.isPrimitiveType(method.returnTypeName()) &&
|
||||
(!DebuggerUtilsEx.isVoid(method) || method.isConstructor()) &&
|
||||
!"clone".equals(method.name());
|
||||
}
|
||||
|
||||
private static @Nullable Value invokeWithHelper(@NotNull ReferenceType type,
|
||||
@Nullable ObjectReference objRef,
|
||||
@NotNull Method method,
|
||||
@NotNull List<? extends Value> originalArgs,
|
||||
@NotNull EvaluationContextImpl evaluationContext) throws EvaluateException {
|
||||
DebugProcessImpl debugProcess = evaluationContext.getDebugProcess();
|
||||
ArrayList<Value> invokerArgs = new ArrayList<>();
|
||||
|
||||
ReferenceType lookupClass =
|
||||
debugProcess.findClass(evaluationContext, "java.lang.invoke.MethodHandles$Lookup", evaluationContext.getClassLoader());
|
||||
ObjectReference implLookup = (ObjectReference)lookupClass.getValue(DebuggerUtils.findField(lookupClass, "IMPL_LOOKUP"));
|
||||
|
||||
invokerArgs.add(implLookup); // lookup
|
||||
invokerArgs.add(type.classObject()); // class
|
||||
invokerArgs.add(objRef); // object
|
||||
invokerArgs.add(DebuggerUtilsEx.mirrorOfString(method.name() + ";" + method.signature(),
|
||||
evaluationContext)); // method name and descriptor
|
||||
invokerArgs.add(method.declaringType().classLoader()); // method's declaring type class loader to be able to resolve parameter types
|
||||
|
||||
// argument values
|
||||
List<Value> args = new ArrayList<>(originalArgs);
|
||||
if (method.isVarArgs()) {
|
||||
// If vararg is Object... and an array of Objects is passed, we need to unwrap it or we'll not be able to distinguish what was passed later
|
||||
List<String> argumentTypeNames = method.argumentTypeNames();
|
||||
int lastIndex = argumentTypeNames.size() - 1;
|
||||
if (args.size() == lastIndex + 1 && args.get(lastIndex) instanceof ArrayReference arrayRef &&
|
||||
argumentTypeNames.get(lastIndex).startsWith(CommonClassNames.JAVA_LANG_OBJECT)) {
|
||||
args.remove(lastIndex);
|
||||
args.addAll(arrayRef.getValues());
|
||||
//noinspection SSBasedInspection
|
||||
return objRef.invokeMethod(thread, method, args, invokePolicy | invocationOptions);
|
||||
}
|
||||
}
|
||||
|
||||
List<Value> boxedArgs = new ArrayList<>(args.size());
|
||||
for (Value arg : args) {
|
||||
boxedArgs.add((Value)BoxingEvaluator.box(arg, evaluationContext));
|
||||
}
|
||||
|
||||
if (boxedArgs.size() < 10) {
|
||||
invokerArgs.addAll(boxedArgs); // args
|
||||
return DebuggerUtilsImpl.invokeHelperMethod(evaluationContext, MethodInvoker.class, "invoke" + boxedArgs.size(), invokerArgs, false);
|
||||
}
|
||||
else {
|
||||
ArrayType objectArrayClass = (ArrayType)debugProcess.findClass(
|
||||
evaluationContext,
|
||||
CommonClassNames.JAVA_LANG_OBJECT + "[]",
|
||||
evaluationContext.getClassLoader());
|
||||
|
||||
invokerArgs.add(DebuggerUtilsEx.mirrorOfArray(objectArrayClass, boxedArgs, evaluationContext)); // args
|
||||
return DebuggerUtilsImpl.invokeHelperMethod(evaluationContext, MethodInvoker.class, "invoke", invokerArgs, false);
|
||||
}
|
||||
}.start(internalEvaluate);
|
||||
}
|
||||
|
||||
private static ThreadReferenceProxy getEvaluationThread(final EvaluationContext evaluationContext) throws EvaluateException {
|
||||
@NotNull
|
||||
static ThreadReferenceProxy getEvaluationThread(final EvaluationContext evaluationContext) throws EvaluateException {
|
||||
ThreadReferenceProxy fromStackFrame =
|
||||
ObjectUtils.doIfNotNull(evaluationContext.getFrameProxy(), stackFrameProxy -> stackFrameProxy.threadProxy());
|
||||
SuspendContextImpl suspendContext = (SuspendContextImpl)evaluationContext.getSuspendContext();
|
||||
@@ -1597,53 +1541,53 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
|
||||
@NotNull List<? extends Value> args,
|
||||
int extraInvocationOptions,
|
||||
boolean internalEvaluate) throws EvaluateException {
|
||||
if (!internalEvaluate && shouldInvokeWithHelper(method, extraInvocationOptions)) {
|
||||
return invokeWithHelper(classType, null, method, args, (EvaluationContextImpl)evaluationContext);
|
||||
InvocationResult result =
|
||||
tryInvokeWithHelper(classType, null, method, args, (EvaluationContextImpl)evaluationContext, extraInvocationOptions, internalEvaluate);
|
||||
if (result.isSuccess()) {
|
||||
return result.getValue();
|
||||
}
|
||||
else {
|
||||
return new InvokeCommand<>(method, args, (EvaluationContextImpl)evaluationContext) {
|
||||
@Override
|
||||
protected Value invokeMethod(ThreadReference thread, int invokePolicy, Method method, List<? extends Value> args)
|
||||
throws InvocationException, ClassNotLoadedException, IncompatibleThreadStateException, InvalidTypeException {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Invoking " + classType.name() + "." + method.name());
|
||||
}
|
||||
//noinspection SSBasedInspection
|
||||
return classType.invokeMethod(thread, method, args, invokePolicy | extraInvocationOptions);
|
||||
return new InvokeCommand<>(method, args, (EvaluationContextImpl)evaluationContext) {
|
||||
@Override
|
||||
protected Value invokeMethod(ThreadReference thread, int invokePolicy, Method method, List<? extends Value> args)
|
||||
throws InvocationException, ClassNotLoadedException, IncompatibleThreadStateException, InvalidTypeException {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Invoking " + classType.name() + "." + method.name());
|
||||
}
|
||||
}.start(internalEvaluate);
|
||||
}
|
||||
//noinspection SSBasedInspection
|
||||
return classType.invokeMethod(thread, method, args, invokePolicy | extraInvocationOptions);
|
||||
}
|
||||
}.start(internalEvaluate);
|
||||
}
|
||||
|
||||
public Value invokeMethod(EvaluationContext evaluationContext,
|
||||
InterfaceType interfaceType,
|
||||
Method method,
|
||||
List<? extends Value> args) throws EvaluateException {
|
||||
if (shouldInvokeWithHelper(method, 0)) {
|
||||
return invokeWithHelper(interfaceType, null, method, args, (EvaluationContextImpl)evaluationContext);
|
||||
InvocationResult result =
|
||||
tryInvokeWithHelper(interfaceType, null, method, args, (EvaluationContextImpl)evaluationContext, 0, false);
|
||||
if (result.isSuccess()) {
|
||||
return result.getValue();
|
||||
}
|
||||
else {
|
||||
return new InvokeCommand<>(method, args, (EvaluationContextImpl)evaluationContext) {
|
||||
@Override
|
||||
protected Value invokeMethod(ThreadReference thread, int invokePolicy, Method method, List<? extends Value> args)
|
||||
throws InvocationException, ClassNotLoadedException, IncompatibleThreadStateException, InvalidTypeException {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Invoking " + interfaceType.name() + "." + method.name());
|
||||
}
|
||||
|
||||
try {
|
||||
//noinspection SSBasedInspection
|
||||
return interfaceType.invokeMethod(thread, method, args, invokePolicy);
|
||||
}
|
||||
catch (LinkageError e) {
|
||||
throw new IllegalStateException("Interface method invocation is not supported in JVM " +
|
||||
SystemInfo.JAVA_VERSION +
|
||||
". Use JVM 1.8.0_45 or higher to run " +
|
||||
ApplicationNamesInfo.getInstance().getFullProductName());
|
||||
}
|
||||
return new InvokeCommand<>(method, args, (EvaluationContextImpl)evaluationContext) {
|
||||
@Override
|
||||
protected Value invokeMethod(ThreadReference thread, int invokePolicy, Method method, List<? extends Value> args)
|
||||
throws InvocationException, ClassNotLoadedException, IncompatibleThreadStateException, InvalidTypeException {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Invoking " + interfaceType.name() + "." + method.name());
|
||||
}
|
||||
}.start(false);
|
||||
}
|
||||
|
||||
try {
|
||||
//noinspection SSBasedInspection
|
||||
return interfaceType.invokeMethod(thread, method, args, invokePolicy);
|
||||
}
|
||||
catch (LinkageError e) {
|
||||
throw new IllegalStateException("Interface method invocation is not supported in JVM " +
|
||||
SystemInfo.JAVA_VERSION +
|
||||
". Use JVM 1.8.0_45 or higher to run " +
|
||||
ApplicationNamesInfo.getInstance().getFullProductName());
|
||||
}
|
||||
}
|
||||
}.start(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -1673,23 +1617,23 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
|
||||
@NotNull List<? extends Value> args,
|
||||
final int invocationOptions,
|
||||
boolean internalEvaluate) throws EvaluateException {
|
||||
if (!internalEvaluate && shouldInvokeWithHelper(method, invocationOptions)) {
|
||||
return (ObjectReference)invokeWithHelper(classType, null, method, args, (EvaluationContextImpl)evaluationContext);
|
||||
InvocationResult result =
|
||||
tryInvokeWithHelper(classType, null, method, args, (EvaluationContextImpl)evaluationContext, invocationOptions, internalEvaluate);
|
||||
if (result.isSuccess()) {
|
||||
return (ObjectReference)result.getValue();
|
||||
}
|
||||
else {
|
||||
InvokeCommand<ObjectReference> invokeCommand = new InvokeCommand<>(method, args, (EvaluationContextImpl)evaluationContext) {
|
||||
@Override
|
||||
protected ObjectReference invokeMethod(ThreadReference thread, int invokePolicy, Method method, List<? extends Value> args)
|
||||
throws InvocationException, ClassNotLoadedException, IncompatibleThreadStateException, InvalidTypeException {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("New instance " + classType.name() + "." + method.name());
|
||||
}
|
||||
//noinspection SSBasedInspection
|
||||
return classType.newInstance(thread, method, args, invokePolicy | invocationOptions);
|
||||
InvokeCommand<ObjectReference> invokeCommand = new InvokeCommand<>(method, args, (EvaluationContextImpl)evaluationContext) {
|
||||
@Override
|
||||
protected ObjectReference invokeMethod(ThreadReference thread, int invokePolicy, Method method, List<? extends Value> args)
|
||||
throws InvocationException, ClassNotLoadedException, IncompatibleThreadStateException, InvalidTypeException {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("New instance " + classType.name() + "." + method.name());
|
||||
}
|
||||
};
|
||||
return invokeCommand.start(internalEvaluate);
|
||||
}
|
||||
//noinspection SSBasedInspection
|
||||
return classType.newInstance(thread, method, args, invokePolicy | invocationOptions);
|
||||
}
|
||||
};
|
||||
return invokeCommand.start(internalEvaluate);
|
||||
}
|
||||
|
||||
public void clearCashes(@NotNull SuspendContextImpl context) {
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.debugger.engine
|
||||
|
||||
import com.intellij.debugger.engine.DebuggerUtils.isPrimitiveType
|
||||
import com.intellij.debugger.engine.MethodInvokeUtils.getHelperExceptionStackTrace
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateException
|
||||
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
|
||||
import com.intellij.debugger.engine.evaluation.expression.BoxingEvaluator
|
||||
import com.intellij.debugger.impl.DebuggerUtilsEx
|
||||
import com.intellij.debugger.impl.DebuggerUtilsEx.isVoid
|
||||
import com.intellij.debugger.impl.DebuggerUtilsImpl
|
||||
import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.psi.CommonClassNames
|
||||
import com.intellij.rt.debugger.MethodInvoker
|
||||
import com.intellij.util.BitUtil.isSet
|
||||
import com.sun.jdi.*
|
||||
import com.sun.jdi.ObjectReference.INVOKE_NONVIRTUAL
|
||||
|
||||
object MethodInvokeUtils {
|
||||
fun getHelperExceptionStackTrace(evaluationContext: EvaluationContextImpl, e: Exception): String? {
|
||||
e as? EvaluateException ?: return null
|
||||
val exceptionFromTargetVM = e.exceptionFromTargetVM ?: return null
|
||||
var exceptionStack = DebuggerUtilsImpl.getExceptionText(evaluationContext, exceptionFromTargetVM)
|
||||
if (!exceptionStack.isNullOrEmpty()) {
|
||||
// drop user frames
|
||||
val currentStackDepth = DebugProcessImpl.getEvaluationThread(evaluationContext).frameCount()
|
||||
val lines = StringUtil.splitByLines(exceptionStack) // exclude empty lines
|
||||
if (lines.size > currentStackDepth) {
|
||||
return lines.asSequence().take(lines.size - currentStackDepth).joinToString(separator = "\n")
|
||||
}
|
||||
else {
|
||||
logger<MethodInvokeUtils>().error("Invalid helper stack (expected currentStackDepth = ${currentStackDepth}) : ${exceptionStack}")
|
||||
return exceptionStack
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(EvaluateException::class)
|
||||
internal fun tryInvokeWithHelper(
|
||||
type: ReferenceType,
|
||||
objRef: ObjectReference?,
|
||||
method: Method,
|
||||
originalArgs: List<Value?>,
|
||||
evaluationContext: EvaluationContextImpl,
|
||||
invocationOptions: Int,
|
||||
internalEvaluate: Boolean,
|
||||
): InvocationResult {
|
||||
if (internalEvaluate ||
|
||||
!Registry.`is`("debugger.evaluate.method.helper") ||
|
||||
isSet(invocationOptions, INVOKE_NONVIRTUAL) || //TODO: support
|
||||
isPrimitiveType(method.returnTypeName()) ||
|
||||
(isVoid(method) && !method.isConstructor) ||
|
||||
"clone" == method.name()) {
|
||||
return InvocationResult(false, null)
|
||||
}
|
||||
|
||||
val debugProcess = evaluationContext.debugProcess
|
||||
val invokerArgs = mutableListOf<Value?>()
|
||||
|
||||
val lookupClass =
|
||||
debugProcess.findClass(evaluationContext, "java.lang.invoke.MethodHandles\$Lookup", evaluationContext.getClassLoader())
|
||||
val implLookup = lookupClass.getValue(DebuggerUtils.findField(lookupClass, "IMPL_LOOKUP")) as ObjectReference
|
||||
|
||||
invokerArgs.add(implLookup) // lookup
|
||||
invokerArgs.add(type.classObject()) // class
|
||||
invokerArgs.add(objRef) // object
|
||||
invokerArgs.add(DebuggerUtilsEx.mirrorOfString(method.name() + ";" + method.signature(), evaluationContext)) // method name and descriptor
|
||||
invokerArgs.add(method.declaringType().classLoader()) // method's declaring type class loader to be able to resolve parameter types
|
||||
|
||||
// argument values
|
||||
val args = originalArgs.toMutableList()
|
||||
if (method.isVarArgs) {
|
||||
// If vararg is Object... and an array of Objects is passed, we need to unwrap it or we'll not be able to distinguish what was passed later
|
||||
val argumentTypeNames = method.argumentTypeNames()
|
||||
(args.lastOrNull() as? ArrayReference)?.let {
|
||||
if (args.size == argumentTypeNames.size && argumentTypeNames.last().startsWith(CommonClassNames.JAVA_LANG_OBJECT)) {
|
||||
args.removeLast()
|
||||
args.addAll(it.values)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val boxedArgs = args.map { BoxingEvaluator.box(it, evaluationContext) as Value? }
|
||||
|
||||
var helperMethodName = "invoke"
|
||||
if (boxedArgs.size > 10) {
|
||||
val objectArrayClass = debugProcess.findClass(
|
||||
evaluationContext,
|
||||
CommonClassNames.JAVA_LANG_OBJECT + "[]",
|
||||
evaluationContext.getClassLoader()) as ArrayType
|
||||
|
||||
invokerArgs.add(DebuggerUtilsEx.mirrorOfArray(objectArrayClass, boxedArgs, evaluationContext)) // args as array
|
||||
}
|
||||
else {
|
||||
helperMethodName = "invoke${boxedArgs.size}"
|
||||
invokerArgs.addAll(boxedArgs) // add all args directly to the helper args
|
||||
}
|
||||
|
||||
try {
|
||||
return InvocationResult(true, DebuggerUtilsImpl.invokeHelperMethod(evaluationContext, MethodInvoker::class.java, helperMethodName, invokerArgs, false))
|
||||
}
|
||||
catch (e: Exception) {
|
||||
val helperExceptionStackTrace = getHelperExceptionStackTrace(evaluationContext, e)
|
||||
if (helperExceptionStackTrace?.contains(method.name() + "(") == true) {
|
||||
throw e
|
||||
}
|
||||
DebuggerUtilsImpl.logError("Exception from helper: ${e.message}", e,
|
||||
*listOfNotNull(helperExceptionStackTrace).toTypedArray()) // log helper exception if available
|
||||
return InvocationResult(false, null)
|
||||
}
|
||||
}
|
||||
|
||||
internal data class InvocationResult(@get:JvmName("isSuccess") val success: Boolean, val value: Value?)
|
||||
|
||||
@@ -10,8 +10,4 @@ public final class ExceptionDebugHelper {
|
||||
t.printStackTrace(new PrintWriter(writer));
|
||||
return writer.getBuffer().toString();
|
||||
}
|
||||
|
||||
public static int getCurrentThreadStackDepth() {
|
||||
return Thread.currentThread().getStackTrace().length;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-21
@@ -4,15 +4,14 @@ package org.jetbrains.kotlin.idea.debugger.coroutine
|
||||
|
||||
import com.intellij.debugger.actions.AsyncStacksToggleAction
|
||||
import com.intellij.debugger.engine.DebugProcessImpl
|
||||
import com.intellij.debugger.engine.MethodInvokeUtils
|
||||
import com.intellij.debugger.engine.SuspendContextImpl
|
||||
import com.intellij.debugger.engine.SuspendManagerUtil
|
||||
import com.intellij.debugger.engine.evaluation.EvaluateException
|
||||
import com.intellij.debugger.impl.DebuggerUtilsEx
|
||||
import com.intellij.debugger.impl.DebuggerUtilsImpl
|
||||
import com.intellij.debugger.jdi.StackFrameProxyImpl
|
||||
import com.intellij.openapi.diagnostic.thisLogger
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.rt.debugger.ExceptionDebugHelper
|
||||
import com.intellij.rt.debugger.coroutines.CoroutinesDebugHelper
|
||||
import com.intellij.xdebugger.frame.XStackFrame
|
||||
import com.intellij.xdebugger.impl.XDebugSessionImpl
|
||||
@@ -196,25 +195,9 @@ class CoroutineStackFrameInterceptor : StackFrameInterceptor {
|
||||
try {
|
||||
return DebuggerUtilsImpl.invokeHelperMethod(context.evaluationContext, helperClass, methodName, args)
|
||||
} catch (e: Exception) {
|
||||
if (e is EvaluateException && e.exceptionFromTargetVM != null) {
|
||||
var exceptionStack = DebuggerUtilsImpl.getExceptionText(context.evaluationContext, e.exceptionFromTargetVM!!)
|
||||
if (exceptionStack != null) {
|
||||
// drop user frames
|
||||
val currentStackDepth = (DebuggerUtilsImpl.invokeHelperMethod(
|
||||
context.evaluationContext,
|
||||
ExceptionDebugHelper::class.java,
|
||||
"getCurrentThreadStackDepth",
|
||||
emptyList()
|
||||
) as IntegerValue).value()
|
||||
val lines = exceptionStack.lines()
|
||||
if (lines.size > currentStackDepth) {
|
||||
exceptionStack = lines.subList(0, lines.size - currentStackDepth + 1).joinToString(separator = "\n")
|
||||
}
|
||||
DebuggerUtilsImpl.logError(e.message, e, exceptionStack)
|
||||
return null
|
||||
}
|
||||
}
|
||||
DebuggerUtilsImpl.logError(e) // for now log everything
|
||||
val helperExceptionStackTrace = MethodInvokeUtils.getHelperExceptionStackTrace(context.evaluationContext, e)
|
||||
DebuggerUtilsImpl.logError("Exception from helper: ${e.message}", e,
|
||||
*listOfNotNull(helperExceptionStackTrace).toTypedArray()) // log helper exception if available
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user