diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 4cca5c91cf0bb9564435f6e8bb5510a6b5636d87..00e8ef06a0b5a94751e3e7c67dafb9d159d4c3b6 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -3557,6 +3557,52 @@ declare namespace vscode { contentChanges: TextDocumentContentChangeEvent[]; } + /** + * An event that is fired when a [document](#TextDocument) will be saved. + * + * To make modifications to the document before it is being saved, call the + * [`waitUntil`](#TextDocumentWillSaveEvent.waitUntil)-function with a thenable + * that resolves to an array of [text edits](#TextEdit). + */ + export interface TextDocumentWillSaveEvent { + + /** + * The document that will be saved. + */ + document: vscode.TextDocument; + + /** + * Allows to pause the event loop and to apply [pre-save-edits](#TextEdit). + * Edits of subsequent calls to this function will be applied in order. The + * edits will be *ignored* if concurrent modifications of the document happened. + * + * *Note:* This function can only be called during event dispatch and not + * in an asynchronous manner: + * + * ```ts + * workspace.onWillSaveTextDocument(event => { + // async, will *throw* an error + setTimeout(() => event.waitUntil(promise)); + + // sync, OK + * event.waitUntil(promise); + * }) + * ``` + * + * @param thenable A thenable that resolves to [pre-save-edits](#TextEdit). + */ + waitUntil(thenable: Thenable): void; + + /** + * Allows to pause the event loop until the provided thenable resolved. + * + * *Note:* This function can only be called during event dispatch. + * + * @param thenable A thenable that delays saving. + */ + waitUntil(thenable: Thenable): void; + } + /** * Namespace for dealing with the current workspace. A workspace is the representation * of the folder that has been opened. There is no workspace when just a file but not a @@ -3692,6 +3738,11 @@ declare namespace vscode { */ export const onDidChangeTextDocument: Event; + /** + * An event that is emitted when a [text document](#TextDocument) will be saved to disk. + */ + export const onWillSaveTextDocument: Event; + /** * An event that is emitted when a [text document](#TextDocument) is saved to disk. */ diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index 163fd0a8e6a695b0912c589dc1447c04da45cd58..2615b5447b864be4b4ff2cc9fa6175d62008fb12 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -103,6 +103,7 @@ export class ExtHostAPIImplementation { const extHostHeapMonitor = col.define(ExtHostContext.ExtHostHeapService).set(new ExtHostHeapService()); const extHostDocuments = col.define(ExtHostContext.ExtHostDocuments).set(new ExtHostDocuments(threadService)); + const estHostDocumentSaveParticipant = col.define(ExtHostContext.ExtHostDocumentSaveParticipant).set(new ExtHostDocumentSaveParticipant(extHostDocuments, threadService.get(MainContext.MainThreadWorkspace))); const extHostEditors = col.define(ExtHostContext.ExtHostEditors).set(new ExtHostEditors(threadService, extHostDocuments)); const extHostCommands = col.define(ExtHostContext.ExtHostCommands).set(new ExtHostCommands(threadService, extHostEditors)); const extHostConfiguration = col.define(ExtHostContext.ExtHostConfiguration).set(new ExtHostConfiguration(threadService.get(MainContext.MainThreadConfiguration))); @@ -111,7 +112,6 @@ export class ExtHostAPIImplementation { const extHostFileSystemEvent = col.define(ExtHostContext.ExtHostFileSystemEventService).set(new ExtHostFileSystemEventService()); const extHostQuickOpen = col.define(ExtHostContext.ExtHostQuickOpen).set(new ExtHostQuickOpen(threadService)); const extHostTerminalService = col.define(ExtHostContext.ExtHostTerminalService).set(new ExtHostTerminalService(threadService)); - col.define(ExtHostContext.ExtHostDocumentSaveParticipant).set(new ExtHostDocumentSaveParticipant(extHostDocuments, threadService.get(MainContext.MainThreadWorkspace))); col.define(ExtHostContext.ExtHostExtensionService).set(extensionService); col.finish(false, threadService); @@ -325,6 +325,9 @@ export class ExtHostAPIImplementation { onDidSaveTextDocument: (listener, thisArgs?, disposables?) => { return extHostDocuments.onDidSaveDocument(listener, thisArgs, disposables); }, + onWillSaveTextDocument: (listener, thisArgs?, disposables?) => { + return estHostDocumentSaveParticipant.onWillSaveTextDocumentEvent(listener, thisArgs, disposables); + }, onDidChangeConfiguration: (listener: () => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) => { return extHostConfiguration.onDidChangeConfiguration(listener, thisArgs, disposables); }, diff --git a/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts b/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts index 319ae064189db90328fa5266c7c39abeb8fea646..e8a551d103a959f8394d6c233fd500c499d9d049 100644 --- a/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts +++ b/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts @@ -16,10 +16,6 @@ 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; - waitUntil(t: Thenable): void; -} export class ExtHostDocumentSaveParticipant extends ExtHostDocumentSaveParticipantShape { @@ -37,7 +33,7 @@ export class ExtHostDocumentSaveParticipant extends ExtHostDocumentSaveParticipa this._callbacks.dispose(); } - get onWillSaveTextDocumentEvent(): Event { + get onWillSaveTextDocumentEvent(): Event { return (listener, thisArg, disposables) => { this._callbacks.add(listener, thisArg); const result = { dispose: () => this._callbacks.remove(listener, thisArg) }; @@ -65,7 +61,7 @@ export class ExtHostDocumentSaveParticipant extends ExtHostDocumentSaveParticipa const {version} = document; - const event = Object.freeze( { + const event = Object.freeze( { document, waitUntil(p: Thenable) { if (Object.isFrozen(promises)) { diff --git a/src/vs/workbench/test/node/api/extHostDocumentSaveParticipant.test.ts b/src/vs/workbench/test/node/api/extHostDocumentSaveParticipant.test.ts index 60f6d16f6885066b868cd3cefc4a12b27174b57f..2ed91e8f17a212369401ca355ccc3e3cb9dcab03 100644 --- a/src/vs/workbench/test/node/api/extHostDocumentSaveParticipant.test.ts +++ b/src/vs/workbench/test/node/api/extHostDocumentSaveParticipant.test.ts @@ -10,7 +10,7 @@ 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 {ExtHostDocumentSaveParticipant} 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'; @@ -52,7 +52,7 @@ suite('ExtHostDocumentSaveParticipant', () => { test('event delivery', () => { const participant = new ExtHostDocumentSaveParticipant(documents, workspace); - let event: TextDocumentWillSaveEvent; + let event: vscode.TextDocumentWillSaveEvent; let sub = participant.onWillSaveTextDocumentEvent(function (e) { event = e; }); @@ -68,7 +68,7 @@ suite('ExtHostDocumentSaveParticipant', () => { test('event delivery, immutable', () => { const participant = new ExtHostDocumentSaveParticipant(documents, workspace); - let event: TextDocumentWillSaveEvent; + let event: vscode.TextDocumentWillSaveEvent; let sub = participant.onWillSaveTextDocumentEvent(function (e) { event = e; }); @@ -145,7 +145,7 @@ suite('ExtHostDocumentSaveParticipant', () => { e.waitUntil(TPromise.wrapError('dddd')); }); - let event: TextDocumentWillSaveEvent; + let event: vscode.TextDocumentWillSaveEvent; let sub2 = participant.onWillSaveTextDocumentEvent(function (e) { event = e; });