1
+ import assert from 'assert' ;
1
2
import * as path from 'path' ;
2
3
import * 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' ;
7
6
8
7
/**
9
8
* Ada Configuration for a debug session
@@ -23,14 +22,14 @@ interface AdaConfig extends vscode.DebugConfiguration {
23
22
}
24
23
25
24
/**
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
29
28
* @returns the debug configuration provider
30
29
*/
31
- export function initializeDebugging ( ctx : vscode . ExtensionContext , clients : ContextClients ) {
30
+ export function initializeDebugging ( ctx : vscode . ExtensionContext ) {
32
31
// Instantiate a DebugConfigProvider for Ada and register it.
33
- const provider = new AdaDebugConfigProvider ( clients ) ;
32
+ const provider = new AdaDebugConfigProvider ( ) ;
34
33
35
34
// This provider is registered for the 'ada' debugger type. It means that
36
35
// it is triggered either when a configuration with type 'ada' is launched,
@@ -55,7 +54,8 @@ export function initializeDebugging(ctx: vscode.ExtensionContext, clients: Conte
55
54
/**
56
55
* Initialize a debug configuration based on 'cppdbg' for the given executable
57
56
* 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.
59
59
*
60
60
* @param program - the executable to debug (optional)
61
61
* @returns an AdaConfig
@@ -88,13 +88,8 @@ function initializeConfig(program?: string): AdaConfig {
88
88
}
89
89
90
90
export class AdaDebugConfigProvider implements vscode . DebugConfigurationProvider {
91
- private readonly clients : ContextClients ;
92
91
public static adaConfigType = 'cppdbg' ;
93
92
94
- constructor ( clients : ContextClients ) {
95
- this . clients = clients ;
96
- }
97
-
98
93
async provideDebugConfigurations (
99
94
folder : vscode . WorkspaceFolder | undefined ,
100
95
_token ?: vscode . CancellationToken | undefined
@@ -110,36 +105,42 @@ export class AdaDebugConfigProvider implements vscode.DebugConfigurationProvider
110
105
111
106
if ( folder != undefined ) {
112
107
// 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 ) ;
115
110
assert (
116
111
execs . length == mains . length ,
117
112
`The ALS returned mains.length = ${ mains . length } and ` +
118
113
`execs.length = ${ execs . length } ` +
119
114
`when they should be equal`
120
115
) ;
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' ,
129
130
} ) ;
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
+ }
142
142
} else {
143
+ void warnAboutNoMains ( ) ;
143
144
return Promise . reject ( 'Cancelled' ) ;
144
145
}
145
146
}
@@ -171,56 +172,79 @@ export class AdaDebugConfigProvider implements vscode.DebugConfigurationProvider
171
172
return debugConfiguration ;
172
173
}
173
174
174
- const exec = await this . getOrAskForProgram ( ) ;
175
+ const exec = await getOrAskForProgram ( ) ;
175
176
176
177
if ( exec ) {
177
178
return initializeConfig ( `\${workspaceFolder}/${ exec } ` ) ;
178
179
}
179
180
180
181
return undefined ;
181
182
}
183
+ }
182
184
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
+ ] ;
203
205
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 ) ;
210
226
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
+ ) ;
212
233
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 ] ) ;
221
243
}
222
244
}
245
+ }
223
246
247
+ if ( mains . length > 0 ) {
224
248
// There is no current file or it matches no known Main of the project,
225
249
// so we offer all Mains in a QuickPicker for the user to choose from.
226
250
const quickpick = [ ] ;
@@ -239,28 +263,16 @@ export class AdaDebugConfigProvider implements vscode.DebugConfigurationProvider
239
263
if ( selectedProgram ) {
240
264
return selectedProgram . execRelPath ;
241
265
}
242
-
243
- return undefined ;
266
+ } else {
267
+ void warnAboutNoMains ( ) ;
244
268
}
245
- }
246
269
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