Skip to content

Commit 07e9310

Browse files
author
Benjamin Pasero
committed
file commands 💄 async/await
1 parent c327c4f commit 07e9310

1 file changed

Lines changed: 124 additions & 115 deletions

File tree

src/vs/workbench/contrib/files/browser/fileCommands.ts

Lines changed: 124 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
3737
import { IEditorService, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
3838
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
3939
import { ILabelService } from 'vs/platform/label/common/label';
40-
import { onUnexpectedError } from 'vs/base/common/errors';
4140
import { basename, toLocalResource, joinPath } from 'vs/base/common/resources';
4241
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
4342
import { 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

258269
CommandsRegistry.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

493501
CommandsRegistry.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

Comments
 (0)