diff --git a/src/vs/platform/configuration/common/configuration.ts b/src/vs/platform/configuration/common/configuration.ts index d541ed739dfe02947613923f04353e48d7b34459..68a89b96819470f2f3f603e4ffb385ac0d4f69de 100644 --- a/src/vs/platform/configuration/common/configuration.ts +++ b/src/vs/platform/configuration/common/configuration.ts @@ -51,8 +51,15 @@ export interface IConfigurationService { */ reloadConfiguration(section?: string): TPromise; + // TODO: @sandy: Merge these to single fine grained configuration change event + // These events were separated to improve the start up performance - #34353 /** - * Event that fires when the configuration changes. + * Event that fires when the configurations from extensions are registered. + */ + onDidRegisterExtensionsConfigurations: Event; + + /** + * Event that fires when the configuration changes. This event is not fired when configurations from extensions are registered. */ onDidUpdateConfiguration: Event; diff --git a/src/vs/platform/configuration/common/configurationRegistry.ts b/src/vs/platform/configuration/common/configurationRegistry.ts index 0d3276bf69df7ae4ce73cbce2678e75820c3fa2f..6a1b0e35374dc8383f03fc0802a0d128652cee35 100644 --- a/src/vs/platform/configuration/common/configurationRegistry.ts +++ b/src/vs/platform/configuration/common/configurationRegistry.ts @@ -35,7 +35,7 @@ export interface IConfigurationRegistry { * Event that fires whenver a configuratio has been * registered. */ - onDidRegisterConfiguration: Event; + onDidRegisterConfiguration: Event; /** * Returns all configuration nodes contributed to this registry. @@ -75,6 +75,7 @@ export interface IConfigurationNode { allOf?: IConfigurationNode[]; overridable?: boolean; scope?: ConfigurationScope; + isFromExtensions?: boolean; } export interface IDefaultConfigurationExtension { @@ -93,14 +94,14 @@ class ConfigurationRegistry implements IConfigurationRegistry { private configurationContributors: IConfigurationNode[]; private configurationProperties: { [qualifiedKey: string]: IJSONSchema }; private editorConfigurationSchema: IJSONSchema; - private _onDidRegisterConfiguration: Emitter; + private _onDidRegisterConfiguration: Emitter; private overrideIdentifiers: string[] = []; private overridePropertyPattern: string; constructor() { this.configurationContributors = []; this.editorConfigurationSchema = { properties: {}, patternProperties: {}, additionalProperties: false, errorMessage: 'Unknown editor configuration setting' }; - this._onDidRegisterConfiguration = new Emitter(); + this._onDidRegisterConfiguration = new Emitter(); this.configurationProperties = {}; this.computeOverridePropertyPattern(); @@ -123,7 +124,7 @@ class ConfigurationRegistry implements IConfigurationRegistry { this.updateSchemaForOverrideSettingsConfiguration(configuration); }); - this._onDidRegisterConfiguration.fire(this); + this._onDidRegisterConfiguration.fire(configurations); } public registerOverrideIdentifiers(overrideIdentifiers: string[]): void { @@ -135,7 +136,8 @@ class ConfigurationRegistry implements IConfigurationRegistry { const configurationNode: IConfigurationNode = { id: 'defaultOverrides', title: nls.localize('defaultConfigurations.title', "Default Configuration Overrides"), - properties: {} + properties: {}, + isFromExtensions: true }; for (const defaultConfiguration of defaultConfigurations) { for (const key in defaultConfiguration.defaults) { diff --git a/src/vs/platform/configuration/node/configurationService.ts b/src/vs/platform/configuration/node/configurationService.ts index 8f6005c6430baf0a55a37584792faa67380ecaa4..daeb7912578428dea4fda1c60fe8f6040169555b 100644 --- a/src/vs/platform/configuration/node/configurationService.ts +++ b/src/vs/platform/configuration/node/configurationService.ts @@ -7,7 +7,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { ConfigWatcher } from 'vs/base/node/config'; import { Registry } from 'vs/platform/registry/common/platform'; -import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry'; +import { IConfigurationRegistry, Extensions, IConfigurationNode } from 'vs/platform/configuration/common/configurationRegistry'; import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; import { ConfigurationSource, IConfigurationService, IConfigurationServiceEvent, IConfigurationValue, IConfigurationKeys, ConfigurationModel, IConfigurationOverrides, Configuration, IConfigurationValues, IConfigurationData } from 'vs/platform/configuration/common/configuration'; import { CustomConfigurationModel, DefaultConfigurationModel } from 'vs/platform/configuration/common/model'; @@ -25,6 +25,9 @@ export class ConfigurationService extends Disposable implements IConfiguratio private _onDidUpdateConfiguration: Emitter = this._register(new Emitter()); public readonly onDidUpdateConfiguration: Event = this._onDidUpdateConfiguration.event; + private _onDidRegisterExtensionsConfigurations: Emitter = this._register(new Emitter()); + public readonly onDidRegisterExtensionsConfigurations: Event = this._onDidRegisterExtensionsConfigurations.event; + constructor( @IEnvironmentService environmentService: IEnvironmentService ) { @@ -41,22 +44,26 @@ export class ConfigurationService extends Disposable implements IConfiguratio // Listeners this._register(this.userConfigModelWatcher.onDidUpdateConfiguration(() => this.onConfigurationChange(ConfigurationSource.User))); - this._register(Registry.as(Extensions.Configuration).onDidRegisterConfiguration(() => this.onConfigurationChange(ConfigurationSource.Default))); + this._register(Registry.as(Extensions.Configuration).onDidRegisterConfiguration(configurations => this.onConfigurationChange(ConfigurationSource.Default, configurations))); } public configuration(): Configuration { return this._configuration || (this._configuration = this.consolidateConfigurations()); } - private onConfigurationChange(source: ConfigurationSource): void { + private onConfigurationChange(source: ConfigurationSource, configurations?: IConfigurationNode[]): void { this.reset(); // reset our caches const cache = this.configuration(); - this._onDidUpdateConfiguration.fire({ - source, - sourceConfig: source === ConfigurationSource.Default ? cache.defaults.contents : cache.user.contents - }); + if (configurations && configurations.length && configurations.every(c => c.isFromExtensions)) { + this._onDidRegisterExtensionsConfigurations.fire(); + } else { + this._onDidUpdateConfiguration.fire({ + source, + sourceConfig: source === ConfigurationSource.Default ? cache.defaults.contents : cache.user.contents + }); + } } public reloadConfiguration(section?: string): TPromise { diff --git a/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts b/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts index 71f54113cfd528bdef54f70c96650dd8d3f89c31..7007e55a25b07d256a05779ac64303d902c95a36 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadConfiguration.ts @@ -6,7 +6,7 @@ import URI from 'vs/base/common/uri'; import { TPromise } from 'vs/base/common/winjs.base'; -import { IDisposable } from 'vs/base/common/lifecycle'; +import { Disposable } from 'vs/base/common/lifecycle'; import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; @@ -16,9 +16,7 @@ import { MainThreadConfigurationShape, MainContext, ExtHostContext, IExtHostCont import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; @extHostNamedCustomer(MainContext.MainThreadConfiguration) -export class MainThreadConfiguration implements MainThreadConfigurationShape { - - private readonly _configurationListener: IDisposable; +export class MainThreadConfiguration extends Disposable implements MainThreadConfigurationShape { constructor( extHostContext: IExtHostContext, @@ -26,15 +24,16 @@ export class MainThreadConfiguration implements MainThreadConfigurationShape { @IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService, @IWorkspaceConfigurationService configurationService: IWorkspaceConfigurationService ) { + super(); const proxy = extHostContext.get(ExtHostContext.ExtHostConfiguration); - this._configurationListener = configurationService.onDidUpdateConfiguration(() => { + this._register(configurationService.onDidUpdateConfiguration(() => { proxy.$acceptConfigurationChanged(configurationService.getConfigurationData()); - }); - } + })); - public dispose(): void { - this._configurationListener.dispose(); + this._register(configurationService.onDidRegisterExtensionsConfigurations(() => { + proxy.$acceptConfigurationChanged(configurationService.getConfigurationData()); + })); } $updateConfigurationOption(target: ConfigurationTarget, key: string, value: any, resource: URI): TPromise { diff --git a/src/vs/workbench/services/configuration/node/configuration.ts b/src/vs/workbench/services/configuration/node/configuration.ts index 74556f8b5ab07a19e0e8d3831927bc1db94abaa6..76e9aa99ced71fe341ae71a45e0e26d99916ace1 100644 --- a/src/vs/workbench/services/configuration/node/configuration.ts +++ b/src/vs/workbench/services/configuration/node/configuration.ts @@ -128,6 +128,7 @@ configurationExtPoint.setHandler(extensions => { validateProperties(configuration, collector); configuration.id = id; + configuration.isFromExtensions = true; configurations.push(configuration); }; @@ -275,6 +276,9 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat protected readonly _onDidUpdateConfiguration: Emitter = this._register(new Emitter()); public readonly onDidUpdateConfiguration: Event = this._onDidUpdateConfiguration.event; + private _onDidRegisterExtensionsConfigurations: Emitter = this._register(new Emitter()); + public readonly onDidRegisterExtensionsConfigurations: Event = this._onDidRegisterExtensionsConfigurations.event; + protected readonly _onDidChangeWorkspaceFolders: Emitter = this._register(new Emitter()); public readonly onDidChangeWorkspaceFolders: Event = this._onDidChangeWorkspaceFolders.event; @@ -292,6 +296,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat this.baseConfigurationService = this._register(new GlobalConfigurationService(environmentService)); this._register(this.baseConfigurationService.onDidUpdateConfiguration(e => this.onBaseConfigurationChanged(e))); + this._register(this.baseConfigurationService.onDidRegisterExtensionsConfigurations(e => this.onDidRegisterExtensionsDefaultsConfigurations())); this._register(configurationRegistry.onDidRegisterConfiguration(e => this.registerConfigurationSchemas())); } @@ -517,15 +522,25 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat } } - private onBaseConfigurationChanged({ source, sourceConfig }: IConfigurationServiceEvent): void { + private onBaseConfigurationChanged({ source, sourceConfig }: IConfigurationServiceEvent, doNotTrigger: boolean = false): boolean { if (this.workspace) { if (source === ConfigurationSource.Default) { this.workspace.folders.forEach(folder => this._configuration.getFolderConfigurationModel(folder.uri).update()); } if (this._configuration.updateBaseConfiguration(this.baseConfigurationService.configuration())) { - this._onDidUpdateConfiguration.fire({ source, sourceConfig }); + if (!doNotTrigger) { + this._onDidUpdateConfiguration.fire({ source, sourceConfig }); + } + return true; } } + return false; + } + + private onDidRegisterExtensionsDefaultsConfigurations(): void { + if (this.onBaseConfigurationChanged({ source: ConfigurationSource.Default, sourceConfig: this.baseConfigurationService.getConfigurationData().defaults.contents }, true)) { + this._onDidRegisterExtensionsConfigurations.fire(); + } } private onWorkspaceConfigurationChanged(): void {