/******************************************************************************* * Copyright (c) 2000, 2018 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.debug.ui; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.commands.operations.IOperationHistory; import org.eclipse.core.commands.operations.IUndoContext; import org.eclipse.core.commands.operations.IUndoableOperation; import org.eclipse.core.commands.operations.ObjectUndoContext; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationType; import org.eclipse.debug.core.ILaunchDelegate; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.debug.core.model.IBreakpoint; import org.eclipse.debug.core.model.IDebugElement; import org.eclipse.debug.core.model.IDebugTarget; import org.eclipse.debug.core.model.IProcess; import org.eclipse.debug.core.model.ISourceLocator; import org.eclipse.debug.internal.core.IConfigurationElementConstants; import org.eclipse.debug.internal.ui.DebugPluginImages; import org.eclipse.debug.internal.ui.DebugUIPlugin; import org.eclipse.debug.internal.ui.DefaultLabelProvider; import org.eclipse.debug.internal.ui.DelegatingModelPresentation; import org.eclipse.debug.internal.ui.IInternalDebugUIConstants; import org.eclipse.debug.internal.ui.LazyModelPresentation; import org.eclipse.debug.internal.ui.TerminateToggleValue; import org.eclipse.debug.internal.ui.actions.ActionMessages; import org.eclipse.debug.internal.ui.actions.ToggleBreakpointsTargetManager; import org.eclipse.debug.internal.ui.contextlaunching.LaunchingResourceManager; import org.eclipse.debug.internal.ui.contexts.DebugContextManager; import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationDialog; import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationManager; import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationPropertiesDialog; import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationTabGroupViewer; import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationsDialog; import org.eclipse.debug.internal.ui.launchConfigurations.LaunchGroupExtension; import org.eclipse.debug.internal.ui.launchConfigurations.LaunchShortcutExtension; import org.eclipse.debug.internal.ui.memory.MemoryRenderingManager; import org.eclipse.debug.internal.ui.sourcelookup.SourceLookupFacility; import org.eclipse.debug.internal.ui.sourcelookup.SourceLookupUIUtils; import org.eclipse.debug.internal.ui.stringsubstitution.SelectedResourceManager; import org.eclipse.debug.ui.actions.IToggleBreakpointsTargetManager; import org.eclipse.debug.ui.contexts.IDebugContextListener; import org.eclipse.debug.ui.contexts.IDebugContextManager; import org.eclipse.debug.ui.contexts.IDebugContextService; import org.eclipse.debug.ui.memory.IMemoryRenderingManager; import org.eclipse.debug.ui.sourcelookup.ISourceContainerBrowser; import org.eclipse.debug.ui.sourcelookup.ISourceLookupResult; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.TreePath; import org.eclipse.jface.viewers.TreeSelection; import org.eclipse.jface.window.Window; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.custom.BusyIndicator; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IViewSite; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.console.IConsole; import org.eclipse.ui.handlers.HandlerUtil; import org.eclipse.ui.ide.undo.DeleteMarkersOperation; import org.eclipse.ui.ide.undo.WorkspaceUndoUtil; /** * This class provides utilities for clients of the debug UI. *
* Images retrieved from this facility should not be disposed. * The images will be disposed when this plug-in is shutdown. *
** Note: all methods in this class are expected to be called * on the Display thread unless otherwise noted. *
* @noinstantiate This class is not intended to be instantiated by clients. * @noextend This class is not intended to be subclassed by clients. */ public class DebugUITools { /** * The undo context for breakpoints. * * @since 3.7 */ private static ObjectUndoContext fgBreakpointsUndoContext; /** * Returns the shared image managed under the given key, ornull
* if none.
* * Note that clients MUST NOT dispose the image returned by this method. *
*
* See IDebugUIConstants
for available images.
*
null
if none
* @see IDebugUIConstants
*/
public static Image getImage(String key) {
return DebugPluginImages.getImage(key);
}
/**
* Returns the shared image descriptor managed under the given key, or
* null
if none.
*
* See IDebugUIConstants
for available image descriptors.
*
null
if none
* @see IDebugUIConstants
*/
public static ImageDescriptor getImageDescriptor(String key) {
return DebugPluginImages.getImageDescriptor(key);
}
/**
* Returns the default image descriptor for the given element.
*
* @param element the element
* @return the image descriptor or null
if none
*/
public static ImageDescriptor getDefaultImageDescriptor(Object element) {
String imageKey= getDefaultImageKey(element);
if (imageKey == null) {
return null;
}
return DebugPluginImages.getImageDescriptor(imageKey);
}
private static String getDefaultImageKey(Object element) {
return ((DefaultLabelProvider)DebugUIPlugin.getDefaultLabelProvider()).getImageKey(element);
}
/**
* Returns the preference store for the debug UI plug-in.
*
* @return preference store
*/
public static IPreferenceStore getPreferenceStore() {
return DebugUIPlugin.getDefault().getPreferenceStore();
}
/**
* Returns a new debug model presentation that delegates to
* appropriate debug models.
* * It is the client's responsibility dispose the presentation. *
* * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose() * @return a debug model presentation * @since 2.0 */ public static IDebugModelPresentation newDebugModelPresentation() { return new DelegatingModelPresentation(); } /** * Returns a new debug model presentation for specified * debug model, ornull
if a presentation does
* not exist.
* * It is the client's responsibility dispose the presentation. *
* * @param identifier debug model identifier * @see org.eclipse.jface.viewers.IBaseLabelProvider#dispose() * @return a debug model presentation, ornull
* @since 2.0
*/
public static IDebugModelPresentation newDebugModelPresentation(String identifier) {
IExtensionPoint point= Platform.getExtensionRegistry().getExtensionPoint(DebugUIPlugin.getUniqueIdentifier(), IDebugUIConstants.ID_DEBUG_MODEL_PRESENTATION);
if (point != null) {
IExtension[] extensions= point.getExtensions();
for (int i= 0; i < extensions.length; i++) {
IExtension extension= extensions[i];
IConfigurationElement[] configElements= extension.getConfigurationElements();
for (int j= 0; j < configElements.length; j++) {
IConfigurationElement elt= configElements[j];
String id= elt.getAttribute("id"); //$NON-NLS-1$
if (id != null && id.equals(identifier)) {
return new LazyModelPresentation(elt);
}
}
}
}
return null;
}
/**
* Returns the element of the currently selected context in the
* active workbench window. Returns null
if there is no
* current debug context.
*
* This method used to return null
when called from a non-UI thread,
* but since 3.1, this methods also works when called from a non-UI thread.
*
null
* @since 2.0
*/
public static IAdaptable getDebugContext() {
IWorkbenchWindow activeWindow = SelectedResourceManager.getDefault().getActiveWindow();
if (activeWindow != null) {
ISelection activeContext = DebugUITools.getDebugContextManager().getContextService(activeWindow).getActiveContext();
return getDebugContextElementForSelection(activeContext);
}
return null;
}
/**
* Returns the currently selected context in the given part or part's
* workbench window. Returns null
if there is no current
* debug context.
* @param part workbench part where the active context is to be evaluated
* @return the currently selected debug context in the given workbench part,
* or null
* @since 3.8
* @see IDebugContextService#getActiveContext(String)
* @see IDebugContextService#getActiveContext(String, String)
*/
public static ISelection getDebugContextForPart(IWorkbenchPart part) {
IWorkbenchPartSite site = part.getSite();
IWorkbenchWindow partWindow = site.getWorkbenchWindow();
if (partWindow != null) {
IDebugContextService contextService = DebugUITools.getDebugContextManager().getContextService(partWindow);
if (site instanceof IViewSite) {
return contextService.getActiveContext(site.getId(), ((IViewSite)site).getSecondaryId());
} else {
return contextService.getActiveContext(site.getId());
}
}
return null;
}
/**
* Return the undo context that should be used for operations involving breakpoints.
*
* @return the undo context for breakpoints
* @since 3.7
*/
public static synchronized IUndoContext getBreakpointsUndoContext() {
if (fgBreakpointsUndoContext == null) {
fgBreakpointsUndoContext= new ObjectUndoContext(new Object(), "Breakpoints Context"); //$NON-NLS-1$
fgBreakpointsUndoContext.addMatch(WorkspaceUndoUtil.getWorkspaceUndoContext());
}
return fgBreakpointsUndoContext;
}
/**
* Deletes the given breakpoints using the operation history, which allows to undo the deletion.
*
* @param breakpoints the breakpoints to delete
* @param shell the shell used for potential user interactions, or null
if unknown
* @param progressMonitor the progress monitor
* @throws CoreException if the deletion fails
* @since 3.7
*/
public static void deleteBreakpoints(IBreakpoint[] breakpoints, final Shell shell, IProgressMonitor progressMonitor) throws CoreException {
IMarker[] markers= new IMarker[breakpoints.length];
int markerCount;
for (markerCount= 0; markerCount < breakpoints.length; markerCount++) {
if (!breakpoints[markerCount].isRegistered()) {
break;
}
markers[markerCount]= breakpoints[markerCount].getMarker();
if (markers[markerCount] == null) {
break;
}
}
// We only offer undo support if all breakpoints are registered and have associated markers
boolean allowUndo= markerCount == breakpoints.length;
DebugPlugin.getDefault().getBreakpointManager().removeBreakpoints(breakpoints, !allowUndo);
if (allowUndo) {
for (int i= 0; i < markers.length; i++) {
markers[i].setAttribute(DebugPlugin.ATTR_BREAKPOINT_IS_DELETED, true);
}
IAdaptable context= null;
if (shell != null) {
context= new IAdaptable() {
@SuppressWarnings("unchecked")
@Override
public null
* if there is no current debug context.
*
* @param site the part's site where to look up the active context
* @return the currently active debug context in the given part, or null
* @since 3.7
*/
public static IAdaptable getPartDebugContext(IWorkbenchPartSite site) {
IDebugContextService service = DebugUITools.getDebugContextManager().getContextService(site.getWorkbenchWindow());
String id = null;
String secondaryId = null;
id = site.getId();
if (site instanceof IViewSite) {
secondaryId = ((IViewSite)site).getSecondaryId();
}
ISelection activeContext = service.getActiveContext(id, secondaryId);
return getDebugContextElementForSelection(activeContext);
}
/**
* Adds the given debug context listener as a listener to the debug context changed events, in
* the context of the given workbench part.
* * This method is a utility method which ultimately calls * {@link IDebugContextService#addDebugContextListener(IDebugContextListener, String, String)} * using the part id parameters extracted from the given part parameter. *
* * @param site the part's site to get the part ID and part secondary ID from * @param listener Debug context listener to add * * @see IDebugContextService#addDebugContextListener(IDebugContextListener, String, String) * @see IDebugContextManager#addDebugContextListener(IDebugContextListener) * @since 3.7 */ public static void addPartDebugContextListener(IWorkbenchPartSite site, IDebugContextListener listener) { IDebugContextService service = DebugUITools.getDebugContextManager().getContextService(site.getWorkbenchWindow()); String id = site.getId(); String secondaryId = null; if (site instanceof IViewSite) { secondaryId = ((IViewSite)site).getSecondaryId(); } service.addDebugContextListener(listener, id, secondaryId); } /** * Removes the given debug context listener as a listener to the debug context changed events, * in the context of the given workbench part. ** This method is a utility method which ultimately calls * {@link IDebugContextService#removeDebugContextListener(IDebugContextListener, String, String)} * using the part id parameters extracted from the given part parameter. *
* * @param site the part's site to get the part ID and part secondary ID from * @param listener Debug context listener to remove * * @see IDebugContextService#removeDebugContextListener(IDebugContextListener, String, String) * @see IDebugContextManager#removeDebugContextListener(IDebugContextListener) * @since 3.7 */ public static void removePartDebugContextListener(IWorkbenchPartSite site, IDebugContextListener listener) { IDebugContextService service = DebugUITools.getDebugContextManager().getContextService(site.getWorkbenchWindow()); String id = site.getId(); String secondaryId = null; if (site instanceof IViewSite) { secondaryId = ((IViewSite)site).getSecondaryId(); } service.removeDebugContextListener(listener, id, secondaryId); } /** * Extracts the first element from the given selection and casts it to IAdaptable. * * @param activeContext the selection * @return an adaptable */ private static IAdaptable getDebugContextElementForSelection(ISelection activeContext) { if (activeContext instanceof IStructuredSelection) { IStructuredSelection selection = (IStructuredSelection) activeContext; if (!selection.isEmpty()) { Object firstElement = selection.getFirstElement(); if (firstElement instanceof IAdaptable) { return (IAdaptable) firstElement; } } } return null; } /** * Returns the currently selected resource in the active workbench window, * ornull
if none. If an editor is active, the resource adapter
* associated with the editor is returned, if any.
*
* @return selected resource or null
* @since 3.0
*/
public static IResource getSelectedResource() {
return SelectedResourceManager.getDefault().getSelectedResource();
}
/**
* Returns the process associated with the current debug context.
* If there is no debug context currently, the most recently
* launched process is returned. If there is no current process
* null
is returned.
*
* @return the current process, or null
* @since 2.0
*/
public static IProcess getCurrentProcess() {
IAdaptable context = getDebugContext();
if (context == null) {
ILaunch[] launches = DebugPlugin.getDefault().getLaunchManager().getLaunches();
if (launches.length > 0) {
context = launches[launches.length - 1];
}
}
if (context instanceof IDebugElement) {
return ((IDebugElement)context).getDebugTarget().getProcess();
}
if (context instanceof IProcess) {
return (IProcess)context;
}
if (context instanceof ILaunch) {
ILaunch launch= (ILaunch)context;
IDebugTarget target= launch.getDebugTarget();
if (target != null) {
IProcess process = target.getProcess();
if (process != null) {
return process;
}
}
IProcess[] ps = launch.getProcesses();
if (ps.length > 0) {
return ps[ps.length - 1];
}
}
if (context != null) {
return context.getAdapter(IProcess.class);
}
return null;
}
/**
* Open the launch configuration dialog with the specified initial selection.
* The selection may be null
, or contain any mix of
* ILaunchConfiguration
or ILaunchConfigurationType
* elements.
* * Before opening a new dialog, this method checks if there is an existing open * launch configuration dialog. If there is, this dialog is used with the * specified selection. If there is no existing dialog, a new one is created. *
*
* Note that if an existing dialog is reused, the mode
argument is ignored
* and the existing dialog keeps its original mode.
*
ILaunchManager
.
* @return the return code from opening the launch configuration dialog -
* one of Window.OK
or Window.CANCEL
. Window.CANCEL
* is returned if an invalid launch group identifier is provided.
* @see ILaunchGroup
* @since 2.0
* @deprecated use openLaunchConfigurationDialogOnGroup(Shell, IStructuredSelection, String)
* to specify the launch group that the dialog should be opened on. This method will open
* on the launch group with the specified mode and a null
category
*/
@Deprecated
public static int openLaunchConfigurationDialog(Shell shell, IStructuredSelection selection, String mode) {
ILaunchGroup[] groups = getLaunchGroups();
for (int i = 0; i < groups.length; i++) {
ILaunchGroup group = groups[i];
if (group.getMode().equals(mode) && group.getCategory() == null) {
return openLaunchConfigurationDialogOnGroup(shell, selection, group.getIdentifier());
}
}
return Window.CANCEL;
}
/**
* Open the launch configuration dialog with the specified initial selection.
* The selection may be null
, or contain any mix of
* ILaunchConfiguration
or ILaunchConfigurationType
* elements.
* * Before opening a new dialog, this method checks if there is an existing open * launch configuration dialog. If there is, this dialog is used with the * specified selection. If there is no existing dialog, a new one is created. *
*
* Note that if an existing dialog is reused, the mode
argument is ignored
* and the existing dialog keeps its original mode.
*
Window.OK
or Window.CANCEL
. Window.CANCEL
* is returned if an invalid launch group identifier is provided.
* @see ILaunchGroup
* @since 2.1
*/
public static int openLaunchConfigurationDialogOnGroup(Shell shell, IStructuredSelection selection, String groupIdentifier) {
return openLaunchConfigurationDialogOnGroup(shell, selection, groupIdentifier, null);
}
/**
* Open the launch configuration dialog with the specified initial selection.
* The selection may be null
, or contain any mix of
* ILaunchConfiguration
or ILaunchConfigurationType
* elements.
* * Before opening a new dialog, this method checks if there is an existing open * launch configuration dialog. If there is, this dialog is used with the * specified selection. If there is no existing dialog, a new one is created. *
*
* Note that if an existing dialog is reused, the mode
argument is ignored
* and the existing dialog keeps its original mode.
*
* If a status is specified, a status handler is consulted to handle the * status. The status handler is passed the instance of the launch * configuration dialog that is opened. This gives the status handler an * opportunity to perform error handling/initialization as required. *
* @param shell the parent shell for the launch configuration dialog * @param selection the initial selection for the dialog * @param groupIdentifier the identifier of the launch group to display (corresponds to * the identifier of a launch group extension) * @param status the status to display in the dialog, ornull
* if none
* @return the return code from opening the launch configuration dialog -
* one of Window.OK
or Window.CANCEL
. Window.CANCEL
* is returned if an invalid launch group identifier is provided.
* @see org.eclipse.debug.core.IStatusHandler
* @see ILaunchGroup
* @since 2.1
*/
public static int openLaunchConfigurationDialogOnGroup(final Shell shell, final IStructuredSelection selection, final String groupIdentifier, final IStatus status) {
final int[] result = new int[1];
Runnable r = () -> {
LaunchConfigurationsDialog dialog = (LaunchConfigurationsDialog) LaunchConfigurationsDialog
.getCurrentlyVisibleLaunchConfigurationDialog();
if (dialog != null) {
dialog.setInitialSelection(selection);
dialog.doInitialTreeSelection();
if (status != null) {
dialog.handleStatus(status);
}
result[0] = Window.OK;
} else {
LaunchGroupExtension ext = DebugUIPlugin.getDefault().getLaunchConfigurationManager()
.getLaunchGroup(groupIdentifier);
if (ext != null) {
dialog = new LaunchConfigurationsDialog(shell, ext);
dialog.setOpenMode(LaunchConfigurationsDialog.LAUNCH_CONFIGURATION_DIALOG_OPEN_ON_SELECTION);
dialog.setInitialSelection(selection);
dialog.setInitialStatus(status);
result[0] = dialog.open();
} else {
result[0] = Window.CANCEL;
}
}
};
BusyIndicator.showWhile(DebugUIPlugin.getStandardDisplay(), r);
return result[0];
}
/**
* Open the launch configuration properties dialog on the specified launch
* configuration.
*
* @param shell the parent shell for the launch configuration dialog
* @param configuration the configuration to display
* @param groupIdentifier group identifier of the launch group the launch configuration
* belongs to
* @return the return code from opening the launch configuration dialog -
* one of Window.OK
or Window.CANCEL
. Window.CANCEL
* is returned if an invalid launch group identifier is provided.
* @see ILaunchGroup
* @since 2.1
*/
public static int openLaunchConfigurationPropertiesDialog(Shell shell, ILaunchConfiguration configuration, String groupIdentifier) {
return openLaunchConfigurationPropertiesDialog(shell, configuration, groupIdentifier, null);
}
/**
* Open the launch configuration properties dialog on the specified launch
* configuration.
*
* @param shell the parent shell for the launch configuration dialog
* @param configuration the configuration to display
* @param groupIdentifier group identifier of the launch group the launch configuration
* belongs to
* @param status the status to display, or null
if none
* @return the return code from opening the launch configuration dialog -
* one of Window.OK
or Window.CANCEL
. Window.CANCEL
* is returned if an invalid launch group identifier is provided.
* @see ILaunchGroup
* @since 3.0
*/
public static int openLaunchConfigurationPropertiesDialog(Shell shell, ILaunchConfiguration configuration, String groupIdentifier, IStatus status) {
LaunchGroupExtension group = DebugUIPlugin.getDefault().getLaunchConfigurationManager().getLaunchGroup(groupIdentifier);
if (group != null) {
LaunchConfigurationPropertiesDialog dialog = new LaunchConfigurationPropertiesDialog(shell, configuration, group);
dialog.setInitialStatus(status);
return dialog.open();
}
return Window.CANCEL;
}
/**
* Open the launch configuration dialog on the specified launch
* configuration. The dialog displays the tabs for a single configuration
* only (a tree of launch configuration is not displayed), and provides a
* launch (run or debug) button.
* * If a status is specified, a status handler is consulted to handle the * status. The status handler is passed the instance of the launch * configuration dialog that is opened. This gives the status handler an * opportunity to perform error handling/initialization as required. *
* @param shell the parent shell for the launch configuration dialog * @param configuration the configuration to display * @param groupIdentifier group identifier of the launch group the launch configuration * belongs to * @param status the status to display, ornull
if none
* @return the return code from opening the launch configuration dialog -
* one of Window.OK
or Window.CANCEL
. Window.CANCEL
* is returned if an invalid launch group identifier is provided.
* @see ILaunchGroup
* @since 2.1
*/
public static int openLaunchConfigurationDialog(Shell shell, ILaunchConfiguration configuration, String groupIdentifier, IStatus status) {
LaunchGroupExtension group = DebugUIPlugin.getDefault().getLaunchConfigurationManager().getLaunchGroup(groupIdentifier);
if (group != null) {
LaunchConfigurationDialog dialog = new LaunchConfigurationDialog(shell, configuration, group);
dialog.setInitialStatus(status);
return dialog.open();
}
return Window.CANCEL;
}
/**
* Saves all dirty editors and builds the workspace according to current
* preference settings, and returns whether a launch should proceed.
* * The following preferences affect whether dirty editors are saved, * and/or if the user is prompted to save dirty editors:
LaunchConfigurationDelegate
to allow for scoped saving
* of resources that are only involved in the current launch, no longer the entire workspace
*/
@Deprecated
public static boolean saveAndBuildBeforeLaunch() {
return DebugUIPlugin.saveAndBuild();
}
/**
* Saves all dirty editors according to current
* preference settings, and returns whether a launch should proceed.
* * The following preferences affect whether dirty editors are saved, * and/or if the user is prompted to save dirty editors:
LaunchConfigurationDelegate
to allow for scoped saving
* of resources that are only involved in the current launch, no longer the entire workspace
*/
@Deprecated
public static boolean saveBeforeLaunch() {
return DebugUIPlugin.preLaunchSave();
}
/**
* Saves and builds the workspace according to current preference settings,
* and launches the given launch configuration in the specified mode. It
* terminates the current launch for the same configuration if it was
* specified via Preferences or toggled by Shift.
* * This method must be called in the UI thread. *
* * @param configuration the configuration to launch * @param mode launch mode - run or debug * @since 2.1 */ public static void launch(final ILaunchConfiguration configuration, final String mode) { launch(configuration, mode, DebugUITools.findToggleLaunchForConfig(configuration, mode)); } private static HashMap