@sussudio/platform
Version:
Internal APIs for VS Code's service injection the base services.
198 lines (197 loc) • 7.97 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var __decorate =
(this && this.__decorate) ||
function (decorators, target, key, desc) {
var c = arguments.length,
r = c < 3 ? target : desc === null ? (desc = Object.getOwnPropertyDescriptor(target, key)) : desc,
d;
if (typeof Reflect === 'object' && typeof Reflect.decorate === 'function')
r = Reflect.decorate(decorators, target, key, desc);
else
for (var i = decorators.length - 1; i >= 0; i--)
if ((d = decorators[i])) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param =
(this && this.__param) ||
function (paramIndex, decorator) {
return function (target, key) {
decorator(target, key, paramIndex);
};
};
import { coalesce } from '@sussudio/base/common/arrays.mjs';
import { Emitter, Event } from '@sussudio/base/common/event.mjs';
import { Disposable } from '@sussudio/base/common/lifecycle.mjs';
import { equals } from '@sussudio/base/common/objects.mjs';
import { isEmptyObject } from '@sussudio/base/common/types.mjs';
import { addToValueTree, toValuesTree } from './configuration.mjs';
import { ConfigurationModel } from './configurationModels.mjs';
import { Extensions, overrideIdentifiersFromKey, OVERRIDE_PROPERTY_REGEX } from './configurationRegistry.mjs';
import { ILogService } from '../../log/common/log.mjs';
import { IPolicyService } from '../../policy/common/policy.mjs';
import { Registry } from '../../registry/common/platform.mjs';
export class DefaultConfiguration extends Disposable {
_onDidChangeConfiguration = this._register(new Emitter());
onDidChangeConfiguration = this._onDidChangeConfiguration.event;
_configurationModel;
get configurationModel() {
if (!this._configurationModel) {
this._configurationModel = new DefaultConfigurationModel(this.getConfigurationDefaultOverrides());
}
return this._configurationModel;
}
async initialize() {
this._configurationModel = undefined;
this._register(
Registry.as(Extensions.Configuration).onDidUpdateConfiguration(({ properties, defaultsOverrides }) =>
this.onDidUpdateConfiguration(Array.from(properties), defaultsOverrides),
),
);
return this.configurationModel;
}
reload() {
this._configurationModel = undefined;
return this.configurationModel;
}
onDidUpdateConfiguration(properties, defaultsOverrides) {
this._configurationModel = undefined;
this._onDidChangeConfiguration.fire({ defaults: this.configurationModel, properties });
}
getConfigurationDefaultOverrides() {
return {};
}
}
export class DefaultConfigurationModel extends ConfigurationModel {
constructor(configurationDefaultsOverrides = {}) {
const properties = Registry.as(Extensions.Configuration).getConfigurationProperties();
const keys = Object.keys(properties);
const contents = Object.create(null);
const overrides = [];
for (const key in properties) {
const defaultOverrideValue = configurationDefaultsOverrides[key];
const value = defaultOverrideValue !== undefined ? defaultOverrideValue : properties[key].default;
addToValueTree(contents, key, value, (message) => console.error(`Conflict in default settings: ${message}`));
}
for (const key of Object.keys(contents)) {
if (OVERRIDE_PROPERTY_REGEX.test(key)) {
overrides.push({
identifiers: overrideIdentifiersFromKey(key),
keys: Object.keys(contents[key]),
contents: toValuesTree(contents[key], (message) =>
console.error(`Conflict in default settings file: ${message}`),
),
});
}
}
super(contents, keys, overrides);
}
}
export class NullPolicyConfiguration {
onDidChangeConfiguration = Event.None;
configurationModel = new ConfigurationModel();
async initialize() {
return this.configurationModel;
}
}
let PolicyConfiguration = class PolicyConfiguration extends Disposable {
defaultConfiguration;
policyService;
logService;
_onDidChangeConfiguration = this._register(new Emitter());
onDidChangeConfiguration = this._onDidChangeConfiguration.event;
_configurationModel = new ConfigurationModel();
get configurationModel() {
return this._configurationModel;
}
constructor(defaultConfiguration, policyService, logService) {
super();
this.defaultConfiguration = defaultConfiguration;
this.policyService = policyService;
this.logService = logService;
}
async initialize() {
this.logService.trace('PolicyConfiguration#initialize');
this.update(await this.updatePolicyDefinitions(this.defaultConfiguration.configurationModel.keys), false);
this._register(this.policyService.onDidChange((policyNames) => this.onDidChangePolicies(policyNames)));
this._register(
this.defaultConfiguration.onDidChangeConfiguration(async ({ properties }) =>
this.update(await this.updatePolicyDefinitions(properties), true),
),
);
return this._configurationModel;
}
async updatePolicyDefinitions(properties) {
this.logService.trace('PolicyConfiguration#updatePolicyDefinitions', properties);
const policyDefinitions = {};
const keys = [];
const configurationProperties = Registry.as(Extensions.Configuration).getConfigurationProperties();
for (const key of properties) {
const config = configurationProperties[key];
if (!config) {
// Config is removed. So add it to the list if in case it was registered as policy before
keys.push(key);
continue;
}
if (config.policy) {
if (config.type !== 'string' && config.type !== 'number') {
this.logService.warn(`Policy ${config.policy.name} has unsupported type ${config.type}`);
continue;
}
keys.push(key);
policyDefinitions[config.policy.name] = { type: config.type };
}
}
if (!isEmptyObject(policyDefinitions)) {
await this.policyService.updatePolicyDefinitions(policyDefinitions);
}
return keys;
}
onDidChangePolicies(policyNames) {
this.logService.trace('PolicyConfiguration#onDidChangePolicies', policyNames);
const policyConfigurations = Registry.as(Extensions.Configuration).getPolicyConfigurations();
const keys = coalesce(policyNames.map((policyName) => policyConfigurations.get(policyName)));
this.update(keys, true);
}
update(keys, trigger) {
this.logService.trace('PolicyConfiguration#update', keys);
const configurationProperties = Registry.as(Extensions.Configuration).getConfigurationProperties();
const changed = [];
const wasEmpty = this._configurationModel.isEmpty();
for (const key of keys) {
const policyName = configurationProperties[key]?.policy?.name;
if (policyName) {
const policyValue = this.policyService.getPolicyValue(policyName);
if (wasEmpty ? policyValue !== undefined : !equals(this._configurationModel.getValue(key), policyValue)) {
changed.push([key, policyValue]);
}
} else {
if (this._configurationModel.getValue(key) !== undefined) {
changed.push([key, undefined]);
}
}
}
if (changed.length) {
this.logService.trace('PolicyConfiguration#changed', changed);
const old = this._configurationModel;
this._configurationModel = new ConfigurationModel();
for (const key of old.keys) {
this._configurationModel.setValue(key, old.getValue(key));
}
for (const [key, policyValue] of changed) {
if (policyValue === undefined) {
this._configurationModel.removeValue(key);
} else {
this._configurationModel.setValue(key, policyValue);
}
}
if (trigger) {
this._onDidChangeConfiguration.fire(this._configurationModel);
}
}
}
};
PolicyConfiguration = __decorate([__param(1, IPolicyService), __param(2, ILogService)], PolicyConfiguration);
export { PolicyConfiguration };