blob: b9c5236951b42925d1ccb4e056833a72596566d3 [file] [log] [blame]
/*********************************************************************
* Copyright (c) 2018 Red Hat Inc. and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Lucas Bullen (Red Hat Inc.) - Initial implementation
*******************************************************************************/
package org.eclipse.corrosion.debug;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.dsf.debug.sourcelookup.DsfSourceLookupDirector;
import org.eclipse.cdt.dsf.gdb.launching.GdbLaunchDelegate;
import org.eclipse.cdt.dsf.gdb.launching.LaunchUtils;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.variables.IStringVariableManager;
import org.eclipse.core.variables.VariablesPlugin;
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.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.ISourceLocator;
import org.eclipse.debug.ui.ILaunchShortcut;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.corrosion.CorrosionPlugin;
import org.eclipse.corrosion.CorrosionPreferenceInitializer;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PlatformUI;
public class RustDebugDelegate extends GdbLaunchDelegate implements ILaunchShortcut {
public static final String BUILD_COMMAND_ATTRIBUTE = CorrosionPlugin.PLUGIN_ID + "BUILD_COMMAND";
@Override
public void launch(ILaunchConfiguration config, String mode, ILaunch launch, IProgressMonitor monitor)
throws CoreException {
IPreferenceStore store = CorrosionPlugin.getDefault().getPreferenceStore();
String cargo = store.getString(CorrosionPreferenceInitializer.cargoPathPreference);
String buildCommand = config.getAttribute(BUILD_COMMAND_ATTRIBUTE, "");
File projectLocation = new File(
config.getAttribute(ICDTLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, ""));
List<String> cmdLine = new ArrayList<>();
cmdLine.add(cargo);
if (buildCommand.isEmpty()) {
buildCommand = "build";
}
IStringVariableManager manager = VariablesPlugin.getDefault().getStringVariableManager();
buildCommand = manager.performStringSubstitution(buildCommand);
cmdLine.addAll(Arrays.asList(buildCommand.replace('\n', ' ').split(" ")));
Process restoreProcess = DebugPlugin.exec(cmdLine.toArray(new String[cmdLine.size()]), projectLocation);
String labelString = "cargo ";
if (buildCommand.length() > 20) {
labelString += buildCommand.substring(0, 20) + "...";
} else {
labelString += buildCommand;
}
IProcess process = DebugPlugin.newProcess(launch, restoreProcess, labelString);
process.setAttribute(IProcess.ATTR_CMDLINE, String.join(" ", cmdLine));
try {
restoreProcess.waitFor();
} catch (InterruptedException e) {
}
if (restoreProcess.exitValue() != 0) { // errors will be shown in console
return;
}
super.launch(config, mode, launch, monitor);
}
@Override
public void launch(ISelection selection, String mode) {
if (selection instanceof IStructuredSelection) {
Iterator<?> selectionIterator = ((IStructuredSelection) selection).iterator();
while (selectionIterator.hasNext()) {
Object element = selectionIterator.next();
IResource resource = null;
if (element instanceof IResource) {
resource = (IResource) element;
} else if (element instanceof IAdaptable) {
resource = ((IAdaptable) element).getAdapter(IResource.class);
}
if (resource != null) {
try {
ILaunchConfiguration launchConfig = getLaunchConfiguration(mode, resource);
if (launchConfig != null) {
launchConfig.launch(mode, new NullProgressMonitor());
}
} catch (CoreException e) {
CorrosionPlugin.logError(e);
}
return;
}
}
}
Display.getDefault().asyncExec(() -> {
MessageDialog.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), "Unable to Launch",
"Unable to launch Rust Project from selection.");
});
}
@Override
public void launch(IEditorPart editor, String mode) {
IEditorInput input = editor.getEditorInput();
IFile file = input.getAdapter(IFile.class);
try {
ILaunchConfiguration launchConfig = getLaunchConfiguration(mode, file);
if (launchConfig != null) {
launchConfig.launch(mode, new NullProgressMonitor());
}
} catch (CoreException e) {
CorrosionPlugin.logError(e);
}
}
@Override
protected ISourceLocator getSourceLocator(ILaunchConfiguration configuration, DsfSession session)
throws CoreException {
SourceLookupDirector locator = new SourceLookupDirector();
String memento = configuration.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_MEMENTO, (String) null);
if (memento == null) {
locator.initializeDefaults(configuration);
} else {
locator.initializeFromMemento(memento, configuration);
}
return locator;
}
@Override
protected DsfSourceLookupDirector createDsfSourceLocator(ILaunchConfiguration configuration, DsfSession session)
throws CoreException {
DsfSourceLookupDirector sourceLookupDirector = new DsfSourceLookupDirector(session);
sourceLookupDirector.setSourceContainers(
((SourceLookupDirector) getSourceLocator(configuration, session)).getSourceContainers());
return sourceLookupDirector;
}
@Override
public ILaunch getLaunch(ILaunchConfiguration configuration, String mode) throws CoreException {
setDefaultProcessFactory(configuration); // Reset process factory to what GdbLaunch expected
ILaunch launch = super.getLaunch(configuration, mode);
// workaround for DLTK bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=419273
launch.setAttribute("org.eclipse.dltk.debug.debugConsole", "false");
return launch;
}
@Override
protected IPath checkBinaryDetails(ILaunchConfiguration config) throws CoreException {
return LaunchUtils.verifyProgramPath(config, null);
}
private ILaunchConfiguration getLaunchConfiguration(String mode, IResource resource) {
ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager();
ILaunchConfigurationType configType = launchManager
.getLaunchConfigurationType("org.eclipse.corrosion.debug.RustDebugDelegate");
try {
ILaunchConfiguration[] launchConfigurations = launchManager.getLaunchConfigurations(configType);
final IProject project = resource.getProject();
final String projectName = project.getName();
for (ILaunchConfiguration iLaunchConfiguration : launchConfigurations) {
if (iLaunchConfiguration.getAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, "")
.equals(projectName)) {
return iLaunchConfiguration;
}
}
String configName = launchManager.generateLaunchConfigurationName(projectName);
ILaunchConfigurationWorkingCopy wc = configType.newInstance(null, configName);
wc.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROJECT_NAME, projectName);
wc.setAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME,
project.getLocation().toString() + "/target/debug/" + projectName);
wc.setAttribute(ICDTLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, project.getLocation().toString());
wc.setAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN, false);
wc.doSave();
return wc;
} catch (CoreException e) {
CorrosionPlugin.logError(e);
}
return null;
}
}