| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435 |
- /*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the MIT License. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
- import * as arrays from '../../../base/common/arrays.js';
- import { ResourceMap } from '../../../base/common/map.js';
- import * as objects from '../../../base/common/objects.js';
- import * as types from '../../../base/common/types.js';
- import { URI } from '../../../base/common/uri.js';
- import { addToValueTree, getConfigurationValue, removeFromValueTree, toValuesTree } from './configuration.js';
- export class ConfigurationModel {
- constructor(_contents = {}, _keys = [], _overrides = []) {
- this._contents = _contents;
- this._keys = _keys;
- this._overrides = _overrides;
- this.frozen = false;
- this.overrideConfigurations = new Map();
- }
- get contents() {
- return this.checkAndFreeze(this._contents);
- }
- get overrides() {
- return this.checkAndFreeze(this._overrides);
- }
- get keys() {
- return this.checkAndFreeze(this._keys);
- }
- isEmpty() {
- return this._keys.length === 0 && Object.keys(this._contents).length === 0 && this._overrides.length === 0;
- }
- getValue(section) {
- return section ? getConfigurationValue(this.contents, section) : this.contents;
- }
- getOverrideValue(section, overrideIdentifier) {
- const overrideContents = this.getContentsForOverrideIdentifer(overrideIdentifier);
- return overrideContents
- ? section ? getConfigurationValue(overrideContents, section) : overrideContents
- : undefined;
- }
- override(identifier) {
- let overrideConfigurationModel = this.overrideConfigurations.get(identifier);
- if (!overrideConfigurationModel) {
- overrideConfigurationModel = this.createOverrideConfigurationModel(identifier);
- this.overrideConfigurations.set(identifier, overrideConfigurationModel);
- }
- return overrideConfigurationModel;
- }
- merge(...others) {
- const contents = objects.deepClone(this.contents);
- const overrides = objects.deepClone(this.overrides);
- const keys = [...this.keys];
- for (const other of others) {
- if (other.isEmpty()) {
- continue;
- }
- this.mergeContents(contents, other.contents);
- for (const otherOverride of other.overrides) {
- const [override] = overrides.filter(o => arrays.equals(o.identifiers, otherOverride.identifiers));
- if (override) {
- this.mergeContents(override.contents, otherOverride.contents);
- override.keys.push(...otherOverride.keys);
- override.keys = arrays.distinct(override.keys);
- }
- else {
- overrides.push(objects.deepClone(otherOverride));
- }
- }
- for (const key of other.keys) {
- if (keys.indexOf(key) === -1) {
- keys.push(key);
- }
- }
- }
- return new ConfigurationModel(contents, keys, overrides);
- }
- freeze() {
- this.frozen = true;
- return this;
- }
- createOverrideConfigurationModel(identifier) {
- const overrideContents = this.getContentsForOverrideIdentifer(identifier);
- if (!overrideContents || typeof overrideContents !== 'object' || !Object.keys(overrideContents).length) {
- // If there are no valid overrides, return self
- return this;
- }
- const contents = {};
- for (const key of arrays.distinct([...Object.keys(this.contents), ...Object.keys(overrideContents)])) {
- let contentsForKey = this.contents[key];
- const overrideContentsForKey = overrideContents[key];
- // If there are override contents for the key, clone and merge otherwise use base contents
- if (overrideContentsForKey) {
- // Clone and merge only if base contents and override contents are of type object otherwise just override
- if (typeof contentsForKey === 'object' && typeof overrideContentsForKey === 'object') {
- contentsForKey = objects.deepClone(contentsForKey);
- this.mergeContents(contentsForKey, overrideContentsForKey);
- }
- else {
- contentsForKey = overrideContentsForKey;
- }
- }
- contents[key] = contentsForKey;
- }
- return new ConfigurationModel(contents, this.keys, this.overrides);
- }
- mergeContents(source, target) {
- for (const key of Object.keys(target)) {
- if (key in source) {
- if (types.isObject(source[key]) && types.isObject(target[key])) {
- this.mergeContents(source[key], target[key]);
- continue;
- }
- }
- source[key] = objects.deepClone(target[key]);
- }
- }
- checkAndFreeze(data) {
- if (this.frozen && !Object.isFrozen(data)) {
- return objects.deepFreeze(data);
- }
- return data;
- }
- getContentsForOverrideIdentifer(identifier) {
- let contentsForIdentifierOnly = null;
- let contents = null;
- const mergeContents = (contentsToMerge) => {
- if (contentsToMerge) {
- if (contents) {
- this.mergeContents(contents, contentsToMerge);
- }
- else {
- contents = objects.deepClone(contentsToMerge);
- }
- }
- };
- for (const override of this.overrides) {
- if (arrays.equals(override.identifiers, [identifier])) {
- contentsForIdentifierOnly = override.contents;
- }
- else if (override.identifiers.includes(identifier)) {
- mergeContents(override.contents);
- }
- }
- // Merge contents of the identifier only at the end to take precedence.
- mergeContents(contentsForIdentifierOnly);
- return contents;
- }
- toJSON() {
- return {
- contents: this.contents,
- overrides: this.overrides,
- keys: this.keys
- };
- }
- // Update methods
- setValue(key, value) {
- this.addKey(key);
- addToValueTree(this.contents, key, value, e => { throw new Error(e); });
- }
- removeValue(key) {
- if (this.removeKey(key)) {
- removeFromValueTree(this.contents, key);
- }
- }
- addKey(key) {
- let index = this.keys.length;
- for (let i = 0; i < index; i++) {
- if (key.indexOf(this.keys[i]) === 0) {
- index = i;
- }
- }
- this.keys.splice(index, 1, key);
- }
- removeKey(key) {
- const index = this.keys.indexOf(key);
- if (index !== -1) {
- this.keys.splice(index, 1);
- return true;
- }
- return false;
- }
- }
- export class Configuration {
- constructor(_defaultConfiguration, _policyConfiguration, _applicationConfiguration, _localUserConfiguration, _remoteUserConfiguration = new ConfigurationModel(), _workspaceConfiguration = new ConfigurationModel(), _folderConfigurations = new ResourceMap(), _memoryConfiguration = new ConfigurationModel(), _memoryConfigurationByResource = new ResourceMap(), _freeze = true) {
- this._defaultConfiguration = _defaultConfiguration;
- this._policyConfiguration = _policyConfiguration;
- this._applicationConfiguration = _applicationConfiguration;
- this._localUserConfiguration = _localUserConfiguration;
- this._remoteUserConfiguration = _remoteUserConfiguration;
- this._workspaceConfiguration = _workspaceConfiguration;
- this._folderConfigurations = _folderConfigurations;
- this._memoryConfiguration = _memoryConfiguration;
- this._memoryConfigurationByResource = _memoryConfigurationByResource;
- this._freeze = _freeze;
- this._workspaceConsolidatedConfiguration = null;
- this._foldersConsolidatedConfigurations = new ResourceMap();
- this._userConfiguration = null;
- }
- getValue(section, overrides, workspace) {
- const consolidateConfigurationModel = this.getConsolidatedConfigurationModel(section, overrides, workspace);
- return consolidateConfigurationModel.getValue(section);
- }
- updateValue(key, value, overrides = {}) {
- let memoryConfiguration;
- if (overrides.resource) {
- memoryConfiguration = this._memoryConfigurationByResource.get(overrides.resource);
- if (!memoryConfiguration) {
- memoryConfiguration = new ConfigurationModel();
- this._memoryConfigurationByResource.set(overrides.resource, memoryConfiguration);
- }
- }
- else {
- memoryConfiguration = this._memoryConfiguration;
- }
- if (value === undefined) {
- memoryConfiguration.removeValue(key);
- }
- else {
- memoryConfiguration.setValue(key, value);
- }
- if (!overrides.resource) {
- this._workspaceConsolidatedConfiguration = null;
- }
- }
- inspect(key, overrides, workspace) {
- const consolidateConfigurationModel = this.getConsolidatedConfigurationModel(key, overrides, workspace);
- const folderConfigurationModel = this.getFolderConfigurationModelForResource(overrides.resource, workspace);
- const memoryConfigurationModel = overrides.resource ? this._memoryConfigurationByResource.get(overrides.resource) || this._memoryConfiguration : this._memoryConfiguration;
- const defaultValue = overrides.overrideIdentifier ? this._defaultConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this._defaultConfiguration.freeze().getValue(key);
- const policyValue = this._policyConfiguration.isEmpty() ? undefined : this._policyConfiguration.freeze().getValue(key);
- const applicationValue = this.applicationConfiguration.isEmpty() ? undefined : this.applicationConfiguration.freeze().getValue(key);
- const userValue = overrides.overrideIdentifier ? this.userConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this.userConfiguration.freeze().getValue(key);
- const userLocalValue = overrides.overrideIdentifier ? this.localUserConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this.localUserConfiguration.freeze().getValue(key);
- const userRemoteValue = overrides.overrideIdentifier ? this.remoteUserConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this.remoteUserConfiguration.freeze().getValue(key);
- const workspaceValue = workspace ? overrides.overrideIdentifier ? this._workspaceConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this._workspaceConfiguration.freeze().getValue(key) : undefined; //Check on workspace exists or not because _workspaceConfiguration is never null
- const workspaceFolderValue = folderConfigurationModel ? overrides.overrideIdentifier ? folderConfigurationModel.freeze().override(overrides.overrideIdentifier).getValue(key) : folderConfigurationModel.freeze().getValue(key) : undefined;
- const memoryValue = overrides.overrideIdentifier ? memoryConfigurationModel.override(overrides.overrideIdentifier).getValue(key) : memoryConfigurationModel.getValue(key);
- const value = consolidateConfigurationModel.getValue(key);
- const overrideIdentifiers = arrays.distinct(consolidateConfigurationModel.overrides.map(override => override.identifiers).flat()).filter(overrideIdentifier => consolidateConfigurationModel.getOverrideValue(key, overrideIdentifier) !== undefined);
- return {
- defaultValue,
- policyValue,
- applicationValue,
- userValue,
- userLocalValue,
- userRemoteValue,
- workspaceValue,
- workspaceFolderValue,
- memoryValue,
- value,
- default: defaultValue !== undefined ? { value: this._defaultConfiguration.freeze().getValue(key), override: overrides.overrideIdentifier ? this._defaultConfiguration.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,
- policy: policyValue !== undefined ? { value: policyValue } : undefined,
- application: applicationValue !== undefined ? { value: applicationValue, override: overrides.overrideIdentifier ? this.applicationConfiguration.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,
- user: userValue !== undefined ? { value: this.userConfiguration.freeze().getValue(key), override: overrides.overrideIdentifier ? this.userConfiguration.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,
- userLocal: userLocalValue !== undefined ? { value: this.localUserConfiguration.freeze().getValue(key), override: overrides.overrideIdentifier ? this.localUserConfiguration.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,
- userRemote: userRemoteValue !== undefined ? { value: this.remoteUserConfiguration.freeze().getValue(key), override: overrides.overrideIdentifier ? this.remoteUserConfiguration.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,
- workspace: workspaceValue !== undefined ? { value: this._workspaceConfiguration.freeze().getValue(key), override: overrides.overrideIdentifier ? this._workspaceConfiguration.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,
- workspaceFolder: workspaceFolderValue !== undefined ? { value: folderConfigurationModel === null || folderConfigurationModel === void 0 ? void 0 : folderConfigurationModel.freeze().getValue(key), override: overrides.overrideIdentifier ? folderConfigurationModel === null || folderConfigurationModel === void 0 ? void 0 : folderConfigurationModel.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,
- memory: memoryValue !== undefined ? { value: memoryConfigurationModel.getValue(key), override: overrides.overrideIdentifier ? memoryConfigurationModel.getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,
- overrideIdentifiers: overrideIdentifiers.length ? overrideIdentifiers : undefined
- };
- }
- get applicationConfiguration() {
- return this._applicationConfiguration;
- }
- get userConfiguration() {
- if (!this._userConfiguration) {
- this._userConfiguration = this._remoteUserConfiguration.isEmpty() ? this._localUserConfiguration : this._localUserConfiguration.merge(this._remoteUserConfiguration);
- if (this._freeze) {
- this._userConfiguration.freeze();
- }
- }
- return this._userConfiguration;
- }
- get localUserConfiguration() {
- return this._localUserConfiguration;
- }
- get remoteUserConfiguration() {
- return this._remoteUserConfiguration;
- }
- getConsolidatedConfigurationModel(section, overrides, workspace) {
- let configurationModel = this.getConsolidatedConfigurationModelForResource(overrides, workspace);
- if (overrides.overrideIdentifier) {
- configurationModel = configurationModel.override(overrides.overrideIdentifier);
- }
- if (!this._policyConfiguration.isEmpty() && this._policyConfiguration.getValue(section) !== undefined) {
- configurationModel = configurationModel.merge(this._policyConfiguration);
- }
- return configurationModel;
- }
- getConsolidatedConfigurationModelForResource({ resource }, workspace) {
- let consolidateConfiguration = this.getWorkspaceConsolidatedConfiguration();
- if (workspace && resource) {
- const root = workspace.getFolder(resource);
- if (root) {
- consolidateConfiguration = this.getFolderConsolidatedConfiguration(root.uri) || consolidateConfiguration;
- }
- const memoryConfigurationForResource = this._memoryConfigurationByResource.get(resource);
- if (memoryConfigurationForResource) {
- consolidateConfiguration = consolidateConfiguration.merge(memoryConfigurationForResource);
- }
- }
- return consolidateConfiguration;
- }
- getWorkspaceConsolidatedConfiguration() {
- if (!this._workspaceConsolidatedConfiguration) {
- this._workspaceConsolidatedConfiguration = this._defaultConfiguration.merge(this.applicationConfiguration, this.userConfiguration, this._workspaceConfiguration, this._memoryConfiguration);
- if (this._freeze) {
- this._workspaceConfiguration = this._workspaceConfiguration.freeze();
- }
- }
- return this._workspaceConsolidatedConfiguration;
- }
- getFolderConsolidatedConfiguration(folder) {
- let folderConsolidatedConfiguration = this._foldersConsolidatedConfigurations.get(folder);
- if (!folderConsolidatedConfiguration) {
- const workspaceConsolidateConfiguration = this.getWorkspaceConsolidatedConfiguration();
- const folderConfiguration = this._folderConfigurations.get(folder);
- if (folderConfiguration) {
- folderConsolidatedConfiguration = workspaceConsolidateConfiguration.merge(folderConfiguration);
- if (this._freeze) {
- folderConsolidatedConfiguration = folderConsolidatedConfiguration.freeze();
- }
- this._foldersConsolidatedConfigurations.set(folder, folderConsolidatedConfiguration);
- }
- else {
- folderConsolidatedConfiguration = workspaceConsolidateConfiguration;
- }
- }
- return folderConsolidatedConfiguration;
- }
- getFolderConfigurationModelForResource(resource, workspace) {
- if (workspace && resource) {
- const root = workspace.getFolder(resource);
- if (root) {
- return this._folderConfigurations.get(root.uri);
- }
- }
- return undefined;
- }
- toData() {
- return {
- defaults: {
- contents: this._defaultConfiguration.contents,
- overrides: this._defaultConfiguration.overrides,
- keys: this._defaultConfiguration.keys
- },
- policy: {
- contents: this._policyConfiguration.contents,
- overrides: this._policyConfiguration.overrides,
- keys: this._policyConfiguration.keys
- },
- application: {
- contents: this.applicationConfiguration.contents,
- overrides: this.applicationConfiguration.overrides,
- keys: this.applicationConfiguration.keys
- },
- user: {
- contents: this.userConfiguration.contents,
- overrides: this.userConfiguration.overrides,
- keys: this.userConfiguration.keys
- },
- workspace: {
- contents: this._workspaceConfiguration.contents,
- overrides: this._workspaceConfiguration.overrides,
- keys: this._workspaceConfiguration.keys
- },
- folders: [...this._folderConfigurations.keys()].reduce((result, folder) => {
- const { contents, overrides, keys } = this._folderConfigurations.get(folder);
- result.push([folder, { contents, overrides, keys }]);
- return result;
- }, [])
- };
- }
- static parse(data) {
- const defaultConfiguration = this.parseConfigurationModel(data.defaults);
- const policyConfiguration = this.parseConfigurationModel(data.policy);
- const applicationConfiguration = this.parseConfigurationModel(data.application);
- const userConfiguration = this.parseConfigurationModel(data.user);
- const workspaceConfiguration = this.parseConfigurationModel(data.workspace);
- const folders = data.folders.reduce((result, value) => {
- result.set(URI.revive(value[0]), this.parseConfigurationModel(value[1]));
- return result;
- }, new ResourceMap());
- return new Configuration(defaultConfiguration, policyConfiguration, applicationConfiguration, userConfiguration, new ConfigurationModel(), workspaceConfiguration, folders, new ConfigurationModel(), new ResourceMap(), false);
- }
- static parseConfigurationModel(model) {
- return new ConfigurationModel(model.contents, model.keys, model.overrides).freeze();
- }
- }
- export class ConfigurationChangeEvent {
- constructor(change, previous, currentConfiguraiton, currentWorkspace) {
- this.change = change;
- this.previous = previous;
- this.currentConfiguraiton = currentConfiguraiton;
- this.currentWorkspace = currentWorkspace;
- this._previousConfiguration = undefined;
- const keysSet = new Set();
- change.keys.forEach(key => keysSet.add(key));
- change.overrides.forEach(([, keys]) => keys.forEach(key => keysSet.add(key)));
- this.affectedKeys = [...keysSet.values()];
- const configurationModel = new ConfigurationModel();
- this.affectedKeys.forEach(key => configurationModel.setValue(key, {}));
- this.affectedKeysTree = configurationModel.contents;
- }
- get previousConfiguration() {
- if (!this._previousConfiguration && this.previous) {
- this._previousConfiguration = Configuration.parse(this.previous.data);
- }
- return this._previousConfiguration;
- }
- affectsConfiguration(section, overrides) {
- var _a;
- if (this.doesAffectedKeysTreeContains(this.affectedKeysTree, section)) {
- if (overrides) {
- const value1 = this.previousConfiguration ? this.previousConfiguration.getValue(section, overrides, (_a = this.previous) === null || _a === void 0 ? void 0 : _a.workspace) : undefined;
- const value2 = this.currentConfiguraiton.getValue(section, overrides, this.currentWorkspace);
- return !objects.equals(value1, value2);
- }
- return true;
- }
- return false;
- }
- doesAffectedKeysTreeContains(affectedKeysTree, section) {
- let requestedTree = toValuesTree({ [section]: true }, () => { });
- let key;
- while (typeof requestedTree === 'object' && (key = Object.keys(requestedTree)[0])) { // Only one key should present, since we added only one property
- affectedKeysTree = affectedKeysTree[key];
- if (!affectedKeysTree) {
- return false; // Requested tree is not found
- }
- requestedTree = requestedTree[key];
- }
- return true;
- }
- }
|