configurationService.ts 4.3 KB
Newer Older
1 2 3 4 5 6
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
'use strict';

J
Johannes Rieken 已提交
7
import { TPromise } from 'vs/base/common/winjs.base';
8
import * as objects from 'vs/base/common/objects';
9
import { getDefaultValues, toValuesTree, getConfigurationKeys } from 'vs/platform/configuration/common/model';
J
Johannes Rieken 已提交
10 11 12 13
import { ConfigWatcher } from 'vs/base/node/config';
import { Registry } from 'vs/platform/platform';
import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry';
import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
14
import { ConfigurationSource, IConfigurationService, IConfigurationServiceEvent, IConfigurationValue, getConfigurationValue, IConfigurationKeys } from 'vs/platform/configuration/common/configuration';
J
Johannes Rieken 已提交
15 16
import Event, { Emitter } from 'vs/base/common/event';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
17 18 19 20 21 22

interface ICache<T> {
	defaults: T;
	user: T;
	consolidated: T;
}
23

B
Benjamin Pasero 已提交
24
export class ConfigurationService<T> implements IConfigurationService, IDisposable {
25 26 27 28 29

	_serviceBrand: any;

	private disposables: IDisposable[];

B
Benjamin Pasero 已提交
30
	private rawConfig: ConfigWatcher<T>;
31
	private cache: ICache<T>;
32 33 34 35 36 37 38 39 40 41 42 43 44 45

	private _onDidUpdateConfiguration: Emitter<IConfigurationServiceEvent>;

	constructor(
		@IEnvironmentService environmentService: IEnvironmentService
	) {
		this.disposables = [];

		this._onDidUpdateConfiguration = new Emitter<IConfigurationServiceEvent>();
		this.disposables.push(this._onDidUpdateConfiguration);

		this.rawConfig = new ConfigWatcher(environmentService.appSettingsPath, { changeBufferDelay: 300, defaultConfig: Object.create(null) });
		this.disposables.push(toDisposable(() => this.rawConfig.dispose()));

B
Benjamin Pasero 已提交
46
		// Listeners
47 48
		this.disposables.push(this.rawConfig.onDidUpdateConfiguration(() => this.onConfigurationChange(ConfigurationSource.User)));
		this.disposables.push(Registry.as<IConfigurationRegistry>(Extensions.Configuration).onDidRegisterConfiguration(() => this.onConfigurationChange(ConfigurationSource.Default)));
49 50
	}

51
	private onConfigurationChange(source: ConfigurationSource): void {
52
		this.cache = void 0; // reset our caches
53 54 55 56 57 58
		const cache = this.getCache();
		this._onDidUpdateConfiguration.fire({
			config: this.getConfiguration(),
			source,
			sourceConfig: source === ConfigurationSource.Default ? cache.defaults : cache.user
		});
59 60 61 62 63 64
	}

	public get onDidUpdateConfiguration(): Event<IConfigurationServiceEvent> {
		return this._onDidUpdateConfiguration.event;
	}

65
	public reloadConfiguration<C>(section?: string): TPromise<C> {
B
Benjamin Pasero 已提交
66
		return new TPromise<C>(c => {
67 68 69
			this.rawConfig.reload(() => {
				this.cache = void 0; // reset our caches

B
Benjamin Pasero 已提交
70
				c(this.getConfiguration<C>(section));
71 72 73 74
			});
		});
	}

B
Benjamin Pasero 已提交
75
	public getConfiguration<C>(section?: string): C {
76 77 78
		const cache = this.getCache();
		return section ? cache.consolidated[section] : cache.consolidated;
	}
79

80 81
	private getCache(): ICache<T> {
		return this.cache || (this.cache = this.consolidateConfigurations());
82 83
	}

B
Benjamin Pasero 已提交
84
	public lookup<C>(key: string): IConfigurationValue<C> {
85
		// make sure to clone the configuration so that the receiver does not tamper with the values
B
Benjamin Pasero 已提交
86
		return {
87
			default: objects.clone(getConfigurationValue<C>(getDefaultValues(), key)),
88
			user: objects.clone(getConfigurationValue<C>(toValuesTree(this.rawConfig.getConfig()), key)),
89
			value: objects.clone(getConfigurationValue<C>(this.getConfiguration(), key))
B
Benjamin Pasero 已提交
90 91 92
		};
	}

B
Benjamin Pasero 已提交
93 94 95 96 97 98 99
	public keys(): IConfigurationKeys {
		return {
			default: getConfigurationKeys(),
			user: Object.keys(this.rawConfig.getConfig())
		};
	}

100
	private consolidateConfigurations(): ICache<T> {
101
		const defaults = getDefaultValues();				// defaults coming from contributions to registries
102
		const user = toValuesTree(this.rawConfig.getConfig());	// user configured settings
103

104
		const consolidated = objects.mixin(
105 106 107 108
			objects.clone(defaults), 	// target: default values (but dont modify!)
			user,						// source: user settings
			true						// overwrite
		);
109 110

		return { defaults, user, consolidated };
111 112 113 114 115 116
	}

	public dispose(): void {
		this.disposables = dispose(this.disposables);
	}
}