custom editors - make conflict resolution actions appear (#118949)

This commit is contained in:
Benjamin Pasero 2021-03-16 11:14:41 +01:00
parent 5060cbe7bc
commit e787d6e384
No known key found for this signature in database
GPG key ID: E6380CC4C8219E65

View file

@ -9,14 +9,13 @@ import { basename, isEqual } from 'vs/base/common/resources';
import { Action, IAction } from 'vs/base/common/actions';
import { URI } from 'vs/base/common/uri';
import { FileOperationError, FileOperationResult } from 'vs/platform/files/common/files';
import { ITextFileService, ISaveErrorHandler, ITextFileEditorModel, IResolvedTextFileEditorModel } from 'vs/workbench/services/textfile/common/textfiles';
import { ITextFileService, ISaveErrorHandler, ITextFileEditorModel, ITextFileSaveAsOptions } from 'vs/workbench/services/textfile/common/textfiles';
import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { ResourceMap } from 'vs/base/common/map';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { ResourceEditorInput } from 'vs/workbench/common/editor/resourceEditorInput';
import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { TextFileContentProvider } from 'vs/workbench/contrib/files/common/files';
import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileEditorInput';
@ -54,7 +53,7 @@ export class TextFileSaveErrorHandler extends Disposable implements ISaveErrorHa
@IEditorService private readonly editorService: IEditorService,
@ITextModelService textModelService: ITextModelService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IStorageService private readonly storageService: IStorageService,
@IStorageService private readonly storageService: IStorageService
) {
super();
@ -78,7 +77,7 @@ export class TextFileSaveErrorHandler extends Disposable implements ISaveErrorHa
let activeConflictResolutionResource: URI | undefined;
const activeInput = this.editorService.activeEditor;
if (activeInput instanceof DiffEditorInput && activeInput.originalInput instanceof ResourceEditorInput && activeInput.modifiedInput instanceof FileEditorInput) {
if (activeInput instanceof DiffEditorInput) {
const resource = activeInput.originalInput.resource;
if (resource?.scheme === CONFLICT_RESOLUTION_SCHEME) {
isActiveEditorSaveConflictResolution = true;
@ -331,16 +330,26 @@ class SaveModelAsAction extends Action {
}
private findEditor(): IEditorIdentifier | undefined {
for (const group of this.editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE)) {
let preferredMatchingEditor: IEditorIdentifier | undefined;
let otherMatchingEditors: IEditorIdentifier[] = [];
FindEditorLoop: for (const group of this.editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE)) {
const editors = this.editorService.findEditors(this.model.resource, group);
for (const editor of editors) {
if (editor instanceof FileEditorInput) {
return { editor, groupId: group.id };
// We prefer a `FileEditorInput` for "Save As", but it is possible
// that a custom editor is leveraging the text file model and as
// such we need to fallback to any other editor having the resource
// opened for running the save.
preferredMatchingEditor = { editor, groupId: group.id };
break FindEditorLoop;
}
otherMatchingEditors.push({ editor, groupId: group.id });
}
}
return undefined;
return preferredMatchingEditor || otherMatchingEditors[0];
}
}
@ -387,9 +396,16 @@ class ConfigureSaveConflictAction extends Action {
}
}
export const acceptLocalChangesCommand = async (accessor: ServicesAccessor, resource: URI) => {
export const acceptLocalChangesCommand = (accessor: ServicesAccessor, resource: URI) => {
return acceptOrRevertLocalChangesCommand(accessor, resource, true);
};
export const revertLocalChangesCommand = (accessor: ServicesAccessor, resource: URI) => {
return acceptOrRevertLocalChangesCommand(accessor, resource, false);
};
async function acceptOrRevertLocalChangesCommand(accessor: ServicesAccessor, resource: URI, accept: boolean) {
const editorService = accessor.get(IEditorService);
const resolverService = accessor.get(ITextModelService);
const editorPane = editorService.activeEditorPane;
if (!editorPane) {
@ -399,58 +415,20 @@ export const acceptLocalChangesCommand = async (accessor: ServicesAccessor, reso
const editor = editorPane.input;
const group = editorPane.group;
const reference = await resolverService.createModelReference(resource);
const model = reference.object as IResolvedTextFileEditorModel;
// Hide any previously shown message about how to use these actions
clearPendingResolveSaveConflictMessages();
try {
// hide any previously shown message about how to use these actions
clearPendingResolveSaveConflictMessages();
// Trigger save
await model.save({ ignoreModifiedSince: true, reason: SaveReason.EXPLICIT });
// Reopen file input
await editorService.openEditor({ resource: model.resource }, group);
// Clean up
group.closeEditor(editor);
editor.dispose();
} finally {
reference.dispose();
}
};
export const revertLocalChangesCommand = async (accessor: ServicesAccessor, resource: URI) => {
const editorService = accessor.get(IEditorService);
const resolverService = accessor.get(ITextModelService);
const editorPane = editorService.activeEditorPane;
if (!editorPane) {
return;
// Accept or revert
if (accept) {
const options: ITextFileSaveAsOptions = { ignoreModifiedSince: true, reason: SaveReason.EXPLICIT };
await editorService.save({ editor, groupId: group.id }, options);
} else {
await editorService.revert({ editor, groupId: group.id });
}
const editor = editorPane.input;
const group = editorPane.group;
// Reopen original editor
await editorService.openEditor({ resource }, group);
const reference = await resolverService.createModelReference(resource);
const model = reference.object as ITextFileEditorModel;
try {
// hide any previously shown message about how to use these actions
clearPendingResolveSaveConflictMessages();
// Revert on model
await model.revert();
// Reopen file input
await editorService.openEditor({ resource: model.resource }, group);
// Clean up
group.closeEditor(editor);
editor.dispose();
} finally {
reference.dispose();
}
};
// Clean up
return group.closeEditor(editor);
}