mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-63378 Switching threads should be optional, not forced - correctly show stepping threads in running state
This commit is contained in:
@@ -416,6 +416,7 @@ public class DebugProcessEvents extends DebugProcessImpl {
|
||||
final int nextStepDepth = hint.getNextStepDepth(suspendContext);
|
||||
if (nextStepDepth == RequestHint.RESUME) {
|
||||
getSession().resetIgnoreStepFiltersFlag();
|
||||
getSession().clearSteppingThrough();
|
||||
shouldResume = true;
|
||||
}
|
||||
else if (nextStepDepth != RequestHint.STOP) {
|
||||
|
||||
@@ -40,6 +40,7 @@ import com.intellij.icons.AllIcons;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -106,7 +107,7 @@ public class JavaDebugProcess extends XDebugProcess {
|
||||
|| event == DebuggerSession.Event.REFRESH
|
||||
&& myJavaSession.isPaused()) {
|
||||
final SuspendContextImpl newSuspendContext = newContext.getSuspendContext();
|
||||
if (newSuspendContext != null && newSuspendContext != getSession().getSuspendContext()) {
|
||||
if (newSuspendContext != null && shouldApplyContext(newContext)) {
|
||||
process.getManagerThread().schedule(new SuspendContextCommandImpl(newSuspendContext) {
|
||||
@Override
|
||||
public void contextAction() throws Exception {
|
||||
@@ -119,10 +120,12 @@ public class JavaDebugProcess extends XDebugProcess {
|
||||
XBreakpoint xBreakpoint = breakpoint.getXBreakpoint();
|
||||
if (xBreakpoint != null) {
|
||||
((XDebugSessionImpl)getSession()).breakpointReachedNoProcessing(xBreakpoint, newSuspendContext);
|
||||
unsetPausedIfNeeded(newContext);
|
||||
return;
|
||||
}
|
||||
}
|
||||
getSession().positionReached(newSuspendContext);
|
||||
unsetPausedIfNeeded(newContext);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -181,6 +184,21 @@ public class JavaDebugProcess extends XDebugProcess {
|
||||
});
|
||||
}
|
||||
|
||||
private void unsetPausedIfNeeded(DebuggerContextImpl context) {
|
||||
SuspendContextImpl suspendContext = context.getSuspendContext();
|
||||
if (suspendContext != null && context.getThreadProxy() != suspendContext.getThread()) {
|
||||
((XDebugSessionImpl)getSession()).unsetPaused();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldApplyContext(DebuggerContextImpl context) {
|
||||
SuspendContextImpl suspendContext = context.getSuspendContext();
|
||||
SuspendContextImpl currentContext = (SuspendContextImpl)getSession().getSuspendContext();
|
||||
if (suspendContext != null && !suspendContext.equals(currentContext)) return true;
|
||||
JavaExecutionStack currentExecutionStack = currentContext != null ? currentContext.getActiveExecutionStack() : null;
|
||||
return currentExecutionStack == null || !Comparing.equal(context.getThreadProxy(), currentExecutionStack.getThreadProxy());
|
||||
}
|
||||
|
||||
public void saveNodeHistory() {
|
||||
saveNodeHistory(getDebuggerStateManager().getContext().getFrameProxy());
|
||||
}
|
||||
|
||||
@@ -48,14 +48,11 @@ public class JavaExecutionStack extends XExecutionStack {
|
||||
super(calcRepresentation(threadProxy), calcIcon(threadProxy, current));
|
||||
myThreadProxy = threadProxy;
|
||||
myDebugProcess = debugProcess;
|
||||
if (current) {
|
||||
initTopFrame();
|
||||
}
|
||||
}
|
||||
|
||||
private static Icon calcIcon(ThreadReferenceProxyImpl threadProxy, boolean current) {
|
||||
if (current) {
|
||||
return AllIcons.Debugger.ThreadCurrent;
|
||||
return threadProxy.isSuspended() ? AllIcons.Debugger.ThreadCurrent : AllIcons.Debugger.ThreadRunning;
|
||||
}
|
||||
else if (threadProxy.isAtBreakpoint()) {
|
||||
return AllIcons.Debugger.ThreadAtBreakpoint;
|
||||
|
||||
@@ -138,7 +138,7 @@ public class JavaStackFrame extends XStackFrame {
|
||||
xFrame.computeChildren(node);
|
||||
return;
|
||||
}
|
||||
myDebugProcess.getManagerThread().schedule(new DebuggerContextCommandImpl(myDebugProcess.getDebuggerContext()) {
|
||||
myDebugProcess.getManagerThread().schedule(new DebuggerContextCommandImpl(myDebugProcess.getDebuggerContext(), myDescriptor.getFrameProxy().threadProxy()) {
|
||||
@Override
|
||||
public Priority getPriority() {
|
||||
return Priority.NORMAL;
|
||||
|
||||
@@ -26,7 +26,6 @@ import com.intellij.debugger.jdi.ThreadReferenceProxyImpl;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import com.intellij.xdebugger.frame.XExecutionStack;
|
||||
import com.intellij.xdebugger.frame.XSuspendContext;
|
||||
import com.sun.jdi.ObjectReference;
|
||||
import com.sun.jdi.ThreadReference;
|
||||
@@ -229,15 +228,18 @@ public abstract class SuspendContextImpl extends XSuspendContext implements Susp
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public XExecutionStack getActiveExecutionStack() {
|
||||
public JavaExecutionStack getActiveExecutionStack() {
|
||||
return myActiveExecutionStack;
|
||||
}
|
||||
|
||||
public void initExecutionStacks(ThreadReferenceProxyImpl newThread) {
|
||||
public void initExecutionStacks(ThreadReferenceProxyImpl activeThread) {
|
||||
DebuggerManagerThreadImpl.assertIsManagerThread();
|
||||
myThread = newThread;
|
||||
if (newThread != null) {
|
||||
myActiveExecutionStack = new JavaExecutionStack(newThread, myDebugProcess, true);
|
||||
if (myThread == null) {
|
||||
myThread = activeThread;
|
||||
}
|
||||
if (activeThread != null) {
|
||||
myActiveExecutionStack = new JavaExecutionStack(activeThread, myDebugProcess, myThread == activeThread);
|
||||
myActiveExecutionStack.initTopFrame();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -115,13 +115,6 @@ public class SuspendManagerImpl implements SuspendManager {
|
||||
return suspendContext;
|
||||
}
|
||||
|
||||
public SuspendContextImpl createDummyContext(@MagicConstant(flagsFromClass = EventRequest.class) int suspendPolicy) {
|
||||
return new SuspendContextImpl(myDebugProcess, suspendPolicy, 0, null) {
|
||||
@Override
|
||||
protected void resumeImpl() {}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public SuspendContextImpl pushSuspendContext(final EventSet set) {
|
||||
SuspendContextImpl suspendContext = new SuspendContextImpl(myDebugProcess, set.suspendPolicy(), set.size(), set) {
|
||||
@@ -360,7 +353,7 @@ public class SuspendManagerImpl implements SuspendManager {
|
||||
processVote(suspendContext);
|
||||
}
|
||||
|
||||
LinkedList<SuspendContextImpl> getPausedContexts() {
|
||||
public List<SuspendContextImpl> getPausedContexts() {
|
||||
return myPausedContexts;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +151,6 @@ public final class DebuggerContextImpl implements DebuggerContext {
|
||||
ThreadReferenceProxyImpl threadProxy,
|
||||
StackFrameProxyImpl frameProxy) {
|
||||
LOG.assertTrue(frameProxy == null || threadProxy == null || threadProxy == frameProxy.threadProxy());
|
||||
LOG.assertTrue(session == null || session.getProcess() != null);
|
||||
return new DebuggerContextImpl(session, session != null ? session.getProcess() : null, context, threadProxy, frameProxy, null, null, context == null);
|
||||
}
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ public class DebuggerSession implements AbstractDebuggerSession {
|
||||
mySteppingThroughThread.set(threadProxy);
|
||||
}
|
||||
|
||||
void clearSteppingThrough() {
|
||||
public void clearSteppingThrough() {
|
||||
mySteppingThroughThread.set(null);
|
||||
}
|
||||
|
||||
@@ -469,6 +469,8 @@ public class DebuggerSession implements AbstractDebuggerSession {
|
||||
LOG.debug("paused");
|
||||
}
|
||||
|
||||
ThreadReferenceProxyImpl currentThread = suspendContext.getThread();
|
||||
|
||||
if (!shouldSetAsActiveContext(suspendContext)) {
|
||||
DebuggerInvocationUtil.invokeLater(getProject(), new Runnable() {
|
||||
@Override
|
||||
@@ -476,7 +478,7 @@ public class DebuggerSession implements AbstractDebuggerSession {
|
||||
getContextManager().fireStateChanged(getContextManager().getContext(), Event.THREADS_REFRESH);
|
||||
}
|
||||
});
|
||||
final ThreadReferenceProxyImpl thread = suspendContext.getThread();
|
||||
ThreadReferenceProxyImpl thread = suspendContext.getThread();
|
||||
if (thread != null) {
|
||||
List<Pair<Breakpoint, com.sun.jdi.event.Event>> descriptors = DebuggerUtilsEx.getEventDescriptors(suspendContext);
|
||||
if (!descriptors.isEmpty()) {
|
||||
@@ -492,7 +494,7 @@ public class DebuggerSession implements AbstractDebuggerSession {
|
||||
@Override
|
||||
public void contextAction() throws Exception {
|
||||
final DebuggerContextImpl debuggerContext =
|
||||
DebuggerContextImpl.createDebuggerContext(DebuggerSession.this, suspendContext, thread, null);
|
||||
DebuggerContextUtil.createDebuggerContext(DebuggerSession.this, suspendContext);
|
||||
|
||||
DebuggerInvocationUtil.invokeLater(getProject(), new Runnable() {
|
||||
@Override
|
||||
@@ -507,12 +509,17 @@ public class DebuggerSession implements AbstractDebuggerSession {
|
||||
}).notify(getProject());
|
||||
}
|
||||
}
|
||||
return;
|
||||
if (((SuspendManagerImpl)myDebugProcess.getSuspendManager()).getPausedContexts().size() > 1) {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
currentThread = mySteppingThroughThread.get();
|
||||
}
|
||||
}
|
||||
else {
|
||||
setSteppingThrough(currentThread);
|
||||
}
|
||||
|
||||
setSteppingThrough(suspendContext.getThread());
|
||||
|
||||
ThreadReferenceProxyImpl currentThread = suspendContext.getThread();
|
||||
final StackFrameContext positionContext;
|
||||
|
||||
if (currentThread == null) {
|
||||
@@ -626,7 +633,7 @@ public class DebuggerSession implements AbstractDebuggerSession {
|
||||
DebuggerInvocationUtil.invokeLater(getProject(), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
getContextManager().setState(debuggerContext, State.PAUSED, Event.PAUSE, null);
|
||||
getContextManager().setState(debuggerContext, State.PAUSED, Event.PAUSE, getDescription(debuggerContext));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -650,25 +657,28 @@ public class DebuggerSession implements AbstractDebuggerSession {
|
||||
|
||||
@Override
|
||||
public void resumed(SuspendContextImpl suspendContext) {
|
||||
SuspendManager suspendManager = getProcess().getSuspendManager();
|
||||
SuspendContextImpl context = suspendManager.getPausedContext();
|
||||
SuspendContextImpl context = getProcess().getSuspendManager().getPausedContext();
|
||||
ThreadReferenceProxyImpl steppingThread = null;
|
||||
// single thread stepping
|
||||
if (suspendContext != null
|
||||
if (context != null
|
||||
&& suspendContext != null
|
||||
&& suspendContext.getSuspendPolicy() == EventRequest.SUSPEND_EVENT_THREAD
|
||||
&& isSteppingThrough(suspendContext.getThread())) {
|
||||
ThreadReferenceProxyImpl thread = suspendContext.getThread();
|
||||
if (context == null || !Comparing.equal(context.getThread(), thread)) {
|
||||
context = ((SuspendManagerImpl)suspendManager).createDummyContext(suspendContext.getSuspendPolicy());
|
||||
context.setThread(thread.getThreadReference());
|
||||
}
|
||||
steppingThread = suspendContext.getThread();
|
||||
}
|
||||
final SuspendContextImpl currentContext = context;
|
||||
final DebuggerContextImpl debuggerContext =
|
||||
context != null ?
|
||||
DebuggerContextImpl.createDebuggerContext(DebuggerSession.this,
|
||||
context,
|
||||
steppingThread != null ? steppingThread : context.getThread(),
|
||||
null)
|
||||
: null;
|
||||
|
||||
DebuggerInvocationUtil.invokeLater(getProject(), new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (currentContext != null) {
|
||||
getContextManager().setState(DebuggerContextUtil.createDebuggerContext(DebuggerSession.this, currentContext),
|
||||
State.PAUSED, Event.CONTEXT, null);
|
||||
if (debuggerContext != null) {
|
||||
getContextManager().setState(debuggerContext, State.PAUSED, Event.CONTEXT, getDescription(debuggerContext));
|
||||
}
|
||||
else {
|
||||
getContextManager().setState(SESSION_EMPTY_CONTEXT, State.RUNNING, Event.CONTEXT, null);
|
||||
@@ -756,6 +766,14 @@ public class DebuggerSession implements AbstractDebuggerSession {
|
||||
}
|
||||
}
|
||||
|
||||
private static String getDescription(DebuggerContextImpl debuggerContext) {
|
||||
SuspendContextImpl suspendContext = debuggerContext.getSuspendContext();
|
||||
if (suspendContext != null && debuggerContext.getThreadProxy() != suspendContext.getThread()) {
|
||||
return DebuggerBundle.message("status.paused.in.another.thread");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private class MyEvaluationListener implements EvaluationListener {
|
||||
@Override
|
||||
public void evaluationStarted(SuspendContextImpl context) {
|
||||
|
||||
@@ -176,7 +176,7 @@ class ReloadClassesWorker {
|
||||
SuspendContextImpl suspendContext = context.getSuspendContext();
|
||||
if (suspendContext != null) {
|
||||
XExecutionStack stack = suspendContext.getActiveExecutionStack();
|
||||
if (stack instanceof JavaExecutionStack) {
|
||||
if (stack != null) {
|
||||
((JavaExecutionStack)stack).initTopFrame();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,6 +193,7 @@ public class StackFrameProxyImpl extends JdiProxy implements StackFrameProxy {
|
||||
throw new EvaluateException(error.getMessage(), error);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ThreadReferenceProxyImpl threadProxy() {
|
||||
return myThreadProxy;
|
||||
|
||||
@@ -814,6 +814,10 @@ public class XDebugSessionImpl implements XDebugSession {
|
||||
});
|
||||
}
|
||||
|
||||
public void unsetPaused() {
|
||||
myPaused.set(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void positionReached(@NotNull final XSuspendContext suspendContext) {
|
||||
enableBreakpoints();
|
||||
|
||||
@@ -91,6 +91,7 @@ status.step.into=Stepping into
|
||||
status.step.over=Stepping over
|
||||
status.run.to.cursor=Run to cursor
|
||||
status.process.resumed=Process resumed
|
||||
status.paused.in.another.thread=Paused in another thread
|
||||
error.pop.bottom.stackframe=Cannot pop bottom frame
|
||||
error.pop.stackframe=An error occurred while popping stack frame: {0}
|
||||
error.class.not.loaded=Class not loaded : {0}
|
||||
|
||||
Reference in New Issue
Block a user