diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index 347ae230bbe..163fd0a8e6a 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -13,6 +13,7 @@ import product from 'vs/platform/product'; import pkg from 'vs/platform/package'; import {ExtHostFileSystemEventService} from 'vs/workbench/api/node/extHostFileSystemEventService'; import {ExtHostDocuments} from 'vs/workbench/api/node/extHostDocuments'; +import {ExtHostDocumentSaveParticipant} from 'vs/workbench/api/node/extHostDocumentSaveParticipant'; import {ExtHostConfiguration} from 'vs/workbench/api/node/extHostConfiguration'; import {ExtHostDiagnostics} from 'vs/workbench/api/node/extHostDiagnostics'; import {ExtHostWorkspace} from 'vs/workbench/api/node/extHostWorkspace'; @@ -110,6 +111,7 @@ 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); diff --git a/src/vs/workbench/api/node/extHost.contribution.ts b/src/vs/workbench/api/node/extHost.contribution.ts index 56753b05010..94891932d8f 100644 --- a/src/vs/workbench/api/node/extHost.contribution.ts +++ b/src/vs/workbench/api/node/extHost.contribution.ts @@ -39,6 +39,7 @@ import {MainProcessTextMateSyntax} from 'vs/editor/node/textMate/TMSyntax'; import {MainProcessTextMateSnippet} from 'vs/editor/node/textMate/TMSnippets'; import {JSONValidationExtensionPoint} from 'vs/platform/jsonschemas/common/jsonValidationExtensionPoint'; import {LanguageConfigurationFileHandler} from 'vs/editor/node/languageConfiguration'; +import {SaveParticipant} from './mainThreadSaveParticipant'; export class ExtHostContribution implements IWorkbenchContribution { @@ -89,6 +90,7 @@ export class ExtHostContribution implements IWorkbenchContribution { create(LanguageConfigurationFileHandler); create(MainThreadFileSystemEventService); create(MainThreadHeapService); + create(SaveParticipant); } } diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 7dabd44f575..36d24bcd965 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -232,6 +232,10 @@ export abstract class ExtHostDocumentsShape { $acceptModelChanged(strURL: string, events: editorCommon.IModelContentChangedEvent2[]): void { throw ni(); } } +export abstract class ExtHostDocumentSaveParticipantShape { + $participateInSave(resource: URI): TPromise { throw ni(); } +} + export interface ITextEditorAddData { id: string; document: URI; @@ -342,6 +346,7 @@ export const ExtHostContext = { ExtHostConfiguration: createExtId('ExtHostConfiguration', ExtHostConfigurationShape), ExtHostDiagnostics: createExtId('ExtHostDiagnostics', ExtHostDiagnosticsShape), ExtHostDocuments: createExtId('ExtHostDocuments', ExtHostDocumentsShape), + ExtHostDocumentSaveParticipant: createExtId('ExtHostDocumentSaveParticipant', ExtHostDocumentSaveParticipantShape), ExtHostEditors: createExtId('ExtHostEditors', ExtHostEditorsShape), ExtHostFileSystemEventService: createExtId('ExtHostFileSystemEventService', ExtHostFileSystemEventServiceShape), ExtHostHeapService: createExtId('ExtHostHeapMonitor', ExtHostHeapServiceShape), diff --git a/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts b/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts index ada1b48de41..319ae064189 100644 --- a/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts +++ b/src/vs/workbench/api/node/extHostDocumentSaveParticipant.ts @@ -10,7 +10,7 @@ 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 {MainThreadWorkspaceShape, ExtHostDocumentSaveParticipantShape} from 'vs/workbench/api/node/extHost.protocol'; import {TextEdit} from 'vs/workbench/api/node/extHostTypes'; import {fromRange} from 'vs/workbench/api/node/extHostTypeConverters'; import {IResourceEdit} from 'vs/editor/common/services/bulkEdit'; @@ -21,13 +21,14 @@ export interface TextDocumentWillSaveEvent { waitUntil(t: Thenable): void; } -export class ExtHostDocumentSaveParticipant { +export class ExtHostDocumentSaveParticipant extends ExtHostDocumentSaveParticipantShape { private _documents: ExtHostDocuments; private _workspace: MainThreadWorkspaceShape; private _callbacks = new CallbackList(); constructor(documents: ExtHostDocuments, workspace: MainThreadWorkspaceShape) { + super(); this._documents = documents; this._workspace = workspace; } diff --git a/src/vs/workbench/parts/files/common/editors/saveParticipant.ts b/src/vs/workbench/api/node/mainThreadSaveParticipant.ts similarity index 72% rename from src/vs/workbench/parts/files/common/editors/saveParticipant.ts rename to src/vs/workbench/api/node/mainThreadSaveParticipant.ts index 40be88ff9cf..c6af4737f32 100644 --- a/src/vs/workbench/parts/files/common/editors/saveParticipant.ts +++ b/src/vs/workbench/api/node/mainThreadSaveParticipant.ts @@ -8,7 +8,7 @@ import {IDisposable, dispose} from 'vs/base/common/lifecycle'; import {TPromise} from 'vs/base/common/winjs.base'; import {ICodeEditorService} from 'vs/editor/common/services/codeEditorService'; -import {IWorkbenchContribution} from 'vs/workbench/common/contributions'; +import {IThreadService} from 'vs/workbench/services/thread/common/threadService'; import {ISaveParticipant, ITextFileEditorModel} from 'vs/workbench/parts/files/common/files'; import {IFilesConfiguration} from 'vs/platform/files/common/files'; import {IPosition, IModel} from 'vs/editor/common/editorCommon'; @@ -16,28 +16,24 @@ import {Selection} from 'vs/editor/common/core/selection'; import {trimTrailingWhitespace} from 'vs/editor/common/commands/trimTrailingWhitespaceCommand'; import {IConfigurationService} from 'vs/platform/configuration/common/configuration'; import {TextFileEditorModel} from 'vs/workbench/parts/files/common/editors/textFileEditorModel'; +import {ExtHostContext, ExtHostDocumentSaveParticipantShape} from './extHost.protocol'; -// The save participant can change a model before its saved to support various scenarios like trimming trailing whitespace -export class SaveParticipant implements ISaveParticipant, IWorkbenchContribution { - private trimTrailingWhitespace: boolean; - private toUnbind: IDisposable[]; +// TODO@joh move this to the extension host +class TrimWhitespaceParticipant { + + private trimTrailingWhitespace: boolean = false; + private toUnbind: IDisposable[] = []; constructor( @IConfigurationService private configurationService: IConfigurationService, @ICodeEditorService private codeEditorService: ICodeEditorService ) { - this.toUnbind = []; - this.trimTrailingWhitespace = false; - this.registerListeners(); this.onConfigurationChange(this.configurationService.getConfiguration()); - - // Hook into model - TextFileEditorModel.setSaveParticipant(this); } - public getId(): string { - return 'vs.files.saveparticipant'; + public dispose(): void { + this.toUnbind = dispose(this.toUnbind); } private registerListeners(): void { @@ -48,11 +44,10 @@ export class SaveParticipant implements ISaveParticipant, IWorkbenchContribution this.trimTrailingWhitespace = configuration && configuration.files && configuration.files.trimTrailingWhitespace; } - public participate(model: ITextFileEditorModel, env: { isAutoSaved: boolean }): TPromise { + public participate(model: ITextFileEditorModel, env: { isAutoSaved: boolean }): any { if (this.trimTrailingWhitespace) { this.doTrimTrailingWhitespace(model.textEditorModel, env.isAutoSaved); } - return TPromise.as(undefined); } private doTrimTrailingWhitespace(model: IModel, isAutoSaved: boolean): void { @@ -92,8 +87,36 @@ export class SaveParticipant implements ISaveParticipant, IWorkbenchContribution model.pushEditOperations(prevSelection, ops, (edits) => prevSelection); } +} - public dispose(): void { - this.toUnbind = dispose(this.toUnbind); +// The save participant can change a model before its saved to support various scenarios like trimming trailing whitespace +export class SaveParticipant implements ISaveParticipant { + + private _mainThreadSaveParticipant: TrimWhitespaceParticipant; + private _extHostSaveParticipant: ExtHostDocumentSaveParticipantShape; + + constructor( + @IConfigurationService configurationService: IConfigurationService, + @ICodeEditorService codeEditorService: ICodeEditorService, + @IThreadService threadService: IThreadService + ) { + this._mainThreadSaveParticipant = new TrimWhitespaceParticipant(configurationService, codeEditorService); + this._extHostSaveParticipant = threadService.get(ExtHostContext.ExtHostDocumentSaveParticipant); + + // Hook into model + TextFileEditorModel.setSaveParticipant(this); + } + + dispose() { + this._mainThreadSaveParticipant.dispose(); + } + + participate(model: ITextFileEditorModel, env: { isAutoSaved: boolean }): TPromise { + try { + this._mainThreadSaveParticipant.participate(model, env); + } catch (err) { + // ignore + } + return this._extHostSaveParticipant.$participateInSave(model.getResource()); } } \ No newline at end of file diff --git a/src/vs/workbench/parts/files/browser/files.contribution.ts b/src/vs/workbench/parts/files/browser/files.contribution.ts index b34f812f1ee..4029f5240e6 100644 --- a/src/vs/workbench/parts/files/browser/files.contribution.ts +++ b/src/vs/workbench/parts/files/browser/files.contribution.ts @@ -20,7 +20,6 @@ import {FileEditorDescriptor} from 'vs/workbench/parts/files/browser/files'; import {AutoSaveConfiguration, SUPPORTED_ENCODINGS} from 'vs/platform/files/common/files'; import {FILE_EDITOR_INPUT_ID, VIEWLET_ID} from 'vs/workbench/parts/files/common/files'; import {FileEditorTracker} from 'vs/workbench/parts/files/common/editors/fileEditorTracker'; -import {SaveParticipant} from 'vs/workbench/parts/files/common/editors/saveParticipant'; import {SaveErrorHandler} from 'vs/workbench/parts/files/browser/saveErrorHandler'; import {FileEditorInput} from 'vs/workbench/parts/files/common/editors/fileEditorInput'; import {TextFileEditor} from 'vs/workbench/parts/files/browser/editors/textFileEditor'; @@ -151,11 +150,6 @@ Registry.as(WorkbenchExtensions.Workbench).regi FileEditorTracker ); -// Register Save Participant -Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution( - SaveParticipant -); - // Register Save Error Handler Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution( SaveErrorHandler