@@ -14,10 +14,10 @@ import * as Telemetry from '../telemetry';
14
14
import * as logger from '../logger' ;
15
15
import * as nls from 'vscode-nls' ;
16
16
import { IConfiguration , IConfigurationSnippet , DebuggerType , DebuggerEvent , MIConfigurations , WindowsConfigurations , WSLConfigurations , PipeTransportConfigurations } from './configurations' ;
17
- import { parse } from 'comment-json' ;
17
+ import * as jsonc from 'comment-json' ;
18
18
import { PlatformInformation } from '../platform' ;
19
19
import { Environment , ParsedEnvironmentFile } from './ParsedEnvironmentFile' ;
20
- import { CppSettings } from '../LanguageServer/settings' ;
20
+ import { CppSettings , OtherSettings } from '../LanguageServer/settings' ;
21
21
import { configPrefix } from '../LanguageServer/extension' ;
22
22
23
23
nls . config ( { messageFormat : nls . MessageFormat . bundle , bundleFormat : nls . BundleFormat . standalone } ) ( ) ;
@@ -593,13 +593,93 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
593
593
return false ;
594
594
}
595
595
596
+ private getLaunchJsonPath ( ) : string | undefined {
597
+ return util . getJsonPath ( "launch.json" ) ;
598
+ }
599
+
600
+ public getRawLaunchJson ( ) : Promise < any > {
601
+ const path : string | undefined = this . getLaunchJsonPath ( ) ;
602
+ return util . getRawJson ( path ) ;
603
+ }
604
+
605
+ public async writeDebugConfig ( config : vscode . DebugConfiguration , folder ?: vscode . WorkspaceFolder ) : Promise < void > {
606
+ const launchJsonPath : string | undefined = this . getLaunchJsonPath ( ) ;
607
+
608
+ if ( this . checkDebugConfigExists ( config . name , folder ) ) {
609
+ if ( launchJsonPath ) {
610
+ const doc : vscode . TextDocument = await vscode . workspace . openTextDocument ( launchJsonPath ) ;
611
+ if ( doc ) {
612
+ vscode . window . showTextDocument ( doc ) ;
613
+ }
614
+ }
615
+ return ;
616
+ }
617
+ const rawLaunchJson : any = await this . getRawLaunchJson ( ) ;
618
+ if ( ! rawLaunchJson . configurations ) {
619
+ rawLaunchJson . configurations = new Array ( ) ;
620
+ }
621
+ if ( ! rawLaunchJson . version ) {
622
+ rawLaunchJson . version = "2.0.0" ;
623
+ }
624
+
625
+ config . detail = undefined ;
626
+ config . existing = undefined ;
627
+ config . isDefault = undefined ;
628
+ rawLaunchJson . configurations . push ( config ) ;
629
+
630
+ if ( ! launchJsonPath ) {
631
+ throw new Error ( "Failed to get tasksJsonPath in checkBuildTaskExists()" ) ;
632
+ }
633
+
634
+ const settings : OtherSettings = new OtherSettings ( ) ;
635
+ await util . writeFileText ( launchJsonPath , jsonc . stringify ( rawLaunchJson , null , settings . editorTabSize ) ) ;
636
+ await vscode . workspace . openTextDocument ( launchJsonPath ) ;
637
+ const doc : vscode . TextDocument = await vscode . workspace . openTextDocument ( launchJsonPath ) ;
638
+ if ( doc ) {
639
+ vscode . window . showTextDocument ( doc ) ;
640
+ }
641
+ }
642
+
643
+ public async addDebugConfiguration ( textEditor : vscode . TextEditor ) : Promise < void > {
644
+ const folder : vscode . WorkspaceFolder | undefined = vscode . workspace . getWorkspaceFolder ( textEditor . document . uri ) ;
645
+ if ( ! folder ) {
646
+ return ;
647
+ }
648
+ const selectedConfig : vscode . DebugConfiguration | undefined = await this . selectConfiguration ( textEditor , true ) ;
649
+ if ( ! selectedConfig ) {
650
+ Telemetry . logDebuggerEvent ( DebuggerEvent . launchPlayButton , { "debugType" : "AddConfigurationOnly" , "folderMode" : folder ? "folder" : "singleFile" , "cancelled" : "true" } ) ;
651
+ return ; // User canceled it.
652
+ }
653
+
654
+ // Write preLaunchTask into tasks.json file.
655
+ if ( selectedConfig . preLaunchTask ) {
656
+ await cppBuildTaskProvider . writeBuildTask ( selectedConfig . preLaunchTask ) ;
657
+ }
658
+ // Write debug configuraion in launch.json file.
659
+ await this . writeDebugConfig ( selectedConfig , folder ) ;
660
+
661
+ }
662
+
596
663
public async buildAndRun ( textEditor : vscode . TextEditor ) : Promise < void > {
597
664
// Turn off the debug mode.
598
665
return this . buildAndDebug ( textEditor , false ) ;
599
666
}
600
667
601
668
public async buildAndDebug ( textEditor : vscode . TextEditor , debugModeOn : boolean = true ) : Promise < void > {
669
+ const folder : vscode . WorkspaceFolder | undefined = vscode . workspace . getWorkspaceFolder ( textEditor . document . uri ) ;
670
+ const selectedConfig : vscode . DebugConfiguration | undefined = await this . selectConfiguration ( textEditor , true ) ;
671
+ if ( ! selectedConfig ) {
672
+ Telemetry . logDebuggerEvent ( DebuggerEvent . launchPlayButton , { "debugType" : debugModeOn ? "debug" : "run" , "folderMode" : folder ? "folder" : "singleFile" , "cancelled" : "true" } ) ;
673
+ return ; // User canceled it.
674
+ }
675
+
676
+ // Keep track of the entry point where the debug has been selected, for telemetry purposes.
677
+ selectedConfig . debuggerEvent = DebuggerEvent . launchPlayButton ;
678
+ // startDebugging will trigger a call to resolveDebugConfiguration.
679
+ await vscode . debug . startDebugging ( folder , selectedConfig , { noDebug : ! debugModeOn } ) ;
680
+ }
602
681
682
+ private async selectConfiguration ( textEditor : vscode . TextEditor , pickDefault : boolean = false ) : Promise < vscode . DebugConfiguration | undefined > {
603
683
const folder : vscode . WorkspaceFolder | undefined = vscode . workspace . getWorkspaceFolder ( textEditor . document . uri ) ;
604
684
if ( ! util . isCppOrCFile ( textEditor . document . uri ) ) {
605
685
vscode . window . showErrorMessage ( localize ( "cannot.build.non.cpp" , 'Cannot build and debug because the active file is not a C or C++ source file.' ) ) ;
@@ -612,14 +692,14 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
612
692
configs = configs . concat ( await this . provideDebugConfigurationsForType ( DebuggerType . cppvsdbg , folder ) ) ;
613
693
}
614
694
615
- const defaultConfig : vscode . DebugConfiguration [ ] = findDefaultConfig ( configs ) ;
695
+ const defaultConfig : vscode . DebugConfiguration [ ] | undefined = pickDefault ? findDefaultConfig ( configs ) : undefined ;
616
696
617
697
const items : MenuItem [ ] = configs . map < MenuItem > ( config => ( { label : config . name , configuration : config , description : config . detail , detail : config . existing } ) ) ;
618
698
619
699
let selection : MenuItem | undefined ;
620
700
621
701
// if there was only one config for the default task, choose that config, otherwise ask the user to choose.
622
- if ( defaultConfig . length === 1 ) {
702
+ if ( defaultConfig && defaultConfig . length === 1 ) {
623
703
selection = { label : defaultConfig [ 0 ] . name , configuration : defaultConfig [ 0 ] , description : defaultConfig [ 0 ] . detail , detail : defaultConfig [ 0 ] . existing } ;
624
704
} else {
625
705
let sortedItems : MenuItem [ ] = [ ] ;
@@ -636,21 +716,10 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
636
716
placeHolder : ( items . length === 0 ? localize ( "no.compiler.found" , "No compiler found" ) : localize ( "select.debug.configuration" , "Select a debug configuration" ) )
637
717
} ) ;
638
718
}
639
-
640
- if ( ! selection ) {
641
- Telemetry . logDebuggerEvent ( DebuggerEvent . launchPlayButton , { "debugType" : debugModeOn ? "debug" : "run" , "folderMode" : folder ? "folder" : "singleFile" , "cancelled" : "true" } ) ;
642
- return ; // User canceled it.
643
- }
644
-
645
- if ( this . isClConfiguration ( selection . label ) && this . showErrorIfClNotAvailable ( selection . label ) ) {
719
+ if ( selection && this . isClConfiguration ( selection . configuration . name ) && this . showErrorIfClNotAvailable ( selection . configuration . name ) ) {
646
720
return ;
647
721
}
648
-
649
- // Keep track of the entry point where the debug has been selected, for telemetry purposes.
650
- selection . configuration . debuggerEvent = DebuggerEvent . launchPlayButton ;
651
- // startDebugging will trigger a call to resolveDebugConfiguration.
652
- await vscode . debug . startDebugging ( folder , selection . configuration , { noDebug : ! debugModeOn } ) ;
653
-
722
+ return selection ?. configuration ;
654
723
}
655
724
656
725
private async resolvePreLaunchTask ( folder : vscode . WorkspaceFolder | undefined , configuration : vscode . DebugConfiguration , debugModeOn : boolean = true ) : Promise < void > {
@@ -662,7 +731,7 @@ export class DebugConfigurationProvider implements vscode.DebugConfigurationProv
662
731
if ( configuration . preLaunchTask ) {
663
732
try {
664
733
if ( folder ) {
665
- await cppBuildTaskProvider . checkBuildTaskExists ( configuration . preLaunchTask ) ;
734
+ await cppBuildTaskProvider . writeBuildTask ( configuration . preLaunchTask ) ;
666
735
} else {
667
736
// In case of singleFile, remove the preLaunch task from the debug configuration and run it here instead.
668
737
await cppBuildTaskProvider . runBuildTask ( configuration . preLaunchTask ) ;
@@ -832,7 +901,7 @@ export class ConfigurationSnippetProvider implements vscode.CompletionItemProvid
832
901
public provideCompletionItems ( document : vscode . TextDocument , position : vscode . Position , token : vscode . CancellationToken , context : vscode . CompletionContext ) : Thenable < vscode . CompletionList > {
833
902
let items : vscode . CompletionItem [ ] = this . snippets ;
834
903
835
- const launch : any = parse ( document . getText ( ) ) ;
904
+ const launch : any = jsonc . parse ( document . getText ( ) ) ;
836
905
// Check to see if the array is empty, so any additional inserted snippets will need commas.
837
906
if ( launch . configurations . length !== 0 ) {
838
907
items = [ ] ;
0 commit comments