1+ import assert from 'assert' ;
12import * as path from 'path' ;
23import * as vscode from 'vscode' ;
3- import { ContextClients } from './clients' ;
4- import { getExecutables , getMains } from './helpers' ;
5- import assert from 'assert' ;
6- import { exec } from 'child_process' ;
4+ import { contextClients } from './extension' ;
5+ import { getExecutables , getMains , getProjectFile } from './helpers' ;
76
87/**
98 * Ada Configuration for a debug session
@@ -23,14 +22,14 @@ interface AdaConfig extends vscode.DebugConfiguration {
2322}
2423
2524/**
26- * Initialize debugging on an ada project by creating a default configuration in launch.json
27- * @param ctx - the ada extension context
28- * @param clients - the language clients
25+ * Initialize debugging support for Ada projects.
26+ *
27+ * @param ctx - the Ada extension context
2928 * @returns the debug configuration provider
3029 */
31- export function initializeDebugging ( ctx : vscode . ExtensionContext , clients : ContextClients ) {
30+ export function initializeDebugging ( ctx : vscode . ExtensionContext ) {
3231 // Instantiate a DebugConfigProvider for Ada and register it.
33- const provider = new AdaDebugConfigProvider ( clients ) ;
32+ const provider = new AdaDebugConfigProvider ( ) ;
3433
3534 // This provider is registered for the 'ada' debugger type. It means that
3635 // it is triggered either when a configuration with type 'ada' is launched,
@@ -55,7 +54,8 @@ export function initializeDebugging(ctx: vscode.ExtensionContext, clients: Conte
5554/**
5655 * Initialize a debug configuration based on 'cppdbg' for the given executable
5756 * if specified. Otherwise the program field includes
58- * ${command:ada.getOrAskForProgram} to prompt the User for an executable to debug.
57+ * $\{command:ada.getOrAskForProgram\} to prompt the User for an executable to
58+ * debug.
5959 *
6060 * @param program - the executable to debug (optional)
6161 * @returns an AdaConfig
@@ -88,13 +88,8 @@ function initializeConfig(program?: string): AdaConfig {
8888}
8989
9090export class AdaDebugConfigProvider implements vscode . DebugConfigurationProvider {
91- private readonly clients : ContextClients ;
9291 public static adaConfigType = 'cppdbg' ;
9392
94- constructor ( clients : ContextClients ) {
95- this . clients = clients ;
96- }
97-
9893 async provideDebugConfigurations (
9994 folder : vscode . WorkspaceFolder | undefined ,
10095 _token ?: vscode . CancellationToken | undefined
@@ -110,36 +105,42 @@ export class AdaDebugConfigProvider implements vscode.DebugConfigurationProvider
110105
111106 if ( folder != undefined ) {
112107 // Offer a list of known Mains from the project
113- const mains = await getMains ( this . clients . adaClient ) ;
114- const execs = await getExecutables ( this . clients . adaClient ) ;
108+ const mains = await getMains ( contextClients . adaClient ) ;
109+ const execs = await getExecutables ( contextClients . adaClient ) ;
115110 assert (
116111 execs . length == mains . length ,
117112 `The ALS returned mains.length = ${ mains . length } and ` +
118113 `execs.length = ${ execs . length } ` +
119114 `when they should be equal`
120115 ) ;
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 ) ,
116+
117+ if ( mains . length > 0 ) {
118+ const quickpick = [ ] ;
119+ for ( let i = 0 ; i < mains . length ; i ++ ) {
120+ const exec = execs [ i ] ;
121+ const main = mains [ i ] ;
122+ quickpick . push ( {
123+ label : vscode . workspace . asRelativePath ( main ) ,
124+ description : 'Generate the associated launch configuration' ,
125+ execPath : vscode . workspace . asRelativePath ( exec ) ,
126+ } ) ;
127+ }
128+ const selectedProgram = await vscode . window . showQuickPick ( quickpick , {
129+ placeHolder : 'Select a main to create a launch configuration' ,
129130 } ) ;
130- }
131- const selectedProgram = await vscode . window . showQuickPick ( quickpick , {
132- placeHolder : 'Select a main to create a launch configuration' ,
133- } ) ;
134- if ( selectedProgram ) {
135- // The cppdbg debug configuration exepects the executable to be
136- // a full path rather than a path relative to the specified
137- // cwd. That is why we include ${workspaceFolder}.
138- const configuration = initializeConfig (
139- `\${workspaceFolder}/${ selectedProgram . execPath } `
140- ) ;
141- configs . push ( configuration ) ;
131+ if ( selectedProgram ) {
132+ // The cppdbg debug configuration exepects the executable to be
133+ // a full path rather than a path relative to the specified
134+ // cwd. That is why we include ${workspaceFolder}.
135+ const configuration = initializeConfig (
136+ `\${workspaceFolder}/${ selectedProgram . execPath } `
137+ ) ;
138+ configs . push ( configuration ) ;
139+ } else {
140+ return Promise . reject ( 'Cancelled' ) ;
141+ }
142142 } else {
143+ void warnAboutNoMains ( ) ;
143144 return Promise . reject ( 'Cancelled' ) ;
144145 }
145146 }
@@ -171,56 +172,79 @@ export class AdaDebugConfigProvider implements vscode.DebugConfigurationProvider
171172 return debugConfiguration ;
172173 }
173174
174- const exec = await this . getOrAskForProgram ( ) ;
175+ const exec = await getOrAskForProgram ( ) ;
175176
176177 if ( exec ) {
177178 return initializeConfig ( `\${workspaceFolder}/${ exec } ` ) ;
178179 }
179180
180181 return undefined ;
181182 }
183+ }
182184
183- /**
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.
190- *
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.
199- */
200- async getOrAskForProgram ( ) : Promise < string | undefined > {
201- const mains = await getMains ( this . clients . adaClient ) ;
202- const execs = await getExecutables ( this . clients . adaClient ) ;
185+ /**
186+ * GDB default setup options
187+ */
188+ const setupCmd = [
189+ {
190+ description : 'Catch all Ada exceptions' ,
191+ text : 'catch exception' ,
192+ ignoreFailures : true ,
193+ } ,
194+ {
195+ description : 'Enable pretty-printing for gdb' ,
196+ text : '-enable-pretty-printing' ,
197+ ignoreFailures : true ,
198+ } ,
199+ {
200+ description : 'Set Disassembly Flavor to Intel' ,
201+ text : '-gdb-set disassembly-flavor intel' ,
202+ ignoreFailures : true ,
203+ } ,
204+ ] ;
203205
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- ) ;
206+ /**
207+ * Get an executable based on the project and the current open file.
208+ *
209+ * If the project only defines one main, it is returned immediately.
210+ *
211+ * If the project defines multiple mains, and if the current open file
212+ * matches one of the mains, the corresponding executable is returned.
213+ *
214+ * Otherwise, the list of mains is offered to the user as a QuickPicker to
215+ * choose a main file. The executable corresponding to the selected main
216+ * file is returned.
217+ *
218+ * Note that paths are returned relative to the workspace.
219+ *
220+ * @returns the path of the executable to debug *relative to the workspace*,
221+ * or *undefined* if no selection was made.
222+ */
223+ async function getOrAskForProgram ( ) : Promise < string | undefined > {
224+ const mains = await getMains ( contextClients . adaClient ) ;
225+ const execs = await getExecutables ( contextClients . adaClient ) ;
210226
211- if ( execs . length == 1 ) return vscode . workspace . asRelativePath ( execs [ 0 ] ) ;
227+ assert (
228+ execs . length == mains . length ,
229+ `The ALS returned mains.length = ${ mains . length } and ` +
230+ `execs.length = ${ execs . length } ` +
231+ `when they should be equal`
232+ ) ;
212233
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 ;
216- if ( file != undefined ) {
217- for ( let i = 0 ; i < mains . length ; i ++ ) {
218- if ( file == mains [ i ] ) {
219- return vscode . workspace . asRelativePath ( execs [ i ] ) ;
220- }
234+ if ( execs . length == 1 ) return vscode . workspace . asRelativePath ( execs [ 0 ] ) ;
235+
236+ // Check if the current file matches one of the mains of the project. If
237+ // so, use it.
238+ const file = vscode . window . activeTextEditor ?. document . uri . path ;
239+ if ( file != undefined ) {
240+ for ( let i = 0 ; i < mains . length ; i ++ ) {
241+ if ( file == mains [ i ] ) {
242+ return vscode . workspace . asRelativePath ( execs [ i ] ) ;
221243 }
222244 }
245+ }
223246
247+ if ( mains . length > 0 ) {
224248 // There is no current file or it matches no known Main of the project,
225249 // so we offer all Mains in a QuickPicker for the user to choose from.
226250 const quickpick = [ ] ;
@@ -239,28 +263,16 @@ export class AdaDebugConfigProvider implements vscode.DebugConfigurationProvider
239263 if ( selectedProgram ) {
240264 return selectedProgram . execRelPath ;
241265 }
242-
243- return undefined ;
266+ } else {
267+ void warnAboutNoMains ( ) ;
244268 }
245- }
246269
247- /**
248- * GDB default setup options
249- */
250- const setupCmd = [
251- {
252- description : 'Catch all Ada exceptions' ,
253- text : 'catch exception' ,
254- ignoreFailures : true ,
255- } ,
256- {
257- description : 'Enable pretty-printing for gdb' ,
258- text : '-enable-pretty-printing' ,
259- ignoreFailures : true ,
260- } ,
261- {
262- description : 'Set Disassembly Flavor to Intel' ,
263- text : '-gdb-set disassembly-flavor intel' ,
264- ignoreFailures : true ,
265- } ,
266- ] ;
270+ return undefined ;
271+ }
272+ async function warnAboutNoMains ( ) {
273+ void vscode . window . showWarningMessage (
274+ `Your Ada project file '${ await getProjectFile (
275+ contextClients . adaClient
276+ ) } ' does not define a 'Main' attribute. ` + 'Debugging is not possible without it.'
277+ ) ;
278+ }
0 commit comments