/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { Registry } from 'vs/platform/registry/common/platform'; import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry'; import { IDisposable, Disposable } from 'vs/base/common/lifecycle'; import { IConfigurationService, IConfigurationChangeEvent, IConfigurationOverrides, ConfigurationTarget, isConfigurationOverrides, IConfigurationData, IConfigurationValue, IConfigurationChange } from 'vs/platform/configuration/common/configuration'; import { DefaultConfigurationModel, Configuration, ConfigurationModel, ConfigurationChangeEvent, UserSettings } from 'vs/platform/configuration/common/configurationModels'; import { Event, Emitter } from 'vs/base/common/event'; import { URI } from 'vs/base/common/uri'; import { IFileService } from 'vs/platform/files/common/files'; import { RunOnceScheduler } from 'vs/base/common/async'; export class ConfigurationService extends Disposable implements IConfigurationService, IDisposable { _serviceBrand: undefined; private configuration: Configuration; private userConfiguration: UserSettings; private readonly reloadConfigurationScheduler: RunOnceScheduler; private readonly _onDidChangeConfiguration: Emitter = this._register(new Emitter()); readonly onDidChangeConfiguration: Event = this._onDidChangeConfiguration.event; constructor( private readonly settingsResource: URI, fileService: IFileService ) { super(); this._register(fileService.watch(settingsResource)); this.userConfiguration = this._register(new UserSettings(this.settingsResource, undefined, fileService)); this.configuration = new Configuration(new DefaultConfigurationModel(), new ConfigurationModel()); this.reloadConfigurationScheduler = this._register(new RunOnceScheduler(() => this.reloadConfiguration(), 50)); this._register(Registry.as(Extensions.Configuration).onDidUpdateConfiguration(configurationProperties => this.onDidDefaultConfigurationChange(configurationProperties))); this._register(this.userConfiguration.onDidChange(() => this.reloadConfigurationScheduler.schedule())); } async initialize(): Promise { const userConfiguration = await this.userConfiguration.loadConfiguration(); this.configuration = new Configuration(new DefaultConfigurationModel(), userConfiguration); } getConfigurationData(): IConfigurationData { return this.configuration.toData(); } getValue(): T; getValue(section: string): T; getValue(overrides: IConfigurationOverrides): T; getValue(section: string, overrides: IConfigurationOverrides): T; getValue(arg1?: any, arg2?: any): any { const section = typeof arg1 === 'string' ? arg1 : undefined; const overrides = isConfigurationOverrides(arg1) ? arg1 : isConfigurationOverrides(arg2) ? arg2 : {}; return this.configuration.getValue(section, overrides, undefined); } updateValue(key: string, value: any): Promise; updateValue(key: string, value: any, overrides: IConfigurationOverrides): Promise; updateValue(key: string, value: any, target: ConfigurationTarget): Promise; updateValue(key: string, value: any, overrides: IConfigurationOverrides, target: ConfigurationTarget): Promise; updateValue(key: string, value: any, arg3?: any, arg4?: any): Promise { return Promise.reject(new Error('not supported')); } inspect(key: string): IConfigurationValue { return this.configuration.inspect(key, {}, undefined); } keys(): { default: string[]; user: string[]; workspace: string[]; workspaceFolder: string[]; } { return this.configuration.keys(undefined); } async reloadConfiguration(): Promise { const configurationModel = await this.userConfiguration.loadConfiguration(); this.onDidChangeUserConfiguration(configurationModel); } private onDidChangeUserConfiguration(userConfigurationModel: ConfigurationModel): void { const previous = this.configuration.toData(); const change = this.configuration.compareAndUpdateLocalUserConfiguration(userConfigurationModel); this.trigger(change, previous, ConfigurationTarget.USER); } private onDidDefaultConfigurationChange(keys: string[]): void { const previous = this.configuration.toData(); const change = this.configuration.compareAndUpdateDefaultConfiguration(new DefaultConfigurationModel(), keys); this.trigger(change, previous, ConfigurationTarget.DEFAULT); } private trigger(configurationChange: IConfigurationChange, previous: IConfigurationData, source: ConfigurationTarget): void { const event = new ConfigurationChangeEvent(configurationChange, { data: previous }, this.configuration); event.source = source; event.sourceConfig = this.getTargetConfiguration(source); this._onDidChangeConfiguration.fire(event); } private getTargetConfiguration(target: ConfigurationTarget): any { switch (target) { case ConfigurationTarget.DEFAULT: return this.configuration.defaults.contents; case ConfigurationTarget.USER: return this.configuration.localUserConfiguration.contents; } return {}; } }