@@ -48,7 +48,7 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
48
48
* Returns a list of initial debug configurations based on contextual information, e.g. package.json or folder.
49
49
*/
50
50
async provideDebugConfigurations ( folder ?: vscode . WorkspaceFolder , token ?: vscode . CancellationToken ) : Promise < vscode . DebugConfiguration [ ] > {
51
- let configs : vscode . DebugConfiguration [ ] | null | undefined = await this . provideDebugConfigurationsTypeSpecific ( this . type , folder , token ) ;
51
+ let configs : vscode . DebugConfiguration [ ] | null | undefined = await this . provideDebugConfigurationsForType ( this . type , folder , token ) ;
52
52
if ( ! configs ) {
53
53
configs = [ ] ;
54
54
}
@@ -80,29 +80,34 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
80
80
81
81
const selection : MenuItem | undefined = await vscode . window . showQuickPick ( items , { placeHolder : localize ( "select.configuration" , "Select a configuration" ) } ) ;
82
82
if ( ! selection ) {
83
- // throw Error(localize("debug.configuration.selection.canceled", "Debug configuration selection canceled")); // User canceled it.
84
- Telemetry . logDebuggerEvent ( DebuggerEvent . debugPanel , { "debugType" : "debug" , "folderMode" : folder ? "folder" : "singleMode" , "cancelled" : "true" } ) ;
83
+ Telemetry . logDebuggerEvent ( DebuggerEvent . debugPanel , { "debugType" : "debug" , "folderMode" : folder ? "folder" : "singleFile" , "cancelled" : "true" } ) ;
85
84
return [ ] ; // User canceled it.
86
85
}
87
- if ( ! this . isClAvailable ( selection . label ) ) {
88
- return [ selection . configuration ] ;
86
+
87
+ if ( this . isClConfiguration ( selection . label ) ) {
88
+ this . showErrorClNotAvailable ( selection . label ) ;
89
89
}
90
90
91
91
return [ selection . configuration ] ;
92
92
}
93
93
94
94
/**
95
95
* Error checks the provided 'config' without any variables substituted.
96
+ * If return "undefined", the debugging will be aborted silently.
97
+ * If return "null", the debugging will be aborted and launch.json will be opened.
96
98
*/
97
99
resolveDebugConfiguration ( folder : vscode . WorkspaceFolder | undefined , config : vscode . DebugConfiguration , token ?: vscode . CancellationToken ) : vscode . ProviderResult < vscode . DebugConfiguration > {
98
100
if ( ! config || ! config . type ) {
99
101
// When DebugConfigurationProviderTriggerKind is Dynamic, this function will be called with an empty config.
100
102
// Providing debug configs, and debugging should be called manually.
103
+ // Currently, we expect only one debug config to be selected.
101
104
this . provideDebugConfigurations ( folder ) . then ( async configs => {
102
105
if ( ! configs || configs . length === 0 ) {
103
- Telemetry . logDebuggerEvent ( DebuggerEvent . debugPanel , { "debugType" : "debug" , "folderMode" : folder ? "folder" : "singleMode " , "cancelled" : "true" } ) ;
106
+ Telemetry . logDebuggerEvent ( DebuggerEvent . debugPanel , { "debugType" : "debug" , "folderMode" : folder ? "folder" : "singleFile " , "cancelled" : "true" } ) ;
104
107
return undefined ; // aborts debugging silently
105
108
} else {
109
+ console . assert ( configs . length === 1 , "More than one debug config is selected." ) ;
110
+ await this . resolvePreLaunchTask ( folder , configs [ 0 ] , DebuggerEvent . debugPanel ) ;
106
111
await this . startDebugging ( folder , configs [ 0 ] , DebuggerEvent . debugPanel ) ;
107
112
return configs [ 0 ] ;
108
113
}
@@ -221,7 +226,7 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
221
226
return config ;
222
227
}
223
228
224
- async provideDebugConfigurationsTypeSpecific ( type : DebuggerType , folder ?: vscode . WorkspaceFolder , token ?: vscode . CancellationToken ) : Promise < vscode . DebugConfiguration [ ] > {
229
+ async provideDebugConfigurationsForType ( type : DebuggerType , folder ?: vscode . WorkspaceFolder , token ?: vscode . CancellationToken ) : Promise < vscode . DebugConfiguration [ ] > {
225
230
const defaultConfig : vscode . DebugConfiguration = this . assetProvider . getInitialConfigurations ( type ) . find ( ( config : any ) =>
226
231
isDebugLaunchStr ( config . name ) && config . request === "launch" ) ;
227
232
console . assert ( defaultConfig , "Could not find default debug configuration." ) ;
@@ -369,17 +374,22 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
369
374
}
370
375
371
376
private buildAndDebugActiveFileStr ( ) : string {
372
- return `${ localize ( "build.and.debug.active.file" , 'Build and debug active file' ) } ` ;
377
+ return `${ localize ( "build.and.debug.active.file" , 'build and debug active file' ) } ` ;
378
+ }
379
+
380
+ private isClConfiguration ( configurationLabel : string ) : boolean {
381
+ return configurationLabel . startsWith ( "C/C++: cl.exe" ) ? true : false ;
373
382
}
374
383
375
- private isClAvailable ( configurationLabel : string ) : boolean {
376
- if ( configurationLabel . startsWith ( "C/C++: cl.exe" ) ) {
384
+ private showErrorClNotAvailable ( configurationLabel : string ) : boolean {
385
+ if ( this . isClConfiguration ( configurationLabel ) ) {
377
386
if ( ! process . env . DevEnvDir || process . env . DevEnvDir . length === 0 ) {
378
387
vscode . window . showErrorMessage ( localize ( "cl.exe.not.available" , "{0} build and debug is only usable when VS Code is run from the Developer Command Prompt for VS." , "cl.exe" ) ) ;
379
- return false ;
388
+ return true ;
380
389
}
390
+ return false ;
381
391
}
382
- return true ;
392
+ throw new Error ( "Config is not a cl.exe config." ) ;
383
393
}
384
394
385
395
private getLLDBFrameworkPath ( ) : string | undefined {
@@ -504,6 +514,11 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
504
514
}
505
515
}
506
516
517
+ public async buildAndRun ( textEditor : vscode . TextEditor ) : Promise < void > {
518
+ // Turn off the debug mode.
519
+ return this . buildAndDebug ( textEditor , false ) ;
520
+ }
521
+
507
522
public async buildAndDebug ( textEditor : vscode . TextEditor , debugModeOn : boolean = true ) : Promise < void > {
508
523
509
524
const folder : vscode . WorkspaceFolder | undefined = vscode . workspace . getWorkspaceFolder ( textEditor . document . uri ) ;
@@ -513,11 +528,10 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
513
528
}
514
529
515
530
// Get debug configurations for all debugger types.
516
- let configs : vscode . DebugConfiguration [ ] = [ ] ;
531
+ let configs : vscode . DebugConfiguration [ ] = await this . provideDebugConfigurationsForType ( DebuggerType . cppdbg , folder ) ;
517
532
if ( os . platform ( ) === 'win32' ) {
518
- configs = await this . provideDebugConfigurationsTypeSpecific ( DebuggerType . cppvsdbg , folder ) ;
533
+ configs = configs . concat ( await this . provideDebugConfigurationsForType ( DebuggerType . cppvsdbg , folder ) ) ;
519
534
}
520
- configs = configs . concat ( await this . provideDebugConfigurationsTypeSpecific ( DebuggerType . cppdbg , folder ) ) ;
521
535
522
536
const defaultConfig : vscode . DebugConfiguration [ ] = configs . filter ( ( config : vscode . DebugConfiguration ) => ( config . hasOwnProperty ( "isDefault" ) && config . isDefault ) ) ;
523
537
interface MenuItem extends vscode . QuickPickItem {
@@ -547,12 +561,15 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
547
561
548
562
const debuggerEvent : string = DebuggerEvent . launchPlayButton ;
549
563
if ( ! selection ) {
550
- Telemetry . logDebuggerEvent ( debuggerEvent , { "debugType" : debugModeOn ? "debug" : "run" , "folderMode" : folder ? "folder" : "singleMode " , "cancelled" : "true" } ) ;
564
+ Telemetry . logDebuggerEvent ( debuggerEvent , { "debugType" : debugModeOn ? "debug" : "run" , "folderMode" : folder ? "folder" : "singleFile " , "cancelled" : "true" } ) ;
551
565
return ; // User canceled it.
552
566
}
553
- if ( ! this . isClAvailable ( selection . label ) ) {
567
+
568
+ if ( this . isClConfiguration ( selection . label ) && this . showErrorClNotAvailable ( selection . label ) ) {
554
569
return ;
555
570
}
571
+
572
+ // Resolve config before start debugging.
556
573
let resolvedConfig : vscode . DebugConfiguration | undefined | null ;
557
574
if ( selection . configuration && selection . configuration . type ) {
558
575
resolvedConfig = await this . resolveDebugConfiguration ( folder , selection . configuration ) ;
@@ -561,24 +578,24 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
561
578
}
562
579
}
563
580
if ( resolvedConfig ) {
581
+ await this . resolvePreLaunchTask ( folder , resolvedConfig , debuggerEvent , debugModeOn ) ;
564
582
await this . startDebugging ( folder , resolvedConfig , debuggerEvent , debugModeOn ) ;
565
583
}
566
584
}
567
585
568
- private async startDebugging ( folder : vscode . WorkspaceFolder | undefined , configuration : vscode . DebugConfiguration , debuggerEvent : string , debugModeOn : boolean = true ) : Promise < void > {
569
-
586
+ private async resolvePreLaunchTask ( folder : vscode . WorkspaceFolder | undefined , configuration : vscode . DebugConfiguration , debuggerEvent : string , debugModeOn : boolean = true ) : Promise < void > {
570
587
const debugType : string = debugModeOn ? "debug" : "run" ;
571
- const folderMode : string = folder ? "folder" : "singleMode " ;
588
+ const folderMode : string = folder ? "folder" : "singleFile " ;
572
589
if ( configuration . preLaunchTask ) {
573
590
try {
574
591
if ( folder ) {
575
592
await cppBuildTaskProvider . checkBuildTaskExists ( configuration . preLaunchTask ) ;
576
593
DebugConfigurationProvider . recentBuildTaskLableStr = configuration . preLaunchTask ;
577
594
} else {
578
- // In case of single mode file , remove the preLaunch task from the debug configuration and run it here instead.
595
+ // In case of singleFile , remove the preLaunch task from the debug configuration and run it here instead.
579
596
await cppBuildTaskProvider . runBuildTask ( configuration . preLaunchTask ) ;
580
597
DebugConfigurationProvider . recentBuildTaskLableStr = configuration . preLaunchTask ;
581
- configuration . preLaunchTask = undefined ;
598
+
582
599
}
583
600
} catch ( errJS ) {
584
601
const e : Error = errJS as Error ;
@@ -588,6 +605,15 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
588
605
Telemetry . logDebuggerEvent ( debuggerEvent , { "debugType" : debugType , "folderMode" : folderMode , "config" : "noBuildConfig" , "success" : "false" } ) ;
589
606
}
590
607
}
608
+ }
609
+
610
+ private async startDebugging ( folder : vscode . WorkspaceFolder | undefined , configuration : vscode . DebugConfiguration , debuggerEvent : string , debugModeOn : boolean = true ) : Promise < void > {
611
+ const debugType : string = debugModeOn ? "debug" : "run" ;
612
+ const folderMode : string = folder ? "folder" : "singleFile" ;
613
+ if ( ! folder ) {
614
+ // In case of singleFile, remove the preLaunch task.
615
+ configuration . preLaunchTask = undefined ;
616
+ }
591
617
try {
592
618
// Check if the debug configuration exists in launch.json.
593
619
await cppBuildTaskProvider . checkDebugConfigExists ( configuration . name ) ;
0 commit comments