mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-25 19:18:59 +01:00
pushEdits and wire up workspace#applyEdits
This commit is contained in:
@@ -10,20 +10,26 @@ import URI from 'vs/base/common/uri';
|
||||
import {sequence} from 'vs/base/common/async';
|
||||
import {illegalState} from 'vs/base/common/errors';
|
||||
import {TPromise} from 'vs/base/common/winjs.base';
|
||||
import {MainThreadWorkspaceShape} from 'vs/workbench/api/node/extHost.protocol';
|
||||
import {fromRange} from 'vs/workbench/api/node/extHostTypeConverters';
|
||||
import {IResourceEdit} from 'vs/editor/common/services/bulkEdit';
|
||||
import {ExtHostDocuments} from 'vs/workbench/api/node/extHostDocuments';
|
||||
|
||||
export interface TextDocumentWillSaveEvent {
|
||||
document: vscode.TextDocument;
|
||||
pushEdits(edits: vscode.TextEdit[]): void;
|
||||
waitUntil(t: Thenable<any>): void;
|
||||
}
|
||||
|
||||
export class ExtHostDocumentSaveParticipant {
|
||||
|
||||
private _callbacks = new CallbackList();
|
||||
private _documents: ExtHostDocuments;
|
||||
private _workspace: MainThreadWorkspaceShape;
|
||||
private _callbacks = new CallbackList();
|
||||
|
||||
constructor(documents: ExtHostDocuments) {
|
||||
constructor(documents: ExtHostDocuments, workspace: MainThreadWorkspaceShape) {
|
||||
this._documents = documents;
|
||||
this._workspace = workspace;
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
@@ -55,22 +61,58 @@ export class ExtHostDocumentSaveParticipant {
|
||||
private _deliverEventAsync(listener: Function, thisArg: any, document: vscode.TextDocument): TPromise<any> {
|
||||
|
||||
const promises: TPromise<any>[] = [];
|
||||
const resourceEdits: IResourceEdit[] = [];
|
||||
|
||||
const event: TextDocumentWillSaveEvent = Object.freeze({
|
||||
const {version} = document;
|
||||
|
||||
const event = Object.freeze(<TextDocumentWillSaveEvent> {
|
||||
document,
|
||||
pushEdits(edits) {
|
||||
if (Object.isFrozen(resourceEdits)) {
|
||||
throw illegalState('pushEdits can not be called anymore');
|
||||
}
|
||||
for (const {newText, range} of edits) {
|
||||
resourceEdits.push({
|
||||
newText,
|
||||
range: fromRange(range),
|
||||
resource: <URI> document.uri,
|
||||
});
|
||||
}
|
||||
},
|
||||
waitUntil(p: Thenable<any>) {
|
||||
if (Object.isFrozen(promises)) {
|
||||
throw illegalState('waitUntil can not be called async');
|
||||
throw illegalState('waitUntil can not be called anymore');
|
||||
}
|
||||
promises.push(TPromise.wrap(p));
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
// fire event
|
||||
listener.apply(thisArg, [event]);
|
||||
} finally {
|
||||
// freeze promises after event call
|
||||
Object.freeze(promises);
|
||||
return TPromise.join(promises).then(() => void 0, err => void 0 /* ignore */);
|
||||
|
||||
return TPromise.join(promises).then(() => {
|
||||
// freeze edits after async/sync is done
|
||||
Object.freeze(resourceEdits);
|
||||
|
||||
if (resourceEdits.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (version !== document.version) {
|
||||
// TODO@joh - fail?
|
||||
return;
|
||||
}
|
||||
|
||||
// apply edits iff any
|
||||
return this._workspace.$applyWorkspaceEdit(resourceEdits);
|
||||
|
||||
}, err => {
|
||||
// ignore error
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,13 +8,17 @@ import * as assert from 'assert';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import {TPromise} from 'vs/base/common/winjs.base';
|
||||
import {ExtHostDocuments} from 'vs/workbench/api/node/extHostDocuments';
|
||||
import {TextEdit, Position} from 'vs/workbench/api/node/extHostTypes';
|
||||
import {MainThreadWorkspaceShape} from 'vs/workbench/api/node/extHost.protocol';
|
||||
import {ExtHostDocumentSaveParticipant, TextDocumentWillSaveEvent} from 'vs/workbench/api/node/extHostDocumentSaveParticipant';
|
||||
import {OneGetThreadService} from './testThreadService';
|
||||
import * as EditorCommon from 'vs/editor/common/editorCommon';
|
||||
import {IResourceEdit} from 'vs/editor/common/services/bulkEdit';
|
||||
|
||||
suite('ExtHostDocumentSaveParticipant', () => {
|
||||
|
||||
let resource = URI.parse('foo:bar');
|
||||
let workspace = new class extends MainThreadWorkspaceShape { };
|
||||
let documents: ExtHostDocuments;
|
||||
|
||||
setup(() => {
|
||||
@@ -41,12 +45,12 @@ suite('ExtHostDocumentSaveParticipant', () => {
|
||||
});
|
||||
|
||||
test('no listeners, no problem', () => {
|
||||
const participant = new ExtHostDocumentSaveParticipant(documents);
|
||||
const participant = new ExtHostDocumentSaveParticipant(documents, workspace);
|
||||
return participant.$participateInSave(resource).then(() => assert.ok(true));
|
||||
});
|
||||
|
||||
test('event delivery', () => {
|
||||
const participant = new ExtHostDocumentSaveParticipant(documents);
|
||||
const participant = new ExtHostDocumentSaveParticipant(documents, workspace);
|
||||
|
||||
let event: TextDocumentWillSaveEvent;
|
||||
let sub = participant.onWillSaveTextDocumentEvent(function (e) {
|
||||
@@ -62,7 +66,7 @@ suite('ExtHostDocumentSaveParticipant', () => {
|
||||
});
|
||||
|
||||
test('event delivery, immutable', () => {
|
||||
const participant = new ExtHostDocumentSaveParticipant(documents);
|
||||
const participant = new ExtHostDocumentSaveParticipant(documents, workspace);
|
||||
|
||||
let event: TextDocumentWillSaveEvent;
|
||||
let sub = participant.onWillSaveTextDocumentEvent(function (e) {
|
||||
@@ -78,7 +82,7 @@ suite('ExtHostDocumentSaveParticipant', () => {
|
||||
});
|
||||
|
||||
test('event delivery, in subscriber order', () => {
|
||||
const participant = new ExtHostDocumentSaveParticipant(documents);
|
||||
const participant = new ExtHostDocumentSaveParticipant(documents, workspace);
|
||||
|
||||
let counter = 0;
|
||||
let sub1 = participant.onWillSaveTextDocumentEvent(function (event) {
|
||||
@@ -96,7 +100,7 @@ suite('ExtHostDocumentSaveParticipant', () => {
|
||||
});
|
||||
|
||||
test('event delivery, waitUntil', () => {
|
||||
const participant = new ExtHostDocumentSaveParticipant(documents);
|
||||
const participant = new ExtHostDocumentSaveParticipant(documents, workspace);
|
||||
|
||||
let sub = participant.onWillSaveTextDocumentEvent(function (event) {
|
||||
|
||||
@@ -112,7 +116,7 @@ suite('ExtHostDocumentSaveParticipant', () => {
|
||||
});
|
||||
|
||||
test('event delivery, waitUntil must be called sync', () => {
|
||||
const participant = new ExtHostDocumentSaveParticipant(documents);
|
||||
const participant = new ExtHostDocumentSaveParticipant(documents, workspace);
|
||||
|
||||
let sub = participant.onWillSaveTextDocumentEvent(function (event) {
|
||||
|
||||
@@ -135,7 +139,7 @@ suite('ExtHostDocumentSaveParticipant', () => {
|
||||
});
|
||||
|
||||
test('event delivery, waitUntil failure handling', () => {
|
||||
const participant = new ExtHostDocumentSaveParticipant(documents);
|
||||
const participant = new ExtHostDocumentSaveParticipant(documents, workspace);
|
||||
|
||||
let sub1 = participant.onWillSaveTextDocumentEvent(function (e) {
|
||||
e.waitUntil(TPromise.wrapError('dddd'));
|
||||
@@ -153,4 +157,24 @@ suite('ExtHostDocumentSaveParticipant', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('event delivery, pushEdits sync', () => {
|
||||
|
||||
let edits: IResourceEdit[];
|
||||
const participant = new ExtHostDocumentSaveParticipant(documents, new class extends MainThreadWorkspaceShape {
|
||||
$applyWorkspaceEdit(_edits) {
|
||||
edits = _edits;
|
||||
return TPromise.as(true);
|
||||
}
|
||||
});
|
||||
|
||||
let sub = participant.onWillSaveTextDocumentEvent(function (e) {
|
||||
e.pushEdits([TextEdit.insert(new Position(0, 0), 'bar')]);
|
||||
});
|
||||
|
||||
return participant.$participateInSave(resource).then(() => {
|
||||
sub.dispose();
|
||||
|
||||
assert.equal(edits.length, 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user