From 736f2c0eac585b349c8047616917b65cd52857c3 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Mon, 6 Jul 2015 12:42:39 +0300 Subject: [PATCH] IDEA-43728 Provide a way to step in a chosen thread while others remain suspended --- .../debugger/engine/DebugProcessEvents.java | 10 ++++- .../debugger/engine/DebugProcessImpl.java | 40 +++++++++++++++---- .../debugger/engine/SuspendManagerImpl.java | 2 +- .../util/resources/misc/registry.properties | 1 + 4 files changed, 42 insertions(+), 11 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java index 4e23d5a93f97..03814017244b 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java @@ -193,8 +193,14 @@ public class DebugProcessEvents extends DebugProcessImpl { // check if there is already one request with policy SUSPEND_ALL for (SuspendContextImpl context : getSuspendManager().getEventContexts()) { if (context.getSuspendPolicy() == EventRequest.SUSPEND_ALL) { - eventSet.resume(); - return; + for (Event event : eventSet) { + if (event instanceof LocatableEvent && SuspendManagerUtil.isEvaluating(getSuspendManager(), + getVirtualMachineProxy().getThreadReferenceProxy( + ((LocatableEvent)event).thread()))) { + eventSet.resume(); + return; + } + } } } } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java index 9da93a15cda6..3215d726ad36 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessImpl.java @@ -56,6 +56,7 @@ import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.UserDataHolderBase; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.ToolWindowId; import com.intellij.openapi.wm.impl.status.StatusBarUtil; @@ -406,7 +407,8 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb // suspend policy to match the suspend policy of the context: // if all threads were suspended, then during stepping all the threads must be suspended // if only event thread were suspended, then only this particular thread must be suspended during stepping - stepRequest.setSuspendPolicy(suspendContext.getSuspendPolicy() == EventRequest.SUSPEND_EVENT_THREAD? EventRequest.SUSPEND_EVENT_THREAD : EventRequest.SUSPEND_ALL); + stepRequest.setSuspendPolicy(Registry.is("debugger.step.resumes.one.thread") ? EventRequest.SUSPEND_EVENT_THREAD + : suspendContext.getSuspendPolicy()); if (hint != null) { //noinspection HardCodedStringLiteral @@ -1464,7 +1466,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb } } - private class StepOutCommand extends ResumeCommand { + private class StepOutCommand extends StepCommand { private final int myStepSize; public StepOutCommand(SuspendContextImpl suspendContext, int stepSize) { @@ -1489,7 +1491,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb } } - private class StepIntoCommand extends ResumeCommand { + private class StepIntoCommand extends StepCommand { private final boolean myForcedIgnoreFilters; private final MethodFilter mySmartStepFilter; @Nullable @@ -1536,7 +1538,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb } } - private class StepOverCommand extends ResumeCommand { + private class StepOverCommand extends StepCommand { private final boolean myIsIgnoreBreakpoints; private final int myStepSize; @@ -1574,7 +1576,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb } } - private class RunToCursorCommand extends ResumeCommand { + private class RunToCursorCommand extends StepCommand { private final RunToCursorBreakpoint myRunToCursorBreakpoint; private final boolean myIgnoreBreakpoints; @@ -1622,9 +1624,27 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb } } - public abstract class ResumeCommand extends SuspendContextCommandImpl { + private abstract class StepCommand extends ResumeCommand { + public StepCommand(SuspendContextImpl suspendContext) { + super(suspendContext); + } - private final ThreadReferenceProxyImpl myContextThread; + @Override + protected void resumeAction() { + SuspendContextImpl context = getSuspendContext(); + if (context != null + && Registry.is("debugger.step.resumes.one.thread") + && context.getSuspendPolicy() == EventRequest.SUSPEND_ALL) { + getSuspendManager().resumeThread(context, myContextThread); + } + else { + super.resumeAction(); + } + } + } + + public abstract class ResumeCommand extends SuspendContextCommandImpl { + protected final ThreadReferenceProxyImpl myContextThread; public ResumeCommand(SuspendContextImpl suspendContext) { super(suspendContext); @@ -1640,10 +1660,14 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb @Override public void contextAction() { showStatusText(DebuggerBundle.message("status.process.resumed")); - getSuspendManager().resume(getSuspendContext()); + resumeAction(); myDebugProcessDispatcher.getMulticaster().resumed(getSuspendContext()); } + protected void resumeAction() { + getSuspendManager().resume(getSuspendContext()); + } + public ThreadReferenceProxyImpl getContextThread() { return myContextThread; } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/SuspendManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/SuspendManagerImpl.java index 0717168a41c8..da2c8a1f3a08 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/SuspendManagerImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/SuspendManagerImpl.java @@ -274,7 +274,7 @@ public class SuspendManagerImpl implements SuspendManager { @Override public void resumeThread(SuspendContextImpl context, ThreadReferenceProxyImpl thread) { - LOG.assertTrue(thread != context.getThread(), "Use resume() instead of resuming breakpoint thread"); + //LOG.assertTrue(thread != context.getThread(), "Use resume() instead of resuming breakpoint thread"); LOG.assertTrue(!context.isExplicitlyResumed(thread)); if(context.myResumedThreads == null) { diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index ddbd89d3f954..f275df3a6506 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -194,6 +194,7 @@ debugger.batch.evaluation=false debugger.compiling.evaluator=true debugger.watches.in.variables=false debugger.auto.fetch.icons=true +debugger.step.resumes.one.thread=false analyze.exceptions.on.the.fly=false analyze.exceptions.on.the.fly.description=Automatically analyze clipboard on frame activation,\