Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 5000cecd6a9dcefca8d4339419f1d48a3980ec88 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*******************************************************************************
 * Copyright (c) 2019 Kichwa Coders and others.
 *
 * 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
 *******************************************************************************/
package org.eclipse.cdt.debug.dap;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.cdt.launch.AbstractCLaunchDelegate2;
import org.eclipse.cdt.launch.LaunchUtils;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.Launch;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.IPersistableSourceLocator;
import org.eclipse.debug.core.sourcelookup.IPersistableSourceLocator2;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.lsp4e.debug.launcher.DSPLaunchDelegate;
import org.eclipse.lsp4e.debug.launcher.DSPLaunchDelegate.DSPLaunchDelegateLaunchBuilder;
import org.eclipse.lsp4e.debug.sourcelookup.DSPSourceLookupDirector;
import org.eclipse.swt.widgets.Display;

public class DapLaunchDelegate extends AbstractCLaunchDelegate2 {

	private static final String DEBUG_ADAPTER_JS = "/debug-servers/node_modules/cdt-gdb-adapter/dist/debugAdapter.js"; //$NON-NLS-1$
	// see https://github.com/eclipse-cdt/cdt-gdb-adapter/blob/73a31934d169555a338f53512b4994c017f67a1a/src/GDBDebugSession.ts#L22
	private static final String GDB = "gdb"; //$NON-NLS-1$
	private static final String PROGRAM = "program"; //$NON-NLS-1$
	private static final String ARGUMENTS = "arguments"; //$NON-NLS-1$
	private static final String VERBOSE = "verbose"; //$NON-NLS-1$
	private static final String LOG_FILE = "logFile"; //$NON-NLS-1$
	private InitializeLaunchConfigurations initializeLaunchConfigurations = new InitializeLaunchConfigurations(
			this::warnNodeJSMissing);

	private void warnNodeJSMissing() {
		Display.getDefault().asyncExec(() -> {
			MessageDialog.openWarning(Display.getCurrent().getActiveShell(), "Missing node.js", //$NON-NLS-1$
					"Could not find node.js. This prevents being able to debug with the CDT Debug Adapter.\n" //$NON-NLS-1$
							+ "Please make sure node.js is installed and that your PATH environement variable contains the location to the `node` executable."); //$NON-NLS-1$
		});
	}

	@Override
	public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor)
			throws CoreException {
		// user settings
		Map<String, Object> param = new HashMap<>();

		param.put(PROGRAM, LaunchUtils.getProgramPath(configuration));
		param.put(ARGUMENTS, LaunchUtils.getProgramArguments(configuration));

		try {
			URL fileURL = FileLocator.toFileURL(getClass().getResource(DEBUG_ADAPTER_JS));
			if (fileURL == null) {
				throw new IOException(Messages.DapLaunchDelegate_missing_debugAdapter_script + Activator.PLUGIN_ID
						+ DEBUG_ADAPTER_JS);
			}
			String path = fileURL.getPath();
			List<String> debugCmdArgs = Collections.singletonList(path);

			DSPLaunchDelegateLaunchBuilder builder = new DSPLaunchDelegateLaunchBuilder(configuration, mode, launch,
					monitor);
			builder.setLaunchDebugAdapter(initializeLaunchConfigurations.getNodeJsLocation()
					.orElseThrow(() -> new IOException("Cannot find node runtime")), debugCmdArgs); //$NON-NLS-1$
			builder.setMonitorDebugAdapter(true);
			builder.setDspParameters(param);

			DSPLaunchDelegate dspLaunchDelegate = new DSPLaunchDelegate() {
				@Override
				protected IDebugTarget createDebugTarget(SubMonitor subMonitor, Runnable cleanup,
						InputStream inputStream, java.io.OutputStream outputStream, ILaunch launch,
						Map<String, Object> dspParameters) throws CoreException {
					DapDebugTarget target = new DapDebugTarget(launch, cleanup, inputStream, outputStream,
							dspParameters);
					target.initialize(subMonitor.split(80));
					return target;
				}
			};
			dspLaunchDelegate.launch(builder);
		} catch (IOException e) {
			IStatus errorStatus = new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e);
			Activator.getDefault().getLog().log(errorStatus);
			ErrorDialog.openError(Display.getDefault().getActiveShell(), "Debug error", e.getMessage(), errorStatus); //$NON-NLS-1$
		}
	}

	@Override
	protected String getPluginID() {
		return Activator.PLUGIN_ID;
	}

	@Override
	public ILaunch getLaunch(ILaunchConfiguration configuration, String mode) throws CoreException {
		IPersistableSourceLocator locator = createLocator(configuration);
		ILaunch launch = new Launch(configuration, mode, locator);
		return launch;
	}

	private IPersistableSourceLocator createLocator(ILaunchConfiguration configuration) throws CoreException {
		String type = DSPSourceLookupDirector.ID;
		IPersistableSourceLocator locator = DebugPlugin.getDefault().getLaunchManager().newSourceLocator(type);
		String memento = configuration.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_MEMENTO, (String) null);
		if (memento == null) {
			locator.initializeDefaults(configuration);
		} else {
			if (locator instanceof IPersistableSourceLocator2) {
				((IPersistableSourceLocator2) locator).initializeFromMemento(memento, configuration);
			} else {
				locator.initializeFromMemento(memento);
			}
		}
		return locator;
	}

}

Back to the top