@@ -47,6 +47,8 @@ jsonRegistry.registerSchema(launchSchemaId, launchSchema);
4747const DEBUG_SELECTED_CONFIG_NAME_KEY = 'debug.selectedconfigname' ;
4848const DEBUG_SELECTED_ROOT = 'debug.selectedroot' ;
4949
50+ interface IDynamicPickItem { label : string , launch : ILaunch , config : IConfig }
51+
5052export class ConfigurationManager implements IConfigurationManager {
5153 private debuggers : Debugger [ ] ;
5254 private breakpointModeIdsSet = new Set < string > ( ) ;
@@ -251,23 +253,50 @@ export class ConfigurationManager implements IConfigurationManager {
251253 async getDynamicProviders ( ) : Promise < { label : string , pick : ( ) => Promise < { launch : ILaunch , config : IConfig } | undefined > } [ ] > {
252254 const extensions = await this . extensionService . getExtensions ( ) ;
253255 const onDebugDynamicConfigurationsName = 'onDebugDynamicConfigurations' ;
254- const debugDynamicExtensionsTypes = extensions . map ( e => {
255- const activationEvent = e . activationEvents && e . activationEvents . find ( e => e . includes ( onDebugDynamicConfigurationsName ) ) ;
256- if ( activationEvent ) {
257- const type = activationEvent . substr ( onDebugDynamicConfigurationsName . length + 1 ) ;
258- return type || ( e . contributes && e . contributes . debuggers && e . contributes . debuggers . length ? e . contributes . debuggers [ 0 ] . type : undefined ) ;
256+ const debugDynamicExtensionsTypes = extensions . reduce ( ( acc , e ) => {
257+ if ( ! e . activationEvents ) {
258+ return acc ;
259259 }
260260
261- return undefined ;
262- } ) . filter ( type => typeof type === 'string' && ! ! this . getDebuggerLabel ( type ) ) as string [ ] ;
261+ const explicitTypes = e . activationEvents . filter ( e => e . includes ( `${ onDebugDynamicConfigurationsName } :` ) ) . map ( type => type . slice ( onDebugDynamicConfigurationsName . length + 1 ) ) ;
262+ if ( explicitTypes . length ) {
263+ return [ ...acc , ...explicitTypes ] ;
264+ }
265+
266+ if ( e . activationEvents . includes ( onDebugDynamicConfigurationsName ) ) {
267+ const debuggerType = e . contributes ?. debuggers ?. [ 0 ] . type ;
268+ return debuggerType ? [ ...acc , debuggerType ] : acc ;
269+ }
270+
271+ return acc ;
272+ } , [ ] as string [ ] ) ;
263273
264274 return debugDynamicExtensionsTypes . map ( type => {
265275 return {
266276 label : this . getDebuggerLabel ( type ) ! ,
267277 pick : async ( ) => {
278+ const input = this . quickInputService . createQuickPick < IDynamicPickItem > ( ) ;
279+ input . busy = true ;
280+ input . placeholder = nls . localize ( 'selectConfiguration' , "Select Launch Configuration" ) ;
281+ input . show ( ) ;
282+
283+ let chosenDidCancel = false ;
284+ const chosenPromise = new Promise < IDynamicPickItem | undefined > ( resolve => {
285+ input . onDidAccept ( ( ) => resolve ( input . activeItems [ 0 ] ) ) ;
286+ input . onDidTriggerItemButton ( async ( context ) => {
287+ resolve ( undefined ) ;
288+ const { launch, config } = context . item ;
289+ await launch . openConfigFile ( false , config . type ) ;
290+ // Only Launch have a pin trigger button
291+ await ( launch as Launch ) . writeConfiguration ( config ) ;
292+ this . selectConfiguration ( launch , config . name ) ;
293+ } ) ;
294+ input . onDidHide ( ( ) => { chosenDidCancel = true ; resolve ( ) ; } ) ;
295+ } ) ;
296+
268297 await this . activateDebuggers ( onDebugDynamicConfigurationsName , type ) ;
269298 const token = new CancellationTokenSource ( ) ;
270- const picks : Promise < { label : string , launch : ILaunch , config : IConfig } [ ] > [ ] = [ ] ;
299+ const picks : Promise < IDynamicPickItem [ ] > [ ] = [ ] ;
271300 const provider = this . configProviders . filter ( p => p . type === type && p . triggerKind === DebugConfigurationProviderTriggerKind . Dynamic && p . provideDebugConfigurations ) [ 0 ] ;
272301 this . getLaunches ( ) . forEach ( launch => {
273302 if ( launch . workspace && provider ) {
@@ -282,25 +311,25 @@ export class ConfigurationManager implements IConfigurationManager {
282311 } ) ) ) ) ;
283312 }
284313 } ) ;
285- const promiseOfPicks = Promise . all ( picks ) . then ( result => result . reduce ( ( first , second ) => first . concat ( second ) , [ ] ) ) ;
286314
287- const result = await this . quickInputService . pick < { label : string , launch : ILaunch , config : IConfig } > ( promiseOfPicks , {
288- placeHolder : nls . localize ( 'selectConfiguration' , "Select Launch Configuration" ) ,
289- onDidTriggerItemButton : async ( context ) => {
290- await this . quickInputService . cancel ( ) ;
291- const { launch , config } = context . item ;
292- await launch . openConfigFile ( false , config . type ) ;
293- // Only Launch have a pin trigger button
294- await ( launch as Launch ) . writeConfiguration ( config ) ;
295- this . selectConfiguration ( launch , config . name ) ;
296- }
297- } ) ;
298- if ( ! result ) {
315+ const items = await Promise . all ( picks ) . then ( result => result . reduce ( ( first , second ) => first . concat ( second ) , [ ] ) ) ;
316+ let chosen : IDynamicPickItem | undefined ;
317+ if ( items . length === 1 && ! chosenDidCancel ) {
318+ chosen = items [ 0 ] ;
319+ } else {
320+ input . items = items ;
321+ input . busy = false ;
322+ chosen = await chosenPromise ;
323+ }
324+
325+ input . dispose ( ) ;
326+ if ( ! chosen ) {
299327 // User canceled quick input we should notify the provider to cancel computing configurations
300328 token . cancel ( ) ;
329+ return ;
301330 }
302331
303- return result ;
332+ return chosen ;
304333 }
305334 } ;
306335 } ) ;
0 commit comments