@@ -15,7 +15,7 @@ import { IFileService, FileOperationEvent, FileOperation, FileChangesEvent, File
1515import { Schemas } from 'vs/base/common/network' ;
1616import { Event , Emitter } from 'vs/base/common/event' ;
1717import { URI } from 'vs/base/common/uri' ;
18- import { basename , isEqualOrParent , joinPath } from 'vs/base/common/resources' ;
18+ import { basename , isEqualOrParent , joinPath , isEqual } from 'vs/base/common/resources' ;
1919import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput' ;
2020import { IEditorGroupsService , IEditorGroup , GroupsOrder , IEditorReplacement , GroupChangeKind , preferredSideBySideGroupDirection } from 'vs/workbench/services/editor/common/editorGroupsService' ;
2121import { IResourceEditorInputType , SIDE_GROUP , IResourceEditorReplacement , IOpenEditorOverrideHandler , IEditorService , SIDE_GROUP_TYPE , ACTIVE_GROUP_TYPE , ISaveEditorsOptions , ISaveAllEditorsOptions , IRevertAllEditorsOptions , IBaseSaveRevertAllEditorOptions , IOpenEditorOverrideEntry , ICustomEditorViewTypesHandler , ICustomEditorInfo } from 'vs/workbench/services/editor/common/editorService' ;
@@ -36,6 +36,7 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace
3636import { indexOfPath } from 'vs/base/common/extpath' ;
3737import { DEFAULT_CUSTOM_EDITOR , updateViewTypeSchema , editorAssociationsConfigurationNode } from 'vs/workbench/services/editor/common/editorAssociationsSetting' ;
3838import { Extensions as ConfigurationExtensions , IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry' ;
39+ import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService' ;
3940
4041type CachedEditorInput = ResourceEditorInput | IFileEditorInput | UntitledTextEditorInput ;
4142type OpenInEditorGroup = IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE ;
@@ -72,7 +73,8 @@ export class EditorService extends Disposable implements EditorServiceImpl {
7273 @ILabelService private readonly labelService : ILabelService ,
7374 @IFileService private readonly fileService : IFileService ,
7475 @IConfigurationService private readonly configurationService : IConfigurationService ,
75- @IWorkspaceContextService private readonly contextService : IWorkspaceContextService
76+ @IWorkspaceContextService private readonly contextService : IWorkspaceContextService ,
77+ @IWorkingCopyService private readonly workingCopyService : IWorkingCopyService
7678 ) {
7779 super ( ) ;
7880
@@ -1109,7 +1111,9 @@ export class EditorService extends Disposable implements EditorServiceImpl {
11091111 //#endregion
11101112
11111113 //#region Custom View Type
1112- private customEditorViewTypesHandlers = new Map < string , ICustomEditorViewTypesHandler > ( ) ;
1114+
1115+ private readonly customEditorViewTypesHandlers = new Map < string , ICustomEditorViewTypesHandler > ( ) ;
1116+
11131117 registerCustomEditorViewTypesHandler ( source : string , handler : ICustomEditorViewTypesHandler ) : IDisposable {
11141118 if ( this . customEditorViewTypesHandlers . has ( source ) ) {
11151119 throw new Error ( `Use a different name for the custom editor component, ${ source } is already occupied.` ) ;
@@ -1150,6 +1154,64 @@ export class EditorService extends Disposable implements EditorServiceImpl {
11501154 }
11511155
11521156 //#endregion
1157+
1158+ //#region Editor Tracking
1159+
1160+ whenClosed ( resources : URI [ ] ) : Promise < void > {
1161+ let remainingResources = [ ...resources ] ;
1162+
1163+ return new Promise ( resolve => {
1164+ const listener = this . onDidCloseEditor ( async event => {
1165+ const detailsResource = toResource ( event . editor , { supportSideBySide : SideBySideEditor . DETAILS } ) ;
1166+ const masterResource = toResource ( event . editor , { supportSideBySide : SideBySideEditor . MASTER } ) ;
1167+
1168+ // Remove from resources to wait for being closed based on the
1169+ // resources from editors that got closed
1170+ remainingResources = remainingResources . filter ( resource => {
1171+ if ( isEqual ( resource , masterResource ) || isEqual ( resource , detailsResource ) ) {
1172+ return false ; // remove - the closing editor matches this resource
1173+ }
1174+
1175+ return true ; // keep - not yet closed
1176+ } ) ;
1177+
1178+ if ( remainingResources . length === 0 ) {
1179+ // If auto save is configured with the default delay (1s) it is possible
1180+ // to close the editor while the save still continues in the background. As such
1181+ // we have to also check if the files to track for are dirty and if so wait
1182+ // for them to get saved.
1183+ const dirtyFiles = resources . filter ( resource => this . workingCopyService . isDirty ( resource ) ) ;
1184+ if ( dirtyFiles . length > 0 ) {
1185+ await Promise . all ( dirtyFiles . map ( async dirtyFile => await this . joinResourceSaved ( dirtyFile ) ) ) ;
1186+ }
1187+
1188+ listener . dispose ( ) ;
1189+
1190+ resolve ( ) ;
1191+ }
1192+ } ) ;
1193+ } ) ;
1194+ }
1195+
1196+ private joinResourceSaved ( resource : URI ) : Promise < void > {
1197+ return new Promise ( resolve => {
1198+ if ( ! this . workingCopyService . isDirty ( resource ) ) {
1199+ return resolve ( ) ; // return early if resource is not dirty
1200+ }
1201+
1202+ // Otherwise resolve promise when resource is saved
1203+ const listener = this . workingCopyService . onDidChangeDirty ( workingCopy => {
1204+ if ( ! workingCopy . isDirty ( ) && isEqual ( resource , workingCopy . resource ) ) {
1205+ listener . dispose ( ) ;
1206+
1207+ resolve ( ) ;
1208+ }
1209+ } ) ;
1210+ } ) ;
1211+ }
1212+
1213+ //#endregion
1214+
11531215 dispose ( ) : void {
11541216 super . dispose ( ) ;
11551217
@@ -1265,9 +1327,9 @@ export class DelegatingEditorService implements IEditorService {
12651327 revert ( editors : IEditorIdentifier | IEditorIdentifier [ ] , options ?: IRevertOptions ) : Promise < boolean > { return this . editorService . revert ( editors , options ) ; }
12661328 revertAll ( options ?: IRevertAllEditorsOptions ) : Promise < boolean > { return this . editorService . revertAll ( options ) ; }
12671329
1268- registerCustomEditorViewTypesHandler ( source : string , handler : ICustomEditorViewTypesHandler ) : IDisposable {
1269- throw new Error ( 'Method not implemented.' ) ;
1270- }
1330+ registerCustomEditorViewTypesHandler ( source : string , handler : ICustomEditorViewTypesHandler ) : IDisposable { return this . editorService . registerCustomEditorViewTypesHandler ( source , handler ) ; }
1331+
1332+ whenClosed ( resources : URI [ ] ) : Promise < void > { return this . editorService . whenClosed ( resources ) ; }
12711333
12721334 //#endregion
12731335}
0 commit comments