configurationRegistry.ts 6.9 KB
Newer Older
E
Erich Gamma 已提交
1 2 3 4 5 6 7
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
'use strict';

import nls = require('vs/nls');
J
Johannes Rieken 已提交
8 9 10
import Event, { Emitter } from 'vs/base/common/event';
import { IJSONSchema } from 'vs/base/common/jsonSchema';
import { Registry } from 'vs/platform/platform';
E
Erich Gamma 已提交
11
import objects = require('vs/base/common/objects');
12
import types = require('vs/base/common/types');
J
Johannes Rieken 已提交
13 14
import { ExtensionsRegistry } from 'vs/platform/extensions/common/extensionsRegistry';
import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
E
Erich Gamma 已提交
15

B
Benjamin Pasero 已提交
16
export const Extensions = {
E
Erich Gamma 已提交
17 18 19 20 21 22 23 24 25 26
	Configuration: 'base.contributions.configuration'
};

export interface IConfigurationRegistry {

	/**
	 * Register a configuration to the registry.
	 */
	registerConfiguration(configuration: IConfigurationNode): void;

27 28 29 30 31
	/**
	 * Register multiple configurations to the registry.
	 */
	registerConfigurations(configurations: IConfigurationNode[]): void;

E
Erich Gamma 已提交
32 33 34 35 36 37 38
	/**
	 * Event that fires whenver a configuratio has been
	 * registered.
	 */
	onDidRegisterConfiguration: Event<IConfigurationRegistry>;

	/**
39
	 * Returns all configuration nodes contributed to this registry.
E
Erich Gamma 已提交
40 41
	 */
	getConfigurations(): IConfigurationNode[];
42 43 44 45 46 47

	/**
	 * Returns all configurations settings of all configuration nodes contributed to this registry.
	 */
	getConfigurationProperties(): { [qualifiedKey: string]: IJSONSchema };

E
Erich Gamma 已提交
48 49
}

50
export interface IConfigurationNode {
E
Erich Gamma 已提交
51 52
	id?: string;
	order?: number;
53
	type?: string | string[];
E
Erich Gamma 已提交
54 55 56
	title?: string;
	description?: string;
	properties?: { [path: string]: IJSONSchema; };
57
	allOf?: IConfigurationNode[];
E
Erich Gamma 已提交
58 59
}

60
const schemaId = 'vscode://schemas/settings';
61
const contributionRegistry = Registry.as<IJSONContributionRegistry>(JSONExtensions.JSONContribution);
62

E
Erich Gamma 已提交
63 64
class ConfigurationRegistry implements IConfigurationRegistry {
	private configurationContributors: IConfigurationNode[];
65
	private configurationProperties: { [qualifiedKey: string]: IJSONSchema };
66
	private configurationSchema: IJSONSchema;
E
Erich Gamma 已提交
67 68 69 70
	private _onDidRegisterConfiguration: Emitter<IConfigurationRegistry>;

	constructor() {
		this.configurationContributors = [];
71
		this.configurationSchema = { properties: {}, additionalProperties: false, errorMessage: 'Unknown configuration setting' };
E
Erich Gamma 已提交
72
		this._onDidRegisterConfiguration = new Emitter<IConfigurationRegistry>();
73
		this.configurationProperties = {};
74 75

		contributionRegistry.registerSchema(schemaId, this.configurationSchema);
E
Erich Gamma 已提交
76 77 78 79 80 81 82
	}

	public get onDidRegisterConfiguration() {
		return this._onDidRegisterConfiguration.event;
	}

	public registerConfiguration(configuration: IConfigurationNode): void {
83 84 85 86 87
		this.registerConfigurations([configuration]);
	}

	public registerConfigurations(configurations: IConfigurationNode[]): void {
		configurations.forEach(configuration => {
88
			this.registerProperties(configuration); // fills in defaults
89 90 91
			this.configurationContributors.push(configuration);
			this.registerJSONConfiguration(configuration);
		});
E
Erich Gamma 已提交
92 93 94 95

		this._onDidRegisterConfiguration.fire(this);
	}

96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
	private registerProperties(configuration: IConfigurationNode) {
		let properties = configuration.properties;
		if (properties) {
			for (let key in properties) {
				// fill in default values
				let property = properties[key];
				let defaultValue = property.default;
				if (types.isUndefined(defaultValue)) {
					property.default = getDefaultValue(property.type);
				}
				// add to properties map
				this.configurationProperties[key] = properties[key];
			}
		}
		let subNodes = configuration.allOf;
		if (subNodes) {
			for (let node of subNodes) {
				this.registerProperties(node);
			}
		}
	}

	getConfigurations(): IConfigurationNode[] {
		return this.configurationContributors;
	}

	getConfigurationProperties(): { [qualifiedKey: string]: IJSONSchema } {
		return this.configurationProperties;
E
Erich Gamma 已提交
124 125 126
	}

	private registerJSONConfiguration(configuration: IConfigurationNode) {
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
		let configurationSchema = this.configurationSchema;
		function register(configuration: IConfigurationNode) {
			let properties = configuration.properties;
			if (properties) {
				for (let key in properties) {
					configurationSchema.properties[key] = properties[key];
				}
			}
			let subNodes = configuration.allOf;
			if (subNodes) {
				subNodes.forEach(register);
			}
		};
		register(configuration);
		contributionRegistry.registerSchema(schemaId, configurationSchema);
E
Erich Gamma 已提交
142 143 144
	}
}

145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
function getDefaultValue(type: string | string[]): any {
	const t = Array.isArray(type) ? (<string[]>type)[0] : <string>type;
	switch (t) {
		case 'boolean':
			return false;
		case 'integer':
		case 'number':
			return 0;
		case 'string':
			return '';
		case 'array':
			return [];
		case 'object':
			return {};
		default:
			return null;
	}
}


B
Benjamin Pasero 已提交
165
const configurationRegistry = new ConfigurationRegistry();
166
Registry.add(Extensions.Configuration, configurationRegistry);
E
Erich Gamma 已提交
167

A
Alex Dima 已提交
168
const configurationExtPoint = ExtensionsRegistry.registerExtensionPoint<IConfigurationNode>('configuration', [], {
E
Erich Gamma 已提交
169 170
	description: nls.localize('vscode.extension.contributes.configuration', 'Contributes configuration settings.'),
	type: 'object',
171
	defaultSnippets: [{ body: { title: '', properties: {} } }],
E
Erich Gamma 已提交
172 173 174 175 176 177 178
	properties: {
		title: {
			description: nls.localize('vscode.extension.contributes.configuration.title', 'A summary of the settings. This label will be used in the settings file as separating comment.'),
			type: 'string'
		},
		properties: {
			description: nls.localize('vscode.extension.contributes.configuration.properties', 'Description of the configuration properties.'),
179 180 181 182
			type: 'object',
			additionalProperties: {
				$ref: 'http://json-schema.org/draft-04/schema#'
			}
E
Erich Gamma 已提交
183 184 185 186
		}
	}
});

187 188 189
configurationExtPoint.setHandler(extensions => {
	const configurations: IConfigurationNode[] = [];

B
Benjamin Pasero 已提交
190
	for (let i = 0; i < extensions.length; i++) {
B
Benjamin Pasero 已提交
191 192
		const configuration = <IConfigurationNode>extensions[i].value;
		const collector = extensions[i].collector;
193 194 195 196 197 198 199 200 201 202 203

		if (configuration.type && configuration.type !== 'object') {
			collector.warn(nls.localize('invalid.type', "if set, 'configuration.type' must be set to 'object"));
		} else {
			configuration.type = 'object';
		}

		if (configuration.title && (typeof configuration.title !== 'string')) {
			collector.error(nls.localize('invalid.title', "'configuration.title' must be a string"));
		}

B
Benjamin Pasero 已提交
204
		if (configuration.properties && (typeof configuration.properties !== 'object')) {
205 206 207
			collector.error(nls.localize('invalid.properties', "'configuration.properties' must be an object"));
			return;
		}
208

B
Benjamin Pasero 已提交
209
		const clonedConfiguration = objects.clone(configuration);
E
Erich Gamma 已提交
210
		clonedConfiguration.id = extensions[i].description.id;
211
		configurations.push(clonedConfiguration);
E
Erich Gamma 已提交
212
	}
213 214

	configurationRegistry.registerConfigurations(configurations);
B
Benjamin Pasero 已提交
215
});