@@ -37,7 +37,6 @@ import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
3737import { IEditorService , SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService' ;
3838import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService' ;
3939import { ILabelService } from 'vs/platform/label/common/label' ;
40- import { onUnexpectedError } from 'vs/base/common/errors' ;
4140import { basename , toLocalResource , joinPath } from 'vs/base/common/resources' ;
4241import { IDisposable , dispose } from 'vs/base/common/lifecycle' ;
4342import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService' ;
@@ -106,7 +105,7 @@ export const newWindowCommand = (accessor: ServicesAccessor, options?: INewWindo
106105 windowsService . openNewWindow ( options ) ;
107106} ;
108107
109- function save (
108+ async function save (
110109 resource : URI | null ,
111110 isSaveAs : boolean ,
112111 options : ISaveOptions | undefined ,
@@ -117,99 +116,110 @@ function save(
117116 editorGroupService : IEditorGroupsService ,
118117 environmentService : IWorkbenchEnvironmentService
119118) : Promise < any > {
119+ if ( ! resource || ( ! fileService . canHandleResource ( resource ) && resource . scheme !== Schemas . untitled ) ) {
120+ return ; // save is not supported
121+ }
120122
121- function ensureForcedSave ( options ?: ISaveOptions ) : ISaveOptions {
122- if ( ! options ) {
123- options = { force : true } ;
124- } else {
125- options . force = true ;
126- }
127-
128- return options ;
123+ // Save As (or Save untitled with associated path)
124+ if ( isSaveAs || resource . scheme === Schemas . untitled ) {
125+ return doSaveAs ( resource , isSaveAs , options , editorService , fileService , untitledEditorService , textFileService , editorGroupService , environmentService ) ;
129126 }
130127
131- if ( resource && ( fileService . canHandleResource ( resource ) || resource . scheme === Schemas . untitled ) ) {
128+ // Save
129+ return doSave ( resource , options , editorService , textFileService ) ;
130+ }
132131
133- // Save As (or Save untitled with associated path)
134- if ( isSaveAs || resource . scheme === Schemas . untitled ) {
135- let encodingOfSource : string | undefined ;
136- if ( resource . scheme === Schemas . untitled ) {
137- encodingOfSource = untitledEditorService . getEncoding ( resource ) ;
138- } else if ( fileService . canHandleResource ( resource ) ) {
139- const textModel = textFileService . models . get ( resource ) ;
140- encodingOfSource = textModel && textModel . getEncoding ( ) ; // text model can be null e.g. if this is a binary file!
141- }
132+ async function doSaveAs (
133+ resource : URI ,
134+ isSaveAs : boolean ,
135+ options : ISaveOptions | undefined ,
136+ editorService : IEditorService ,
137+ fileService : IFileService ,
138+ untitledEditorService : IUntitledEditorService ,
139+ textFileService : ITextFileService ,
140+ editorGroupService : IEditorGroupsService ,
141+ environmentService : IWorkbenchEnvironmentService
142+ ) : Promise < boolean > {
143+ let viewStateOfSource : IEditorViewState | null = null ;
144+ const activeTextEditorWidget = getCodeEditor ( editorService . activeTextEditorWidget ) ;
145+ if ( activeTextEditorWidget ) {
146+ const activeResource = toResource ( editorService . activeEditor , { supportSideBySide : SideBySideEditor . MASTER } ) ;
147+ if ( activeResource && ( fileService . canHandleResource ( activeResource ) || resource . scheme === Schemas . untitled ) && activeResource . toString ( ) === resource . toString ( ) ) {
148+ viewStateOfSource = activeTextEditorWidget . saveViewState ( ) ;
149+ }
150+ }
142151
143- let viewStateOfSource : IEditorViewState | null ;
144- const activeTextEditorWidget = getCodeEditor ( editorService . activeTextEditorWidget ) ;
145- if ( activeTextEditorWidget ) {
146- const activeResource = toResource ( editorService . activeEditor , { supportSideBySide : SideBySideEditor . MASTER } ) ;
147- if ( activeResource && ( fileService . canHandleResource ( activeResource ) || resource . scheme === Schemas . untitled ) && activeResource . toString ( ) === resource . toString ( ) ) {
148- viewStateOfSource = activeTextEditorWidget . saveViewState ( ) ;
149- }
150- }
152+ // Special case: an untitled file with associated path gets saved directly unless "saveAs" is true
153+ let target : URI | undefined ;
154+ if ( ! isSaveAs && resource . scheme === Schemas . untitled && untitledEditorService . hasAssociatedFilePath ( resource ) ) {
155+ const result = await textFileService . save ( resource , options ) ;
156+ if ( result ) {
157+ target = toLocalResource ( resource , environmentService . configuration . remoteAuthority ) ;
158+ }
159+ }
151160
152- // Special case: an untitled file with associated path gets saved directly unless "saveAs" is true
153- let savePromise : Promise < URI | undefined > ;
154- if ( ! isSaveAs && resource . scheme === Schemas . untitled && untitledEditorService . hasAssociatedFilePath ( resource ) ) {
155- savePromise = textFileService . save ( resource , options ) . then ( result => {
156- if ( result ) {
157- return toLocalResource ( resource , environmentService . configuration . remoteAuthority ) ;
158- }
161+ // Otherwise, really "Save As..."
162+ else {
159163
160- return undefined ;
161- } ) ;
162- }
164+ // Force a change to the file to trigger external watchers if any
165+ // fixes https://github.com/Microsoft/vscode/issues/59655
166+ options = ensureForcedSave ( options ) ;
163167
164- // Otherwise, really "Save As..."
165- else {
168+ target = await textFileService . saveAs ( resource , undefined , options ) ;
169+ }
166170
167- // Force a change to the file to trigger external watchers if any
168- // fixes https://github.com/Microsoft/vscode/issues/59655
169- options = ensureForcedSave ( options ) ;
171+ if ( ! target || target . toString ( ) === resource . toString ( ) ) {
172+ return false ; // save canceled or same resource used
173+ }
170174
171- savePromise = textFileService . saveAs ( resource , undefined , options ) ;
172- }
175+ const replacement : IResourceInput = {
176+ resource : target ,
177+ options : {
178+ pinned : true ,
179+ viewState : viewStateOfSource || undefined
180+ }
181+ } ;
173182
174- return savePromise . then ( target => {
175- if ( ! target || target . toString ( ) === resource . toString ( ) ) {
176- return false ; // save canceled or same resource used
177- }
183+ await Promise . all ( editorGroupService . groups . map ( group =>
184+ editorService . replaceEditors ( [ {
185+ editor : { resource } ,
186+ replacement
187+ } ] , group ) ) ) ;
178188
179- const replacement : IResourceInput = {
180- resource : target ,
181- encoding : encodingOfSource ,
182- options : {
183- pinned : true ,
184- viewState : viewStateOfSource || undefined
185- }
186- } ;
189+ return true ;
190+ }
187191
188- return Promise . all ( editorGroupService . groups . map ( g =>
189- editorService . replaceEditors ( [ {
190- editor : { resource } ,
191- replacement
192- } ] , g ) ) ) . then ( ( ) => true ) ;
193- } ) ;
194- }
192+ async function doSave (
193+ resource : URI ,
194+ options : ISaveOptions | undefined ,
195+ editorService : IEditorService ,
196+ textFileService : ITextFileService
197+ ) : Promise < boolean > {
198+
199+ // Pin the active editor if we are saving it
200+ const activeControl = editorService . activeControl ;
201+ const activeEditorResource = activeControl && activeControl . input && activeControl . input . getResource ( ) ;
202+ if ( activeControl && activeEditorResource && activeEditorResource . toString ( ) === resource . toString ( ) ) {
203+ activeControl . group . pinEditor ( activeControl . input ) ;
204+ }
195205
196- // Pin the active editor if we are saving it
197- const activeControl = editorService . activeControl ;
198- const activeEditorResource = activeControl && activeControl . input && activeControl . input . getResource ( ) ;
199- if ( activeControl && activeEditorResource && activeEditorResource . toString ( ) === resource . toString ( ) ) {
200- activeControl . group . pinEditor ( activeControl . input ) ;
201- }
206+ // Just save (force a change to the file to trigger external watchers if any)
207+ options = ensureForcedSave ( options ) ;
202208
203- // Just save (force a change to the file to trigger external watchers if any)
204- options = ensureForcedSave ( options ) ;
209+ return textFileService . save ( resource , options ) ;
210+ }
205211
206- return textFileService . save ( resource , options ) ;
212+ function ensureForcedSave ( options ?: ISaveOptions ) : ISaveOptions {
213+ if ( ! options ) {
214+ options = { force : true } ;
215+ } else {
216+ options . force = true ;
207217 }
208218
209- return Promise . resolve ( false ) ;
219+ return options ;
210220}
211221
212- function saveAll ( saveAllArguments : any , editorService : IEditorService , untitledEditorService : IUntitledEditorService ,
222+ async function saveAll ( saveAllArguments : any , editorService : IEditorService , untitledEditorService : IUntitledEditorService ,
213223 textFileService : ITextFileService , editorGroupService : IEditorGroupsService ) : Promise < any > {
214224
215225 // Store some properties per untitled file to restore later after save is completed
@@ -239,38 +249,39 @@ function saveAll(saveAllArguments: any, editorService: IEditorService, untitledE
239249 } ) ;
240250
241251 // Save all
242- return textFileService . saveAll ( saveAllArguments ) . then ( result => {
243- groupIdToUntitledResourceInput . forEach ( ( inputs , groupId ) => {
244- // Update untitled resources to the saved ones, so we open the proper files
245- inputs . forEach ( i => {
246- const targetResult = result . results . filter ( r => r . success && r . source . toString ( ) === i . resource . toString ( ) ) . pop ( ) ;
247- if ( targetResult && targetResult . target ) {
248- i . resource = targetResult . target ;
249- }
250- } ) ;
251- editorService . openEditors ( inputs , groupId ) ;
252+ const result = await textFileService . saveAll ( saveAllArguments ) ;
253+
254+ // Update untitled resources to the saved ones, so we open the proper files
255+ groupIdToUntitledResourceInput . forEach ( ( inputs , groupId ) => {
256+ inputs . forEach ( i => {
257+ const targetResult = result . results . filter ( r => r . success && r . source . toString ( ) === i . resource . toString ( ) ) . pop ( ) ;
258+ if ( targetResult && targetResult . target ) {
259+ i . resource = targetResult . target ;
260+ }
252261 } ) ;
262+
263+ editorService . openEditors ( inputs , groupId ) ;
253264 } ) ;
254265}
255266
256267// Command registration
257268
258269CommandsRegistry . registerCommand ( {
259270 id : REVERT_FILE_COMMAND_ID ,
260- handler : ( accessor , resource : URI | object ) => {
271+ handler : async ( accessor , resource : URI | object ) => {
261272 const editorService = accessor . get ( IEditorService ) ;
262273 const textFileService = accessor . get ( ITextFileService ) ;
263274 const notificationService = accessor . get ( INotificationService ) ;
264275 const resources = getMultiSelectedResources ( resource , accessor . get ( IListService ) , editorService )
265276 . filter ( resource => resource . scheme !== Schemas . untitled ) ;
266277
267278 if ( resources . length ) {
268- return textFileService . revertAll ( resources , { force : true } ) . then ( undefined , error => {
279+ try {
280+ await textFileService . revertAll ( resources , { force : true } ) ;
281+ } catch ( error ) {
269282 notificationService . error ( nls . localize ( 'genericRevertError' , "Failed to revert '{0}': {1}" , resources . map ( r => basename ( r ) ) . join ( ', ' ) , toErrorMessage ( error , false ) ) ) ;
270- } ) ;
283+ }
271284 }
272-
273- return Promise . resolve ( true ) ;
274285 }
275286} ) ;
276287
@@ -281,24 +292,21 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
281292 mac : {
282293 primary : KeyMod . WinCtrl | KeyCode . Enter
283294 } ,
284- id : OPEN_TO_SIDE_COMMAND_ID , handler : ( accessor , resource : URI | object ) => {
295+ id : OPEN_TO_SIDE_COMMAND_ID , handler : async ( accessor , resource : URI | object ) => {
285296 const editorService = accessor . get ( IEditorService ) ;
286297 const listService = accessor . get ( IListService ) ;
287298 const fileService = accessor . get ( IFileService ) ;
288299 const resources = getMultiSelectedResources ( resource , listService , editorService ) ;
289300
290301 // Set side input
291302 if ( resources . length ) {
292- return fileService . resolveAll ( resources . map ( resource => ( { resource } ) ) ) . then ( resolved => {
293- const editors = resolved . filter ( r => r . stat && r . success && ! r . stat . isDirectory ) . map ( r => ( {
294- resource : r . stat ! . resource
295- } ) ) ;
303+ const resolved = await fileService . resolveAll ( resources . map ( resource => ( { resource } ) ) ) ;
304+ const editors = resolved . filter ( r => r . stat && r . success && ! r . stat . isDirectory ) . map ( r => ( {
305+ resource : r . stat ! . resource
306+ } ) ) ;
296307
297- return editorService . openEditors ( editors , SIDE_GROUP ) ;
298- } ) ;
308+ await editorService . openEditors ( editors , SIDE_GROUP ) ;
299309 }
300-
301- return Promise . resolve ( true ) ;
302310 }
303311} ) ;
304312
@@ -393,7 +401,7 @@ CommandsRegistry.registerCommand({
393401 editorService . openEditor ( {
394402 leftResource : globalResourceToCompare ,
395403 rightResource
396- } ) . then ( undefined , onUnexpectedError ) ;
404+ } ) ;
397405 }
398406 }
399407} ) ;
@@ -492,27 +500,28 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
492500
493501CommandsRegistry . registerCommand ( {
494502 id : REVEAL_IN_EXPLORER_COMMAND_ID ,
495- handler : ( accessor , resource : URI | object ) => {
503+ handler : async ( accessor , resource : URI | object ) => {
496504 const viewletService = accessor . get ( IViewletService ) ;
497505 const contextService = accessor . get ( IWorkspaceContextService ) ;
498506 const explorerService = accessor . get ( IExplorerService ) ;
499507 const uri = getResourceForCommand ( resource , accessor . get ( IListService ) , accessor . get ( IEditorService ) ) ;
500508
501- viewletService . openViewlet ( VIEWLET_ID , false ) . then ( ( viewlet : ExplorerViewlet ) => {
502- if ( uri && contextService . isInsideWorkspace ( uri ) ) {
503- const explorerView = viewlet . getExplorerView ( ) ;
504- if ( explorerView ) {
505- explorerView . setExpanded ( true ) ;
506- explorerService . select ( uri , true ) . then ( ( ) => explorerView . focus ( ) , onUnexpectedError ) ;
507- }
508- } else {
509- const openEditorsView = viewlet . getOpenEditorsView ( ) ;
510- if ( openEditorsView ) {
511- openEditorsView . setExpanded ( true ) ;
512- openEditorsView . focus ( ) ;
513- }
509+ const viewlet = await viewletService . openViewlet ( VIEWLET_ID , false ) as ExplorerViewlet ;
510+
511+ if ( uri && contextService . isInsideWorkspace ( uri ) ) {
512+ const explorerView = viewlet . getExplorerView ( ) ;
513+ if ( explorerView ) {
514+ explorerView . setExpanded ( true ) ;
515+ await explorerService . select ( uri , true ) ;
516+ explorerView . focus ( ) ;
514517 }
515- } ) ;
518+ } else {
519+ const openEditorsView = viewlet . getOpenEditorsView ( ) ;
520+ if ( openEditorsView ) {
521+ openEditorsView . setExpanded ( true ) ;
522+ openEditorsView . focus ( ) ;
523+ }
524+ }
516525 }
517526} ) ;
518527
0 commit comments