src/vs/platform/configuration/common/configurationModels.ts

1298 LOC · 1198 covered · 100 uncovered · 398 ranges · 2492 concepts · 147 introducers · 1276 tests

File neighbourhood

The centred file is linked to every concept that introduces one of its ranges, every test that runs code from the file, and the gray connector concepts standing between those tests and the file's own introducer concepts. Undirected links join concepts to every file where they introduce source and concepts to the tests they introduce; arrows show specialization between the displayed concepts and bridge only concepts omitted from this view. Concept colors match the source ranges below; connector concepts have no source color and are shown in gray.

Focused file, its introducer and connector concepts, their introduced files, and tests that run code from the file

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the related-file, concept, and source links on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the related-file, concept, and source links on this page while the interactive map is unavailable.

1 > /*--------------------------------------------------------------------------------------------- configurationModels.ts ×92
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import * as arrays from '../../../base/common/arrays.js';
7 > import { IStringDictionary } from '../../../base/common/collections.js';
8 > import { Emitter, Event } from '../../../base/common/event.js';
9 > import * as json from '../../../base/common/json.js';
10 > import { Disposable } from '../../../base/common/lifecycle.js';
11 > import { getOrSet, ResourceMap } from '../../../base/common/map.js';
12 > import * as objects from '../../../base/common/objects.js';
13 > import { IExtUri } from '../../../base/common/resources.js';
14 > import * as types from '../../../base/common/types.js';
15 > import { URI, UriComponents } from '../../../base/common/uri.js';
16 > import { addToValueTree, ConfigurationTarget, getConfigurationValue, IConfigurationChange, IConfigurationChangeEvent, IConfigurationCompareResult, IConfigurationData, IConfigurationModel, IConfigurationOverrides, IConfigurationUpdateOverrides, IConfigurationValue, IInspectValue, IOverrides, removeFromValueTree, toValuesTree } from './configuration.js';
17 > import { ConfigurationScope, Extensions, IConfigurationPropertySchema, IConfigurationRegistry, overrideIdentifiersFromKey, OVERRIDE_PROPERTY_REGEX, IRegisteredConfigurationPropertySchema } from './configurationRegistry.js';
18 > import { FileOperation, IFileService } from '../../files/common/files.js';
19 > import { ILogService } from '../../log/common/log.js';
20 > import { Registry } from '../../registry/common/platform.js';
21 > import { Workspace } from '../../workspace/common/workspace.js';
22 >
23 > function freeze<T>(data: T): T { configurationModels.ts ×1
24 > return Object.isFrozen(data) ? data : objects.deepFreeze(data);
25 > }
27 > type InspectValue<V> = IInspectValue<V> & { merged?: V };
28 >
29 > export class ConfigurationModel implements IConfigurationModel {
30 >
31 > static createEmptyModel(logService: ILogService): ConfigurationModel {
32 > return new ConfigurationModel({}, [], [], undefined, logService);
33 > }
34 >
35 > private readonly overrideConfigurations = new Map<string, ConfigurationModel>();
36 >
37 > constructor(
38 > private readonly _contents: IStringDictionary<unknown>, configurationModels.ts ×1
39 > private readonly _keys: string[],
40 > private readonly _overrides: IOverrides[],
41 > private readonly _raw: IStringDictionary<unknown> | ReadonlyArray<IStringDictionary<unknown> | ConfigurationModel> | undefined,
42 > private readonly logService: ILogService
43 > ) {
44 > }
46 > private _rawConfiguration: ConfigurationModel | undefined;
47 > get rawConfiguration(): ConfigurationModel {
48 > if (!this._rawConfiguration) { configurationModels.ts ×3
49 > if (this._raw) {
50 > const rawConfigurationModels = (Array.isArray(this._raw) ? this._raw : [this._raw]).map(raw => { configurationModels.ts ×2
51 > if (raw instanceof ConfigurationModel) {
52 > return raw; configurationModels.ts ×1
53 > }
54 > const parser = new ConfigurationModelParser('', this.logService); configurationModels.ts ×2
55 > parser.parseRaw(raw);
56 > return parser.configurationModel;
57 > });
58 > this._rawConfiguration = rawConfigurationModels.reduce((previous, current) => current === previous ? current : previous.merge(current), rawConfigurationModels[0]);
60 > // raw is same as current configurationModels.ts ×1
61 > this._rawConfiguration = this;
62 > }
64 > return this._rawConfiguration;
65 > }
67 > get contents(): IStringDictionary<unknown> {
68 > return this._contents; configurationModels.ts ×1
69 > }
71 > get overrides(): IOverrides[] {
72 > return this._overrides; configurationModels.ts ×1
73 > }
75 > get keys(): string[] {
76 > return this._keys; configurationModels.ts ×1
77 > }
79 > get raw(): IStringDictionary<unknown> | IStringDictionary<unknown>[] | undefined {
80 > if (!this._raw) { configurationModels.ts ×3
81 > return undefined; configurationModels.ts ×3
82 > }
83 > if (Array.isArray(this._raw) && this._raw.every(raw => raw instanceof ConfigurationModel)) { configurationModels.ts ×3
84 return undefined;
85 }
86 > return this._raw as IStringDictionary<unknown> | IStringDictionary<unknown>[]; configurationModels.ts ×1
89 > isEmpty(): boolean {
90 > return this._keys.length === 0 && Object.keys(this._contents).length === 0 && this._overrides.length === 0; configurationModels.ts ×1
91 > }
93 > getValue<V>(section: string | undefined): V | undefined {
94 > return section ? getConfigurationValue<V>(this.contents, section) : this.contents as V; configurationModels.ts ×1
95 > }
97 > inspect<V>(section: string | undefined, overrideIdentifier?: string | null): InspectValue<V> {
98 > const that = this; configurationModels.ts ×5
99 > return {
100 > get value() {
101 > return freeze(that.rawConfiguration.getValue<V>(section)); configurationModels.ts ×2
102 > },
103 > get override() { configurationModels.ts ×5
104 > return overrideIdentifier ? freeze(that.rawConfiguration.getOverrideValue<V>(section, overrideIdentifier)) : undefined; configurationModels.ts ×2
105 > },
106 > get merged() { configurationModels.ts ×5
107 > return freeze(overrideIdentifier ? that.rawConfiguration.override(overrideIdentifier).getValue<V>(section) : that.rawConfiguration.getValue<V>(section)); configurationModels.ts ×1
108 > },
109 > get overrides() { configurationModels.ts ×5
110 > const overrides: { readonly identifiers: string[]; readonly value: V }[] = []; configurationModels.ts ×2
111 > for (const { contents, identifiers, keys } of that.rawConfiguration.overrides) {
112 > const value = new ConfigurationModel(contents, keys, [], undefined, that.logService).getValue<V>(section); objects.ts ×1
113 > if (value !== undefined) {
114 > overrides.push({ identifiers, value });
115 > }
116 > }
117 > return overrides.length ? freeze(overrides) : undefined; configurationModels.ts ×2
118 > }
120 > }
122 > getOverrideValue<V>(section: string | undefined, overrideIdentifier: string): V | undefined {
123 > const overrideContents = this.getContentsForOverrideIdentifer(overrideIdentifier); configurationModels.ts ×2
124 > return overrideContents
125 > ? section ? getConfigurationValue<V>(overrideContents, section) : overrideContents as V configurationModels.ts ×1
126 > : undefined; configurationModels.ts ×1
129 > getKeysForOverrideIdentifier(identifier: string): string[] {
130 > const keys: string[] = []; configurationModels.ts ×1
131 > for (const override of this.overrides) {
132 > if (override.identifiers.includes(identifier)) {
133 > keys.push(...override.keys);
134 > }
135 > }
136 > return arrays.distinct(keys);
137 > }
139 > getAllOverrideIdentifiers(): string[] {
140 > const result: string[] = []; configurationModels.ts ×2
141 > for (const override of this.overrides) {
142 > result.push(...override.identifiers); configurationModels.ts ×1
143 > }
144 > return arrays.distinct(result); configurationModels.ts ×2
145 > }
147 > override(identifier: string): ConfigurationModel {
148 > let overrideConfigurationModel = this.overrideConfigurations.get(identifier); configurationModels.ts ×3
149 > if (!overrideConfigurationModel) {
150 > overrideConfigurationModel = this.createOverrideConfigurationModel(identifier);
151 > this.overrideConfigurations.set(identifier, overrideConfigurationModel);
152 > }
153 > return overrideConfigurationModel;
154 > }
156 > merge(...others: ConfigurationModel[]): ConfigurationModel {
157 > const contents = objects.deepClone(this.contents); configurationModels.ts ×2
158 > const overrides = objects.deepClone(this.overrides);
159 > const keys = [...this.keys];
160 > const raws = this._raw ? Array.isArray(this._raw) ? [...this._raw] : [this._raw] : [this];
161 >
162 > for (const other of others) {
163 > raws.push(...(other._raw ? Array.isArray(other._raw) ? other._raw : [other._raw] : [other]));
164 > if (other.isEmpty()) {
165 > continue; configurationModels.ts ×1
166 > }
167 > this.mergeContents(contents, other.contents); configurationModels.ts ×3
168 >
169 > for (const otherOverride of other.overrides) {
170 > const [override] = overrides.filter(o => arrays.equals(o.identifiers, otherOverride.identifiers)); configurationModels.ts ×3
171 > if (override) {
172 > this.mergeContents(override.contents, otherOverride.contents); configurationModels.ts ×1
173 > override.keys.push(...otherOverride.keys);
174 > override.keys = arrays.distinct(override.keys);
176 > overrides.push(objects.deepClone(otherOverride)); configurationModels.ts ×1
177 > }
179 > for (const key of other.keys) { configurationModels.ts ×3
180 > if (keys.indexOf(key) === -1) {
181 > keys.push(key); configurationModels.ts ×1
182 > }
184 > }
185 > return new ConfigurationModel(contents, keys, overrides, !raws.length || raws.every(raw => raw instanceof ConfigurationModel) ? undefined : raws, this.logService); configurationModels.ts ×2
186 > }
188 > private createOverrideConfigurationModel(identifier: string): ConfigurationModel {
189 > const overrideContents = this.getContentsForOverrideIdentifer(identifier); configurationModels.ts ×3
190 >
191 > if (!overrideContents || typeof overrideContents !== 'object' || !Object.keys(overrideContents).length) {
192 > // If there are no valid overrides, return self configurationModels.ts ×1
193 > return this;
194 > }
196 > const contents: IStringDictionary<unknown> = {};
197 > for (const key of arrays.distinct([...Object.keys(this.contents), ...Object.keys(overrideContents)])) {
198 >
199 > let contentsForKey = this.contents[key];
200 > const overrideContentsForKey = overrideContents[key];
201 >
202 > // If there are override contents for the key, clone and merge otherwise use base contents
203 > if (overrideContentsForKey) {
204 > // Clone and merge only if base contents and override contents are of type object otherwise just override
205 > if (typeof contentsForKey === 'object' && typeof overrideContentsForKey === 'object') {
206 > contentsForKey = objects.deepClone(contentsForKey); configurationModels.ts ×1
207 > this.mergeContents(contentsForKey as IStringDictionary<unknown>, overrideContentsForKey as IStringDictionary<unknown>);
209 > contentsForKey = overrideContentsForKey; configurationModels.ts ×1
210 > }
212 >
213 > contents[key] = contentsForKey;
214 > }
215 >
216 > return new ConfigurationModel(contents, this.keys, this.overrides, undefined, this.logService);
219 > private mergeContents(source: IStringDictionary<unknown>, target: IStringDictionary<unknown>): void {
220 > for (const key of Object.keys(target)) { configurationModels.ts ×2
221 > if (key in source) {
222 > if (types.isObject(source[key]) && types.isObject(target[key])) { configurationModels.ts ×2
223 > this.mergeContents(source[key] as IStringDictionary<unknown>, target[key] as IStringDictionary<unknown>); configurationModels.ts ×1
224 > continue;
225 > }
227 > source[key] = objects.deepClone(target[key]); configurationModels.ts ×2
228 > }
229 > }
231 > private getContentsForOverrideIdentifer(identifier: string): IStringDictionary<unknown> | null {
232 > let contentsForIdentifierOnly: IStringDictionary<unknown> | null = null; configurationModels.ts ×3
233 > let contents: IStringDictionary<unknown> | null = null;
234 > const mergeContents = (contentsToMerge: IStringDictionary<unknown> | null) => {
235 > if (contentsToMerge) {
236 > if (contents) { configurationModels.ts ×2
237 > this.mergeContents(contents, contentsToMerge); configurationModels.ts ×1
239 > contents = objects.deepClone(contentsToMerge);
240 > }
241 > }
243 > for (const override of this.overrides) {
244 > if (override.identifiers.length === 1 && override.identifiers[0] === identifier) { configurationModels.ts ×3
245 > contentsForIdentifierOnly = override.contents; configurationModels.ts ×1
246 > } else if (override.identifiers.includes(identifier)) { configurationModels.ts ×3
247 > mergeContents(override.contents); configurationModels.ts ×1
248 > }
250 > // Merge contents of the identifier only at the end to take precedence. configurationModels.ts ×3
251 > mergeContents(contentsForIdentifierOnly);
252 > return contents;
253 > }
255 > toJSON(): IConfigurationModel {
256 return {
257 contents: this.contents,
258 overrides: this.overrides,
259 keys: this.keys
260 };
261 }
263 > // Update methods
264 >
265 > public addValue(key: string, value: unknown): void {
266 this.updateValue(key, value, true);
267 }
269 > public setValue(key: string, value: unknown): void {
270 > this.updateValue(key, value, false); configurationModels.ts ×4
271 > }
273 > public removeValue(key: string): void {
274 > const index = this.keys.indexOf(key); configurationModels.ts ×2
275 > if (index === -1) {
277 > }
278 > this.keys.splice(index, 1); configurationModels.ts ×1
279 > removeFromValueTree(this.contents, key);
280 > if (OVERRIDE_PROPERTY_REGEX.test(key)) {
281 > this.overrides.splice(this.overrides.findIndex(o => arrays.equals(o.identifiers, overrideIdentifiersFromKey(key))), 1); configurationModels.ts ×1
282 > }
285 > private updateValue(key: string, value: unknown, add: boolean): void {
286 > addToValueTree(this.contents, key, value, e => this.logService.error(e)); configurationModels.ts ×4
287 > add = add || this.keys.indexOf(key) === -1;
288 > if (add) {
289 > this.keys.push(key); configurationModels.ts ×1
290 > }
291 > if (OVERRIDE_PROPERTY_REGEX.test(key)) { configurationModels.ts ×4
292 > const overrideContents = this.contents[key] as IStringDictionary<unknown>; configurationModels.ts ×2
293 > const identifiers = overrideIdentifiersFromKey(key);
294 > const override = {
295 > identifiers,
296 > keys: Object.keys(overrideContents),
297 > contents: toValuesTree(overrideContents, message => this.logService.error(message)),
298 > };
299 > const index = this.overrides.findIndex(o => arrays.equals(o.identifiers, identifiers));
300 > if (index !== -1) {
301 > this.overrides[index] = override; configurationModels.ts ×1
303 > this.overrides.push(override);
304 > }
305 > }
308 >
309 > export interface ConfigurationParseOptions {
310 > skipUnregistered?: boolean;
311 > scopes?: ConfigurationScope[];
312 > skipRestricted?: boolean;
313 > include?: string[];
314 > exclude?: string[];
315 > }
316 >
317 > export class ConfigurationModelParser {
318 >
319 > private _raw: IStringDictionary<unknown> | null = null;
320 > private _configurationModel: ConfigurationModel | null = null;
321 > private _restrictedConfigurations: string[] = [];
322 > private _parseErrors: json.ParseError[] = [];
323 >
324 > constructor(
325 > protected readonly _name: string, configurationModels.ts ×1
326 > protected readonly logService: ILogService
327 > ) { }
329 > get configurationModel(): ConfigurationModel {
330 > return this._configurationModel || ConfigurationModel.createEmptyModel(this.logService); configurationModels.ts ×1
331 > }
333 > get restrictedConfigurations(): string[] {
334 > return this._restrictedConfigurations; configurationModels.ts ×1
335 > }
337 > get errors(): json.ParseError[] {
338 return this._parseErrors;
339 }
341 > public parse(content: string | null | undefined, options?: ConfigurationParseOptions): void {
342 > if (!types.isUndefinedOrNull(content)) { configurationModels.ts ×10
343 > const raw = this.doParseContent(content);
344 > this.parseRaw(raw, options);
345 > }
346 > }
348 > public reparse(options: ConfigurationParseOptions): void {
349 > if (this._raw) { configurationModels.ts ×1
350 > this.parseRaw(this._raw, options);
351 > }
352 > }
354 > public parseRaw(raw: IStringDictionary<unknown>, options?: ConfigurationParseOptions): void {
355 > this._raw = raw; configurationModels.ts ×6
356 > const { contents, keys, overrides, restricted, hasExcludedProperties } = this.doParseRaw(raw, options);
357 > this._configurationModel = new ConfigurationModel(contents, keys, overrides, hasExcludedProperties ? [raw] : undefined /* raw has not changed */, this.logService);
358 > this._restrictedConfigurations = restricted || [];
359 > }
361 > private doParseContent(content: string): IStringDictionary<unknown> {
362 > let raw: IStringDictionary<unknown> = {}; configurationModels.ts ×10
363 > let currentProperty: string | null = null;
364 > let currentParent: unknown[] | IStringDictionary<unknown> = [];
365 > const previousParents: (unknown[] | IStringDictionary<unknown>)[] = [];
366 > const parseErrors: json.ParseError[] = [];
367 >
368 > function onValue(value: unknown) {
369 > if (Array.isArray(currentParent)) { configurationModels.ts ×2
370 > currentParent.push(value);
371 > } else if (currentProperty !== null) {
372 > currentParent[currentProperty] = value; configurationModels.ts ×2
373 > }
376 > const visitor: json.JSONVisitor = {
377 > onObjectBegin: () => {
378 > const object = {}; configurationModels.ts ×2
379 > onValue(object);
380 > previousParents.push(currentParent);
381 > currentParent = object;
382 > currentProperty = null;
383 > },
384 > onObjectProperty: (name: string) => { configurationModels.ts ×10
385 > currentProperty = name; configurationModels.ts ×2
386 > },
387 > onObjectEnd: () => { configurationModels.ts ×10
388 > currentParent = previousParents.pop()!; configurationModels.ts ×2
389 > },
390 > onArrayBegin: () => { configurationModels.ts ×10
391 > const array: unknown[] = []; configurationModels.ts ×2
392 > onValue(array);
393 > previousParents.push(currentParent);
394 > currentParent = array;
395 > currentProperty = null;
396 > },
397 > onArrayEnd: () => { configurationModels.ts ×10
398 > currentParent = previousParents.pop()!; configurationModels.ts ×2
399 > },
400 > onLiteralValue: onValue, configurationModels.ts ×10
401 > onError: (error: json.ParseErrorCode, offset: number, length: number) => {
402 > parseErrors.push({ error, offset, length }); configurationModels.ts ×1
403 > }
405 > if (content) {
407 > json.visit(content, visitor);
408 > raw = (currentParent[0] as IStringDictionary<unknown>) || {};
409 > } catch (e) {
410 this.logService.error(`Error while parsing settings file ${this._name}: ${e}`);
411 this._parseErrors = [e as json.ParseError];
412 }
415 > return raw;
416 > }
418 > protected doParseRaw(raw: IStringDictionary<unknown>, options?: ConfigurationParseOptions): IConfigurationModel & { restricted?: string[]; hasExcludedProperties?: boolean } {
419 > const registry = Registry.as<IConfigurationRegistry>(Extensions.Configuration); configurationModels.ts ×6
420 > const configurationProperties = registry.getConfigurationProperties();
421 > const excludedConfigurationProperties = registry.getExcludedConfigurationProperties();
422 > const filtered = this.filter(raw, configurationProperties, excludedConfigurationProperties, true, options);
423 > raw = filtered.raw;
424 > const contents = toValuesTree(raw, message => this.logService.error(`Conflict in settings file ${this._name}: ${message}`));
425 > const keys = Object.keys(raw);
426 > const overrides = this.toOverrides(raw, message => this.logService.error(`Conflict in settings file ${this._name}: ${message}`));
427 > return { contents, keys, overrides, restricted: filtered.restricted, hasExcludedProperties: filtered.hasExcludedProperties };
428 > }
430 > private filter(properties: IStringDictionary<unknown>, configurationProperties: IStringDictionary<IRegisteredConfigurationPropertySchema>, excludedConfigurationProperties: IStringDictionary<IRegisteredConfigurationPropertySchema>, filterOverriddenProperties: boolean, options?: ConfigurationParseOptions): { raw: IStringDictionary<unknown>; restricted: string[]; hasExcludedProperties: boolean } {
431 > let hasExcludedProperties = false; configurationModels.ts ×6
432 > if (!options?.scopes && !options?.skipRestricted && !options?.skipUnregistered && !options?.exclude?.length) {
433 > return { raw: properties, restricted: [], hasExcludedProperties }; configurationModels.ts ×1
434 > }
435 > const raw: IStringDictionary<unknown> = {}; configurationModels.ts ×11
436 > const restricted: string[] = [];
437 > for (const key in properties) {
438 > if (OVERRIDE_PROPERTY_REGEX.test(key) && filterOverriddenProperties) {
439 > const result = this.filter(properties[key] as IStringDictionary<unknown>, configurationProperties, excludedConfigurationProperties, false, options); configurationModels.ts ×1
440 > raw[key] = result.raw;
441 > hasExcludedProperties = hasExcludedProperties || result.hasExcludedProperties;
442 > restricted.push(...result.restricted);
444 > const propertySchema = configurationProperties[key];
445 > if (propertySchema?.restricted) {
446 > restricted.push(key); configurationModels.ts ×2
447 > }
448 > if (this.shouldInclude(key, propertySchema, excludedConfigurationProperties, options)) { configurationModels.ts ×11
449 > raw[key] = properties[key]; configurationModels.ts ×1
451 > hasExcludedProperties = true; configurationModels.ts ×3
452 > }
454 > }
455 > return { raw, restricted, hasExcludedProperties };
458 > private shouldInclude(key: string, propertySchema: IConfigurationPropertySchema | undefined, excludedConfigurationProperties: IStringDictionary<IRegisteredConfigurationPropertySchema>, options: ConfigurationParseOptions): boolean {
459 > if (options.exclude?.includes(key)) { configurationModels.ts ×11
460 > return false; configurationModels.ts ×1
461 > }
463 > if (options.include?.includes(key)) {
464 > return true; configurationModels.ts ×1
465 > }
467 > if (options.skipRestricted && propertySchema?.restricted) { configurationModels.ts ×11
468 > return false; configurationModels.ts ×2
469 > }
471 > if (options.skipUnregistered && !propertySchema) { configurationModels.ts ×11
472 > return false; configurationModels.ts ×1
473 > }
475 > const schema = propertySchema ?? excludedConfigurationProperties[key];
476 > const scope = schema ? typeof schema.scope !== 'undefined' ? schema.scope : ConfigurationScope.WINDOW : undefined; configurationModels.ts ×11
477 > if (scope === undefined || options.scopes === undefined) {
478 > return true; configurationModels.ts ×1
479 > }
481 > return options.scopes.includes(scope);
484 > private toOverrides(raw: IStringDictionary<unknown>, conflictReporter: (message: string) => void): IOverrides[] {
485 > const overrides: IOverrides[] = []; configurationModels.ts ×6
486 > for (const key of Object.keys(raw)) {
487 > if (OVERRIDE_PROPERTY_REGEX.test(key)) { configurationModels.ts ×2
488 > const overrideRaw: IStringDictionary<unknown> = {}; configurationModels.ts ×1
489 > const rawKey = raw[key] as IStringDictionary<unknown>;
490 > for (const keyInOverrideRaw in rawKey) {
491 > overrideRaw[keyInOverrideRaw] = rawKey[keyInOverrideRaw];
492 > }
493 > overrides.push({
494 > identifiers: overrideIdentifiersFromKey(key),
495 > keys: Object.keys(overrideRaw),
496 > contents: toValuesTree(overrideRaw, conflictReporter)
497 > });
498 > }
500 > return overrides; configurationModels.ts ×6
501 > }
503 > }
504 >
505 > export class UserSettings extends Disposable {
506 >
507 > private readonly parser: ConfigurationModelParser;
508 > protected readonly _onDidChange: Emitter<void> = this._register(new Emitter<void>());
509 > readonly onDidChange: Event<void> = this._onDidChange.event;
510 >
511 > constructor(
512 > private readonly userSettingsResource: URI, configurationService.ts ×2
513 > protected parseOptions: ConfigurationParseOptions,
514 > extUri: IExtUri,
515 > private readonly fileService: IFileService,
516 > private readonly logService: ILogService,
517 > ) {
518 > super();
519 > this.parser = new ConfigurationModelParser(this.userSettingsResource.toString(), logService);
520 > this._register(this.fileService.watch(extUri.dirname(this.userSettingsResource)));
521 > // Also listen to the resource incase the resource is a symlink - https://github.com/microsoft/vscode/issues/118134
522 > this._register(this.fileService.watch(this.userSettingsResource));
523 > this._register(Event.any(
524 > Event.filter(this.fileService.onDidFilesChange, e => e.contains(this.userSettingsResource)),
525 > Event.filter(this.fileService.onDidRunOperation, e => (e.isOperation(FileOperation.CREATE) || e.isOperation(FileOperation.COPY) || e.isOperation(FileOperation.DELETE) || e.isOperation(FileOperation.WRITE)) && extUri.isEqual(e.resource, userSettingsResource))
526 > )(() => this._onDidChange.fire()));
527 > }
529 > async loadConfiguration(): Promise<ConfigurationModel> {
531 > const content = await this.fileService.readFile(this.userSettingsResource);
532 > this.parser.parse(content.value.toString() || '{}', this.parseOptions);
533 > return this.parser.configurationModel;
534 > } catch (e) {
535 > return ConfigurationModel.createEmptyModel(this.logService); configurationModels.ts ×1
536 > }
539 > reparse(parseOptions?: ConfigurationParseOptions): ConfigurationModel {
540 if (parseOptions) {
541 this.parseOptions = parseOptions;
542 }
543 this.parser.reparse(this.parseOptions);
544 return this.parser.configurationModel;
545 }
547 > getRestrictedSettings(): string[] {
548 return this.parser.restrictedConfigurations;
549 }
551 >
552 > class ConfigurationInspectValue<V> implements IConfigurationValue<V> {
553 >
554 > constructor(
555 > private readonly key: string, configurationModels.ts ×5
556 > private readonly overrides: IConfigurationOverrides,
557 > private readonly _value: V | undefined,
558 > readonly overrideIdentifiers: string[] | undefined,
559 > private readonly defaultConfiguration: ConfigurationModel,
560 > private readonly policyConfiguration: ConfigurationModel | undefined,
561 > private readonly applicationConfiguration: ConfigurationModel | undefined,
562 > private readonly userConfiguration: ConfigurationModel,
563 > private readonly localUserConfiguration: ConfigurationModel,
564 > private readonly remoteUserConfiguration: ConfigurationModel,
565 > private readonly workspaceConfiguration: ConfigurationModel | undefined,
566 > private readonly folderConfigurationModel: ConfigurationModel | undefined,
567 > private readonly memoryConfigurationModel: ConfigurationModel
568 > ) {
569 > }
571 > get value(): V | undefined {
572 > return freeze(this._value); configurationModels.ts ×1
573 > }
575 > private toInspectValue(inspectValue: IInspectValue<V> | undefined | null): IInspectValue<V> | undefined {
576 > return inspectValue?.value !== undefined || inspectValue?.override !== undefined || inspectValue?.overrides !== undefined ? inspectValue : undefined; configurationModels.ts ×4
577 > }
579 > private _defaultInspectValue: InspectValue<V> | undefined;
580 > private get defaultInspectValue(): InspectValue<V> {
581 > if (!this._defaultInspectValue) { configurationModels.ts ×2
582 > this._defaultInspectValue = this.defaultConfiguration.inspect<V>(this.key, this.overrides.overrideIdentifier);
583 > }
584 > return this._defaultInspectValue;
585 > }
587 > get defaultValue(): V | undefined {
588 > return this.defaultInspectValue.merged; configurationModels.ts ×2
589 > }
591 > get default(): IInspectValue<V> | undefined {
592 return this.toInspectValue(this.defaultInspectValue);
593 }
595 > private _policyInspectValue: InspectValue<V> | undefined | null;
596 > private get policyInspectValue(): InspectValue<V> | null {
597 > if (this._policyInspectValue === undefined) { configurationModels.ts ×2
598 > this._policyInspectValue = this.policyConfiguration ? this.policyConfiguration.inspect<V>(this.key) : null;
599 > }
600 > return this._policyInspectValue;
601 > }
603 > get policyValue(): V | undefined {
604 > return this.policyInspectValue?.merged; configurationModels.ts ×2
605 > }
607 > get policy(): IInspectValue<V> | undefined {
608 return this.policyInspectValue?.value !== undefined ? { value: this.policyInspectValue.value } : undefined;
609 }
611 > private _applicationInspectValue: InspectValue<V> | undefined | null;
612 > private get applicationInspectValue(): InspectValue<V> | null {
613 > if (this._applicationInspectValue === undefined) { configurationModels.ts ×8
614 > this._applicationInspectValue = this.applicationConfiguration ? this.applicationConfiguration.inspect<V>(this.key) : null;
615 > }
616 > return this._applicationInspectValue;
617 > }
619 > get applicationValue(): V | undefined {
620 > return this.applicationInspectValue?.merged; configurationModels.ts ×8
621 > }
623 > get application(): IInspectValue<V> | undefined {
624 return this.toInspectValue(this.applicationInspectValue);
625 }
627 > private _userInspectValue: InspectValue<V> | undefined;
628 > private get userInspectValue(): InspectValue<V> {
629 > if (!this._userInspectValue) { configurationModels.ts ×1
630 > this._userInspectValue = this.userConfiguration.inspect<V>(this.key, this.overrides.overrideIdentifier);
631 > }
632 > return this._userInspectValue;
633 > }
635 > get userValue(): V | undefined {
636 > return this.userInspectValue.merged; configurationModels.ts ×1
637 > }
639 > get user(): IInspectValue<V> | undefined {
640 > return this.toInspectValue(this.userInspectValue); configurationModels.ts ×4
641 > }
643 > private _userLocalInspectValue: InspectValue<V> | undefined;
644 > private get userLocalInspectValue(): InspectValue<V> {
645 > if (!this._userLocalInspectValue) { configurationModels.ts ×2
646 > this._userLocalInspectValue = this.localUserConfiguration.inspect<V>(this.key, this.overrides.overrideIdentifier);
647 > }
648 > return this._userLocalInspectValue;
649 > }
651 > get userLocalValue(): V | undefined {
652 > return this.userLocalInspectValue.merged; configurationModels.ts ×8
653 > }
655 > get userLocal(): IInspectValue<V> | undefined {
656 > return this.toInspectValue(this.userLocalInspectValue); configurationModels.ts ×4
657 > }
659 > private _userRemoteInspectValue: InspectValue<V> | undefined;
660 > private get userRemoteInspectValue(): InspectValue<V> {
661 > if (!this._userRemoteInspectValue) { configurationModels.ts ×2
662 > this._userRemoteInspectValue = this.remoteUserConfiguration.inspect<V>(this.key, this.overrides.overrideIdentifier);
663 > }
664 > return this._userRemoteInspectValue;
665 > }
667 > get userRemoteValue(): V | undefined {
668 > return this.userRemoteInspectValue.merged; configurationModels.ts ×8
669 > }
671 > get userRemote(): IInspectValue<V> | undefined {
672 > return this.toInspectValue(this.userRemoteInspectValue); configurationModels.ts ×4
673 > }
675 > private _workspaceInspectValue: InspectValue<V> | undefined | null;
676 > private get workspaceInspectValue(): InspectValue<V> | null {
677 > if (this._workspaceInspectValue === undefined) { configurationModels.ts ×8
678 > this._workspaceInspectValue = this.workspaceConfiguration ? this.workspaceConfiguration.inspect<V>(this.key, this.overrides.overrideIdentifier) : null;
679 > }
680 > return this._workspaceInspectValue;
681 > }
683 > get workspaceValue(): V | undefined {
684 > return this.workspaceInspectValue?.merged; configurationModels.ts ×8
685 > }
687 > get workspace(): IInspectValue<V> | undefined {
688 return this.toInspectValue(this.workspaceInspectValue);
689 }
691 > private _workspaceFolderInspectValue: InspectValue<V> | undefined | null;
692 > private get workspaceFolderInspectValue(): InspectValue<V> | null {
693 > if (this._workspaceFolderInspectValue === undefined) { configurationModels.ts ×8
694 > this._workspaceFolderInspectValue = this.folderConfigurationModel ? this.folderConfigurationModel.inspect<V>(this.key, this.overrides.overrideIdentifier) : null;
695 > }
696 > return this._workspaceFolderInspectValue;
697 > }
699 > get workspaceFolderValue(): V | undefined {
700 > return this.workspaceFolderInspectValue?.merged; configurationModels.ts ×8
701 > }
703 > get workspaceFolder(): IInspectValue<V> | undefined {
704 return this.toInspectValue(this.workspaceFolderInspectValue);
705 }
707 > private _memoryInspectValue: InspectValue<V> | undefined;
708 > private get memoryInspectValue(): InspectValue<V> {
709 if (this._memoryInspectValue === undefined) {
710 this._memoryInspectValue = this.memoryConfigurationModel.inspect<V>(this.key, this.overrides.overrideIdentifier);
711 }
712 return this._memoryInspectValue;
713 }
715 > get memoryValue(): V | undefined {
716 return this.memoryInspectValue.merged;
717 }
719 > get memory(): IInspectValue<V> | undefined {
720 return this.toInspectValue(this.memoryInspectValue);
721 }
723 > }
724 >
725 > export class Configuration {
726 >
727 > private _workspaceConsolidatedConfiguration: ConfigurationModel | null = null;
728 > private _foldersConsolidatedConfigurations = new ResourceMap<ConfigurationModel>();
729 >
730 > constructor(
731 > private _defaultConfiguration: ConfigurationModel, configurationModels.ts ×23
732 > private _policyConfiguration: ConfigurationModel,
733 > private _applicationConfiguration: ConfigurationModel,
734 > private _localUserConfiguration: ConfigurationModel,
735 > private _remoteUserConfiguration: ConfigurationModel,
736 > private _workspaceConfiguration: ConfigurationModel,
737 > private _folderConfigurations: ResourceMap<ConfigurationModel>,
738 > private _memoryConfiguration: ConfigurationModel,
739 > private _memoryConfigurationByResource: ResourceMap<ConfigurationModel>,
740 > private readonly logService: ILogService
741 > ) {
742 > }
743 >
744 > getValue(section: string | undefined, overrides: IConfigurationOverrides, workspace: Workspace | undefined): unknown {
745 > const consolidateConfigurationModel = this.getConsolidatedConfigurationModel(section, overrides, workspace); configurationModels.ts ×1
746 > return consolidateConfigurationModel.getValue(section);
747 > }
749 > updateValue(key: string, value: unknown, overrides: IConfigurationUpdateOverrides = {}): void {
750 > let memoryConfiguration: ConfigurationModel | undefined; configurationModels.ts ×3
751 > if (overrides.resource) {
752 memoryConfiguration = this._memoryConfigurationByResource.get(overrides.resource);
753 if (!memoryConfiguration) {
754 memoryConfiguration = ConfigurationModel.createEmptyModel(this.logService);
755 this._memoryConfigurationByResource.set(overrides.resource, memoryConfiguration);
756 }
758 > memoryConfiguration = this._memoryConfiguration;
759 > }
760 >
761 > if (value === undefined) {
762 memoryConfiguration.removeValue(key);
764 > memoryConfiguration.setValue(key, value);
765 > }
766 >
767 > if (!overrides.resource) {
768 > this._workspaceConsolidatedConfiguration = null;
769 > }
770 > }
772 > inspect<C>(key: string, overrides: IConfigurationOverrides, workspace: Workspace | undefined): IConfigurationValue<C> {
773 > const consolidateConfigurationModel = this.getConsolidatedConfigurationModel(key, overrides, workspace); configurationModels.ts ×5
774 > const folderConfigurationModel = this.getFolderConfigurationModelForResource(overrides.resource, workspace);
775 > const memoryConfigurationModel = overrides.resource ? this._memoryConfigurationByResource.get(overrides.resource) || this._memoryConfiguration : this._memoryConfiguration;
776 > const overrideIdentifiers = new Set<string>();
777 > for (const override of consolidateConfigurationModel.overrides) {
778 > for (const overrideIdentifier of override.identifiers) { configurationModels.ts ×1
779 > if (consolidateConfigurationModel.getOverrideValue(key, overrideIdentifier) !== undefined) {
780 > overrideIdentifiers.add(overrideIdentifier);
781 > }
782 > }
783 > }
785 > return new ConfigurationInspectValue<C>(
786 > key,
787 > overrides,
788 > consolidateConfigurationModel.getValue<C>(key),
789 > overrideIdentifiers.size ? [...overrideIdentifiers] : undefined,
790 > this._defaultConfiguration,
791 > this._policyConfiguration.isEmpty() ? undefined : this._policyConfiguration,
792 > this.applicationConfiguration.isEmpty() ? undefined : this.applicationConfiguration,
793 > this.userConfiguration,
794 > this.localUserConfiguration,
795 > this.remoteUserConfiguration,
796 > workspace ? this._workspaceConfiguration : undefined,
797 > folderConfigurationModel ? folderConfigurationModel : undefined,
798 > memoryConfigurationModel
799 > );
800 >
801 > }
803 > keys(workspace: Workspace | undefined): {
804 default: string[];
805 policy: string[];
806 user: string[];
807 workspace: string[];
808 workspaceFolder: string[];
809 } {
810 const folderConfigurationModel = this.getFolderConfigurationModelForResource(undefined, workspace);
811 return {
812 default: this._defaultConfiguration.keys.slice(0),
813 policy: this._policyConfiguration.keys.slice(0),
814 user: this.userConfiguration.keys.slice(0),
815 workspace: this._workspaceConfiguration.keys.slice(0),
816 workspaceFolder: folderConfigurationModel ? folderConfigurationModel.keys.slice(0) : []
817 };
818 }
820 > updateDefaultConfiguration(defaultConfiguration: ConfigurationModel): void {
821 > this._defaultConfiguration = defaultConfiguration; configurationModels.ts ×1
822 > this._workspaceConsolidatedConfiguration = null;
823 > this._foldersConsolidatedConfigurations.clear();
824 > }
826 > updatePolicyConfiguration(policyConfiguration: ConfigurationModel): void {
827 this._policyConfiguration = policyConfiguration;
828 }
830 > updateApplicationConfiguration(applicationConfiguration: ConfigurationModel): void {
831 > this._applicationConfiguration = applicationConfiguration; configurationModels.ts ×2
832 > this._workspaceConsolidatedConfiguration = null;
833 > this._foldersConsolidatedConfigurations.clear();
834 > }
836 > updateLocalUserConfiguration(localUserConfiguration: ConfigurationModel): void {
837 > this._localUserConfiguration = localUserConfiguration; configurationModels.ts ×1
838 > this._userConfiguration = null;
839 > this._workspaceConsolidatedConfiguration = null;
840 > this._foldersConsolidatedConfigurations.clear();
841 > }
843 > updateRemoteUserConfiguration(remoteUserConfiguration: ConfigurationModel): void {
844 this._remoteUserConfiguration = remoteUserConfiguration;
845 this._userConfiguration = null;
846 this._workspaceConsolidatedConfiguration = null;
847 this._foldersConsolidatedConfigurations.clear();
848 }
850 > updateWorkspaceConfiguration(workspaceConfiguration: ConfigurationModel): void {
851 > this._workspaceConfiguration = workspaceConfiguration; configurationModels.ts ×1
852 > this._workspaceConsolidatedConfiguration = null;
853 > this._foldersConsolidatedConfigurations.clear();
854 > }
856 > updateFolderConfiguration(resource: URI, configuration: ConfigurationModel): void {
857 > this._folderConfigurations.set(resource, configuration); configurationModels.ts ×1
858 > this._foldersConsolidatedConfigurations.delete(resource);
859 > }
861 > deleteFolderConfiguration(resource: URI): void {
862 > this.folderConfigurations.delete(resource); configurationModels.ts ×4
863 > this._foldersConsolidatedConfigurations.delete(resource);
864 > }
866 > compareAndUpdateDefaultConfiguration(defaults: ConfigurationModel, keys?: string[]): IConfigurationChange {
867 > const overrides: [string, string[]][] = []; configurationModels.ts ×3
868 > if (!keys) {
869 const { added, updated, removed } = compare(this._defaultConfiguration, defaults);
870 keys = [...added, ...updated, ...removed];
871 }
872 > for (const key of keys) { configurationModels.ts ×3
873 > for (const overrideIdentifier of overrideIdentifiersFromKey(key)) { configurationModels.ts ×1
874 > const fromKeys = this._defaultConfiguration.getKeysForOverrideIdentifier(overrideIdentifier);
875 > const toKeys = defaults.getKeysForOverrideIdentifier(overrideIdentifier);
876 > const keys = [
877 > ...toKeys.filter(key => fromKeys.indexOf(key) === -1),
878 > ...fromKeys.filter(key => toKeys.indexOf(key) === -1),
879 > ...fromKeys.filter(key => !objects.equals(this._defaultConfiguration.override(overrideIdentifier).getValue(key), defaults.override(overrideIdentifier).getValue(key)))
880 > ];
881 > overrides.push([overrideIdentifier, keys]);
882 > }
883 > }
884 > this.updateDefaultConfiguration(defaults); configurationModels.ts ×3
885 > return { keys, overrides };
886 > }
888 > compareAndUpdatePolicyConfiguration(policyConfiguration: ConfigurationModel): IConfigurationChange {
889 const { added, updated, removed } = compare(this._policyConfiguration, policyConfiguration);
890 const keys = [...added, ...updated, ...removed];
891 if (keys.length) {
892 this.updatePolicyConfiguration(policyConfiguration);
893 }
894 return { keys, overrides: [] };
895 }
897 > compareAndUpdateApplicationConfiguration(application: ConfigurationModel): IConfigurationChange {
898 > const { added, updated, removed, overrides } = compare(this.applicationConfiguration, application); configurationModels.ts ×2
899 > const keys = [...added, ...updated, ...removed];
900 > if (keys.length) {
901 > this.updateApplicationConfiguration(application);
902 > }
903 > return { keys, overrides };
904 > }
906 > compareAndUpdateLocalUserConfiguration(user: ConfigurationModel): IConfigurationChange {
907 > const { added, updated, removed, overrides } = compare(this.localUserConfiguration, user); configurationModels.ts ×2
908 > const keys = [...added, ...updated, ...removed];
909 > if (keys.length) {
910 > this.updateLocalUserConfiguration(user); configurationModels.ts ×1
911 > }
912 > return { keys, overrides }; configurationModels.ts ×2
913 > }
915 > compareAndUpdateRemoteUserConfiguration(user: ConfigurationModel): IConfigurationChange {
916 const { added, updated, removed, overrides } = compare(this.remoteUserConfiguration, user);
917 const keys = [...added, ...updated, ...removed];
918 if (keys.length) {
919 this.updateRemoteUserConfiguration(user);
920 }
921 return { keys, overrides };
922 }
924 > compareAndUpdateWorkspaceConfiguration(workspaceConfiguration: ConfigurationModel): IConfigurationChange {
925 > const { added, updated, removed, overrides } = compare(this.workspaceConfiguration, workspaceConfiguration); configurationModels.ts ×2
926 > const keys = [...added, ...updated, ...removed];
927 > if (keys.length) {
928 > this.updateWorkspaceConfiguration(workspaceConfiguration);
929 > }
930 > return { keys, overrides };
931 > }
933 > compareAndUpdateFolderConfiguration(resource: URI, folderConfiguration: ConfigurationModel): IConfigurationChange {
934 > const currentFolderConfiguration = this.folderConfigurations.get(resource); configurationModels.ts ×1
935 > const { added, updated, removed, overrides } = compare(currentFolderConfiguration, folderConfiguration);
936 > const keys = [...added, ...updated, ...removed];
937 > if (keys.length || !currentFolderConfiguration) {
938 > this.updateFolderConfiguration(resource, folderConfiguration);
939 > }
940 > return { keys, overrides };
941 > }
943 > compareAndDeleteFolderConfiguration(folder: URI): IConfigurationChange {
944 > const folderConfig = this.folderConfigurations.get(folder); configurationModels.ts ×4
945 > if (!folderConfig) {
946 throw new Error('Unknown folder');
947 }
948 > this.deleteFolderConfiguration(folder); configurationModels.ts ×4
949 > const { added, updated, removed, overrides } = compare(folderConfig, undefined);
950 > return { keys: [...added, ...updated, ...removed], overrides };
951 > }
953 > get defaults(): ConfigurationModel {
954 return this._defaultConfiguration;
955 }
957 > get applicationConfiguration(): ConfigurationModel {
958 > return this._applicationConfiguration; configurationModels.ts ×1
959 > }
961 > private _userConfiguration: ConfigurationModel | null = null;
962 > get userConfiguration(): ConfigurationModel { configurationModels.ts ×92
963 > if (!this._userConfiguration) { configurationModels.ts ×9
964 > if (this._remoteUserConfiguration.isEmpty()) {
965 > this._userConfiguration = this._localUserConfiguration; configurationModels.ts ×1
967 > const merged = this._localUserConfiguration.merge(this._remoteUserConfiguration); configurationModels.ts ×1
968 > this._userConfiguration = new ConfigurationModel(merged.contents, merged.keys, merged.overrides, undefined, this.logService);
969 > }
971 > return this._userConfiguration;
972 > }
974 > get localUserConfiguration(): ConfigurationModel {
975 > return this._localUserConfiguration; configurationModels.ts ×1
976 > }
978 > get remoteUserConfiguration(): ConfigurationModel {
979 > return this._remoteUserConfiguration; configurationModels.ts ×1
980 > }
982 > get workspaceConfiguration(): ConfigurationModel {
983 > return this._workspaceConfiguration; configurationModels.ts ×2
984 > }
986 > get folderConfigurations(): ResourceMap<ConfigurationModel> {
987 > return this._folderConfigurations; configurationModels.ts ×1
988 > }
990 > private getConsolidatedConfigurationModel(section: string | undefined, overrides: IConfigurationOverrides, workspace: Workspace | undefined): ConfigurationModel {
991 > let configurationModel = this.getConsolidatedConfigurationModelForResource(overrides, workspace); configurationModels.ts ×9
992 > if (overrides.overrideIdentifier) {
993 > configurationModel = configurationModel.override(overrides.overrideIdentifier); configurationModels.ts ×1
994 > }
995 > if (!this._policyConfiguration.isEmpty() && this._policyConfiguration.getValue(section) !== undefined) { configurationModels.ts ×9
996 > // clone by merging configurationModels.ts ×1
997 > configurationModel = configurationModel.merge();
998 > for (const key of this._policyConfiguration.keys) {
999 > configurationModel.setValue(key, this._policyConfiguration.getValue(key));
1000 > }
1001 > }
1002 > return configurationModel; configurationModels.ts ×9
1003 > }
1005 > private getConsolidatedConfigurationModelForResource({ resource }: IConfigurationOverrides, workspace: Workspace | undefined): ConfigurationModel {
1006 > let consolidateConfiguration = this.getWorkspaceConsolidatedConfiguration(); configurationModels.ts ×9
1007 >
1008 > if (workspace && resource) {
1009 > const root = workspace.getFolder(resource); configurationModels.ts ×3
1010 > if (root) {
1011 > consolidateConfiguration = this.getFolderConsolidatedConfiguration(root.uri) || consolidateConfiguration;
1012 > }
1013 > const memoryConfigurationForResource = this._memoryConfigurationByResource.get(resource);
1014 > if (memoryConfigurationForResource) {
1015 consolidateConfiguration = consolidateConfiguration.merge(memoryConfigurationForResource);
1016 }
1019 > return consolidateConfiguration;
1020 > }
1022 > private getWorkspaceConsolidatedConfiguration(): ConfigurationModel {
1023 > if (!this._workspaceConsolidatedConfiguration) { configurationModels.ts ×9
1024 > this._workspaceConsolidatedConfiguration = this._defaultConfiguration.merge(this.applicationConfiguration, this.userConfiguration, this._workspaceConfiguration, this._memoryConfiguration);
1025 > }
1026 > return this._workspaceConsolidatedConfiguration;
1027 > }
1029 > private getFolderConsolidatedConfiguration(folder: URI): ConfigurationModel {
1030 > let folderConsolidatedConfiguration = this._foldersConsolidatedConfigurations.get(folder); configurationModels.ts ×3
1031 > if (!folderConsolidatedConfiguration) {
1032 > const workspaceConsolidateConfiguration = this.getWorkspaceConsolidatedConfiguration();
1033 > const folderConfiguration = this._folderConfigurations.get(folder);
1034 > if (folderConfiguration) {
1035 > folderConsolidatedConfiguration = workspaceConsolidateConfiguration.merge(folderConfiguration);
1036 > this._foldersConsolidatedConfigurations.set(folder, folderConsolidatedConfiguration);
1037 > } else {
1038 > folderConsolidatedConfiguration = workspaceConsolidateConfiguration;
1039 > }
1040 > }
1041 > return folderConsolidatedConfiguration;
1042 > }
1044 > private getFolderConfigurationModelForResource(resource: URI | null | undefined, workspace: Workspace | undefined): ConfigurationModel | undefined {
1045 > if (workspace && resource) { configurationModels.ts ×5
1046 const root = workspace.getFolder(resource);
1047 if (root) {
1048 return this._folderConfigurations.get(root.uri);
1049 }
1050 }
1051 > return undefined; configurationModels.ts ×5
1052 > }
1054 > toData(): IConfigurationData {
1055 > return { configurationModels.ts ×3
1056 > defaults: {
1057 > contents: this._defaultConfiguration.contents,
1058 > overrides: this._defaultConfiguration.overrides,
1059 > keys: this._defaultConfiguration.keys,
1060 > },
1061 > policy: {
1062 > contents: this._policyConfiguration.contents,
1063 > overrides: this._policyConfiguration.overrides,
1064 > keys: this._policyConfiguration.keys
1065 > },
1066 > application: {
1067 > contents: this.applicationConfiguration.contents,
1068 > overrides: this.applicationConfiguration.overrides,
1069 > keys: this.applicationConfiguration.keys,
1070 > raw: Array.isArray(this.applicationConfiguration.raw) ? undefined : this.applicationConfiguration.raw
1071 > },
1072 > userLocal: {
1073 > contents: this.localUserConfiguration.contents,
1074 > overrides: this.localUserConfiguration.overrides,
1075 > keys: this.localUserConfiguration.keys,
1076 > raw: Array.isArray(this.localUserConfiguration.raw) ? undefined : this.localUserConfiguration.raw
1077 > },
1078 > userRemote: {
1079 > contents: this.remoteUserConfiguration.contents,
1080 > overrides: this.remoteUserConfiguration.overrides,
1081 > keys: this.remoteUserConfiguration.keys,
1082 > raw: Array.isArray(this.remoteUserConfiguration.raw) ? undefined : this.remoteUserConfiguration.raw
1083 > },
1084 > workspace: {
1085 > contents: this._workspaceConfiguration.contents,
1086 > overrides: this._workspaceConfiguration.overrides,
1087 > keys: this._workspaceConfiguration.keys
1088 > },
1089 > folders: [...this._folderConfigurations.keys()].reduce<[UriComponents, IConfigurationModel][]>((result, folder) => {
1090 > const { contents, overrides, keys } = this._folderConfigurations.get(folder)!; configurationModels.ts ×2
1091 > result.push([folder, { contents, overrides, keys }]);
1092 > return result;
1094 > };
1095 > }
1097 > allKeys(): string[] {
1098 > const keys: Set<string> = new Set<string>(); configurationModels.ts ×6
1099 > this._defaultConfiguration.keys.forEach(key => keys.add(key));
1100 > this.userConfiguration.keys.forEach(key => keys.add(key));
1101 > this._workspaceConfiguration.keys.forEach(key => keys.add(key));
1102 > this._folderConfigurations.forEach(folderConfiguration => folderConfiguration.keys.forEach(key => keys.add(key)));
1103 > return [...keys.values()];
1104 > }
1106 > protected allOverrideIdentifiers(): string[] {
1107 > const keys: Set<string> = new Set<string>(); configurationModels.ts ×6
1108 > this._defaultConfiguration.getAllOverrideIdentifiers().forEach(key => keys.add(key));
1109 > this.userConfiguration.getAllOverrideIdentifiers().forEach(key => keys.add(key));
1110 > this._workspaceConfiguration.getAllOverrideIdentifiers().forEach(key => keys.add(key));
1111 > this._folderConfigurations.forEach(folderConfiguration => folderConfiguration.getAllOverrideIdentifiers().forEach(key => keys.add(key)));
1112 > return [...keys.values()];
1113 > }
1115 > protected getAllKeysForOverrideIdentifier(overrideIdentifier: string): string[] {
1116 > const keys: Set<string> = new Set<string>(); configurationModels.ts ×6
1117 > this._defaultConfiguration.getKeysForOverrideIdentifier(overrideIdentifier).forEach(key => keys.add(key));
1118 > this.userConfiguration.getKeysForOverrideIdentifier(overrideIdentifier).forEach(key => keys.add(key));
1119 > this._workspaceConfiguration.getKeysForOverrideIdentifier(overrideIdentifier).forEach(key => keys.add(key));
1120 > this._folderConfigurations.forEach(folderConfiguration => folderConfiguration.getKeysForOverrideIdentifier(overrideIdentifier).forEach(key => keys.add(key)));
1121 > return [...keys.values()];
1122 > }
1124 > static parse(data: IConfigurationData, logService: ILogService): Configuration {
1125 > const defaultConfiguration = this.parseConfigurationModel(data.defaults, logService); configurationModels.ts ×3
1126 > const policyConfiguration = this.parseConfigurationModel(data.policy, logService);
1127 > const applicationConfiguration = this.parseConfigurationModel(data.application, logService);
1128 > const userLocalConfiguration = this.parseConfigurationModel(data.userLocal, logService);
1129 > const userRemoteConfiguration = this.parseConfigurationModel(data.userRemote, logService);
1130 > const workspaceConfiguration = this.parseConfigurationModel(data.workspace, logService);
1131 > const folders: ResourceMap<ConfigurationModel> = data.folders.reduce((result, value) => {
1132 > result.set(URI.revive(value[0]), this.parseConfigurationModel(value[1], logService)); configurationModels.ts ×2
1133 > return result;
1134 > }, new ResourceMap<ConfigurationModel>()); configurationModels.ts ×3
1135 > return new Configuration(
1136 > defaultConfiguration,
1137 > policyConfiguration,
1138 > applicationConfiguration,
1139 > userLocalConfiguration,
1140 > userRemoteConfiguration,
1141 > workspaceConfiguration,
1142 > folders,
1143 > ConfigurationModel.createEmptyModel(logService),
1144 > new ResourceMap<ConfigurationModel>(),
1145 > logService
1146 > );
1147 > }
1149 > private static parseConfigurationModel(model: IConfigurationModel, logService: ILogService): ConfigurationModel {
1150 > return new ConfigurationModel(model.contents, model.keys, model.overrides, model.raw, logService); configurationModels.ts ×3
1151 > }
1153 > }
1154 >
1155 > export function mergeChanges(...changes: IConfigurationChange[]): IConfigurationChange {
1156 > if (changes.length === 0) { configurationModels.ts ×1
1157 > return { keys: [], overrides: [] }; configurationModels.ts ×1
1158 > }
1159 > if (changes.length === 1) { configurationModels.ts ×1
1160 > return changes[0]; configurationModels.ts ×1
1161 > }
1162 > const keysSet = new Set<string>(); configurationModels.ts ×2
1163 > const overridesMap = new Map<string, Set<string>>();
1164 > for (const change of changes) {
1165 > change.keys.forEach(key => keysSet.add(key));
1166 > change.overrides.forEach(([identifier, keys]) => {
1167 > const result = getOrSet(overridesMap, identifier, new Set<string>()); map.ts ×1
1168 > keys.forEach(key => result.add(key));
1170 > }
1171 > const overrides: [string, string[]][] = [];
1172 > overridesMap.forEach((keys, identifier) => overrides.push([identifier, [...keys.values()]]));
1173 > return { keys: [...keysSet.values()], overrides };
1174 > }
1176 > export class ConfigurationChangeEvent implements IConfigurationChangeEvent {
1177 >
1178 > private readonly _marker = '\n';
1179 > private readonly _markerCode1 = this._marker.charCodeAt(0);
1180 > private readonly _markerCode2 = '.'.charCodeAt(0);
1181 > private readonly _affectsConfigStr: string;
1182 >
1183 > readonly affectedKeys = new Set<string>();
1184 > source!: ConfigurationTarget;
1185 >
1186 > constructor(
1187 > readonly change: IConfigurationChange, configurationModels.ts ×4
1188 > private readonly previous: { workspace?: Workspace; data: IConfigurationData } | undefined,
1189 > private readonly currentConfiguraiton: Configuration,
1190 > private readonly currentWorkspace: Workspace | undefined,
1191 > private readonly logService: ILogService
1192 > ) {
1193 > for (const key of change.keys) {
1194 > this.affectedKeys.add(key); configurationModels.ts ×2
1195 > }
1196 > for (const [, keys] of change.overrides) { configurationModels.ts ×4
1197 > for (const key of keys) { configurationModels.ts ×1
1198 > this.affectedKeys.add(key);
1199 > }
1200 > }
1202 > // Example: '\nfoo.bar\nabc.def\n'
1203 > this._affectsConfigStr = this._marker;
1204 > for (const key of this.affectedKeys) {
1205 > this._affectsConfigStr += key + this._marker; configurationModels.ts ×2
1206 > }
1209 > private _previousConfiguration: Configuration | undefined = undefined;
1210 > get previousConfiguration(): Configuration | undefined {
1211 > if (!this._previousConfiguration && this.previous) { configurationModels.ts ×3
1212 > this._previousConfiguration = Configuration.parse(this.previous.data, this.logService); configurationModels.ts ×1
1213 > }
1214 > return this._previousConfiguration; configurationModels.ts ×3
1215 > }
1217 > affectsConfiguration(section: string, overrides?: IConfigurationOverrides): boolean {
1218 > // we have one large string with all keys that have changed. we pad (marker) the section configurationModels.ts ×3
1219 > // and check that either find it padded or before a segment character
1220 > const needle = this._marker + section;
1221 > const idx = this._affectsConfigStr.indexOf(needle);
1222 > if (idx < 0) {
1223 > // NOT: (marker + section) configurationModels.ts ×1
1224 > return false;
1225 > }
1226 > const pos = idx + needle.length; configurationModels.ts ×2
1227 > if (pos >= this._affectsConfigStr.length) {
1228 return false;
1229 }
1230 > const code = this._affectsConfigStr.charCodeAt(pos); configurationModels.ts ×2
1231 > if (code !== this._markerCode1 && code !== this._markerCode2) { configurationModels.ts ×3
1232 > // NOT: section + (marker | segment) configurationModels.ts ×1
1233 > return false;
1234 > }
1235 > if (overrides) { configurationModels.ts ×2
1236 > const value1 = this.previousConfiguration ? this.previousConfiguration.getValue(section, overrides, this.previous?.workspace) : undefined; configurationModels.ts ×3
1237 > const value2 = this.currentConfiguraiton.getValue(section, overrides, this.currentWorkspace);
1238 > return !objects.equals(value1, value2);
1239 > }
1240 > return true; configurationModels.ts ×2
1243 >
1244 > function compare(from: ConfigurationModel | undefined, to: ConfigurationModel | undefined): IConfigurationCompareResult { configurationModels.ts ×8
1245 > const { added, removed, updated } = compareConfigurationContents(to?.rawConfiguration, from?.rawConfiguration);
1246 > const overrides: [string, string[]][] = [];
1247 >
1248 > const fromOverrideIdentifiers = from?.getAllOverrideIdentifiers() || [];
1249 > const toOverrideIdentifiers = to?.getAllOverrideIdentifiers() || [];
1250 >
1251 > if (to) {
1252 > const addedOverrideIdentifiers = toOverrideIdentifiers.filter(key => !fromOverrideIdentifiers.includes(key)); configurationModels.ts ×7
1253 > for (const identifier of addedOverrideIdentifiers) {
1254 > overrides.push([identifier, to.getKeysForOverrideIdentifier(identifier)]); configurationModels.ts ×1
1255 > }
1258 > if (from) {
1259 > const removedOverrideIdentifiers = fromOverrideIdentifiers.filter(key => !toOverrideIdentifiers.includes(key));
1260 > for (const identifier of removedOverrideIdentifiers) {
1261 > overrides.push([identifier, from.getKeysForOverrideIdentifier(identifier)]); configurationModels.ts ×1
1262 > }
1264 >
1265 > if (to && from) {
1266 > for (const identifier of fromOverrideIdentifiers) { configurationModels.ts ×7
1267 > if (toOverrideIdentifiers.includes(identifier)) { configurationModels.ts ×1
1268 > const result = compareConfigurationContents({ contents: from.getOverrideValue(undefined, identifier) || {}, keys: from.getKeysForOverrideIdentifier(identifier) }, { contents: to.getOverrideValue(undefined, identifier) || {}, keys: to.getKeysForOverrideIdentifier(identifier) });
1269 > overrides.push([identifier, [...result.added, ...result.removed, ...result.updated]]);
1270 > }
1271 > }
1274 > return { added, removed, updated, overrides };
1275 > }
1277 > function compareConfigurationContents(to: { keys: string[]; contents: IStringDictionary<unknown> } | undefined, from: { keys: string[]; contents: IStringDictionary<unknown> } | undefined) { configurationModels.ts ×8
1278 > const added = to
1279 > ? from ? to.keys.filter(key => from.keys.indexOf(key) === -1) : [...to.keys] configurationModels.ts ×7
1281 > const removed = from configurationModels.ts ×8
1282 > ? to ? from.keys.filter(key => to.keys.indexOf(key) === -1) : [...from.keys]
1284 > const updated: string[] = []; configurationModels.ts ×8
1285 >
1286 > if (to && from) {
1287 > for (const key of from.keys) { configurationModels.ts ×7
1288 > if (to.keys.indexOf(key) !== -1) { configurationModels.ts ×2
1289 > const value1 = getConfigurationValue(from.contents, key); configurationModels.ts ×2
1290 > const value2 = getConfigurationValue(to.contents, key);
1291 > if (!objects.equals(value1, value2)) {
1292 > updated.push(key); configurationModels.ts ×1
1293 > }
1297 > return { added, removed, updated }; configurationModels.ts ×8
1298 > }