123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288 |
- /*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
- import { distinct } from '../../../base/common/arrays.js';
- import { Emitter } from '../../../base/common/event.js';
- import * as types from '../../../base/common/types.js';
- import * as nls from '../../../nls.js';
- import { Extensions as JSONExtensions } from '../../jsonschemas/common/jsonContributionRegistry.js';
- import { Registry } from '../../registry/common/platform.js';
- export const Extensions = {
- Configuration: 'base.contributions.configuration'
- };
- export const allSettings = { properties: {}, patternProperties: {} };
- export const applicationSettings = { properties: {}, patternProperties: {} };
- export const machineSettings = { properties: {}, patternProperties: {} };
- export const machineOverridableSettings = { properties: {}, patternProperties: {} };
- export const windowSettings = { properties: {}, patternProperties: {} };
- export const resourceSettings = { properties: {}, patternProperties: {} };
- export const resourceLanguageSettingsSchemaId = 'vscode://schemas/settings/resourceLanguage';
- const contributionRegistry = Registry.as(JSONExtensions.JSONContribution);
- class ConfigurationRegistry {
- constructor() {
- this.overrideIdentifiers = new Set();
- this._onDidSchemaChange = new Emitter();
- this._onDidUpdateConfiguration = new Emitter();
- this.configurationDefaultsOverrides = new Map();
- this.defaultLanguageConfigurationOverridesNode = {
- id: 'defaultOverrides',
- title: nls.localize('defaultLanguageConfigurationOverrides.title', "Default Language Configuration Overrides"),
- properties: {}
- };
- this.configurationContributors = [this.defaultLanguageConfigurationOverridesNode];
- this.resourceLanguageSettingsSchema = { properties: {}, patternProperties: {}, additionalProperties: false, errorMessage: 'Unknown editor configuration setting', allowTrailingCommas: true, allowComments: true };
- this.configurationProperties = {};
- this.excludedConfigurationProperties = {};
- contributionRegistry.registerSchema(resourceLanguageSettingsSchemaId, this.resourceLanguageSettingsSchema);
- this.registerOverridePropertyPatternKey();
- }
- registerConfiguration(configuration, validate = true) {
- this.registerConfigurations([configuration], validate);
- }
- registerConfigurations(configurations, validate = true) {
- const properties = this.doRegisterConfigurations(configurations, validate);
- contributionRegistry.registerSchema(resourceLanguageSettingsSchemaId, this.resourceLanguageSettingsSchema);
- this._onDidSchemaChange.fire();
- this._onDidUpdateConfiguration.fire({ properties });
- }
- registerDefaultConfigurations(configurationDefaults) {
- var _a;
- const properties = [];
- const overrideIdentifiers = [];
- for (const { overrides, source } of configurationDefaults) {
- for (const key in overrides) {
- properties.push(key);
- if (OVERRIDE_PROPERTY_REGEX.test(key)) {
- const defaultValue = Object.assign(Object.assign({}, (((_a = this.configurationDefaultsOverrides.get(key)) === null || _a === void 0 ? void 0 : _a.value) || {})), overrides[key]);
- this.configurationDefaultsOverrides.set(key, { source, value: defaultValue });
- const property = {
- type: 'object',
- default: defaultValue,
- description: nls.localize('defaultLanguageConfiguration.description', "Configure settings to be overridden for {0} language.", key),
- $ref: resourceLanguageSettingsSchemaId,
- defaultDefaultValue: defaultValue,
- source: types.isString(source) ? undefined : source,
- };
- overrideIdentifiers.push(...overrideIdentifiersFromKey(key));
- this.configurationProperties[key] = property;
- this.defaultLanguageConfigurationOverridesNode.properties[key] = property;
- }
- else {
- this.configurationDefaultsOverrides.set(key, { value: overrides[key], source });
- const property = this.configurationProperties[key];
- if (property) {
- this.updatePropertyDefaultValue(key, property);
- this.updateSchema(key, property);
- }
- }
- }
- }
- this.registerOverrideIdentifiers(overrideIdentifiers);
- this._onDidSchemaChange.fire();
- this._onDidUpdateConfiguration.fire({ properties, defaultsOverrides: true });
- }
- registerOverrideIdentifiers(overrideIdentifiers) {
- for (const overrideIdentifier of overrideIdentifiers) {
- this.overrideIdentifiers.add(overrideIdentifier);
- }
- this.updateOverridePropertyPatternKey();
- }
- doRegisterConfigurations(configurations, validate) {
- const properties = [];
- configurations.forEach(configuration => {
- properties.push(...this.validateAndRegisterProperties(configuration, validate, configuration.extensionInfo, configuration.restrictedProperties)); // fills in defaults
- this.configurationContributors.push(configuration);
- this.registerJSONConfiguration(configuration);
- });
- return properties;
- }
- validateAndRegisterProperties(configuration, validate = true, extensionInfo, restrictedProperties, scope = 3 /* WINDOW */) {
- scope = types.isUndefinedOrNull(configuration.scope) ? scope : configuration.scope;
- let propertyKeys = [];
- let properties = configuration.properties;
- if (properties) {
- for (let key in properties) {
- if (validate && validateProperty(key)) {
- delete properties[key];
- continue;
- }
- const property = properties[key];
- property.source = extensionInfo;
- // update default value
- property.defaultDefaultValue = properties[key].default;
- this.updatePropertyDefaultValue(key, property);
- // update scope
- if (OVERRIDE_PROPERTY_REGEX.test(key)) {
- property.scope = undefined; // No scope for overridable properties `[${identifier}]`
- }
- else {
- property.scope = types.isUndefinedOrNull(property.scope) ? scope : property.scope;
- property.restricted = types.isUndefinedOrNull(property.restricted) ? !!(restrictedProperties === null || restrictedProperties === void 0 ? void 0 : restrictedProperties.includes(key)) : property.restricted;
- }
- // Add to properties maps
- // Property is included by default if 'included' is unspecified
- if (properties[key].hasOwnProperty('included') && !properties[key].included) {
- this.excludedConfigurationProperties[key] = properties[key];
- delete properties[key];
- continue;
- }
- else {
- this.configurationProperties[key] = properties[key];
- }
- if (!properties[key].deprecationMessage && properties[key].markdownDeprecationMessage) {
- // If not set, default deprecationMessage to the markdown source
- properties[key].deprecationMessage = properties[key].markdownDeprecationMessage;
- }
- propertyKeys.push(key);
- }
- }
- let subNodes = configuration.allOf;
- if (subNodes) {
- for (let node of subNodes) {
- propertyKeys.push(...this.validateAndRegisterProperties(node, validate, extensionInfo, restrictedProperties, scope));
- }
- }
- return propertyKeys;
- }
- getConfigurationProperties() {
- return this.configurationProperties;
- }
- registerJSONConfiguration(configuration) {
- const register = (configuration) => {
- let properties = configuration.properties;
- if (properties) {
- for (const key in properties) {
- this.updateSchema(key, properties[key]);
- }
- }
- let subNodes = configuration.allOf;
- if (subNodes) {
- subNodes.forEach(register);
- }
- };
- register(configuration);
- }
- updateSchema(key, property) {
- allSettings.properties[key] = property;
- switch (property.scope) {
- case 1 /* APPLICATION */:
- applicationSettings.properties[key] = property;
- break;
- case 2 /* MACHINE */:
- machineSettings.properties[key] = property;
- break;
- case 6 /* MACHINE_OVERRIDABLE */:
- machineOverridableSettings.properties[key] = property;
- break;
- case 3 /* WINDOW */:
- windowSettings.properties[key] = property;
- break;
- case 4 /* RESOURCE */:
- resourceSettings.properties[key] = property;
- break;
- case 5 /* LANGUAGE_OVERRIDABLE */:
- resourceSettings.properties[key] = property;
- this.resourceLanguageSettingsSchema.properties[key] = property;
- break;
- }
- }
- updateOverridePropertyPatternKey() {
- for (const overrideIdentifier of this.overrideIdentifiers.values()) {
- const overrideIdentifierProperty = `[${overrideIdentifier}]`;
- const resourceLanguagePropertiesSchema = {
- type: 'object',
- description: nls.localize('overrideSettings.defaultDescription', "Configure editor settings to be overridden for a language."),
- errorMessage: nls.localize('overrideSettings.errorMessage', "This setting does not support per-language configuration."),
- $ref: resourceLanguageSettingsSchemaId,
- };
- this.updatePropertyDefaultValue(overrideIdentifierProperty, resourceLanguagePropertiesSchema);
- allSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;
- applicationSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;
- machineSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;
- machineOverridableSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;
- windowSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;
- resourceSettings.properties[overrideIdentifierProperty] = resourceLanguagePropertiesSchema;
- }
- this._onDidSchemaChange.fire();
- }
- registerOverridePropertyPatternKey() {
- const resourceLanguagePropertiesSchema = {
- type: 'object',
- description: nls.localize('overrideSettings.defaultDescription', "Configure editor settings to be overridden for a language."),
- errorMessage: nls.localize('overrideSettings.errorMessage', "This setting does not support per-language configuration."),
- $ref: resourceLanguageSettingsSchemaId,
- };
- allSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;
- applicationSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;
- machineSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;
- machineOverridableSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;
- windowSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;
- resourceSettings.patternProperties[OVERRIDE_PROPERTY_PATTERN] = resourceLanguagePropertiesSchema;
- this._onDidSchemaChange.fire();
- }
- updatePropertyDefaultValue(key, property) {
- const configurationdefaultOverride = this.configurationDefaultsOverrides.get(key);
- let defaultValue = configurationdefaultOverride === null || configurationdefaultOverride === void 0 ? void 0 : configurationdefaultOverride.value;
- let defaultSource = configurationdefaultOverride === null || configurationdefaultOverride === void 0 ? void 0 : configurationdefaultOverride.source;
- if (types.isUndefined(defaultValue)) {
- defaultValue = property.defaultDefaultValue;
- defaultSource = undefined;
- }
- if (types.isUndefined(defaultValue)) {
- defaultValue = getDefaultValue(property.type);
- }
- property.default = defaultValue;
- property.defaultValueSource = defaultSource;
- }
- }
- const OVERRIDE_IDENTIFIER_PATTERN = `\\[([^\\]]+)\\]`;
- const OVERRIDE_IDENTIFIER_REGEX = new RegExp(OVERRIDE_IDENTIFIER_PATTERN, 'g');
- export const OVERRIDE_PROPERTY_PATTERN = `^(${OVERRIDE_IDENTIFIER_PATTERN})+$`;
- export const OVERRIDE_PROPERTY_REGEX = new RegExp(OVERRIDE_PROPERTY_PATTERN);
- export function overrideIdentifiersFromKey(key) {
- const identifiers = [];
- if (OVERRIDE_PROPERTY_REGEX.test(key)) {
- let matches = OVERRIDE_IDENTIFIER_REGEX.exec(key);
- while (matches === null || matches === void 0 ? void 0 : matches.length) {
- const identifier = matches[1].trim();
- if (identifier) {
- identifiers.push(identifier);
- }
- matches = OVERRIDE_IDENTIFIER_REGEX.exec(key);
- }
- }
- return distinct(identifiers);
- }
- export function getDefaultValue(type) {
- const t = Array.isArray(type) ? type[0] : 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;
- }
- }
- const configurationRegistry = new ConfigurationRegistry();
- Registry.add(Extensions.Configuration, configurationRegistry);
- export function validateProperty(property) {
- if (!property.trim()) {
- return nls.localize('config.property.empty', "Cannot register an empty property");
- }
- if (OVERRIDE_PROPERTY_REGEX.test(property)) {
- return nls.localize('config.property.languageDefault', "Cannot register '{0}'. This matches property pattern '\\\\[.*\\\\]$' for describing language specific editor settings. Use 'configurationDefaults' contribution.", property);
- }
- if (configurationRegistry.getConfigurationProperties()[property] !== undefined) {
- return nls.localize('config.property.duplicate', "Cannot register '{0}'. This property is already registered.", property);
- }
- return null;
- }
|