configurationModels.ts ×92

Frontier kind: Code frontier

unlabeled · c_e170760c74a2

1276 tests · 8823 LOC · 39 files · introduces 0 tests · 271 LOC · 1 file

Introduces — evidence that enters the hierarchy at this concept

Code
92 ranges271 lines · 1 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
1078 ranges8823 lines · 39 files · Browse complete extent
All tests (intent)
1276 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

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 native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

1 file ranked by introduced lines: 271 introduced LOC across 92 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/platform/configuration/common/configurationModels.ts 271 introduced LOC · 92 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- configurationModels.ts
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 {
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>,
39 private readonly _keys: string[],
43 ) {
44 }
46 > private _rawConfiguration: ConfigurationModel | undefined;
47 > get rawConfiguration(): ConfigurationModel {
48 if (!this._rawConfiguration) {
49 if (this._raw) {
64 return this._rawConfiguration;
65 }
67 > get contents(): IStringDictionary<unknown> {
68 return this._contents;
69 }
71 > get overrides(): IOverrides[] {
72 return this._overrides;
73 }
75 > get keys(): string[] {
76 return this._keys;
77 }
79 > get raw(): IStringDictionary<unknown> | IStringDictionary<unknown>[] | undefined {
80 if (!this._raw) {
81 return undefined;
86 return this._raw as IStringDictionary<unknown> | IStringDictionary<unknown>[];
87 }
89 > isEmpty(): boolean {
90 return this._keys.length === 0 && Object.keys(this._contents).length === 0 && this._overrides.length === 0;
91 }
93 > getValue<V>(section: string | undefined): V | undefined {
94 return section ? getConfigurationValue<V>(this.contents, section) : this.contents as V;
95 }
97 > inspect<V>(section: string | undefined, overrideIdentifier?: string | null): InspectValue<V> {
98 const that = this;
99 return {
119 };
120 }
122 > getOverrideValue<V>(section: string | undefined, overrideIdentifier: string): V | undefined {
123 const overrideContents = this.getContentsForOverrideIdentifer(overrideIdentifier);
124 return overrideContents
126 : undefined;
127 }
129 > getKeysForOverrideIdentifier(identifier: string): string[] {
130 const keys: string[] = [];
131 for (const override of this.overrides) {
136 return arrays.distinct(keys);
137 }
139 > getAllOverrideIdentifiers(): string[] {
140 const result: string[] = [];
141 for (const override of this.overrides) {
144 return arrays.distinct(result);
145 }
147 > override(identifier: string): ConfigurationModel {
148 let overrideConfigurationModel = this.overrideConfigurations.get(identifier);
149 if (!overrideConfigurationModel) {
153 return overrideConfigurationModel;
154 }
156 > merge(...others: ConfigurationModel[]): ConfigurationModel {
157 const contents = objects.deepClone(this.contents);
158 const overrides = objects.deepClone(this.overrides);
185 return new ConfigurationModel(contents, keys, overrides, !raws.length || raws.every(raw => raw instanceof ConfigurationModel) ? undefined : raws, this.logService);
186 }
188 > private createOverrideConfigurationModel(identifier: string): ConfigurationModel {
189 const overrideContents = this.getContentsForOverrideIdentifer(identifier);
190
216 return new ConfigurationModel(contents, this.keys, this.overrides, undefined, this.logService);
217 }
219 > private mergeContents(source: IStringDictionary<unknown>, target: IStringDictionary<unknown>): void {
220 for (const key of Object.keys(target)) {
221 if (key in source) {
228 }
229 }
231 > private getContentsForOverrideIdentifer(identifier: string): IStringDictionary<unknown> | null {
232 let contentsForIdentifierOnly: IStringDictionary<unknown> | null = null;
233 let contents: IStringDictionary<unknown> | null = null;
252 return contents;
253 }
255 > toJSON(): IConfigurationModel {
256 return {
257 contents: this.contents,
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);
271 }
273 > public removeValue(key: string): void {
274 const index = this.keys.indexOf(key);
275 if (index === -1) {
282 }
283 }
285 > private updateValue(key: string, value: unknown, add: boolean): void {
286 addToValueTree(this.contents, key, value, e => this.logService.error(e));
287 add = add || this.keys.indexOf(key) === -1;
305 }
306 }
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,
326 protected readonly logService: ILogService
327 ) { }
329 > get configurationModel(): ConfigurationModel {
330 return this._configurationModel || ConfigurationModel.createEmptyModel(this.logService);
331 }
333 > get restrictedConfigurations(): string[] {
334 return this._restrictedConfigurations;
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)) {
343 const raw = this.doParseContent(content);
345 }
346 }
348 > public reparse(options: ConfigurationParseOptions): void {
349 if (this._raw) {
350 this.parseRaw(this._raw, options);
351 }
352 }
354 > public parseRaw(raw: IStringDictionary<unknown>, options?: ConfigurationParseOptions): void {
355 this._raw = raw;
356 const { contents, keys, overrides, restricted, hasExcludedProperties } = this.doParseRaw(raw, options);
358 this._restrictedConfigurations = restricted || [];
359 }
361 > private doParseContent(content: string): IStringDictionary<unknown> {
362 let raw: IStringDictionary<unknown> = {};
363 let currentProperty: string | null = null;
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);
420 const configurationProperties = registry.getConfigurationProperties();
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;
432 if (!options?.scopes && !options?.skipRestricted && !options?.skipUnregistered && !options?.exclude?.length) {
455 return { raw, restricted, hasExcludedProperties };
456 }
458 > private shouldInclude(key: string, propertySchema: IConfigurationPropertySchema | undefined, excludedConfigurationProperties: IStringDictionary<IRegisteredConfigurationPropertySchema>, options: ConfigurationParseOptions): boolean {
459 if (options.exclude?.includes(key)) {
460 return false;
481 return options.scopes.includes(scope);
482 }
484 > private toOverrides(raw: IStringDictionary<unknown>, conflictReporter: (message: string) => void): IOverrides[] {
485 const overrides: IOverrides[] = [];
486 for (const key of Object.keys(raw)) {
500 return overrides;
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,
513 protected parseOptions: ConfigurationParseOptions,
526 )(() => this._onDidChange.fire()));
527 }
529 > async loadConfiguration(): Promise<ConfigurationModel> {
530 try {
531 const content = await this.fileService.readFile(this.userSettingsResource);
536 }
537 }
539 > reparse(parseOptions?: ConfigurationParseOptions): ConfigurationModel {
540 if (parseOptions) {
541 this.parseOptions = 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,
556 private readonly overrides: IConfigurationOverrides,
568 ) {
569 }
571 > get value(): V | undefined {
572 return freeze(this._value);
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;
577 }
579 > private _defaultInspectValue: InspectValue<V> | undefined;
580 > private get defaultInspectValue(): InspectValue<V> {
581 if (!this._defaultInspectValue) {
582 this._defaultInspectValue = this.defaultConfiguration.inspect<V>(this.key, this.overrides.overrideIdentifier);
584 return this._defaultInspectValue;
585 }
587 > get defaultValue(): V | undefined {
588 return this.defaultInspectValue.merged;
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) {
598 this._policyInspectValue = this.policyConfiguration ? this.policyConfiguration.inspect<V>(this.key) : null;
600 return this._policyInspectValue;
601 }
603 > get policyValue(): V | undefined {
604 return this.policyInspectValue?.merged;
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) {
614 this._applicationInspectValue = this.applicationConfiguration ? this.applicationConfiguration.inspect<V>(this.key) : null;
616 return this._applicationInspectValue;
617 }
619 > get applicationValue(): V | undefined {
620 return this.applicationInspectValue?.merged;
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) {
630 this._userInspectValue = this.userConfiguration.inspect<V>(this.key, this.overrides.overrideIdentifier);
632 return this._userInspectValue;
633 }
635 > get userValue(): V | undefined {
636 return this.userInspectValue.merged;
637 }
639 > get user(): IInspectValue<V> | undefined {
640 return this.toInspectValue(this.userInspectValue);
641 }
643 > private _userLocalInspectValue: InspectValue<V> | undefined;
644 > private get userLocalInspectValue(): InspectValue<V> {
645 if (!this._userLocalInspectValue) {
646 this._userLocalInspectValue = this.localUserConfiguration.inspect<V>(this.key, this.overrides.overrideIdentifier);
648 return this._userLocalInspectValue;
649 }
651 > get userLocalValue(): V | undefined {
652 return this.userLocalInspectValue.merged;
653 }
655 > get userLocal(): IInspectValue<V> | undefined {
656 return this.toInspectValue(this.userLocalInspectValue);
657 }
659 > private _userRemoteInspectValue: InspectValue<V> | undefined;
660 > private get userRemoteInspectValue(): InspectValue<V> {
661 if (!this._userRemoteInspectValue) {
662 this._userRemoteInspectValue = this.remoteUserConfiguration.inspect<V>(this.key, this.overrides.overrideIdentifier);
664 return this._userRemoteInspectValue;
665 }
667 > get userRemoteValue(): V | undefined {
668 return this.userRemoteInspectValue.merged;
669 }
671 > get userRemote(): IInspectValue<V> | undefined {
672 return this.toInspectValue(this.userRemoteInspectValue);
673 }
675 > private _workspaceInspectValue: InspectValue<V> | undefined | null;
676 > private get workspaceInspectValue(): InspectValue<V> | null {
677 if (this._workspaceInspectValue === undefined) {
678 this._workspaceInspectValue = this.workspaceConfiguration ? this.workspaceConfiguration.inspect<V>(this.key, this.overrides.overrideIdentifier) : null;
680 return this._workspaceInspectValue;
681 }
683 > get workspaceValue(): V | undefined {
684 return this.workspaceInspectValue?.merged;
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) {
694 this._workspaceFolderInspectValue = this.folderConfigurationModel ? this.folderConfigurationModel.inspect<V>(this.key, this.overrides.overrideIdentifier) : null;
696 return this._workspaceFolderInspectValue;
697 }
699 > get workspaceFolderValue(): V | undefined {
700 return this.workspaceFolderInspectValue?.merged;
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);
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,
732 private _policyConfiguration: ConfigurationModel,
960
961 private _userConfiguration: ConfigurationModel | null = null;
962 > get userConfiguration(): ConfigurationModel { configurationModels.ts
963 if (!this._userConfiguration) {
964 if (this._remoteUserConfiguration.isEmpty()) {
971 return this._userConfiguration;
972 }
974 > get localUserConfiguration(): ConfigurationModel {
975 return this._localUserConfiguration;
976 }
978 > get remoteUserConfiguration(): ConfigurationModel {
979 return this._remoteUserConfiguration;
980 }
982 > get workspaceConfiguration(): ConfigurationModel {
983 return this._workspaceConfiguration;
984 }
986 > get folderConfigurations(): ResourceMap<ConfigurationModel> {
987 return this._folderConfigurations;
988 }
990 > private getConsolidatedConfigurationModel(section: string | undefined, overrides: IConfigurationOverrides, workspace: Workspace | undefined): ConfigurationModel {
991 let configurationModel = this.getConsolidatedConfigurationModelForResource(overrides, workspace);
992 if (overrides.overrideIdentifier) {
1002 return configurationModel;
1003 }
1005 > private getConsolidatedConfigurationModelForResource({ resource }: IConfigurationOverrides, workspace: Workspace | undefined): ConfigurationModel {
1006 let consolidateConfiguration = this.getWorkspaceConsolidatedConfiguration();
1007
1019 return consolidateConfiguration;
1020 }
1022 > private getWorkspaceConsolidatedConfiguration(): ConfigurationModel {
1023 if (!this._workspaceConsolidatedConfiguration) {
1024 this._workspaceConsolidatedConfiguration = this._defaultConfiguration.merge(this.applicationConfiguration, this.userConfiguration, this._workspaceConfiguration, this._memoryConfiguration);
1026 return this._workspaceConsolidatedConfiguration;
1027 }
1029 > private getFolderConsolidatedConfiguration(folder: URI): ConfigurationModel {
1030 let folderConsolidatedConfiguration = this._foldersConsolidatedConfigurations.get(folder);
1031 if (!folderConsolidatedConfiguration) {
1041 return folderConsolidatedConfiguration;
1042 }
1044 > private getFolderConfigurationModelForResource(resource: URI | null | undefined, workspace: Workspace | undefined): ConfigurationModel | undefined {
1045 if (workspace && resource) {
1046 const root = workspace.getFolder(resource);
1051 return undefined;
1052 }
1054 > toData(): IConfigurationData {
1055 return {
1056 defaults: {
1094 };
1095 }
1097 > allKeys(): string[] {
1098 const keys: Set<string> = new Set<string>();
1099 this._defaultConfiguration.keys.forEach(key => keys.add(key));
1103 return [...keys.values()];
1104 }
1106 > protected allOverrideIdentifiers(): string[] {
1107 const keys: Set<string> = new Set<string>();
1108 this._defaultConfiguration.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>();
1117 this._defaultConfiguration.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);
1126 const policyConfiguration = this.parseConfigurationModel(data.policy, 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);
1151 }
1153 > }
1154 >
1155 > export function mergeChanges(...changes: IConfigurationChange[]): IConfigurationChange {
1156 if (changes.length === 0) {
1157 return { keys: [], overrides: [] };
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,
1188 private readonly previous: { workspace?: Workspace; data: IConfigurationData } | undefined,
1206 }
1207 }
1209 > private _previousConfiguration: Configuration | undefined = undefined;
1210 > get previousConfiguration(): Configuration | undefined {
1211 if (!this._previousConfiguration && this.previous) {
1212 this._previousConfiguration = Configuration.parse(this.previous.data, this.logService);
1214 return this._previousConfiguration;
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
1219 // and check that either find it padded or before a segment character
1240 return true;
1241 }
1243 >
1244 function compare(from: ConfigurationModel | undefined, to: ConfigurationModel | undefined): IConfigurationCompareResult {
1245 const { added, removed, updated } = compareConfigurationContents(to?.rawConfiguration, from?.rawConfiguration);
1274 return { added, removed, updated, overrides };
1275 }
1277 function compareConfigurationContents(to: { keys: string[]; contents: IStringDictionary<unknown> } | undefined, from: { keys: string[]; contents: IStringDictionary<unknown> } | undefined) {
1278 const added = to