diff --git a/debug/org.eclipse.debug.core/META-INF/MANIFEST.MF b/debug/org.eclipse.debug.core/META-INF/MANIFEST.MF index 0da7e243db5..25dd2cac8fd 100644 --- a/debug/org.eclipse.debug.core/META-INF/MANIFEST.MF +++ b/debug/org.eclipse.debug.core/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.debug.core; singleton:=true -Bundle-Version: 3.23.400.qualifier +Bundle-Version: 3.24.0.qualifier Bundle-Activator: org.eclipse.debug.core.DebugPlugin Bundle-Vendor: %providerName Bundle-Localization: plugin diff --git a/debug/org.eclipse.debug.core/core/org/eclipse/debug/core/commands/IResumeOthersHandler.java b/debug/org.eclipse.debug.core/core/org/eclipse/debug/core/commands/IResumeOthersHandler.java new file mode 100644 index 00000000000..86b7804f854 --- /dev/null +++ b/debug/org.eclipse.debug.core/core/org/eclipse/debug/core/commands/IResumeOthersHandler.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2026 IBM Corporation. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.core.commands; + +/** + * A resume others handler typically resumes all suspended threads associated + * with the same debug target, excluding the selected thread. + *

+ * Clients may implement this interface. The debug platform provides a "Resume + * Others" action that delegates to this handler interface. + *

+ * + * @since 3.24 + */ +public interface IResumeOthersHandler extends IDebugCommandHandler { + +} diff --git a/debug/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/commands/CommandAdapterFactory.java b/debug/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/commands/CommandAdapterFactory.java index e0ea4e64bf1..7f1da866362 100644 --- a/debug/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/commands/CommandAdapterFactory.java +++ b/debug/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/commands/CommandAdapterFactory.java @@ -18,6 +18,7 @@ import org.eclipse.debug.core.commands.IDisconnectHandler; import org.eclipse.debug.core.commands.IDropToFrameHandler; import org.eclipse.debug.core.commands.IResumeHandler; +import org.eclipse.debug.core.commands.IResumeOthersHandler; import org.eclipse.debug.core.commands.IStepFiltersHandler; import org.eclipse.debug.core.commands.IStepIntoHandler; import org.eclipse.debug.core.commands.IStepOverHandler; @@ -31,6 +32,7 @@ import org.eclipse.debug.core.model.IStep; import org.eclipse.debug.core.model.ISuspendResume; import org.eclipse.debug.core.model.ITerminate; +import org.eclipse.debug.core.model.IThread; /** * Adapter factory for debug commands. @@ -48,6 +50,7 @@ public class CommandAdapterFactory implements IAdapterFactory { private static IDisconnectHandler fgDisconnectCommand = new DisconnectCommand(); private static ISuspendHandler fgSuspendCommand = new SuspendCommand(); private static IResumeHandler fgResumeCommand = new ResumeCommand(); + private static IResumeOthersHandler fgResumeOthersCommand = new ResumeOthersCommand(); private static IStepFiltersHandler fgStepFiltersCommand = new StepFiltersCommand(); @SuppressWarnings("unchecked") @@ -91,6 +94,11 @@ public T getAdapter(Object adaptableObject, Class adapterType) { return (T) fgResumeCommand; } } + if (IResumeOthersHandler.class.equals(adapterType)) { + if (adaptableObject instanceof ISuspendResume && adaptableObject instanceof IThread) { + return (T) fgResumeOthersCommand; + } + } if (IDisconnectHandler.class.equals(adapterType)) { if (adaptableObject instanceof IDisconnect) { return (T) fgDisconnectCommand; @@ -113,6 +121,7 @@ public Class[] getAdapterList() { IStepReturnHandler.class, ISuspendHandler.class, IResumeHandler.class, + IResumeOthersHandler.class, IDropToFrameHandler.class, IDisconnectHandler.class, IStepFiltersHandler.class}; diff --git a/debug/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/commands/ResumeOthersCommand.java b/debug/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/commands/ResumeOthersCommand.java new file mode 100644 index 00000000000..66265b1d4cc --- /dev/null +++ b/debug/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/commands/ResumeOthersCommand.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2026 IBM Corporation. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.internal.core.commands; + +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.debug.core.IRequest; +import org.eclipse.debug.core.commands.IDebugCommandRequest; +import org.eclipse.debug.core.commands.IResumeOthersHandler; +import org.eclipse.debug.core.model.IDebugTarget; +import org.eclipse.debug.core.model.IThread; + +/** + * Default resume others command for the standard debug model. + * + * @since 3.3 + */ +public class ResumeOthersCommand extends SuspendCommand implements IResumeOthersHandler { + + @Override + protected void execute(Object target) throws CoreException { + IThread currentThread = (IThread) target; + if (currentThread.canResume()) { + currentThread.resume(); + } + } + @Override + protected void doExecute(Object[] targets, IProgressMonitor monitor, IRequest request) throws CoreException { + + Set selectedThreads = Arrays.stream(targets).map(IThread.class::cast).collect(Collectors.toSet()); + + IDebugTarget debugTarget = ((IThread) targets[0]).getDebugTarget(); + + for (IThread thread : debugTarget.getThreads()) { + if (!selectedThreads.contains(thread)) { + execute(thread); + monitor.worked(1); + } + } + } + + @Override + protected boolean isExecutable(Object target) { + return ((IThread) target).canResume(); + } + + @Override + protected Object getEnabledStateJobFamily(IDebugCommandRequest request) { + return IResumeOthersHandler.class; + } + +} diff --git a/debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java b/debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java index efd2349e0c8..9ca4736a1db 100644 --- a/debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java +++ b/debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/AutomatedSuite.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2023 IBM Corporation and others. + * Copyright (c) 2009, 2026 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -48,6 +48,7 @@ import org.eclipse.debug.tests.statushandlers.StatusHandlerTests; import org.eclipse.debug.tests.stepfilters.StepFiltersTests; import org.eclipse.debug.tests.ui.LaunchConfigurationTabGroupViewerTest; +import org.eclipse.debug.tests.ui.ResumeOthersCommandTests; import org.eclipse.debug.tests.ui.VariableValueEditorManagerTests; import org.eclipse.debug.tests.view.memory.MemoryRenderingTests; import org.eclipse.debug.tests.view.memory.TableRenderingTests; @@ -142,6 +143,7 @@ // Logical structure LogicalStructureCacheTest.class, // + ResumeOthersCommandTests.class, }) public class AutomatedSuite { } diff --git a/debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/ui/ResumeOthersCommandTests.java b/debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/ui/ResumeOthersCommandTests.java new file mode 100644 index 00000000000..9719edfadc0 --- /dev/null +++ b/debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/ui/ResumeOthersCommandTests.java @@ -0,0 +1,326 @@ +/******************************************************************************* + * Copyright (c) 2026 IBM Corporation. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.tests.ui; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.eclipse.core.resources.IMarkerDelta; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.IRequest; +import org.eclipse.debug.core.model.IBreakpoint; +import org.eclipse.debug.core.model.IDebugTarget; +import org.eclipse.debug.core.model.IMemoryBlock; +import org.eclipse.debug.core.model.IProcess; +import org.eclipse.debug.core.model.IStackFrame; +import org.eclipse.debug.core.model.IThread; +import org.eclipse.debug.internal.core.commands.ResumeOthersCommand; +import org.junit.jupiter.api.Test; + +public class ResumeOthersCommandTests { + + @Test + public void testResumeOthers() throws Exception { + + FakeDebugTarget target = new FakeDebugTarget(); + + FakeThread threadA = new FakeThread(target); + FakeThread threadB = new FakeThread(target); + FakeThread threadC = new FakeThread(target); + + target.setThreads(threadA, threadB, threadC); + + assertTrue(threadA.isSuspended()); + assertTrue(threadB.isSuspended()); + assertTrue(threadC.isSuspended()); + + TestResumeOthersCommand command = new TestResumeOthersCommand(); + + command.run(new Object[] { threadA }); + + assertTrue(threadA.isSuspended()); + assertFalse(threadB.isSuspended()); + assertFalse(threadC.isSuspended()); + } + + private static class TestResumeOthersCommand extends ResumeOthersCommand { + + void run(Object[] targets) throws Exception { + doExecute(targets, new NullProgressMonitor(), (IRequest) null); + } + } + + private static class FakeDebugTarget implements IDebugTarget { + + private IThread[] threads; + + void setThreads(IThread... threads) { + this.threads = threads; + } + + @Override + public IThread[] getThreads() { + return threads; + } + + @Override + public String getModelIdentifier() { + return null; + } + + @Override + public IDebugTarget getDebugTarget() { + return null; + } + + @Override + public ILaunch getLaunch() { + return null; + } + + @Override + public T getAdapter(Class adapter) { + return null; + } + + @Override + public boolean canTerminate() { + return false; + } + + @Override + public boolean isTerminated() { + return false; + } + + @Override + public void terminate() throws DebugException { + + } + + @Override + public boolean canResume() { + return false; + } + + @Override + public boolean canSuspend() { + return false; + } + + @Override + public boolean isSuspended() { + return false; + } + + @Override + public void resume() throws DebugException { + } + + @Override + public void suspend() throws DebugException { + } + + @Override + public void breakpointAdded(IBreakpoint breakpoint) { + } + + @Override + public void breakpointRemoved(IBreakpoint breakpoint, IMarkerDelta delta) { + } + + @Override + public void breakpointChanged(IBreakpoint breakpoint, IMarkerDelta delta) { + } + + @Override + public boolean canDisconnect() { + return false; + } + + @Override + public void disconnect() throws DebugException { + + } + + @Override + public boolean isDisconnected() { + return false; + } + + @Override + public boolean supportsStorageRetrieval() { + return false; + } + + @Override + public IMemoryBlock getMemoryBlock(long startAddress, long length) throws DebugException { + return null; + } + + @Override + public IProcess getProcess() { + return null; + } + + @Override + public boolean hasThreads() throws DebugException { + return false; + } + + @Override + public String getName() throws DebugException { + return null; + } + + @Override + public boolean supportsBreakpoint(IBreakpoint breakpoint) { + return false; + } + } + + private static class FakeThread implements IThread { + + private boolean suspended = true; + private final IDebugTarget target; + + FakeThread(IDebugTarget target) { + this.target = target; + } + + @Override + public boolean canResume() { + return suspended; + } + + @Override + public void resume() { + suspended = false; + } + + @Override + public boolean isSuspended() { + return suspended; + } + + @Override + public IDebugTarget getDebugTarget() { + return target; + } + + @Override + public boolean canSuspend() { + return !suspended; + } + + @Override + public void suspend() { + suspended = true; + } + + @Override + public String getModelIdentifier() { + return null; + } + + @Override + public ILaunch getLaunch() { + return null; + } + + @Override + public T getAdapter(Class adapter) { + return null; + } + + @Override + public boolean canStepInto() { + return false; + } + + @Override + public boolean canStepOver() { + return false; + } + + @Override + public boolean canStepReturn() { + return false; + } + + @Override + public boolean isStepping() { + return false; + } + + @Override + public void stepInto() throws DebugException { + } + + @Override + public void stepOver() throws DebugException { + } + + @Override + public void stepReturn() throws DebugException { + } + + @Override + public boolean canTerminate() { + return false; + } + + @Override + public boolean isTerminated() { + return false; + } + + @Override + public void terminate() throws DebugException { + } + + @Override + public IStackFrame[] getStackFrames() throws DebugException { + return null; + } + + @Override + public boolean hasStackFrames() throws DebugException { + + return false; + } + + @Override + public int getPriority() throws DebugException { + return 0; + } + + @Override + public IStackFrame getTopStackFrame() throws DebugException { + return null; + } + + @Override + public String getName() throws DebugException { + return null; + } + + @Override + public IBreakpoint[] getBreakpoints() { + return null; + } + } +} \ No newline at end of file diff --git a/debug/org.eclipse.debug.ui/plugin.properties b/debug/org.eclipse.debug.ui/plugin.properties index 7238fb2d65e..104e6a5d502 100644 --- a/debug/org.eclipse.debug.ui/plugin.properties +++ b/debug/org.eclipse.debug.ui/plugin.properties @@ -426,4 +426,8 @@ prototype.decorator.description = Decorates launch configurations that are marke breakpointLabel.label= Label breakpointLabel.tooltip= Provide a custom label to quickly identify breakpoint breakpointLabelCommand = EditBreakpointLabel -breakpointLabelCommand.description = Opens inline editor to change breakpoint label \ No newline at end of file +breakpointLabelCommand.description = Opens inline editor to change breakpoint label + +ResumeOthers.name = Resume Others +ResumeOthers.description= Resume all other suspended threads in the same debug target +ResumeOthersAction.label = Resume Others \ No newline at end of file diff --git a/debug/org.eclipse.debug.ui/plugin.xml b/debug/org.eclipse.debug.ui/plugin.xml index cb04a05a725..d12eeb62fbb 100644 --- a/debug/org.eclipse.debug.ui/plugin.xml +++ b/debug/org.eclipse.debug.ui/plugin.xml @@ -419,6 +419,16 @@ toolbarPath="org.eclipse.debug.ui.main.toolbar/threadGroup" initialEnabled="false"> + + + + + + getCommandType() { + return IResumeOthersHandler.class; + } + + @Override + public ImageDescriptor getDisabledImageDescriptor() { + return null; + } + + @Override + public ImageDescriptor getHoverImageDescriptor() { + return null; + } + + @Override + public ImageDescriptor getImageDescriptor() { + return null; + } +} diff --git a/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/commands/actions/ResumeOthersCommandActionDelegate.java b/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/commands/actions/ResumeOthersCommandActionDelegate.java new file mode 100644 index 00000000000..cbe4263b113 --- /dev/null +++ b/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/commands/actions/ResumeOthersCommandActionDelegate.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2026 IBM Corporation. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.debug.internal.ui.commands.actions; + +import org.eclipse.debug.ui.actions.DebugCommandAction; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.widgets.Event; +import org.eclipse.ui.IActionDelegate2; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.IWorkbenchWindowActionDelegate; + +/** + * Resume others action delegate. + * + * @since 3.3 + */ +public class ResumeOthersCommandActionDelegate implements IWorkbenchWindowActionDelegate, IActionDelegate2 { + + private final DebugCommandAction fDebugAction = new ResumeOthersCommandAction(); + + @Override + public void dispose() { + fDebugAction.dispose(); + } + + @Override + public void init(IWorkbenchWindow window) { + fDebugAction.init(window); + } + + @Override + public void run(IAction action) { + fDebugAction.run(); + } + + @Override + public void selectionChanged(IAction action, ISelection selection) { + // do nothing + } + + @Override + public void init(IAction action) { + fDebugAction.setActionProxy(action); + + } + + @Override + public void runWithEvent(IAction action, Event event) { + run(action); + } +} diff --git a/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/commands/actions/ResumeOthersCommandHandler.java b/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/commands/actions/ResumeOthersCommandHandler.java new file mode 100644 index 00000000000..0f0c1235d07 --- /dev/null +++ b/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/commands/actions/ResumeOthersCommandHandler.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2026 IBM Corporation. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Wind River Systems - initial API and implementation + * IBM Corporation - bug fixing + *******************************************************************************/ +package org.eclipse.debug.internal.ui.commands.actions; + +import org.eclipse.debug.core.commands.IResumeOthersHandler; +import org.eclipse.debug.ui.actions.DebugCommandHandler; + +/** + * Default handler for command. It ensures that the keyboard accelerator works even + * if the menu action set is not enabled. + * + * @since 3.8 + */ +public class ResumeOthersCommandHandler extends DebugCommandHandler { + + @Override + protected Class getCommandType() { + return IResumeOthersHandler.class; + } + +} diff --git a/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/launch/LaunchView.java b/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/launch/LaunchView.java index c7227b7a33a..894a755a0c1 100644 --- a/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/launch/LaunchView.java +++ b/debug/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/views/launch/LaunchView.java @@ -42,6 +42,7 @@ import org.eclipse.debug.core.model.IDebugTarget; import org.eclipse.debug.core.model.IProcess; import org.eclipse.debug.core.model.IStackFrame; +import org.eclipse.debug.core.model.IThread; import org.eclipse.debug.internal.ui.DebugPluginImages; import org.eclipse.debug.internal.ui.DebugUIPlugin; import org.eclipse.debug.internal.ui.DelegatingModelPresentation; @@ -52,6 +53,7 @@ import org.eclipse.debug.internal.ui.commands.actions.DropToFrameCommandAction; import org.eclipse.debug.internal.ui.commands.actions.RestartCommandAction; import org.eclipse.debug.internal.ui.commands.actions.ResumeCommandAction; +import org.eclipse.debug.internal.ui.commands.actions.ResumeOthersCommandAction; import org.eclipse.debug.internal.ui.commands.actions.StepIntoCommandAction; import org.eclipse.debug.internal.ui.commands.actions.StepOverCommandAction; import org.eclipse.debug.internal.ui.commands.actions.StepReturnCommandAction; @@ -154,6 +156,8 @@ public class LaunchView extends AbstractDebugView private static final String RESUME = "resume"; //$NON-NLS-1$ + private static final String RESUME_OTHERS = "resume_others"; //$NON-NLS-1$ + private static final String STEP_RETURN = "step_return"; //$NON-NLS-1$ private static final String STEP_OVER = "step_over"; //$NON-NLS-1$ @@ -538,6 +542,7 @@ protected void createActions() { addCapabilityAction(new DisconnectCommandAction(), DISCONNECT); addCapabilityAction(new SuspendCommandAction(), SUSPEND); addCapabilityAction(new ResumeCommandAction(), RESUME); + addCapabilityAction(new ResumeOthersCommandAction(), RESUME_OTHERS); addCapabilityAction(new StepReturnCommandAction(), STEP_RETURN); addCapabilityAction(new StepOverCommandAction(), STEP_OVER); addCapabilityAction(new StepIntoCommandAction(), STEP_INTO); @@ -976,6 +981,7 @@ protected void configureToolBar(IToolBarManager tbm) { protected void addDebugToolbarActions(IToolBarManager tbm) { tbm.appendToGroup(IDebugUIConstants.THREAD_GROUP, getAction(RESUME)); + tbm.appendToGroup(IDebugUIConstants.THREAD_GROUP, getAction(RESUME_OTHERS)); tbm.appendToGroup(IDebugUIConstants.THREAD_GROUP, getAction(SUSPEND)); tbm.appendToGroup(IDebugUIConstants.THREAD_GROUP, getAction(TERMINATE)); tbm.appendToGroup(IDebugUIConstants.THREAD_GROUP, getAction(DISCONNECT)); @@ -995,6 +1001,7 @@ protected void addDebugToolbarActions(IToolBarManager tbm) { */ protected void removeDebugToolbarActions(IToolBarManager tbm) { tbm.remove(new ActionContributionItem(getAction(RESUME))); + tbm.remove(new ActionContributionItem(getAction(RESUME_OTHERS))); tbm.remove(new ActionContributionItem(getAction(SUSPEND))); tbm.remove(new ActionContributionItem(getAction(TERMINATE))); tbm.remove(new ActionContributionItem(getAction(DISCONNECT))); @@ -1092,6 +1099,7 @@ private void disposeActions() { disposeCommandAction(DISCONNECT); disposeCommandAction(SUSPEND); disposeCommandAction(RESUME); + disposeCommandAction(RESUME_OTHERS); disposeCommandAction(STEP_RETURN); disposeCommandAction(STEP_OVER); disposeCommandAction(STEP_INTO); @@ -1204,8 +1212,10 @@ protected void fillContextMenu(IMenuManager menu) { menu.appendToGroup(IDebugUIConstants.LAUNCH_GROUP, getAction(TERMINATE_AND_REMOVE)); menu.appendToGroup(IDebugUIConstants.LAUNCH_GROUP, getAction(TERMINATE_ALL)); - menu.appendToGroup(IDebugUIConstants.THREAD_GROUP, getAction(RESUME)); + if (element instanceof IThread) { + menu.appendToGroup(IDebugUIConstants.THREAD_GROUP, getAction(RESUME_OTHERS)); + } menu.appendToGroup(IDebugUIConstants.THREAD_GROUP, getAction(SUSPEND)); menu.appendToGroup(IDebugUIConstants.THREAD_GROUP, getAction(TERMINATE)); menu.appendToGroup(IDebugUIConstants.THREAD_GROUP, getAction(TERMINATE_AND_RELAUNCH));