Merge remote-tracking branch 'origin/master' into treeExplorerAPI

This commit is contained in:
Pine Wu
2016-10-31 12:50:19 -07:00
629 changed files with 9188 additions and 6394 deletions

View File

@@ -37,27 +37,34 @@ import Severity from 'vs/base/common/severity';
import EditorCommon = require('vs/editor/common/editorCommon');
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
import { ExtensionsRegistry } from 'vs/platform/extensions/common/extensionsRegistry';
import { TPromise } from 'vs/base/common/winjs.base';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import * as vscode from 'vscode';
import * as paths from 'vs/base/common/paths';
import { realpathSync } from 'fs';
import { ITelemetryService, ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
import { MainContext, ExtHostContext, InstanceCollection } from './extHost.protocol';
import { ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
import { MainContext, ExtHostContext, InstanceCollection, IInitConfiguration } from './extHost.protocol';
export interface IExtensionApiFactory {
(extension: IExtensionDescription): typeof vscode;
}
function proposedApiFunction<T>(extension: IExtensionDescription, fn: T): T {
if (extension.enableProposedApi) {
return fn;
} else {
return <any>(() => {
throw new Error(`${extension.id} cannot access proposed api`);
});
}
}
/**
* This method instantiates and returns the extension API surface
*/
export function createApiFactory(threadService: IThreadService, extensionService: ExtHostExtensionService, contextService: IWorkspaceContextService, telemetryService: ITelemetryService): IExtensionApiFactory {
export function createApiFactory(initDataConfiguration: IInitConfiguration, initTelemetryInfo: ITelemetryInfo, threadService: IThreadService, extensionService: ExtHostExtensionService, contextService: IWorkspaceContextService): IExtensionApiFactory {
// Addressable instances
const col = new InstanceCollection();
@@ -67,7 +74,7 @@ export function createApiFactory(threadService: IThreadService, extensionService
const extHostEditors = col.define(ExtHostContext.ExtHostEditors).set<ExtHostEditors>(new ExtHostEditors(threadService, extHostDocuments));
const extHostCommands = col.define(ExtHostContext.ExtHostCommands).set<ExtHostCommands>(new ExtHostCommands(threadService, extHostEditors, extHostHeapService));
const extHostExplorers = col.define(ExtHostContext.ExtHostExplorers).set<ExtHostTreeExplorers>(new ExtHostTreeExplorers(threadService, extHostCommands));
const extHostConfiguration = col.define(ExtHostContext.ExtHostConfiguration).set<ExtHostConfiguration>(new ExtHostConfiguration(threadService.get(MainContext.MainThreadConfiguration)));
const extHostConfiguration = col.define(ExtHostContext.ExtHostConfiguration).set<ExtHostConfiguration>(new ExtHostConfiguration(threadService.get(MainContext.MainThreadConfiguration), initDataConfiguration));
const extHostDiagnostics = col.define(ExtHostContext.ExtHostDiagnostics).set<ExtHostDiagnostics>(new ExtHostDiagnostics(threadService));
const languageFeatures = col.define(ExtHostContext.ExtHostLanguageFeatures).set<ExtHostLanguageFeatures>(new ExtHostLanguageFeatures(threadService, extHostDocuments, extHostCommands, extHostHeapService, extHostDiagnostics));
const extHostFileSystemEvent = col.define(ExtHostContext.ExtHostFileSystemEventService).set<ExtHostFileSystemEventService>(new ExtHostFileSystemEventService());
@@ -84,22 +91,15 @@ export function createApiFactory(threadService: IThreadService, extensionService
const extHostWorkspace = new ExtHostWorkspace(threadService, workspacePath);
const extHostLanguages = new ExtHostLanguages(threadService);
// Error forwarding
const mainThreadErrors = threadService.get(MainContext.MainThreadErrors);
errors.setUnexpectedErrorHandler((err) => {
mainThreadErrors.onUnexpectedExtHostError(errors.transformErrorForSerialization(err));
});
// Register API-ish commands
ExtHostApiCommands.register(extHostCommands);
// TODO@joh,alex - this is lifecycle critical
// fetch and store telemetry info
let telemetryInfo: ITelemetryInfo;
telemetryService.getTelemetryInfo().then(info => telemetryInfo = info, errors.onUnexpectedError);
return function (extension: IExtensionDescription): typeof vscode {
if (extension.enableProposedApi) {
console.warn(`${extension.name} (${extension.id}) uses PROPOSED API which is subject to change and removal without notice`);
}
// namespace: commands
const commands: typeof vscode.commands = {
registerCommand<T>(id: string, command: <T>(...args: any[]) => T | Thenable<T>, thisArgs?: any): vscode.Disposable {
@@ -136,8 +136,8 @@ export function createApiFactory(threadService: IThreadService, extensionService
// namespace: env
const env: typeof vscode.env = Object.freeze({
get machineId() { return telemetryInfo.machineId; },
get sessionId() { return telemetryInfo.sessionId; },
get machineId() { return initTelemetryInfo.machineId; },
get sessionId() { return initTelemetryInfo.sessionId; },
get language() { return Platform.language; },
get appName() { return product.nameLong; }
});
@@ -145,13 +145,13 @@ export function createApiFactory(threadService: IThreadService, extensionService
// namespace: extensions
const extensions: typeof vscode.extensions = {
getExtension(extensionId: string): Extension<any> {
let desc = ExtensionsRegistry.getExtensionDescription(extensionId);
let desc = extensionService.getExtensionDescription(extensionId);
if (desc) {
return new Extension(extensionService, desc);
}
},
get all(): Extension<any>[] {
return ExtensionsRegistry.getAllExtensionDescriptions().map((desc) => new Extension(extensionService, desc));
return extensionService.getAllExtensionDescriptions().map((desc) => new Extension(extensionService, desc));
}
};
@@ -230,30 +230,34 @@ export function createApiFactory(threadService: IThreadService, extensionService
createTextEditorDecorationType(options: vscode.DecorationRenderOptions): vscode.TextEditorDecorationType {
return extHostEditors.createTextEditorDecorationType(options);
},
onDidChangeActiveTextEditor: extHostEditors.onDidChangeActiveTextEditor.bind(extHostEditors),
onDidChangeActiveTextEditor(listener, thisArg?, disposables?) {
return extHostEditors.onDidChangeActiveTextEditor(listener, thisArg, disposables);
},
onDidChangeVisibleTextEditors(listener, thisArg, disposables) {
return extHostEditors.onDidChangeVisibleTextEditors(listener, thisArg, disposables);
},
onDidChangeTextEditorSelection: (listener: (e: vscode.TextEditorSelectionChangeEvent) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) => {
onDidChangeTextEditorSelection(listener: (e: vscode.TextEditorSelectionChangeEvent) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) {
return extHostEditors.onDidChangeTextEditorSelection(listener, thisArgs, disposables);
},
onDidChangeTextEditorOptions: (listener: (e: vscode.TextEditorOptionsChangeEvent) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) => {
onDidChangeTextEditorOptions(listener: (e: vscode.TextEditorOptionsChangeEvent) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) {
return extHostEditors.onDidChangeTextEditorOptions(listener, thisArgs, disposables);
},
onDidChangeTextEditorViewColumn(listener, thisArg?, disposables?) {
return extHostEditors.onDidChangeTextEditorViewColumn(listener, thisArg, disposables);
},
onDidCloseTerminal: extHostTerminalService.onDidCloseTerminal.bind(extHostTerminalService),
showInformationMessage: (message, ...items) => {
onDidCloseTerminal(listener, thisArg?, disposables?) {
return extHostTerminalService.onDidCloseTerminal(listener, thisArg, disposables);
},
showInformationMessage(message, ...items) {
return extHostMessageService.showMessage(Severity.Info, message, items);
},
showWarningMessage: (message, ...items) => {
showWarningMessage(message, ...items) {
return extHostMessageService.showMessage(Severity.Warning, message, items);
},
showErrorMessage: (message, ...items) => {
showErrorMessage(message, ...items) {
return extHostMessageService.showMessage(Severity.Error, message, items);
},
showQuickPick: (items: any, options: vscode.QuickPickOptions, token?: vscode.CancellationToken) => {
showQuickPick(items: any, options: vscode.QuickPickOptions, token?: vscode.CancellationToken) {
return extHostQuickOpen.showQuickPick(items, options, token);
},
showInputBox(options?: vscode.InputBoxOptions, token?: vscode.CancellationToken) {
@@ -270,7 +274,11 @@ export function createApiFactory(threadService: IThreadService, extensionService
},
createTerminal(name?: string, shellPath?: string, shellArgs?: string[]): vscode.Terminal {
return extHostTerminalService.createTerminal(name, shellPath, shellArgs);
}
},
// proposed API
sampleFunction: proposedApiFunction(extension, () => {
return extHostMessageService.showMessage(Severity.Info, 'Hello Proposed Api!', []);
})
};
// namespace: workspace
@@ -422,7 +430,7 @@ class Extension<T> implements vscode.Extension<T> {
}
}
export function defineAPI(factory: IExtensionApiFactory, extensions: IExtensionDescription[]): void {
export function defineAPI(factory: IExtensionApiFactory, extensionService: ExtHostExtensionService): void {
// each extension is meant to get its own api implementation
const extApiImpl: { [id: string]: typeof vscode } = Object.create(null);
@@ -430,6 +438,7 @@ export function defineAPI(factory: IExtensionApiFactory, extensions: IExtensionD
// create trie to enable fast 'filename -> extension id' look up
const trie = new TrieMap<IExtensionDescription>(TrieMap.PathSplitter);
const extensions = extensionService.getAllExtensionDescriptions();
for (const ext of extensions) {
if (ext.name) {
const path = realpathSync(ext.extensionFolderPath);

View File

@@ -18,10 +18,11 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { IMarkerData } from 'vs/platform/markers/common/markers';
import { Position as EditorPosition } from 'vs/platform/editor/common/editor';
import { IMessage, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { StatusbarAlignment as MainThreadStatusBarAlignment } from 'vs/platform/statusbar/common/statusbar';
import { ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
import { IWorkspace } from 'vs/platform/workspace/common/workspace';
import * as editorCommon from 'vs/editor/common/editorCommon';
import * as modes from 'vs/editor/common/modes';
@@ -36,6 +37,29 @@ import { IApplyEditsOptions, TextEditorRevealType, ITextEditorConfigurationUpdat
import { InternalTreeExplorerNode } from 'vs/workbench/parts/explorers/common/treeExplorerViewModel';
export interface IEnvironment {
appSettingsHome: string;
disableExtensions: boolean;
userExtensionsHome: string;
extensionDevelopmentPath: string;
extensionTestsPath: string;
}
export interface IInitConfiguration {
_initConfigurationBrand: void;
}
export interface IInitData {
parentPid: number;
environment: IEnvironment;
contextService: {
workspace: IWorkspace;
};
extensions: IExtensionDescription[];
configuration: IInitConfiguration;
telemetryInfo: ITelemetryInfo;
}
export interface InstanceSetter<T> {
set<R extends T>(instance: T): R;
}
@@ -202,7 +226,6 @@ export abstract class MainThreadWorkspaceShape {
}
export abstract class MainProcessExtensionServiceShape {
$onExtensionHostReady(extensionDescriptions: IExtensionDescription[], messages: IMessage[]): TPromise<void> { throw ni(); }
$localShowMessage(severity: Severity, msg: string): void { throw ni(); }
$onExtensionActivated(extensionId: string): void { throw ni(); }
$onExtensionActivationFailed(extensionId: string): void { throw ni(); }
@@ -242,7 +265,7 @@ export abstract class ExtHostDocumentsShape {
}
export abstract class ExtHostDocumentSaveParticipantShape {
$participateInSave(resource: URI, reason: SaveReason): TPromise<any[]> { throw ni(); }
$participateInSave(resource: URI, reason: SaveReason): TPromise<boolean[]> { throw ni(); }
}
export interface ITextEditorAddData {

View File

@@ -5,7 +5,6 @@
'use strict';
import { mixin } from 'vs/base/common/objects';
import { illegalState } from 'vs/base/common/errors';
import Event, { Emitter } from 'vs/base/common/event';
import { WorkspaceConfiguration } from 'vscode';
import { ExtHostConfigurationShape, MainThreadConfigurationShape } from './extHost.protocol';
@@ -14,13 +13,13 @@ import { ConfigurationTarget } from 'vs/workbench/services/configuration/common/
export class ExtHostConfiguration extends ExtHostConfigurationShape {
private _proxy: MainThreadConfigurationShape;
private _hasConfig: boolean;
private _config: any;
private _onDidChangeConfiguration = new Emitter<void>();
constructor(proxy: MainThreadConfigurationShape) {
constructor(proxy: MainThreadConfigurationShape, configuration: any) {
super();
this._proxy = proxy;
this._config = configuration;
}
get onDidChangeConfiguration(): Event<void> {
@@ -29,14 +28,10 @@ export class ExtHostConfiguration extends ExtHostConfigurationShape {
public $acceptConfigurationChanged(config: any) {
this._config = config;
this._hasConfig = true;
this._onDidChangeConfiguration.fire(undefined);
}
public getConfiguration(section?: string): WorkspaceConfiguration {
if (!this._hasConfig) {
throw illegalState('missing config');
}
const config = section
? ExtHostConfiguration._lookUp(section, this._config)

View File

@@ -10,8 +10,7 @@ import * as paths from 'vs/base/common/paths';
import Severity from 'vs/base/common/severity';
import { TPromise } from 'vs/base/common/winjs.base';
import { AbstractExtensionService, ActivatedExtension } from 'vs/platform/extensions/common/abstractExtensionService';
import { IMessage, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { ExtensionsRegistry } from 'vs/platform/extensions/common/extensionsRegistry';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { ExtHostStorage } from 'vs/workbench/api/node/extHostStorage';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
@@ -119,8 +118,9 @@ export class ExtHostExtensionService extends AbstractExtensionService<ExtHostExt
/**
* This class is constructed manually because it is a service, so it doesn't use any ctor injection
*/
constructor(threadService: IThreadService, telemetryService: ITelemetryService, args: { _serviceBrand: any; workspaceStoragePath: string; }) {
super(false);
constructor(availableExtensions: IExtensionDescription[], threadService: IThreadService, telemetryService: ITelemetryService, args: { _serviceBrand: any; workspaceStoragePath: string; }) {
super(true);
this._registry.registerExtensions(availableExtensions);
this._threadService = threadService;
this._storage = new ExtHostStorage(threadService);
this._proxy = this._threadService.get(MainContext.MainProcessExtensionService);
@@ -128,6 +128,14 @@ export class ExtHostExtensionService extends AbstractExtensionService<ExtHostExt
this._workspaceStoragePath = args.workspaceStoragePath;
}
public getAllExtensionDescriptions(): IExtensionDescription[] {
return this._registry.getAllExtensionDescriptions();
}
public getExtensionDescription(extensionId: string): IExtensionDescription {
return this._registry.getExtensionDescription(extensionId);
}
public $localShowMessage(severity: Severity, msg: string): void {
switch (severity) {
case Severity.Error:
@@ -178,14 +186,6 @@ export class ExtHostExtensionService extends AbstractExtensionService<ExtHostExt
return result;
}
public registrationDone(messages: IMessage[]): void {
this._proxy.$onExtensionHostReady(ExtensionsRegistry.getAllExtensionDescriptions(), messages).then(() => {
// Wait for the main process to acknowledge its receival of the extensions descriptions
// before allowing extensions to be activated
this._triggerOnReady();
});
}
// -- overwriting AbstractExtensionService
protected _showMessage(severity: Severity, msg: string): void {

View File

@@ -113,22 +113,12 @@ class DefinitionAdapter {
let pos = TypeConverters.toPosition(position);
return asWinJsPromise(token => this._provider.provideDefinition(doc, pos, token)).then(value => {
if (Array.isArray(value)) {
return value.map(DefinitionAdapter._convertLocation);
return value.map(TypeConverters.location.from);
} else if (value) {
return DefinitionAdapter._convertLocation(value);
return TypeConverters.location.from(value);
}
});
}
private static _convertLocation(location: vscode.Location): modes.Location {
if (!location) {
return;
}
return <modes.Location>{
uri: location.uri,
range: TypeConverters.fromRange(location.range)
};
}
}
class HoverAdapter {
@@ -208,17 +198,10 @@ class ReferenceAdapter {
return asWinJsPromise(token => this._provider.provideReferences(doc, pos, context, token)).then(value => {
if (Array.isArray(value)) {
return value.map(ReferenceAdapter._convertLocation);
return value.map(TypeConverters.location.from);
}
});
}
private static _convertLocation(location: vscode.Location): modes.Location {
return <modes.Location>{
uri: location.uri,
range: TypeConverters.fromRange(location.range)
};
}
}
class QuickFixAdapter {

View File

@@ -68,7 +68,7 @@ export class ExtHostTerminal implements vscode.Terminal {
}
}
public setProcessId(processId: number): void {
public _setProcessId(processId: number): void {
this._pidPromiseComplete(processId);
this._pidPromiseComplete = null;
}
@@ -123,7 +123,7 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
public $acceptTerminalProcessId(id: number, processId: number): void {
let terminal = this._getTerminalById(id);
terminal.setProcessId(processId);
terminal._setProcessId(processId);
}
private _getTerminalById(id: number): ExtHostTerminal {

View File

@@ -248,10 +248,10 @@ export function toSymbolInformation(bearing: IWorkspaceSymbol): types.SymbolInfo
export const location = {
from(value: types.Location): modes.Location {
from(value: vscode.Location): modes.Location {
return {
range: fromRange(value.range),
uri: value.uri
range: value.range && fromRange(value.range),
uri: <URI>value.uri
};
},
to(value: modes.Location): types.Location {

View File

@@ -25,7 +25,6 @@ export class MainThreadConfiguration extends MainThreadConfigurationShape {
this._configurationEditingService = configurationEditingService;
const proxy = threadService.get(ExtHostContext.ExtHostConfiguration);
this._toDispose = configurationService.onDidUpdateConfiguration(event => proxy.$acceptConfigurationChanged(event.config));
proxy.$acceptConfigurationChanged(configurationService.getConfiguration());
}
public dispose(): void {

View File

@@ -7,8 +7,8 @@
import Severity from 'vs/base/common/severity';
import { TPromise } from 'vs/base/common/winjs.base';
import { AbstractExtensionService, ActivatedExtension } from 'vs/platform/extensions/common/abstractExtensionService';
import { IMessage, IExtensionDescription, IExtensionsStatus } from 'vs/platform/extensions/common/extensions';
import { ExtensionsRegistry } from 'vs/platform/extensions/common/extensionsRegistry';
import { IExtensionsRuntimeService, IMessage, IExtensionDescription, IExtensionsStatus } from 'vs/platform/extensions/common/extensions';
import { ExtensionsRegistry, ExtensionPoint, IExtensionPointUser, ExtensionMessageCollector } from 'vs/platform/extensions/common/extensionsRegistry';
import { IMessageService } from 'vs/platform/message/common/message';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { ExtHostContext, ExtHostExtensionServiceShape } from './extHost.protocol';
@@ -37,6 +37,8 @@ function messageWithSource(msg: IMessage): string {
return (msg.source ? '[' + msg.source + ']: ' : '') + msg.message;
}
const hasOwnProperty = Object.hasOwnProperty;
export class MainProcessExtensionService extends AbstractExtensionService<ActivatedExtension> {
private _threadService: IThreadService;
@@ -51,7 +53,8 @@ export class MainProcessExtensionService extends AbstractExtensionService<Activa
constructor(
@IThreadService threadService: IThreadService,
@IMessageService messageService: IMessageService,
@IEnvironmentService private environmentService: IEnvironmentService
@IEnvironmentService private environmentService: IEnvironmentService,
@IExtensionsRuntimeService extensionsRuntimeService: IExtensionsRuntimeService
) {
super(false);
this._isDev = !environmentService.isBuilt || !!environmentService.extensionDevelopmentPath;
@@ -61,7 +64,7 @@ export class MainProcessExtensionService extends AbstractExtensionService<Activa
this._proxy = this._threadService.get(ExtHostContext.ExtHostExtensionService);
this._extensionsStatus = {};
ExtensionsRegistry.handleExtensionPoints((msg) => this._handleMessage(msg));
extensionsRuntimeService.getExtensions().then((extensionDescriptions) => this._onExtensionDescriptions(extensionDescriptions));
}
private _handleMessage(msg: IMessage) {
@@ -124,11 +127,36 @@ export class MainProcessExtensionService extends AbstractExtensionService<Activa
// -- called by extension host
public $onExtensionHostReady(extensionDescriptions: IExtensionDescription[], messages: IMessage[]): TPromise<void> {
ExtensionsRegistry.registerExtensions(extensionDescriptions);
messages.forEach((entry) => this._handleMessage(entry));
private _onExtensionDescriptions(extensionDescriptions: IExtensionDescription[]): void {
this._registry.registerExtensions(extensionDescriptions);
let availableExtensions = this._registry.getAllExtensionDescriptions();
let extensionPoints = ExtensionsRegistry.getExtensionPoints();
for (let i = 0, len = extensionPoints.length; i < len; i++) {
this._handleExtensionPoint(extensionPoints[i], availableExtensions);
}
this._triggerOnReady();
return;
}
private _handleExtensionPoint<T>(extensionPoint: ExtensionPoint<T>, availableExtensions: IExtensionDescription[]): void {
let messageHandler = (msg: IMessage) => this._handleMessage(msg);
let users: IExtensionPointUser<T>[] = [], usersLen = 0;
for (let i = 0, len = availableExtensions.length; i < len; i++) {
let desc = availableExtensions[i];
if (desc.contributes && hasOwnProperty.call(desc.contributes, extensionPoint.name)) {
users[usersLen++] = {
description: desc,
value: desc.contributes[extensionPoint.name],
collector: new ExtensionMessageCollector(messageHandler, desc.extensionFolderPath)
};
}
}
extensionPoint.acceptUsers(users);
}
public $onExtensionActivated(extensionId: string): void {

View File

@@ -11,6 +11,7 @@ import { ICodeEditorService } from 'vs/editor/common/services/codeEditorService'
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { ISaveParticipant, ITextFileEditorModel, SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IPosition, IModel, ICommonCodeEditor, ISingleEditOperation, IIdentifiedSingleEditOperation } from 'vs/editor/common/editorCommon';
import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
@@ -21,7 +22,13 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel';
import { ExtHostContext, ExtHostDocumentSaveParticipantShape } from './extHost.protocol';
class TrimWhitespaceParticipant implements ISaveParticipant {
interface INamedSaveParticpant extends ISaveParticipant {
readonly name: string;
}
class TrimWhitespaceParticipant implements INamedSaveParticpant {
readonly name = 'TrimWhitespaceParticipant';
constructor(
@IConfigurationService private configurationService: IConfigurationService,
@@ -75,7 +82,9 @@ class TrimWhitespaceParticipant implements ISaveParticipant {
}
}
class FormatOnSaveParticipant implements ISaveParticipant {
class FormatOnSaveParticipant implements INamedSaveParticpant {
readonly name = 'FormatOnSaveParticipant';
constructor(
@ICodeEditorService private _editorService: ICodeEditorService,
@@ -97,7 +106,7 @@ class FormatOnSaveParticipant implements ISaveParticipant {
const {tabSize, insertSpaces} = model.getOptions();
return new TPromise<ISingleEditOperation[]>((resolve, reject) => {
setTimeout(resolve, 750);
setTimeout(reject, 750);
getDocumentFormattingEdits(model, { tabSize, insertSpaces }).then(resolve, reject);
}).then(edits => {
@@ -158,25 +167,37 @@ class FormatOnSaveParticipant implements ISaveParticipant {
}
}
class ExtHostSaveParticipant implements ISaveParticipant {
class ExtHostSaveParticipant implements INamedSaveParticpant {
private _proxy: ExtHostDocumentSaveParticipantShape;
readonly name = 'ExtHostSaveParticipant';
constructor( @IThreadService threadService: IThreadService) {
this._proxy = threadService.get(ExtHostContext.ExtHostDocumentSaveParticipant);
}
participate(editorModel: ITextFileEditorModel, env: { reason: SaveReason }): TPromise<any> {
return this._proxy.$participateInSave(editorModel.getResource(), env.reason);
return new TPromise<any>((resolve, reject) => {
setTimeout(reject, 1750);
this._proxy.$participateInSave(editorModel.getResource(), env.reason).then(values => {
for (const success of values) {
if (!success) {
return TPromise.wrapError('listener failed');
}
}
}).then(resolve, reject);
});
}
}
// The save participant can change a model before its saved to support various scenarios like trimming trailing whitespace
export class SaveParticipant implements ISaveParticipant {
private _saveParticipants: ISaveParticipant[];
private _saveParticipants: INamedSaveParticpant[];
constructor(
@ITelemetryService private _telemetryService: ITelemetryService,
@IInstantiationService instantiationService: IInstantiationService,
@IThreadService threadService: IThreadService
) {
@@ -191,11 +212,24 @@ export class SaveParticipant implements ISaveParticipant {
TextFileEditorModel.setSaveParticipant(this);
}
participate(model: ITextFileEditorModel, env: { reason: SaveReason }): TPromise<any> {
const stats: { [name: string]: number } = Object.create(null);
const promiseFactory = this._saveParticipants.map(p => () => {
return TPromise.as(p.participate(model, env)).then(undefined, err => {
const {name} = p;
const t1 = Date.now();
return TPromise.as(p.participate(model, env)).then(() => {
stats[`Success-${name}`] = Date.now() - t1;
}, err => {
stats[`Failure-${name}`] = Date.now() - t1;
// console.error(err);
});
});
return sequence(promiseFactory);
return sequence(promiseFactory).then(() => {
this._telemetryService.publicLog('saveParticipantStats', stats);
});
}
}