@@ -376,22 +376,29 @@ export class UndoRedoService implements IUndoRedoService {
376376 }
377377 }
378378
379- private _verifyWorkspaceUndo ( element : WorkspaceStackElement ) : WorkspaceVerificationResult {
379+ private _getAffectedEditStacks ( element : WorkspaceStackElement ) : ResourceEditStack [ ] {
380+ const affectedEditStacks : ResourceEditStack [ ] = [ ] ;
381+ for ( const strResource of element . strResources ) {
382+ affectedEditStacks . push ( this . _editStacks . get ( strResource ) ! ) ;
383+ }
384+ return affectedEditStacks ;
385+ }
386+
387+ private _checkWorkspaceUndo ( resource : URI , element : WorkspaceStackElement , affectedEditStacks : ResourceEditStack [ ] ) : WorkspaceVerificationError | null {
380388 if ( element . removedResources ) {
389+ this . _splitPastWorkspaceElement ( element , element . removedResources ) ;
381390 const message = nls . localize ( 'cannotWorkspaceUndo' , "Could not undo '{0}' across all files. {1}" , element . label , element . removedResources . createMessage ( ) ) ;
382- return new InvalidWorkspaceVerificationResult ( message , element . removedResources ) ;
391+ this . _notificationService . info ( message ) ;
392+ return new WorkspaceVerificationError ( this . undo ( resource ) ) ;
383393 }
384394 if ( element . invalidatedResources ) {
395+ this . _splitPastWorkspaceElement ( element , element . invalidatedResources ) ;
385396 const message = nls . localize ( 'cannotWorkspaceUndo' , "Could not undo '{0}' across all files. {1}" , element . label , element . invalidatedResources . createMessage ( ) ) ;
386- return new InvalidWorkspaceVerificationResult ( message , element . invalidatedResources ) ;
397+ this . _notificationService . info ( message ) ;
398+ return new WorkspaceVerificationError ( this . undo ( resource ) ) ;
387399 }
388400
389401 // this must be the last past element in all the impacted resources!
390- const affectedEditStacks : ResourceEditStack [ ] = [ ] ;
391- for ( const strResource of element . strResources ) {
392- affectedEditStacks . push ( this . _editStacks . get ( strResource ) ! ) ;
393- }
394-
395402 const cannotUndoDueToResources : URI [ ] = [ ] ;
396403 for ( const editStack of affectedEditStacks ) {
397404 if ( editStack . past . length === 0 || editStack . past [ editStack . past . length - 1 ] !== element ) {
@@ -400,29 +407,27 @@ export class UndoRedoService implements IUndoRedoService {
400407 }
401408
402409 if ( cannotUndoDueToResources . length > 0 ) {
410+ this . _splitPastWorkspaceElement ( element , null ) ;
403411 const paths = cannotUndoDueToResources . map ( r => r . scheme === Schemas . file ? r . fsPath : r . path ) ;
404412 const message = nls . localize ( 'cannotWorkspaceUndoDueToChanges' , "Could not undo '{0}' across all files because changes were made to {1}" , element . label , paths . join ( ', ' ) ) ;
405- return new InvalidWorkspaceVerificationResult ( message , null ) ;
413+ this . _notificationService . info ( message ) ;
414+ return new WorkspaceVerificationError ( this . undo ( resource ) ) ;
406415 }
407416
408- return new ValidWorkspaceVerificationResult ( affectedEditStacks ) ;
417+ return null ;
409418 }
410419
411420 private _workspaceUndo ( resource : URI , element : WorkspaceStackElement ) : Promise < void > | void {
412- const verificationResult = this . _verifyWorkspaceUndo ( element ) ;
413- if ( verificationResult . type === WorkspaceVerificationResultType . Invalid ) {
414- // cannot apply the workspace undo
415- this . _splitPastWorkspaceElement ( element , verificationResult . ignoreResources ) ;
416- this . _notificationService . info ( verificationResult . message ) ;
417- return this . undo ( resource ) ;
421+ const affectedEditStacks = this . _getAffectedEditStacks ( element ) ;
422+ const verificationError = this . _checkWorkspaceUndo ( resource , element , affectedEditStacks ) ;
423+ if ( verificationError ) {
424+ return verificationError . returnValue ;
418425 }
419-
420- const affectedEditStacks = verificationResult . affectedEditStacks ;
421426 return this . _confirmAndExecuteWorkspaceUndo ( resource , element , affectedEditStacks ) ;
422427 }
423428
424429 private async _confirmAndExecuteWorkspaceUndo ( resource : URI , element : WorkspaceStackElement , affectedEditStacks : ResourceEditStack [ ] ) : Promise < void > {
425- return this . _dialogService . show (
430+ const result = await this . _dialogService . show (
426431 Severity . Info ,
427432 nls . localize ( 'confirmWorkspace' , "Would you like to undo '{0}' across all files?" , element . label ) ,
428433 [
@@ -433,21 +438,29 @@ export class UndoRedoService implements IUndoRedoService {
433438 {
434439 cancelId : 2
435440 }
436- ) . then ( ( result ) => {
437- if ( result . choice === 2 ) {
438- // cancel
439- return ;
440- } else if ( result . choice === 0 ) {
441- for ( const editStack of affectedEditStacks ) {
442- editStack . past . pop ( ) ;
443- editStack . future . push ( element ) ;
444- }
445- return this . _safeInvoke ( element , ( ) => element . actual . undo ( ) ) ;
446- } else {
447- this . _splitPastWorkspaceElement ( element , null ) ;
448- return this . undo ( resource ) ;
441+ ) ;
442+
443+ // At this point, it is possible that the element has been made invalid in the meantime (due to the confirmation await)
444+ const verificationError = this . _checkWorkspaceUndo ( resource , element , affectedEditStacks ) ;
445+ if ( verificationError ) {
446+ return verificationError . returnValue ;
447+ }
448+
449+ if ( result . choice === 2 ) {
450+ // cancel
451+ return ;
452+ }
453+
454+ if ( result . choice === 0 ) {
455+ for ( const editStack of affectedEditStacks ) {
456+ editStack . past . pop ( ) ;
457+ editStack . future . push ( element ) ;
449458 }
450- } ) ;
459+ return this . _safeInvoke ( element , ( ) => element . actual . undo ( ) ) ;
460+ } else {
461+ this . _splitPastWorkspaceElement ( element , null ) ;
462+ return this . undo ( resource ) ;
463+ }
451464 }
452465
453466 private _resourceUndo ( editStack : ResourceEditStack , element : ResourceStackElement ) : Promise < void > | void {
@@ -490,48 +503,46 @@ export class UndoRedoService implements IUndoRedoService {
490503 return false ;
491504 }
492505
493- private _verifyWorkspaceRedo ( element : WorkspaceStackElement ) : WorkspaceVerificationResult {
506+ private _checkWorkspaceRedo ( resource : URI , element : WorkspaceStackElement , affectedEditStacks : ResourceEditStack [ ] ) : WorkspaceVerificationError | null {
494507 if ( element . removedResources ) {
508+ this . _splitFutureWorkspaceElement ( element , element . removedResources ) ;
495509 const message = nls . localize ( 'cannotWorkspaceRedo' , "Could not redo '{0}' across all files. {1}" , element . label , element . removedResources . createMessage ( ) ) ;
496- return new InvalidWorkspaceVerificationResult ( message , element . removedResources ) ;
510+ this . _notificationService . info ( message ) ;
511+ return new WorkspaceVerificationError ( this . redo ( resource ) ) ;
497512 }
498513 if ( element . invalidatedResources ) {
514+ this . _splitFutureWorkspaceElement ( element , element . invalidatedResources ) ;
499515 const message = nls . localize ( 'cannotWorkspaceRedo' , "Could not redo '{0}' across all files. {1}" , element . label , element . invalidatedResources . createMessage ( ) ) ;
500- return new InvalidWorkspaceVerificationResult ( message , element . invalidatedResources ) ;
516+ this . _notificationService . info ( message ) ;
517+ return new WorkspaceVerificationError ( this . redo ( resource ) ) ;
501518 }
502519
503520 // this must be the last future element in all the impacted resources!
504- let affectedEditStacks : ResourceEditStack [ ] = [ ] ;
505- for ( const strResource of element . strResources ) {
506- affectedEditStacks . push ( this . _editStacks . get ( strResource ) ! ) ;
507- }
508-
509- let cannotRedoDueToResources : URI [ ] = [ ] ;
521+ const cannotRedoDueToResources : URI [ ] = [ ] ;
510522 for ( const editStack of affectedEditStacks ) {
511523 if ( editStack . future . length === 0 || editStack . future [ editStack . future . length - 1 ] !== element ) {
512524 cannotRedoDueToResources . push ( editStack . resource ) ;
513525 }
514526 }
515527
516528 if ( cannotRedoDueToResources . length > 0 ) {
529+ this . _splitFutureWorkspaceElement ( element , null ) ;
517530 const paths = cannotRedoDueToResources . map ( r => r . scheme === Schemas . file ? r . fsPath : r . path ) ;
518531 const message = nls . localize ( 'cannotWorkspaceRedoDueToChanges' , "Could not redo '{0}' across all files because changes were made to {1}" , element . label , paths . join ( ', ' ) ) ;
519- return new InvalidWorkspaceVerificationResult ( message , null ) ;
532+ this . _notificationService . info ( message ) ;
533+ return new WorkspaceVerificationError ( this . redo ( resource ) ) ;
520534 }
521535
522- return new ValidWorkspaceVerificationResult ( affectedEditStacks ) ;
536+ return null ;
523537 }
524538
525539 private _workspaceRedo ( resource : URI , element : WorkspaceStackElement ) : Promise < void > | void {
526- const verificationResult = this . _verifyWorkspaceRedo ( element ) ;
527- if ( verificationResult . type === WorkspaceVerificationResultType . Invalid ) {
528- // cannot apply the workspace redo
529- this . _splitFutureWorkspaceElement ( element , verificationResult . ignoreResources ) ;
530- this . _notificationService . info ( verificationResult . message ) ;
531- return this . redo ( resource ) ;
540+ const affectedEditStacks = this . _getAffectedEditStacks ( element ) ;
541+ const verificationError = this . _checkWorkspaceRedo ( resource , element , affectedEditStacks ) ;
542+ if ( verificationError ) {
543+ return verificationError . returnValue ;
532544 }
533545
534- const affectedEditStacks = verificationResult . affectedEditStacks ;
535546 for ( const editStack of affectedEditStacks ) {
536547 editStack . future . pop ( ) ;
537548 editStack . past . push ( element ) ;
@@ -571,21 +582,8 @@ export class UndoRedoService implements IUndoRedoService {
571582 }
572583}
573584
574- const enum WorkspaceVerificationResultType {
575- Invalid = 0 ,
576- Valid = 1
577- }
578- class InvalidWorkspaceVerificationResult {
579- public readonly type = WorkspaceVerificationResultType . Invalid ;
580- constructor (
581- public readonly message : string ,
582- public readonly ignoreResources : RemovedResources | null
583- ) { }
584- }
585- class ValidWorkspaceVerificationResult {
586- public readonly type = WorkspaceVerificationResultType . Valid ;
587- constructor ( public readonly affectedEditStacks : ResourceEditStack [ ] ) { }
585+ class WorkspaceVerificationError {
586+ constructor ( public readonly returnValue : Promise < void > | void ) { }
588587}
589- type WorkspaceVerificationResult = InvalidWorkspaceVerificationResult | ValidWorkspaceVerificationResult ;
590588
591589registerSingleton ( IUndoRedoService , UndoRedoService ) ;
0 commit comments