diff options
Diffstat (limited to 'editors/code/src/debug.ts')
-rw-r--r-- | editors/code/src/debug.ts | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/editors/code/src/debug.ts b/editors/code/src/debug.ts new file mode 100644 index 000000000..d3fe588e8 --- /dev/null +++ b/editors/code/src/debug.ts | |||
@@ -0,0 +1,124 @@ | |||
1 | import * as os from "os"; | ||
2 | import * as vscode from 'vscode'; | ||
3 | import * as path from 'path'; | ||
4 | import * as ra from './rust-analyzer-api'; | ||
5 | |||
6 | import { Cargo } from './cargo'; | ||
7 | import { Ctx } from "./ctx"; | ||
8 | |||
9 | const debugOutput = vscode.window.createOutputChannel("Debug"); | ||
10 | type DebugConfigProvider = (config: ra.Runnable, executable: string, sourceFileMap?: Record<string, string>) => vscode.DebugConfiguration; | ||
11 | |||
12 | function getLldbDebugConfig(config: ra.Runnable, executable: string, sourceFileMap?: Record<string, string>): vscode.DebugConfiguration { | ||
13 | return { | ||
14 | type: "lldb", | ||
15 | request: "launch", | ||
16 | name: config.label, | ||
17 | program: executable, | ||
18 | args: config.extraArgs, | ||
19 | cwd: config.cwd, | ||
20 | sourceMap: sourceFileMap, | ||
21 | sourceLanguages: ["rust"] | ||
22 | }; | ||
23 | } | ||
24 | |||
25 | function getCppvsDebugConfig(config: ra.Runnable, executable: string, sourceFileMap?: Record<string, string>): vscode.DebugConfiguration { | ||
26 | return { | ||
27 | type: (os.platform() === "win32") ? "cppvsdbg" : "cppdbg", | ||
28 | request: "launch", | ||
29 | name: config.label, | ||
30 | program: executable, | ||
31 | args: config.extraArgs, | ||
32 | cwd: config.cwd, | ||
33 | sourceFileMap: sourceFileMap, | ||
34 | }; | ||
35 | } | ||
36 | |||
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); | ||
40 | |||
41 | // if we are here, there were no compilation errors. | ||
42 | return executable; | ||
43 | } | ||
44 | |||
45 | export async function getDebugConfiguration(ctx: Ctx, config: ra.Runnable): Promise<vscode.DebugConfiguration | undefined> { | ||
46 | const editor = ctx.activeRustEditor; | ||
47 | if (!editor) return; | ||
48 | |||
49 | const knownEngines: Record<string, DebugConfigProvider> = { | ||
50 | "vadimcn.vscode-lldb": getLldbDebugConfig, | ||
51 | "ms-vscode.cpptools": getCppvsDebugConfig | ||
52 | }; | ||
53 | const debugOptions = ctx.config.debug; | ||
54 | |||
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; | ||
60 | } | ||
61 | } else { | ||
62 | debugEngine = vscode.extensions.getExtension(debugOptions.engine); | ||
63 | } | ||
64 | |||
65 | if (!debugEngine) { | ||
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.`); | ||
68 | return; | ||
69 | } | ||
70 | |||
71 | debugOutput.clear(); | ||
72 | if (ctx.config.debug.openUpDebugPane) { | ||
73 | debugOutput.show(true); | ||
74 | } | ||
75 | |||
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}'); | ||
79 | } | ||
80 | |||
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]; | ||
87 | } | ||
88 | } | ||
89 | |||
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)}`; | ||
94 | } | ||
95 | |||
96 | if (debugConfig.cwd) { | ||
97 | debugConfig.cwd = simplifyPath(debugConfig.cwd); | ||
98 | } | ||
99 | |||
100 | return debugConfig; | ||
101 | } | ||
102 | |||
103 | export async function startDebugSession(ctx: Ctx, config: ra.Runnable): Promise<boolean> { | ||
104 | let debugConfig: vscode.DebugConfiguration | undefined = undefined; | ||
105 | let message = ""; | ||
106 | |||
107 | const wsLaunchSection = vscode.workspace.getConfiguration("launch"); | ||
108 | const configurations = wsLaunchSection.get<any[]>("configurations") || []; | ||
109 | |||
110 | const index = configurations.findIndex(c => c.name === config.label); | ||
111 | if (-1 !== index) { | ||
112 | debugConfig = configurations[index]; | ||
113 | message = " (from launch.json)"; | ||
114 | debugOutput.clear(); | ||
115 | } else { | ||
116 | debugConfig = await getDebugConfiguration(ctx, config); | ||
117 | } | ||
118 | |||
119 | if (!debugConfig) return false; | ||
120 | |||
121 | debugOutput.appendLine(`Launching debug configuration${message}:`); | ||
122 | debugOutput.appendLine(JSON.stringify(debugConfig, null, 2)); | ||
123 | return vscode.debug.startDebugging(undefined, debugConfig); | ||
124 | } | ||