@@ -76,15 +76,15 @@ interface Operations {
7676
7777function hasOperations ( operations : Operations ) {
7878 return operations . addLaunchJson ||
79- operations . updateTasksJson ||
80- operations . addLaunchJson ;
79+ operations . updateTasksJson ||
80+ operations . addLaunchJson ;
8181}
8282
8383function getOperations ( ) {
8484 const paths = getPaths ( ) ;
8585
8686 return getBuildOperations ( paths . tasksJsonPath ) . then ( operations =>
87- getLaunchOperations ( paths . launchJsonPath , operations ) ) ;
87+ getLaunchOperations ( paths . launchJsonPath , operations ) ) ;
8888}
8989
9090function getBuildOperations ( tasksJsonPath : string ) {
@@ -120,15 +120,27 @@ function getLaunchOperations(launchJsonPath: string, operations: Operations) {
120120 } ) ;
121121}
122122
123+ enum PromptResult {
124+ Yes ,
125+ No ,
126+ Disable
127+ }
128+
129+ interface PromptItem extends vscode . MessageItem {
130+ result : PromptResult
131+ }
132+
123133function promptToAddAssets ( ) {
124- return new Promise < boolean > ( ( resolve , reject ) => {
125- const item = { title : 'Yes' }
134+ return new Promise < PromptResult > ( ( resolve , reject ) => {
135+ const yesItem : PromptItem = { title : 'Yes' , result : PromptResult . Yes } ;
136+ const noItem : PromptItem = { title : 'Not Now' , result : PromptResult . No , isCloseAffordance : true }
137+ const disableItem : PromptItem = { title : "Don't Ask Again" , result : PromptResult . Disable } ;
126138
127- vscode . window . showInformationMessage ( 'Required assets to build and debug are missing from your project. Add them?' , item ) . then ( selection => {
128- return selection
129- ? resolve ( true )
130- : resolve ( false ) ;
131- } ) ;
139+ const projectName = path . basename ( vscode . workspace . rootPath ) ;
140+
141+ vscode . window . showWarningMessage (
142+ `Required assets to build and debug are missing from ' ${ projectName } '. Add them?` , disableItem , noItem , yesItem )
143+ . then ( selection => resolve ( selection . result ) ) ;
132144 } ) ;
133145}
134146
@@ -208,8 +220,8 @@ function createAttachConfiguration(): AttachConfiguration {
208220}
209221
210222function createLaunchJson ( projectData : TargetProjectData , isWebProject : boolean ) : any {
211- let version = '0.2.0' ;
212- if ( ! isWebProject ) {
223+ let version = '0.2.0' ;
224+ if ( ! isWebProject ) {
213225 return {
214226 version : version ,
215227 configurations : [
@@ -249,7 +261,7 @@ function createTasksConfiguration(projectData: TargetProjectData): tasks.TaskCon
249261 command : 'dotnet' ,
250262 isShellCommand : true ,
251263 args : [ ] ,
252- tasks : [ createBuildTaskDescription ( projectData ) ]
264+ tasks : [ createBuildTaskDescription ( projectData ) ]
253265 } ;
254266}
255267
@@ -365,35 +377,140 @@ function addLaunchJsonIfNecessary(projectData: TargetProjectData, paths: Paths,
365377 } ) ;
366378}
367379
368- export function addAssetsIfNecessary ( server : OmnisharpServer ) {
369- if ( ! vscode . workspace . rootPath ) {
370- return ;
371- }
380+ function addAssets ( data : TargetProjectData , paths : Paths , operations : Operations ) {
381+ const promises = [
382+ addTasksJsonIfNecessary ( data , paths , operations ) ,
383+ addLaunchJsonIfNecessary ( data , paths , operations )
384+ ] ;
372385
373- return serverUtils . requestWorkspaceInformation ( server ) . then ( info => {
374- // If there are no .NET Core projects, we won't bother offering to add assets.
375- if ( 'DotNet' in info && info . DotNet . Projects . length > 0 ) {
376- return getOperations ( ) . then ( operations => {
377- if ( ! hasOperations ( operations ) ) {
378- return ;
379- }
386+ return Promise . all ( promises ) ;
387+ }
388+
389+ export enum AddAssetResult {
390+ NotApplicable ,
391+ Done ,
392+ Disable ,
393+ Cancelled
394+ }
395+
396+ export function addAssetsIfNecessary ( server : OmnisharpServer ) : Promise < AddAssetResult > {
397+ return new Promise < AddAssetResult > ( ( resolve , reject ) => {
398+ if ( ! vscode . workspace . rootPath ) {
399+ return resolve ( AddAssetResult . NotApplicable ) ;
400+ }
380401
381- promptToAddAssets ( ) . then ( addAssets => {
382- if ( ! addAssets ) {
383- return ;
402+ serverUtils . requestWorkspaceInformation ( server ) . then ( info => {
403+ // If there are no .NET Core projects, we won't bother offering to add assets.
404+ if ( info . DotNet && info . DotNet . Projects . length > 0 ) {
405+ return getOperations ( ) . then ( operations => {
406+ if ( ! hasOperations ( operations ) ) {
407+ return resolve ( AddAssetResult . NotApplicable ) ;
384408 }
385409
386- const data = findTargetProjectData ( info . DotNet . Projects ) ;
387- const paths = getPaths ( ) ;
410+ promptToAddAssets ( ) . then ( result => {
411+ if ( result === PromptResult . Disable ) {
412+ return resolve ( AddAssetResult . Disable ) ;
413+ }
414+
415+ if ( result !== PromptResult . Yes ) {
416+ return resolve ( AddAssetResult . Cancelled ) ;
417+ }
388418
389- return fs . ensureDirAsync ( paths . vscodeFolder ) . then ( ( ) => {
390- return Promise . all ( [
391- addTasksJsonIfNecessary ( data , paths , operations ) ,
392- addLaunchJsonIfNecessary ( data , paths , operations )
393- ] ) ;
419+ const data = findTargetProjectData ( info . DotNet . Projects ) ;
420+ const paths = getPaths ( ) ;
421+
422+ return fs . ensureDirAsync ( paths . vscodeFolder ) . then ( ( ) =>
423+ addAssets ( data , paths , operations ) . then ( ( ) =>
424+ resolve ( AddAssetResult . Done ) ) ) ;
394425 } ) ;
395426 } ) ;
427+ }
428+ } ) . catch ( err =>
429+ reject ( err ) ) ;
430+ } ) ;
431+ }
432+
433+ function doesAnyAssetExist ( paths : Paths ) {
434+ return new Promise < boolean > ( ( resolve , reject ) => {
435+ fs . existsAsync ( paths . launchJsonPath ) . then ( res => {
436+ if ( res ) {
437+ resolve ( true ) ;
438+ }
439+ else {
440+ fs . existsAsync ( paths . tasksJsonPath ) . then ( res => {
441+ resolve ( res ) ;
442+ } ) ;
443+ }
444+ } ) ;
445+ } ) ;
446+ }
447+
448+ function deleteAsset ( path : string ) {
449+ return new Promise < void > ( ( resolve , reject ) => {
450+ fs . existsAsync ( path ) . then ( res => {
451+ if ( res ) {
452+ // TODO: Should we check after unlinking to see if the file still exists?
453+ fs . unlinkAsync ( path ) . then ( ( ) => {
454+ resolve ( ) ;
455+ } ) ;
456+ }
457+ } ) ;
458+ } ) ;
459+ }
460+
461+ function deleteAssets ( paths : Paths ) {
462+ return Promise . all ( [
463+ deleteAsset ( paths . launchJsonPath ) ,
464+ deleteAsset ( paths . tasksJsonPath )
465+ ] ) ;
466+ }
467+
468+ function shouldGenerateAssets ( paths : Paths ) {
469+ return new Promise < boolean > ( ( resolve , reject ) => {
470+ doesAnyAssetExist ( paths ) . then ( res => {
471+ if ( res ) {
472+ const yesItem = { title : 'Yes' } ;
473+ const cancelItem = { title : 'Cancel' , isCloseAffordance : true } ;
474+
475+ vscode . window . showWarningMessage ( 'Replace existing build and debug assets?' , cancelItem , yesItem )
476+ . then ( selection => {
477+ if ( selection === yesItem ) {
478+ deleteAssets ( paths ) . then ( _ => resolve ( true ) ) ;
479+ }
480+ else {
481+ // The user clicked cancel
482+ resolve ( false ) ;
483+ }
484+ } ) ;
485+ }
486+ else {
487+ // The assets don't exist, so we're good to go.
488+ resolve ( true ) ;
489+ }
490+ } ) ;
491+
492+ } ) ;
493+ }
494+
495+ export function generateAssets ( server : OmnisharpServer ) {
496+ serverUtils . requestWorkspaceInformation ( server ) . then ( info => {
497+ if ( info . DotNet && info . DotNet . Projects . length > 0 ) {
498+ getOperations ( ) . then ( operations => {
499+ if ( hasOperations ( operations ) ) {
500+ const paths = getPaths ( ) ;
501+ shouldGenerateAssets ( paths ) . then ( res => {
502+ if ( res ) {
503+ fs . ensureDirAsync ( paths . vscodeFolder ) . then ( ( ) => {
504+ const data = findTargetProjectData ( info . DotNet . Projects ) ;
505+ addAssets ( data , paths , operations ) ;
506+ } ) ;
507+ }
508+ } ) ;
509+ }
396510 } ) ;
397511 }
512+ else {
513+ vscode . window . showErrorMessage ( "Could not locate .NET Core project. Assets were not generated." ) ;
514+ }
398515 } ) ;
399516}
0 commit comments