IDEA-43728 Provide a way to step in a chosen thread while others remain suspended...
authorEgor.Ushakov <egor.ushakov@jetbrains.com>
Mon, 13 Jul 2015 10:47:19 +0000 (13:47 +0300)
committerEgor.Ushakov <egor.ushakov@jetbrains.com>
Mon, 13 Jul 2015 10:48:33 +0000 (13:48 +0300)
java/debugger/impl/src/com/intellij/debugger/actions/ResumeThreadAction.java
java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java

index 4c9e57aa13c7ac94ddef0eca6dae66cd8580a0cc..2e506ebdacd9261ee408cdc13d013ce13a82917f 100644 (file)
@@ -17,7 +17,9 @@ package com.intellij.debugger.actions;
 
 import com.intellij.debugger.DebuggerBundle;
 import com.intellij.debugger.engine.DebugProcessImpl;
-import com.intellij.debugger.engine.events.SuspendContextCommandImpl;
+import com.intellij.debugger.engine.SuspendContextImpl;
+import com.intellij.debugger.engine.SuspendManagerUtil;
+import com.intellij.debugger.engine.events.DebuggerCommandImpl;
 import com.intellij.debugger.impl.DebuggerContextImpl;
 import com.intellij.debugger.jdi.ThreadReferenceProxyImpl;
 import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeImpl;
@@ -26,6 +28,8 @@ import com.intellij.debugger.ui.impl.watch.ThreadDescriptorImpl;
 import com.intellij.openapi.actionSystem.AnActionEvent;
 import com.intellij.openapi.actionSystem.Presentation;
 
+import java.util.Set;
+
 /**
  * User: lex
  * Date: Sep 26, 2003
@@ -37,15 +41,21 @@ public class ResumeThreadAction extends DebuggerAction{
     final DebuggerContextImpl debuggerContext = getDebuggerContext(e.getDataContext());
     final DebugProcessImpl debugProcess = debuggerContext.getDebugProcess();
 
+    if (debugProcess == null) return;
+
     //noinspection ConstantConditions
     for (final DebuggerTreeNodeImpl debuggerTreeNode : selectedNode) {
       final ThreadDescriptorImpl threadDescriptor = ((ThreadDescriptorImpl)debuggerTreeNode.getDescriptor());
 
       if (threadDescriptor.isSuspended()) {
         final ThreadReferenceProxyImpl thread = threadDescriptor.getThreadReference();
-        debugProcess.getManagerThread().schedule(new SuspendContextCommandImpl(debuggerContext.getSuspendContext()) {
-          public void contextAction() throws Exception {
-            debugProcess.createResumeThreadCommand(getSuspendContext(), thread).run();
+        debugProcess.getManagerThread().schedule(new DebuggerCommandImpl() {
+          @Override
+          protected void action() throws Exception {
+            Set<SuspendContextImpl> contexts = SuspendManagerUtil.getSuspendingContexts(debugProcess.getSuspendManager(), thread);
+            if (!contexts.isEmpty()) {
+              debugProcess.createResumeThreadCommand(contexts.iterator().next(), thread).run();
+            }
             debuggerTreeNode.calcValue();
           }
         });
index 4910d870799f2f5747e688f74c15648306613cb0..9ffe54e4e731baf4bac1705857ed29581362ec81 100644 (file)
@@ -39,6 +39,7 @@ import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.MessageType;
 import com.intellij.openapi.ui.Messages;
 import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.registry.Registry;
 import com.intellij.ui.classFilter.ClassFilter;
 import com.intellij.xdebugger.XDebugSession;
 import com.intellij.xdebugger.breakpoints.XBreakpoint;
@@ -52,6 +53,7 @@ import com.sun.jdi.request.EventRequest;
 import com.sun.jdi.request.EventRequestManager;
 import com.sun.jdi.request.ThreadDeathRequest;
 import com.sun.jdi.request.ThreadStartRequest;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.List;
 
@@ -189,24 +191,44 @@ public class DebugProcessEvents extends DebugProcessImpl {
             getManagerThread().invokeAndWait(new DebuggerCommandImpl() {
               @Override
               protected void action() throws Exception {
-                if (eventSet.suspendPolicy() == EventRequest.SUSPEND_ALL && !DebuggerSession.enableBreakpointsDuringEvaluation()) {
+                if (eventSet.suspendPolicy() == EventRequest.SUSPEND_ALL) {
                   // check if there is already one request with policy SUSPEND_ALL
-                  contexts: for (SuspendContextImpl context : getSuspendManager().getEventContexts()) {
+                  for (SuspendContextImpl context : getSuspendManager().getEventContexts()) {
                     if (context.getSuspendPolicy() == EventRequest.SUSPEND_ALL) {
-                      for (Event event : eventSet) {
-                        if (event instanceof StepEvent) {
-                          // if step event is present - switch context
-                          ((SuspendManagerImpl)getSuspendManager()).popContext(context);
-                          continue contexts;
-                        }
+                      if (Registry.is("debugger.step.resumes.one.thread") && getStepEvent(eventSet) != null) {
+                        // if step event is present - switch context
+                        getSuspendManager().resume(context);
+                        //((SuspendManagerImpl)getSuspendManager()).popContext(context);
+                        continue;
                       }
-                      eventSet.resume();
-                      return;
+                      if (!DebuggerSession.enableBreakpointsDuringEvaluation()) {
+                        eventSet.resume();
+                        return;
+                      }
+                    }
+                  }
+                }
+
+                SuspendContextImpl suspendContext = null;
+
+                StepEvent stepEvent = getStepEvent(eventSet);
+                if (Registry.is("debugger.step.resumes.one.thread") && stepEvent != null) {
+                  for (SuspendContextImpl context : getSuspendManager().getEventContexts()) {
+                    ThreadReferenceProxyImpl threadProxy = getVirtualMachineProxy().getThreadReferenceProxy(stepEvent.thread());
+                    if (context.getSuspendPolicy() == EventRequest.SUSPEND_ALL &&
+                        context.isExplicitlyResumed(threadProxy)) {
+                      context.myResumedThreads.remove(threadProxy);
+                      suspendContext = context;
+                      suspendContext.myVotesToVote = eventSet.size();
+                      break;
                     }
                   }
                 }
 
-                final SuspendContextImpl suspendContext = getSuspendManager().pushSuspendContext(eventSet);
+                if (suspendContext == null) {
+                  suspendContext = getSuspendManager().pushSuspendContext(eventSet);
+                }
+
                 for (EventIterator eventIterator = eventSet.eventIterator(); eventIterator.hasNext();) {
                   final Event event = eventIterator.nextEvent();
                   //if (LOG.isDebugEnabled()) {
@@ -515,6 +537,16 @@ public class DebugProcessEvents extends DebugProcessImpl {
     });
   }
 
+  @Nullable
+  private static StepEvent getStepEvent(EventSet eventSet) {
+    for (Event event : eventSet) {
+      if (event instanceof StepEvent) {
+        return (StepEvent)event;
+      }
+    }
+    return null;
+  }
+
   private void processDefaultEvent(SuspendContextImpl suspendContext) {
     preprocessEvent(suspendContext, null);
     getSuspendManager().voteResume(suspendContext);