Skip to content

Commit fd3c10d

Browse files
committed
Auto merge of #17772 - Veykril:debug.ts, r=Veykril
internal: Reorganize debug.ts
2 parents ce73b7c + 7e94f3f commit fd3c10d

File tree

3 files changed

+187
-99
lines changed

3 files changed

+187
-99
lines changed

editors/code/src/debug.ts

Lines changed: 175 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,15 @@ import { Cargo } from "./toolchain";
77
import type { Ctx } from "./ctx";
88
import { prepareEnv } from "./run";
99
import { execute, isCargoRunnableArgs, unwrapUndefinable } from "./util";
10+
import type { Config } from "./config";
1011

1112
const debugOutput = vscode.window.createOutputChannel("Debug");
12-
type DebugConfigProvider = (
13-
runnable: ra.Runnable,
14-
runnableArgs: ra.CargoRunnableArgs,
15-
executable: string,
16-
env: Record<string, string>,
17-
sourceFileMap?: Record<string, string>,
18-
) => vscode.DebugConfiguration;
1913

2014
export async function makeDebugConfig(ctx: Ctx, runnable: ra.Runnable): Promise<void> {
2115
const scope = ctx.activeRustEditor?.document.uri;
2216
if (!scope) return;
2317

24-
const debugConfig = await getDebugConfiguration(ctx, runnable);
18+
const debugConfig = await getDebugConfiguration(ctx.config, runnable, false);
2519
if (!debugConfig) return;
2620

2721
const wsLaunchSection = vscode.workspace.getConfiguration("launch", scope);
@@ -57,7 +51,7 @@ export async function startDebugSession(ctx: Ctx, runnable: ra.Runnable): Promis
5751
message = " (from launch.json)";
5852
debugOutput.clear();
5953
} else {
60-
debugConfig = await getDebugConfiguration(ctx, runnable);
54+
debugConfig = await getDebugConfiguration(ctx.config, runnable);
6155
}
6256

6357
if (!debugConfig) return false;
@@ -74,35 +68,35 @@ function createCommandLink(extensionId: string): string {
7468
}
7569

7670
async function getDebugConfiguration(
77-
ctx: Ctx,
71+
config: Config,
7872
runnable: ra.Runnable,
73+
inheritEnv: boolean = true,
7974
): Promise<vscode.DebugConfiguration | undefined> {
8075
if (!isCargoRunnableArgs(runnable.args)) {
8176
return;
8277
}
8378
const runnableArgs: ra.CargoRunnableArgs = runnable.args;
8479

85-
const editor = ctx.activeRustEditor;
86-
if (!editor) return;
80+
const debugOptions = config.debug;
8781

88-
const knownEngines: Record<string, DebugConfigProvider> = {
89-
"vadimcn.vscode-lldb": getCodeLldbDebugConfig,
90-
"ms-vscode.cpptools": getCCppDebugConfig,
91-
"webfreak.debug": getNativeDebugConfig,
92-
};
93-
const debugOptions = ctx.config.debug;
82+
let provider: null | KnownEnginesType = null;
9483

95-
let debugEngine = null;
9684
if (debugOptions.engine === "auto") {
97-
for (var engineId in knownEngines) {
98-
debugEngine = vscode.extensions.getExtension(engineId);
99-
if (debugEngine) break;
85+
for (const engineId in knownEngines) {
86+
const debugEngine = vscode.extensions.getExtension(engineId);
87+
if (debugEngine) {
88+
provider = knownEngines[engineId as keyof typeof knownEngines];
89+
break;
90+
}
10091
}
10192
} else if (debugOptions.engine) {
102-
debugEngine = vscode.extensions.getExtension(debugOptions.engine);
93+
const debugEngine = vscode.extensions.getExtension(debugOptions.engine);
94+
if (debugEngine && Object.keys(knownEngines).includes(debugOptions.engine)) {
95+
provider = knownEngines[debugOptions.engine as keyof typeof knownEngines];
96+
}
10397
}
10498

105-
if (!debugEngine) {
99+
if (!provider) {
106100
const commandCCpp: string = createCommandLink("ms-vscode.cpptools");
107101
const commandCodeLLDB: string = createCommandLink("vadimcn.vscode-lldb");
108102
const commandNativeDebug: string = createCommandLink("webfreak.debug");
@@ -116,7 +110,7 @@ async function getDebugConfiguration(
116110
}
117111

118112
debugOutput.clear();
119-
if (ctx.config.debug.openDebugPane) {
113+
if (config.debug.openDebugPane) {
120114
debugOutput.show(true);
121115
}
122116
// folder exists or RA is not active.
@@ -131,37 +125,36 @@ async function getDebugConfiguration(
131125
firstWorkspace;
132126

133127
const workspace = unwrapUndefinable(maybeWorkspace);
134-
const wsFolder = path.normalize(workspace.uri.fsPath);
128+
let wsFolder = path.normalize(workspace.uri.fsPath);
129+
if (os.platform() === "win32") {
130+
// in windows, the drive letter can vary in casing for VSCode, so we gotta normalize that first
131+
wsFolder = wsFolder.replace(/^[a-z]:\\/, (c) => c.toUpperCase());
132+
}
133+
135134
const workspaceQualifier = isMultiFolderWorkspace ? `:${workspace.name}` : "";
136135
function simplifyPath(p: string): string {
136+
// in windows, the drive letter can vary in casing for VSCode, so we gotta normalize that first
137+
if (os.platform() === "win32") {
138+
p = p.replace(/^[a-z]:\\/, (c) => c.toUpperCase());
139+
}
137140
// see https://github.com/rust-lang/rust-analyzer/pull/5513#issuecomment-663458818 for why this is needed
138141
return path.normalize(p).replace(wsFolder, `\${workspaceFolder${workspaceQualifier}}`);
139142
}
140143

141-
const env = prepareEnv(runnable.label, runnableArgs, ctx.config.runnablesExtraEnv);
144+
const env = prepareEnv(inheritEnv, runnable.label, runnableArgs, config.runnablesExtraEnv);
142145
const executable = await getDebugExecutable(runnableArgs, env);
143146
let sourceFileMap = debugOptions.sourceFileMap;
144147
if (sourceFileMap === "auto") {
145148
sourceFileMap = {};
146-
const sysroot = env["RUSTC_TOOLCHAIN"];
147-
if (sysroot) {
148-
// let's try to use the default toolchain
149-
const data = await execute(`rustc -V -v`, { cwd: wsFolder, env });
150-
const rx = /commit-hash:\s(.*)$/m;
151-
152-
const commitHash = rx.exec(data)?.[1];
153-
if (commitHash) {
154-
const rustlib = path.normalize(sysroot + "/lib/rustlib/src/rust");
155-
sourceFileMap[`/rustc/${commitHash}/`] = rustlib;
156-
}
157-
}
149+
await discoverSourceFileMap(sourceFileMap, env, wsFolder);
158150
}
159151

160-
const provider = unwrapUndefinable(knownEngines[debugEngine.id]);
161-
const debugConfig = provider(
152+
const debugConfig = getDebugConfig(
153+
provider,
154+
simplifyPath,
162155
runnable,
163156
runnableArgs,
164-
simplifyPath(executable),
157+
executable,
165158
env,
166159
sourceFileMap,
167160
);
@@ -186,6 +179,92 @@ async function getDebugConfiguration(
186179
return debugConfig;
187180
}
188181

182+
async function discoverSourceFileMap(
183+
sourceFileMap: Record<string, string>,
184+
env: Record<string, string>,
185+
cwd: string,
186+
) {
187+
const sysroot = env["RUSTC_TOOLCHAIN"];
188+
if (sysroot) {
189+
// let's try to use the default toolchain
190+
const data = await execute(`rustc -V -v`, { cwd, env });
191+
const rx = /commit-hash:\s(.*)$/m;
192+
193+
const commitHash = rx.exec(data)?.[1];
194+
if (commitHash) {
195+
const rustlib = path.normalize(sysroot + "/lib/rustlib/src/rust");
196+
sourceFileMap[`/rustc/${commitHash}/`] = rustlib;
197+
}
198+
}
199+
}
200+
201+
type PropertyFetcher<Config, Input, Key extends keyof Config> = (
202+
input: Input,
203+
) => [Key, Config[Key]];
204+
205+
type DebugConfigProvider<Type extends string, DebugConfig extends BaseDebugConfig<Type>> = {
206+
executableProperty: keyof DebugConfig;
207+
environmentProperty: PropertyFetcher<DebugConfig, Record<string, string>, keyof DebugConfig>;
208+
runnableArgsProperty: PropertyFetcher<DebugConfig, ra.CargoRunnableArgs, keyof DebugConfig>;
209+
sourceFileMapProperty?: keyof DebugConfig;
210+
type: Type;
211+
additional?: Record<string, unknown>;
212+
};
213+
214+
type KnownEnginesType = (typeof knownEngines)[keyof typeof knownEngines];
215+
const knownEngines: {
216+
"vadimcn.vscode-lldb": DebugConfigProvider<"lldb", CodeLldbDebugConfig>;
217+
"ms-vscode.cpptools": DebugConfigProvider<"cppvsdbg" | "cppdbg", CCppDebugConfig>;
218+
"webfreak.debug": DebugConfigProvider<"gdb", NativeDebugConfig>;
219+
} = {
220+
"vadimcn.vscode-lldb": {
221+
type: "lldb",
222+
executableProperty: "program",
223+
environmentProperty: (env) => ["env", env],
224+
runnableArgsProperty: (runnableArgs: ra.CargoRunnableArgs) => [
225+
"args",
226+
runnableArgs.executableArgs,
227+
],
228+
sourceFileMapProperty: "sourceMap",
229+
additional: {
230+
sourceLanguages: ["rust"],
231+
},
232+
},
233+
"ms-vscode.cpptools": {
234+
type: os.platform() === "win32" ? "cppvsdbg" : "cppdbg",
235+
executableProperty: "program",
236+
environmentProperty: (env) => [
237+
"environment",
238+
Object.entries(env).map((entry) => ({
239+
name: entry[0],
240+
value: entry[1],
241+
})),
242+
],
243+
runnableArgsProperty: (runnableArgs: ra.CargoRunnableArgs) => [
244+
"args",
245+
runnableArgs.executableArgs,
246+
],
247+
sourceFileMapProperty: "sourceFileMap",
248+
additional: {
249+
osx: {
250+
MIMode: "lldb",
251+
},
252+
},
253+
},
254+
"webfreak.debug": {
255+
type: "gdb",
256+
executableProperty: "target",
257+
runnableArgsProperty: (runnableArgs: ra.CargoRunnableArgs) => [
258+
"arguments",
259+
quote(runnableArgs.executableArgs),
260+
],
261+
environmentProperty: (env) => ["env", env],
262+
additional: {
263+
valuesFormatting: "prettyPrinters",
264+
},
265+
},
266+
};
267+
189268
async function getDebugExecutable(
190269
runnableArgs: ra.CargoRunnableArgs,
191270
env: Record<string, string>,
@@ -197,71 +276,74 @@ async function getDebugExecutable(
197276
return executable;
198277
}
199278

200-
function getCCppDebugConfig(
201-
runnable: ra.Runnable,
202-
runnableArgs: ra.CargoRunnableArgs,
203-
executable: string,
204-
env: Record<string, string>,
205-
sourceFileMap?: Record<string, string>,
206-
): vscode.DebugConfiguration {
207-
return {
208-
type: os.platform() === "win32" ? "cppvsdbg" : "cppdbg",
209-
request: "launch",
210-
name: runnable.label,
211-
program: executable,
212-
args: runnableArgs.executableArgs,
213-
cwd: runnable.args.cwd || runnableArgs.workspaceRoot || ".",
214-
sourceFileMap,
215-
environment: Object.entries(env).map((entry) => ({
216-
name: entry[0],
217-
value: entry[1],
218-
})),
219-
// See https://github.com/rust-lang/rust-analyzer/issues/16901#issuecomment-2024486941
220-
osx: {
221-
MIMode: "lldb",
222-
},
223-
};
224-
}
279+
type BaseDebugConfig<type extends string> = {
280+
type: type;
281+
request: "launch";
282+
name: string;
283+
cwd: string;
284+
};
225285

226-
function getCodeLldbDebugConfig(
286+
function getDebugConfig(
287+
provider: KnownEnginesType,
288+
simplifyPath: (p: string) => string,
227289
runnable: ra.Runnable,
228290
runnableArgs: ra.CargoRunnableArgs,
229291
executable: string,
230292
env: Record<string, string>,
231293
sourceFileMap?: Record<string, string>,
232294
): vscode.DebugConfiguration {
295+
const {
296+
environmentProperty,
297+
executableProperty,
298+
runnableArgsProperty,
299+
type,
300+
additional,
301+
sourceFileMapProperty,
302+
} = provider;
303+
const [envProperty, envValue] = environmentProperty(env);
304+
const [argsProperty, argsValue] = runnableArgsProperty(runnableArgs);
233305
return {
234-
type: "lldb",
306+
type,
235307
request: "launch",
236308
name: runnable.label,
237-
program: executable,
238-
args: runnableArgs.executableArgs,
239-
cwd: runnable.args.cwd || runnableArgs.workspaceRoot || ".",
240-
sourceMap: sourceFileMap,
241-
sourceLanguages: ["rust"],
242-
env,
309+
cwd: simplifyPath(runnable.args.cwd || runnableArgs.workspaceRoot || "."),
310+
[executableProperty]: simplifyPath(executable),
311+
[envProperty]: envValue,
312+
[argsProperty]: argsValue,
313+
...(sourceFileMapProperty ? { [sourceFileMapProperty]: sourceFileMap } : {}),
314+
...additional,
243315
};
244316
}
245317

246-
function getNativeDebugConfig(
247-
runnable: ra.Runnable,
248-
runnableArgs: ra.CargoRunnableArgs,
249-
executable: string,
250-
env: Record<string, string>,
251-
_sourceFileMap?: Record<string, string>,
252-
): vscode.DebugConfiguration {
253-
return {
254-
type: "gdb",
255-
request: "launch",
256-
name: runnable.label,
257-
target: executable,
258-
// See https://github.com/WebFreak001/code-debug/issues/359
259-
arguments: quote(runnableArgs.executableArgs),
260-
cwd: runnable.args.cwd || runnableArgs.workspaceRoot || ".",
261-
env,
262-
valuesFormatting: "prettyPrinters",
318+
type CCppDebugConfig = {
319+
program: string;
320+
args: string[];
321+
sourceFileMap: Record<string, string> | undefined;
322+
environment: {
323+
name: string;
324+
value: string;
325+
}[];
326+
// See https://github.com/rust-lang/rust-analyzer/issues/16901#issuecomment-2024486941
327+
osx: {
328+
MIMode: "lldb";
263329
};
264-
}
330+
} & BaseDebugConfig<"cppvsdbg" | "cppdbg">;
331+
332+
type CodeLldbDebugConfig = {
333+
program: string;
334+
args: string[];
335+
sourceMap: Record<string, string> | undefined;
336+
sourceLanguages: ["rust"];
337+
env: Record<string, string>;
338+
} & BaseDebugConfig<"lldb">;
339+
340+
type NativeDebugConfig = {
341+
target: string;
342+
// See https://github.com/WebFreak001/code-debug/issues/359
343+
arguments: string;
344+
env: Record<string, string>;
345+
valuesFormatting: "prettyPrinters";
346+
} & BaseDebugConfig<"gdb">;
265347

266348
// Based on https://github.com/ljharb/shell-quote/blob/main/quote.js
267349
function quote(xs: string[]) {

0 commit comments

Comments
 (0)