Skip to content

Commit b3f055d

Browse files
committed
Factorize code that asks for the executable to debug
1 parent 2dacdd1 commit b3f055d

File tree

3 files changed

+71
-58
lines changed

3 files changed

+71
-58
lines changed

integration/vscode/ada/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,7 @@
600600
"type": "cppdbg",
601601
"request": "launch",
602602
"name": "Ada: Debugger Launch",
603-
"program": "^\"\\${workspaceFolder}/\\${command:ada.askForProgram}\"",
603+
"program": "^\"\\${workspaceFolder}/\\${command:ada.getOrAskForProgram}\"",
604604
"args": [],
605605
"cwd": "^\"\\${workspaceFolder}\"",
606606
"stopAtEntry": false,
@@ -609,7 +609,7 @@
609609
}
610610
],
611611
"variables": {
612-
"AskForProgram": "ada.askForProgram"
612+
"AskForProgram": "ada.getOrAskForProgram"
613613
}
614614
}
615615
]

integration/vscode/ada/src/commands.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ export function registerCommands(
3333
// This is a hidden command that gets called in the default debug
3434
// configuration snippet that gets offered in the launch.json file.
3535
context.subscriptions.push(
36-
vscode.commands.registerCommand('ada.askForProgram', async () => {
37-
const p = await debug.askForProgram();
36+
vscode.commands.registerCommand('ada.getOrAskForProgram', async () => {
37+
const p = await debug.getOrAskForProgram();
3838
return p;
3939
})
4040
);

integration/vscode/ada/src/debugConfigProvider.ts

Lines changed: 67 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import * as path from 'path';
22
import * as vscode from 'vscode';
33
import { ContextClients } from './clients';
44
import { getExecutables, getMains } from './helpers';
5+
import assert from 'assert';
6+
import { exec } from 'child_process';
57

68
/**
79
* Ada Configuration for a debug session
@@ -53,7 +55,7 @@ export function initializeDebugging(ctx: vscode.ExtensionContext, clients: Conte
5355
/**
5456
* Initialize a debug configuration based on 'cppdbg' for the given executable
5557
* if specified. Otherwise the program field includes
56-
* ${command:ada.askForProgram} to prompt the User for an executable to debug.
58+
* ${command:ada.getOrAskForProgram} to prompt the User for an executable to debug.
5759
*
5860
* @param program - the executable to debug (optional)
5961
* @returns an AdaConfig
@@ -67,7 +69,7 @@ function initializeConfig(program?: string): AdaConfig {
6769
request: 'launch',
6870
targetArchitecture: process.arch,
6971
cwd: '${workspaceFolder}',
70-
program: '${workspaceFolder}/${command:ada.askForProgram}',
72+
program: '${workspaceFolder}/${command:ada.getOrAskForProgram}',
7173
stopAtEntry: false,
7274
externalConsole: false,
7375
args: [],
@@ -108,20 +110,33 @@ export class AdaDebugConfigProvider implements vscode.DebugConfigurationProvider
108110

109111
if (folder != undefined) {
110112
// Offer a list of known Mains from the project
113+
const mains = await getMains(this.clients.adaClient);
111114
const execs = await getExecutables(this.clients.adaClient);
112-
const quickpick = execs.map((e) => ({
113-
label: vscode.workspace.asRelativePath(e),
114-
description: 'Generate the associated configuration',
115-
}));
115+
assert(
116+
execs.length == mains.length,
117+
`The ALS returned mains.length = ${mains.length} and ` +
118+
`execs.length = ${execs.length}` +
119+
`when they should be equal`
120+
);
121+
const quickpick = [];
122+
for (let i = 0; i < mains.length; i++) {
123+
const exec = execs[i];
124+
const main = mains[i];
125+
quickpick.push({
126+
label: vscode.workspace.asRelativePath(main),
127+
description: 'Generate the associated launch configuration',
128+
execPath: vscode.workspace.asRelativePath(exec),
129+
});
130+
}
116131
const selectedProgram = await vscode.window.showQuickPick(quickpick, {
117-
placeHolder: 'Select a program to debug',
132+
placeHolder: 'Select a main to create a launch configuration',
118133
});
119134
if (selectedProgram) {
120135
// The cppdbg debug configuration exepects the executable to be
121136
// a full path rather than a path relative to the specified
122137
// cwd. That is why we include ${workspaceFolder}.
123138
const configuration = initializeConfig(
124-
`\${workspaceFolder}/${selectedProgram.label}`
139+
`\${workspaceFolder}/${selectedProgram.execPath}`
125140
);
126141
configs.push(configuration);
127142
} else {
@@ -156,75 +171,73 @@ export class AdaDebugConfigProvider implements vscode.DebugConfigurationProvider
156171
return debugConfiguration;
157172
}
158173

159-
// We are operating without a launch.json. So we try to determine the
160-
// program to debug dynamically. If the current editor matches one of
161-
// the Mains of the project, then debug the corresponding executable.
162-
const file = vscode.window.activeTextEditor?.document.uri.path;
163-
if (file != undefined) {
164-
const mains = await getMains(this.clients.adaClient);
165-
const execs = await getExecutables(this.clients.adaClient);
166-
for (let i = 0; i < mains.length; i++) {
167-
if (file == mains[i]) {
168-
const config = initializeConfig(execs[i]);
169-
return config;
170-
}
171-
}
172-
}
174+
const exec = await this.getOrAskForProgram();
173175

174-
// There is no current file or it matches no known Main of the project,
175-
// so we offer all Main in a QuickPicker for the user to choose from.
176-
const quickpick = execs.map((e) => ({
177-
label: vscode.workspace.asRelativePath(e),
178-
description: 'Run & Debug',
179-
fullPath: e,
180-
}));
181-
const selectedProgram = await vscode.window.showQuickPick(quickpick, {
182-
placeHolder: 'Select an executable to debug',
183-
});
184-
if (selectedProgram) {
185-
// This is an in-memory configuration that will not be stored. It's
186-
// okay to use the full path directly instead of using
187-
// ${workspaceFolder}.
188-
const configuration = initializeConfig(selectedProgram.fullPath);
189-
return configuration;
176+
if (exec) {
177+
return initializeConfig(`\${workspaceFolder}/${exec}`);
190178
}
191179

192180
return undefined;
193181
}
194182

195183
/**
196-
* Consults the project for a list of Mains. If only one is defined, it is
197-
* returned immediately. If multiple ones are defines, a QuickPicker is
198-
* given to the User to choose and executable to debug or to specify in a
199-
* debug configuration.
184+
* Get an executable based on the project and the current open file.
185+
*
186+
* If the project only defines one main, it is returned immediately.
187+
*
188+
* If the project defines multiple mains, and if the current open file
189+
* matches one of the mains, the corresponding executable is returned.
200190
*
201-
* @returns the path of the executable to debug relative to the workspace
191+
* Otherwise, the list of mains is offered to the user as a QuickPicker to
192+
* choose a main file. The executable corresponding to the selected main
193+
* file is returned.
194+
*
195+
* Note that paths are returned relative to the workspace.
196+
*
197+
* @returns the path of the executable to debug *relative to the workspace*,
198+
* or *undefined* if no selection was made.
202199
*/
203-
async askForProgram(): Promise<string | undefined> {
204-
const file = vscode.window.activeTextEditor?.document.uri.path;
200+
async getOrAskForProgram(): Promise<string | undefined> {
205201
const mains = await getMains(this.clients.adaClient);
206202
const execs = await getExecutables(this.clients.adaClient);
207203

204+
assert(
205+
execs.length == mains.length,
206+
`The ALS returned mains.length = ${mains.length} and ` +
207+
`execs.length = ${execs.length}` +
208+
`when they should be equal`
209+
);
210+
208211
if (execs.length == 1) return vscode.workspace.asRelativePath(execs[0]);
209212

213+
// Check if the current file matches one of the mains of the project. If
214+
// so, use it.
215+
const file = vscode.window.activeTextEditor?.document.uri.path;
210216
if (file != undefined) {
211217
for (let i = 0; i < mains.length; i++) {
212218
if (file == mains[i]) {
213-
return execs[i];
219+
return vscode.workspace.asRelativePath(execs[i]);
214220
}
215221
}
216222
}
217-
const quickpick = mains.map((e) => ({
218-
label: vscode.workspace.asRelativePath(e),
219-
description: 'Run & Debug',
220-
main: e,
221-
}));
223+
224+
// There is no current file or it matches no known Main of the project,
225+
// so we offer all Mains in a QuickPicker for the user to choose from.
226+
const quickpick = [];
227+
for (let i = 0; i < mains.length; i++) {
228+
const exec = execs[i];
229+
const main = mains[i];
230+
quickpick.push({
231+
label: vscode.workspace.asRelativePath(main),
232+
description: 'Select for debugging',
233+
execRelPath: vscode.workspace.asRelativePath(exec),
234+
});
235+
}
222236
const selectedProgram = await vscode.window.showQuickPick(quickpick, {
223-
placeHolder: 'Select a main file',
237+
placeHolder: 'Select a main file to debug',
224238
});
225239
if (selectedProgram) {
226-
const index = mains.indexOf(selectedProgram.main);
227-
return vscode.workspace.asRelativePath(execs[index]);
240+
return selectedProgram.execRelPath;
228241
}
229242

230243
return undefined;

0 commit comments

Comments
 (0)