Use unique resource for custom editor working copy

For #92037

Ensures that we can open multiple types of custom editors are opened for the same resource, and that our dirty tracking works as expected in that case (by only marking editors of a given type dirty)
This commit is contained in:
Matt Bierner
2020-03-12 22:15:21 -07:00
parent fb5dc0083b
commit 89d3b684a2

View File

@@ -536,6 +536,8 @@ namespace HotExitState {
export type State = typeof Allowed | typeof NotAllowed | Pending;
}
const customDocumentFileScheme = 'custom';
class MainThreadCustomEditorModel extends Disposable implements ICustomEditorModel, IWorkingCopy {
private _hotExitState: HotExitState.State = HotExitState.Allowed;
@@ -556,7 +558,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
constructor(
private readonly _proxy: extHostProtocol.ExtHostWebviewsShape,
private readonly _viewType: string,
private readonly _resource: URI,
private readonly _realResource: URI,
private readonly _editable: boolean,
@IWorkingCopyService workingCopyService: IWorkingCopyService,
@ILabelService private readonly _labelService: ILabelService,
@@ -564,6 +566,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
@IUndoRedoService private readonly _undoService: IUndoRedoService,
) {
super();
if (_editable) {
this._register(workingCopyService.registerWorkingCopy(this));
}
@@ -571,18 +574,26 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
dispose() {
if (this._editable) {
this._undoService.removeElements(this.resource);
this._undoService.removeElements(this._realResource);
}
this._proxy.$disposeWebviewCustomEditorDocument(this.resource, this._viewType);
this._proxy.$disposeWebviewCustomEditorDocument(this._realResource, this._viewType);
super.dispose();
}
//#region IWorkingCopy
public get resource() { return this._resource; } // custom://viewType/path/file
public get resource() {
// Make sure each custom editor has a unique resource for backup and edits
return URI.from({
scheme: customDocumentFileScheme,
authority: this._viewType,
path: this._realResource.path,
query: JSON.stringify(this._realResource.toJSON())
});
}
public get name() {
return basename(this._labelService.getUriLabel(this._resource));
return basename(this._labelService.getUriLabel(this._realResource));
}
public get capabilities(): WorkingCopyCapabilities {
@@ -617,7 +628,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
this._undoService.pushElement({
type: UndoRedoElementType.Resource,
resource: this.resource,
resource: this._realResource,
label: label ?? localize('defaultEditLabel', "Edit"),
undo: () => this.undo(),
redo: () => this.redo(),
@@ -635,7 +646,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
}
const undoneEdit = this._edits[this._currentEditIndex];
await this._proxy.$undo(this.resource, this.viewType, undoneEdit);
await this._proxy.$undo(this._realResource, this.viewType, undoneEdit);
this.change(() => {
--this._currentEditIndex;
@@ -653,7 +664,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
}
const redoneEdit = this._edits[this._currentEditIndex + 1];
await this._proxy.$redo(this.resource, this.viewType, redoneEdit);
await this._proxy.$redo(this._realResource, this.viewType, redoneEdit);
this.change(() => {
++this._currentEditIndex;
});
@@ -668,7 +679,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
: this._edits.splice(start, toRemove);
if (removedEdits.length) {
this._proxy.$disposeEdits(this.resource, this._viewType, removedEdits);
this._proxy.$disposeEdits(this._realResource, this._viewType, removedEdits);
}
}
@@ -700,7 +711,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
editsToRedo = this._edits.slice(this._currentEditIndex, this._savePoint);
}
this._proxy.$revert(this.resource, this.viewType, { undoneEdits: editsToUndo, redoneEdits: editsToRedo });
this._proxy.$revert(this._realResource, this.viewType, { undoneEdits: editsToUndo, redoneEdits: editsToRedo });
this.change(() => {
this._currentEditIndex = this._savePoint;
this.spliceEdits();
@@ -711,7 +722,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
if (!this._editable) {
return false;
}
await createCancelablePromise(token => this._proxy.$onSave(this.resource, this.viewType, token));
await createCancelablePromise(token => this._proxy.$onSave(this._realResource, this.viewType, token));
this.change(() => {
this._savePoint = this._currentEditIndex;
});
@@ -720,7 +731,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
public async saveAs(resource: URI, targetResource: URI, _options?: ISaveOptions): Promise<boolean> {
if (this._editable) {
await this._proxy.$onSaveAs(this.resource, this.viewType, targetResource);
await this._proxy.$onSaveAs(this._realResource, this.viewType, targetResource);
this.change(() => {
this._savePoint = this._currentEditIndex;
});
@@ -749,7 +760,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod
const pendingState = new HotExitState.Pending(
createCancelablePromise(token =>
this._proxy.$backup(this.resource.toJSON(), this.viewType, token)));
this._proxy.$backup(this._realResource.toJSON(), this.viewType, token)));
this._hotExitState = pendingState;
try {