XDebugProcess — pass suspend context to resume methods

This commit is contained in:
Vladimir Krivosheev
2016-03-02 14:28:04 +01:00
parent 75dc531480
commit 8699b0e4ae
9 changed files with 112 additions and 72 deletions
@@ -30,6 +30,7 @@ import com.intellij.xdebugger.breakpoints.XBreakpointHandler
import com.intellij.xdebugger.breakpoints.XBreakpointType
import com.intellij.xdebugger.breakpoints.XLineBreakpoint
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider
import com.intellij.xdebugger.frame.XSuspendContext
import com.intellij.xdebugger.stepping.XSmartStepIntoHandler
import org.jetbrains.concurrency.Promise
import org.jetbrains.debugger.connection.VmConnection
@@ -118,25 +119,28 @@ abstract class DebugProcessImpl<C : VmConnection<*>>(session: XDebugSession,
override final fun isValuesCustomSorted() = true
override final fun startStepOver() {
val vm = activeOrMainVm!!
override final fun startStepOver(context: XSuspendContext?) {
val vm = context.vm
updateLastCallFrame(vm)
continueVm(vm, StepAction.OVER)
}
val XSuspendContext?.vm: Vm
get() = (this as? SuspendContextView)?.activeExecutionStack?.suspendContext?.vm ?: mainVm!!
override final fun startForceStepInto() {
isForceStep = true
startStepInto()
}
override final fun startStepInto() {
val vm = activeOrMainVm!!
override final fun startStepInto(context: XSuspendContext?) {
val vm = context.vm
updateLastCallFrame(vm)
continueVm(vm, if (vm.captureAsyncStackTraces) StepAction.IN_ASYNC else StepAction.IN)
}
override final fun startStepOut() {
val vm = activeOrMainVm!!
override final fun startStepOut(context: XSuspendContext?) {
val vm = context.vm
if (isVmStepOutCorrect()) {
lastCallFrame = null
}
@@ -149,10 +153,8 @@ abstract class DebugProcessImpl<C : VmConnection<*>>(session: XDebugSession,
// some VM (firefox for example) doesn't implement step out correctly, so, we need to fix it
protected open fun isVmStepOutCorrect() = true
@Deprecated("Pass vm explicitly", ReplaceWith("resume(vm!!)"))
override fun resume() {
@Suppress("DEPRECATION")
continueVm(activeOrMainVm!!, StepAction.CONTINUE)
override fun resume(context: XSuspendContext?) {
continueVm(context.vm, StepAction.CONTINUE)
}
open fun resume(vm: Vm) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@ import com.intellij.xdebugger.breakpoints.XBreakpointHandler;
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
import com.intellij.xdebugger.frame.XStackFrame;
import com.intellij.xdebugger.frame.XSuspendContext;
import com.intellij.xdebugger.frame.XValueMarkerProvider;
import com.intellij.xdebugger.stepping.XSmartStepIntoHandler;
import com.intellij.xdebugger.ui.XDebugTabLayouter;
@@ -92,7 +93,13 @@ public abstract class XDebugProcess {
* when next line in current method/function is reached.
* Do not call this method directly. Use {@link XDebugSession#stepOver} instead
*/
public abstract void startStepOver();
public void startStepOver() {
throw new AbstractMethodError();
}
public void startStepOver(@Nullable XSuspendContext context) {
startStepOver();
}
/**
* Steps into suppressed call
@@ -104,19 +111,36 @@ public abstract class XDebugProcess {
public void startForceStepInto(){
startStepInto();
}
public void startForceStepInto(@Nullable XSuspendContext context) {
startForceStepInto();
}
/**
* Resume execution and call {@link XDebugSession#positionReached}
* when next line is reached.
* Do not call this method directly. Use {@link XDebugSession#stepInto} instead
*/
public abstract void startStepInto();
public void startStepInto() {
throw new AbstractMethodError();
}
public void startStepInto(@Nullable XSuspendContext context) {
startStepInto();
}
/**
* Resume execution and call {@link XDebugSession#positionReached}
* after returning from current method/function.
* Do not call this method directly. Use {@link XDebugSession#stepOut} instead
*/
public abstract void startStepOut();
public void startStepOut() {
throw new AbstractMethodError();
}
public void startStepOut(@Nullable XSuspendContext context) {
startStepOut();
}
/**
* Implement {@link com.intellij.xdebugger.stepping.XSmartStepIntoHandler} and return its instance from this method to enable Smart Step Into action
@@ -145,7 +169,13 @@ public abstract class XDebugProcess {
* Resume execution.
* Do not call this method directly. Use {@link XDebugSession#resume} instead
*/
public abstract void resume();
public void resume() {
throw new AbstractMethodError();
}
public void resume(@Nullable XSuspendContext context) {
resume();
}
/**
* Resume execution and call {@link XDebugSession#positionReached(com.intellij.xdebugger.frame.XSuspendContext)}
@@ -153,7 +183,13 @@ public abstract class XDebugProcess {
* Do not call this method directly. Use {@link XDebugSession#runToPosition} instead
* @param position position in source code
*/
public abstract void runToPosition(@NotNull XSourcePosition position);
public void runToPosition(@NotNull XSourcePosition position) {
throw new AbstractMethodError();
}
public void runToPosition(@NotNull XSourcePosition position, @Nullable XSuspendContext context) {
runToPosition(position);
}
/**
* Check is it is possible to perform commands such as resume, step etc. And notify user if necessary
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,9 @@
package com.intellij.xdebugger.stepping;
import com.intellij.xdebugger.XSourcePosition;
import com.intellij.xdebugger.frame.XSuspendContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
@@ -40,7 +42,13 @@ public abstract class XSmartStepIntoHandler<Variant extends XSmartStepIntoVarian
* when <code>variant</code> function/method is reached
* @param variant selected variant
*/
public abstract void startStepInto(@NotNull Variant variant);
public void startStepInto(@NotNull Variant variant) {
throw new AbstractMethodError();
}
public void startStepInto(@NotNull Variant variant, @Nullable XSuspendContext context) {
startStepInto(variant);
}
/**
* @return title for popup which will be shown to select method/function
@@ -476,24 +476,21 @@ public class XDebugSessionImpl implements XDebugSession {
if (ignoreBreakpoints) {
disableBreakpoints();
}
doResume();
myDebugProcess.startStepOver();
myDebugProcess.startStepOver(doResume());
}
@Override
public void stepInto() {
if (!myDebugProcess.checkCanPerformCommands()) return;
doResume();
myDebugProcess.startStepInto();
myDebugProcess.startStepInto(doResume());
}
@Override
public void stepOut() {
if (!myDebugProcess.checkCanPerformCommands()) return;
doResume();
myDebugProcess.startStepOut();
myDebugProcess.startStepOut(doResume());
}
@Override
@@ -508,8 +505,7 @@ public class XDebugSessionImpl implements XDebugSession {
public void forceStepInto() {
if (!myDebugProcess.checkCanPerformCommands()) return;
doResume();
myDebugProcess.startForceStepInto();
myDebugProcess.startForceStepInto(doResume());
}
@Override
@@ -519,8 +515,7 @@ public class XDebugSessionImpl implements XDebugSession {
if (ignoreBreakpoints) {
disableBreakpoints();
}
doResume();
myDebugProcess.runToPosition(position);
myDebugProcess.runToPosition(position, doResume());
}
@Override
@@ -545,14 +540,17 @@ public class XDebugSessionImpl implements XDebugSession {
public void resume() {
if (!myDebugProcess.checkCanPerformCommands()) return;
doResume();
myDebugProcess.resume();
myDebugProcess.resume(doResume());
}
public void doResume() {
if (!myPaused.getAndSet(false)) return;
@Nullable
private XSuspendContext doResume() {
if (!myPaused.getAndSet(false)) {
return null;
}
myDispatcher.getMulticaster().beforeSessionResume();
XSuspendContext context = mySuspendContext;
mySuspendContext = null;
myCurrentExecutionStack = null;
myCurrentStackFrame = null;
@@ -565,6 +563,7 @@ public class XDebugSessionImpl implements XDebugSession {
}
});
myDispatcher.getMulticaster().sessionResumed();
return context;
}
@Override
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -52,6 +52,7 @@ import com.intellij.xdebugger.breakpoints.XBreakpointHandler;
import com.intellij.xdebugger.breakpoints.XBreakpointType;
import com.intellij.xdebugger.breakpoints.XLineBreakpoint;
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
import com.intellij.xdebugger.frame.XSuspendContext;
import com.intellij.xdebugger.frame.XValueChildrenList;
import com.intellij.xdebugger.impl.XSourcePositionImpl;
import com.intellij.xdebugger.stepping.XSmartStepIntoHandler;
@@ -104,7 +105,6 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
private PyPositionConverter myPositionConverter;
private final XSmartStepIntoHandler<?> mySmartStepIntoHandler;
private boolean myWaitingForConnection = false;
private PyStackFrame myStackFrameBeforeResume;
private PyStackFrame myConsoleContextFrame = null;
private PyReferrersLoader myReferrersProvider;
@@ -158,18 +158,6 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
detachDebuggedProcess();
}
});
session.addSessionListener(new XDebugSessionAdapter() {
@Override
public void beforeSessionResume() {
if (session.getCurrentStackFrame() instanceof PyStackFrame) {
myStackFrameBeforeResume = (PyStackFrame)session.getCurrentStackFrame();
}
else {
myStackFrameBeforeResume = null;
}
}
});
}
private MultiProcessDebugger createMultiprocessDebugger(ServerSocket serverSocket) {
@@ -384,24 +372,24 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
}
@Override
public void startStepOver() {
passToCurrentThread(ResumeOrStepCommand.Mode.STEP_OVER);
public void startStepOver(@Nullable XSuspendContext context) {
passToCurrentThread(context, ResumeOrStepCommand.Mode.STEP_OVER);
}
@Override
public void startStepInto() {
passToCurrentThread(ResumeOrStepCommand.Mode.STEP_INTO);
public void startStepInto(@Nullable XSuspendContext context) {
passToCurrentThread(context, ResumeOrStepCommand.Mode.STEP_INTO);
}
public void startStepIntoMyCode() {
public void startStepIntoMyCode(@Nullable XSuspendContext context) {
if (!checkCanPerformCommands()) return;
getSession().sessionResumed();
passToCurrentThread(ResumeOrStepCommand.Mode.STEP_INTO_MY_CODE);
passToCurrentThread(context, ResumeOrStepCommand.Mode.STEP_INTO_MY_CODE);
}
@Override
public void startStepOut() {
passToCurrentThread(ResumeOrStepCommand.Mode.STEP_OUT);
public void startStepOut(@Nullable XSuspendContext context) {
passToCurrentThread(context, ResumeOrStepCommand.Mode.STEP_OUT);
}
public void startSmartStepInto(String functionName) {
@@ -439,10 +427,10 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
}
}
private void passToCurrentThread(final ResumeOrStepCommand.Mode mode) {
private void passToCurrentThread(@Nullable XSuspendContext context, final ResumeOrStepCommand.Mode mode) {
dropFrameCaches();
if (isConnected()) {
String threadId = threadIdBeforeResumeOrStep();
String threadId = threadIdBeforeResumeOrStep(context);
for (PyThreadInfo suspendedThread : mySuspendedThreads) {
if (threadId == null || threadId.equals(suspendedThread.getId())) {
@@ -454,13 +442,13 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
}
@Nullable
private String threadIdBeforeResumeOrStep() {
String threadId = null;
if (myStackFrameBeforeResume != null) {
threadId = myStackFrameBeforeResume.getThreadId();
private static String threadIdBeforeResumeOrStep(@Nullable XSuspendContext context) {
if (context instanceof PySuspendContext) {
return ((PySuspendContext)context).getActiveExecutionStack().getThreadId();
}
else {
return null;
}
return threadId;
}
protected boolean isConnected() {
@@ -486,7 +474,7 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
}
@Override
public void runToPosition(@NotNull final XSourcePosition position) {
public void runToPosition(@NotNull final XSourcePosition position, @Nullable XSuspendContext context) {
dropFrameCaches();
if (isConnected() && !mySuspendedThreads.isEmpty()) {
final PySourcePosition pyPosition = myPositionConverter.convertToPython(position);
@@ -509,7 +497,7 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr
}
myDebugger.setTempBreakpoint(type, pyPosition.getFile(), pyPosition.getLine());
passToCurrentThread(ResumeOrStepCommand.Mode.RESUME);
passToCurrentThread(context, ResumeOrStepCommand.Mode.RESUME);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -87,4 +87,8 @@ public class PyExecutionStack extends XExecutionStack {
public int hashCode() {
return myThreadInfo != null ? myThreadInfo.hashCode() : 0;
}
public String getThreadId() {
return myThreadInfo.getId();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,7 +40,7 @@ public class PyStepIntoMyCodeAction extends XDebuggerActionBase {
@Override
protected void perform(@NotNull final XDebugSession session, final DataContext dataContext) {
PyDebugProcess debugProcess = (PyDebugProcess)session.getDebugProcess();
debugProcess.startStepIntoMyCode();
debugProcess.startStepIntoMyCode(debugProcess.getSession().getSuspendContext());
}
};
}
@@ -24,7 +24,7 @@ import java.util.Collection;
public class PySuspendContext extends XSuspendContext {
private final XExecutionStack myActiveStack;
private final PyExecutionStack myActiveStack;
private PyDebugProcess myDebugProcess;
public PySuspendContext(@NotNull final PyDebugProcess debugProcess, @NotNull final PyThreadInfo threadInfo) {
@@ -33,7 +33,8 @@ public class PySuspendContext extends XSuspendContext {
}
@Override
public XExecutionStack getActiveExecutionStack() {
@NotNull
public PyExecutionStack getActiveExecutionStack() {
return myActiveStack;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,6 +36,7 @@ import com.jetbrains.python.debugger.PyDebugValue;
import com.jetbrains.python.debugger.PyDebuggerException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import org.junit.Assert;
import java.io.PrintWriter;
@@ -106,6 +107,7 @@ public abstract class PyBaseDebuggerTask extends PyExecutionFixtureTestTask {
currentSession.stepInto();
}
@TestOnly
protected void stepIntoMyCode() {
XDebugSession currentSession = XDebuggerManager.getInstance(getProject()).getCurrentSession();
@@ -113,7 +115,7 @@ public abstract class PyBaseDebuggerTask extends PyExecutionFixtureTestTask {
Assert.assertEquals(0, myPausedSemaphore.availablePermits());
PyDebugProcess debugProcess = (PyDebugProcess)currentSession.getDebugProcess();
debugProcess.startStepIntoMyCode();
debugProcess.startStepIntoMyCode(currentSession.getSuspendContext());
}
protected void smartStepInto(String funcName) {
@@ -317,7 +319,7 @@ public abstract class PyBaseDebuggerTask extends PyExecutionFixtureTestTask {
}
finally {
doFinally();
clearAllBreakpoints();
setProcessCanTerminate(true);