@@ -2,6 +2,8 @@ import * as path from 'path';
22import * as vscode from 'vscode' ;
33import { ContextClients } from './clients' ;
44import { 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