1 import * as os from "os";
2 import * as vscode from 'vscode';
3 import * as path from 'path';
4 import * as ra from './lsp_ext';
6 import { Cargo } from './cargo';
7 import { Ctx } from "./ctx";
9 const debugOutput = vscode.window.createOutputChannel("Debug");
10 type DebugConfigProvider = (config: ra.Runnable, executable: string, sourceFileMap?: Record<string, string>) => vscode.DebugConfiguration;
12 function getLldbDebugConfig(config: ra.Runnable, executable: string, sourceFileMap?: Record<string, string>): vscode.DebugConfiguration {
18 args: config.extraArgs,
20 sourceMap: sourceFileMap,
21 sourceLanguages: ["rust"]
25 function getCppvsDebugConfig(config: ra.Runnable, executable: string, sourceFileMap?: Record<string, string>): vscode.DebugConfiguration {
27 type: (os.platform() === "win32") ? "cppvsdbg" : "cppdbg",
31 args: config.extraArgs,
33 sourceFileMap: sourceFileMap,
37 async function getDebugExecutable(config: ra.Runnable): Promise<string> {
38 const cargo = new Cargo(config.cwd || '.', debugOutput);
39 const executable = await cargo.executableFromArgs(config.args);
41 // if we are here, there were no compilation errors.
45 export async function getDebugConfiguration(ctx: Ctx, config: ra.Runnable): Promise<vscode.DebugConfiguration | undefined> {
46 const editor = ctx.activeRustEditor;
49 const knownEngines: Record<string, DebugConfigProvider> = {
50 "vadimcn.vscode-lldb": getLldbDebugConfig,
51 "ms-vscode.cpptools": getCppvsDebugConfig
53 const debugOptions = ctx.config.debug;
55 let debugEngine = null;
56 if (debugOptions.engine === "auto") {
57 for (var engineId in knownEngines) {
58 debugEngine = vscode.extensions.getExtension(engineId);
59 if (debugEngine) break;
62 debugEngine = vscode.extensions.getExtension(debugOptions.engine);
66 vscode.window.showErrorMessage(`Install [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb)`
67 + ` or [MS C++ tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) extension for debugging.`);
72 if (ctx.config.debug.openUpDebugPane) {
73 debugOutput.show(true);
76 const wsFolder = path.normalize(vscode.workspace.workspaceFolders![0].uri.fsPath); // folder exists or RA is not active.
77 function simplifyPath(p: string): string {
78 return path.normalize(p).replace(wsFolder, '${workspaceRoot}');
81 const executable = await getDebugExecutable(config);
82 const debugConfig = knownEngines[debugEngine.id](config, simplifyPath(executable), debugOptions.sourceFileMap);
83 if (debugConfig.type in debugOptions.engineSettings) {
84 const settingsMap = (debugOptions.engineSettings as any)[debugConfig.type];
85 for (var key in settingsMap) {
86 debugConfig[key] = settingsMap[key];
90 if (debugConfig.name === "run binary") {
91 // The LSP side: crates\rust-analyzer\src\main_loop\handlers.rs,
92 // fn to_lsp_runnable(...) with RunnableKind::Bin
93 debugConfig.name = `run ${path.basename(executable)}`;
96 if (debugConfig.cwd) {
97 debugConfig.cwd = simplifyPath(debugConfig.cwd);
103 export async function startDebugSession(ctx: Ctx, config: ra.Runnable): Promise<boolean> {
104 let debugConfig: vscode.DebugConfiguration | undefined = undefined;
107 const wsLaunchSection = vscode.workspace.getConfiguration("launch");
108 const configurations = wsLaunchSection.get<any[]>("configurations") || [];
110 const index = configurations.findIndex(c => c.name === config.label);
112 debugConfig = configurations[index];
113 message = " (from launch.json)";
116 debugConfig = await getDebugConfiguration(ctx, config);
119 if (!debugConfig) return false;
121 debugOutput.appendLine(`Launching debug configuration${message}:`);
122 debugOutput.appendLine(JSON.stringify(debugConfig, null, 2));
123 return vscode.debug.startDebugging(undefined, debugConfig);