Skip to content

Commit 155f060

Browse files
committed
"rust-analyzer.debug" command
1 parent eb892d7 commit 155f060

File tree

4 files changed

+144
-106
lines changed

4 files changed

+144
-106
lines changed

editors/code/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@
120120
"title": "Run",
121121
"category": "Rust Analyzer"
122122
},
123+
{
124+
"command": "rust-analyzer.debug",
125+
"title": "Debug",
126+
"category": "Rust Analyzer"
127+
},
123128
{
124129
"command": "rust-analyzer.analyzerStatus",
125130
"title": "Status",

editors/code/src/commands/runnables.ts

Lines changed: 43 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,46 @@
11
import * as vscode from 'vscode';
22
import * as lc from 'vscode-languageclient';
33
import * as ra from '../rust-analyzer-api';
4-
import * as os from "os";
54

65
import { Ctx, Cmd } from '../ctx';
7-
import { Cargo } from '../cargo';
6+
import { startDebugSession } from '../debug';
7+
8+
async function selectRunnable(ctx: Ctx, prevRunnable: RunnableQuickPick | undefined): Promise<RunnableQuickPick | undefined> {
9+
const editor = ctx.activeRustEditor;
10+
const client = ctx.client;
11+
if (!editor || !client) return;
12+
13+
const textDocument: lc.TextDocumentIdentifier = {
14+
uri: editor.document.uri.toString(),
15+
};
16+
17+
const runnables = await client.sendRequest(ra.runnables, {
18+
textDocument,
19+
position: client.code2ProtocolConverter.asPosition(
20+
editor.selection.active,
21+
),
22+
});
23+
const items: RunnableQuickPick[] = [];
24+
if (prevRunnable) {
25+
items.push(prevRunnable);
26+
}
27+
for (const r of runnables) {
28+
if (
29+
prevRunnable &&
30+
JSON.stringify(prevRunnable.runnable) === JSON.stringify(r)
31+
) {
32+
continue;
33+
}
34+
items.push(new RunnableQuickPick(r));
35+
}
36+
return await vscode.window.showQuickPick(items);
37+
}
838

939
export function run(ctx: Ctx): Cmd {
1040
let prevRunnable: RunnableQuickPick | undefined;
1141

1242
return async () => {
13-
const editor = ctx.activeRustEditor;
14-
const client = ctx.client;
15-
if (!editor || !client) return;
16-
17-
const textDocument: lc.TextDocumentIdentifier = {
18-
uri: editor.document.uri.toString(),
19-
};
20-
21-
const runnables = await client.sendRequest(ra.runnables, {
22-
textDocument,
23-
position: client.code2ProtocolConverter.asPosition(
24-
editor.selection.active,
25-
),
26-
});
27-
const items: RunnableQuickPick[] = [];
28-
if (prevRunnable) {
29-
items.push(prevRunnable);
30-
}
31-
for (const r of runnables) {
32-
if (
33-
prevRunnable &&
34-
JSON.stringify(prevRunnable.runnable) === JSON.stringify(r)
35-
) {
36-
continue;
37-
}
38-
items.push(new RunnableQuickPick(r));
39-
}
40-
const item = await vscode.window.showQuickPick(items);
43+
const item = await selectRunnable(ctx, prevRunnable);
4144
if (!item) return;
4245

4346
item.detail = 'rerun';
@@ -64,88 +67,22 @@ export function runSingle(ctx: Ctx): Cmd {
6467
};
6568
}
6669

67-
function getLldbDebugConfig(config: ra.Runnable, executable: string, sourceFileMap?: Record<string, string>): vscode.DebugConfiguration {
68-
return {
69-
type: "lldb",
70-
request: "launch",
71-
name: config.label,
72-
program: executable,
73-
args: config.extraArgs,
74-
cwd: config.cwd,
75-
sourceMap: sourceFileMap,
76-
sourceLanguages: ["rust"]
77-
};
78-
}
79-
80-
function getCppvsDebugConfig(config: ra.Runnable, executable: string, sourceFileMap?: Record<string, string>): vscode.DebugConfiguration {
81-
return {
82-
type: (os.platform() === "win32") ? "cppvsdbg" : 'cppdbg',
83-
request: "launch",
84-
name: config.label,
85-
program: executable,
86-
args: config.extraArgs,
87-
cwd: config.cwd,
88-
sourceFileMap: sourceFileMap,
89-
};
90-
}
70+
export function debug(ctx: Ctx): Cmd {
71+
let prevDebuggee: RunnableQuickPick | undefined;
9172

92-
const debugOutput = vscode.window.createOutputChannel("Debug");
93-
94-
async function getDebugExecutable(config: ra.Runnable): Promise<string> {
95-
const cargo = new Cargo(config.cwd || '.', debugOutput);
96-
const executable = await cargo.executableFromArgs(config.args);
73+
return async () => {
74+
const item = await selectRunnable(ctx, prevDebuggee);
75+
if (!item) return;
9776

98-
// if we are here, there were no compilation errors.
99-
return executable;
77+
item.detail = 'restart';
78+
prevDebuggee = item;
79+
return await startDebugSession(ctx, item.runnable);
80+
};
10081
}
10182

102-
type DebugConfigProvider = (config: ra.Runnable, executable: string, sourceFileMap?: Record<string, string>) => vscode.DebugConfiguration;
103-
10483
export function debugSingle(ctx: Ctx): Cmd {
10584
return async (config: ra.Runnable) => {
106-
const editor = ctx.activeRustEditor;
107-
if (!editor) return;
108-
109-
const knownEngines: Record<string, DebugConfigProvider> = {
110-
"vadimcn.vscode-lldb": getLldbDebugConfig,
111-
"ms-vscode.cpptools": getCppvsDebugConfig
112-
};
113-
const debugOptions = ctx.config.debug;
114-
115-
let debugEngine = null;
116-
if (debugOptions.engine === "auto") {
117-
for (var engineId in knownEngines) {
118-
debugEngine = vscode.extensions.getExtension(engineId);
119-
if (debugEngine) break;
120-
}
121-
}
122-
else {
123-
debugEngine = vscode.extensions.getExtension(debugOptions.engine);
124-
}
125-
126-
if (!debugEngine) {
127-
vscode.window.showErrorMessage(`Install [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb)`
128-
+ ` or [MS C++ tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) extension for debugging.`);
129-
return;
130-
}
131-
132-
debugOutput.clear();
133-
if (ctx.config.debug.openUpDebugPane) {
134-
debugOutput.show(true);
135-
}
136-
137-
const executable = await getDebugExecutable(config);
138-
const debugConfig = knownEngines[debugEngine.id](config, executable, debugOptions.sourceFileMap);
139-
if (debugConfig.type in debugOptions.engineSettings) {
140-
const settingsMap = (debugOptions.engineSettings as any)[debugConfig.type];
141-
for (var key in settingsMap) {
142-
debugConfig[key] = settingsMap[key];
143-
}
144-
}
145-
146-
debugOutput.appendLine("Launching debug configuration:");
147-
debugOutput.appendLine(JSON.stringify(debugConfig, null, 2));
148-
return vscode.debug.startDebugging(undefined, debugConfig);
85+
await startDebugSession(ctx, config);
14986
};
15087
}
15188

editors/code/src/debug.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import * as os from "os";
2+
import * as vscode from 'vscode';
3+
import * as ra from './rust-analyzer-api';
4+
5+
import { Cargo } from './cargo';
6+
import { Ctx } from "./ctx";
7+
8+
const debugOutput = vscode.window.createOutputChannel("Debug");
9+
type DebugConfigProvider = (config: ra.Runnable, executable: string, sourceFileMap?: Record<string, string>) => vscode.DebugConfiguration;
10+
11+
function getLldbDebugConfig(config: ra.Runnable, executable: string, sourceFileMap?: Record<string, string>): vscode.DebugConfiguration {
12+
return {
13+
type: "lldb",
14+
request: "launch",
15+
name: config.label,
16+
program: executable,
17+
args: config.extraArgs,
18+
cwd: config.cwd,
19+
sourceMap: sourceFileMap,
20+
sourceLanguages: ["rust"]
21+
};
22+
}
23+
24+
function getCppvsDebugConfig(config: ra.Runnable, executable: string, sourceFileMap?: Record<string, string>): vscode.DebugConfiguration {
25+
return {
26+
type: (os.platform() === "win32") ? "cppvsdbg" : "cppdbg",
27+
request: "launch",
28+
name: config.label,
29+
program: executable,
30+
args: config.extraArgs,
31+
cwd: config.cwd,
32+
sourceFileMap: sourceFileMap,
33+
};
34+
}
35+
36+
async function getDebugExecutable(config: ra.Runnable): Promise<string> {
37+
const cargo = new Cargo(config.cwd || '.', debugOutput);
38+
const executable = await cargo.executableFromArgs(config.args);
39+
40+
// if we are here, there were no compilation errors.
41+
return executable;
42+
}
43+
44+
export async function getDebugConfiguration(ctx: Ctx, config: ra.Runnable): Promise<vscode.DebugConfiguration | undefined> {
45+
const editor = ctx.activeRustEditor;
46+
if (!editor) return;
47+
48+
const knownEngines: Record<string, DebugConfigProvider> = {
49+
"vadimcn.vscode-lldb": getLldbDebugConfig,
50+
"ms-vscode.cpptools": getCppvsDebugConfig
51+
};
52+
const debugOptions = ctx.config.debug;
53+
54+
let debugEngine = null;
55+
if (debugOptions.engine === "auto") {
56+
for (var engineId in knownEngines) {
57+
debugEngine = vscode.extensions.getExtension(engineId);
58+
if (debugEngine) break;
59+
}
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 executable = await getDebugExecutable(config);
77+
const debugConfig = knownEngines[debugEngine.id](config, executable, debugOptions.sourceFileMap);
78+
if (debugConfig.type in debugOptions.engineSettings) {
79+
const settingsMap = (debugOptions.engineSettings as any)[debugConfig.type];
80+
for (var key in settingsMap) {
81+
debugConfig[key] = settingsMap[key];
82+
}
83+
}
84+
85+
return debugConfig;
86+
}
87+
88+
export async function startDebugSession(ctx: Ctx, config: ra.Runnable): Promise<boolean> {
89+
const debugConfig = await getDebugConfiguration(ctx, config);
90+
if (!debugConfig) return false;
91+
92+
debugOutput.appendLine("Launching debug configuration:");
93+
debugOutput.appendLine(JSON.stringify(debugConfig, null, 2));
94+
return vscode.debug.startDebugging(undefined, debugConfig);
95+
}

editors/code/src/main.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ export async function activate(context: vscode.ExtensionContext) {
7777
ctx.registerCommand('syntaxTree', commands.syntaxTree);
7878
ctx.registerCommand('expandMacro', commands.expandMacro);
7979
ctx.registerCommand('run', commands.run);
80+
ctx.registerCommand('debug', commands.debug);
8081

8182
defaultOnEnter.dispose();
8283
ctx.registerCommand('onEnter', commands.onEnter);

0 commit comments

Comments
 (0)