Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/services/configuration/common/configurationModels.ts
5241 views
1
/*---------------------------------------------------------------------------------------------
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 { equals } from '../../../../base/common/objects.js';
7
import { toValuesTree, IConfigurationModel, IConfigurationOverrides, IConfigurationValue, IConfigurationChange } from '../../../../platform/configuration/common/configuration.js';
8
import { Configuration as BaseConfiguration, ConfigurationModelParser, ConfigurationModel, ConfigurationParseOptions } from '../../../../platform/configuration/common/configurationModels.js';
9
import { IStoredWorkspaceFolder } from '../../../../platform/workspaces/common/workspaces.js';
10
import { Workspace } from '../../../../platform/workspace/common/workspace.js';
11
import { ResourceMap } from '../../../../base/common/map.js';
12
import { URI } from '../../../../base/common/uri.js';
13
import { isBoolean } from '../../../../base/common/types.js';
14
import { distinct } from '../../../../base/common/arrays.js';
15
import { ILogService } from '../../../../platform/log/common/log.js';
16
import { IStringDictionary } from '../../../../base/common/collections.js';
17
18
export class WorkspaceConfigurationModelParser extends ConfigurationModelParser {
19
20
private _folders: IStoredWorkspaceFolder[] = [];
21
private _transient: boolean = false;
22
private _settingsModelParser: ConfigurationModelParser;
23
private _launchModel: ConfigurationModel;
24
private _tasksModel: ConfigurationModel;
25
26
constructor(name: string, logService: ILogService) {
27
super(name, logService);
28
this._settingsModelParser = new ConfigurationModelParser(name, logService);
29
this._launchModel = ConfigurationModel.createEmptyModel(logService);
30
this._tasksModel = ConfigurationModel.createEmptyModel(logService);
31
}
32
33
get folders(): IStoredWorkspaceFolder[] {
34
return this._folders;
35
}
36
37
get transient(): boolean {
38
return this._transient;
39
}
40
41
get settingsModel(): ConfigurationModel {
42
return this._settingsModelParser.configurationModel;
43
}
44
45
get launchModel(): ConfigurationModel {
46
return this._launchModel;
47
}
48
49
get tasksModel(): ConfigurationModel {
50
return this._tasksModel;
51
}
52
53
reparseWorkspaceSettings(configurationParseOptions: ConfigurationParseOptions): void {
54
this._settingsModelParser.reparse(configurationParseOptions);
55
}
56
57
getRestrictedWorkspaceSettings(): string[] {
58
return this._settingsModelParser.restrictedConfigurations;
59
}
60
61
protected override doParseRaw(raw: IStringDictionary<unknown>, configurationParseOptions?: ConfigurationParseOptions): IConfigurationModel {
62
this._folders = (raw['folders'] || []) as IStoredWorkspaceFolder[];
63
this._transient = isBoolean(raw['transient']) && raw['transient'];
64
this._settingsModelParser.parseRaw(raw['settings'] as IStringDictionary<unknown>, configurationParseOptions);
65
this._launchModel = this.createConfigurationModelFrom(raw, 'launch');
66
this._tasksModel = this.createConfigurationModelFrom(raw, 'tasks');
67
return super.doParseRaw(raw, configurationParseOptions);
68
}
69
70
private createConfigurationModelFrom(raw: IStringDictionary<unknown>, key: string): ConfigurationModel {
71
const data = raw[key] as IStringDictionary<unknown> | undefined;
72
if (data) {
73
const contents = toValuesTree(data, message => console.error(`Conflict in settings file ${this._name}: ${message}`));
74
const scopedContents = Object.create(null);
75
scopedContents[key] = contents;
76
const keys = Object.keys(data).map(k => `${key}.${k}`);
77
return new ConfigurationModel(scopedContents, keys, [], undefined, this.logService);
78
}
79
return ConfigurationModel.createEmptyModel(this.logService);
80
}
81
}
82
83
export class StandaloneConfigurationModelParser extends ConfigurationModelParser {
84
85
constructor(name: string, private readonly scope: string, logService: ILogService,) {
86
super(name, logService);
87
}
88
89
protected override doParseRaw(raw: IStringDictionary<unknown>, configurationParseOptions?: ConfigurationParseOptions): IConfigurationModel {
90
const contents = toValuesTree(raw, message => console.error(`Conflict in settings file ${this._name}: ${message}`));
91
const scopedContents = Object.create(null);
92
scopedContents[this.scope] = contents;
93
const keys = Object.keys(raw).map(key => `${this.scope}.${key}`);
94
return { contents: scopedContents, keys, overrides: [] };
95
}
96
97
}
98
99
export class Configuration extends BaseConfiguration {
100
101
constructor(
102
defaults: ConfigurationModel,
103
policy: ConfigurationModel,
104
application: ConfigurationModel,
105
localUser: ConfigurationModel,
106
remoteUser: ConfigurationModel,
107
workspaceConfiguration: ConfigurationModel,
108
folders: ResourceMap<ConfigurationModel>,
109
memoryConfiguration: ConfigurationModel,
110
memoryConfigurationByResource: ResourceMap<ConfigurationModel>,
111
private readonly _workspace: Workspace | undefined,
112
logService: ILogService
113
) {
114
super(defaults, policy, application, localUser, remoteUser, workspaceConfiguration, folders, memoryConfiguration, memoryConfigurationByResource, logService);
115
}
116
117
override getValue(key: string | undefined, overrides: IConfigurationOverrides = {}): unknown {
118
return super.getValue(key, overrides, this._workspace);
119
}
120
121
override inspect<C>(key: string, overrides: IConfigurationOverrides = {}): IConfigurationValue<C> {
122
return super.inspect(key, overrides, this._workspace);
123
}
124
125
override keys(): {
126
default: string[];
127
policy: string[];
128
user: string[];
129
workspace: string[];
130
workspaceFolder: string[];
131
} {
132
return super.keys(this._workspace);
133
}
134
135
override compareAndDeleteFolderConfiguration(folder: URI): IConfigurationChange {
136
if (this._workspace && this._workspace.folders.length > 0 && this._workspace.folders[0].uri.toString() === folder.toString()) {
137
// Do not remove workspace configuration
138
return { keys: [], overrides: [] };
139
}
140
return super.compareAndDeleteFolderConfiguration(folder);
141
}
142
143
compare(other: Configuration): IConfigurationChange {
144
const compare = (fromKeys: string[], toKeys: string[], overrideIdentifier?: string): string[] => {
145
const keys: string[] = [];
146
keys.push(...toKeys.filter(key => fromKeys.indexOf(key) === -1));
147
keys.push(...fromKeys.filter(key => toKeys.indexOf(key) === -1));
148
keys.push(...fromKeys.filter(key => {
149
// Ignore if the key does not exist in both models
150
if (toKeys.indexOf(key) === -1) {
151
return false;
152
}
153
// Compare workspace value
154
if (!equals(this.getValue(key, { overrideIdentifier }), other.getValue(key, { overrideIdentifier }))) {
155
return true;
156
}
157
// Compare workspace folder value
158
return this._workspace && this._workspace.folders.some(folder => !equals(this.getValue(key, { resource: folder.uri, overrideIdentifier }), other.getValue(key, { resource: folder.uri, overrideIdentifier })));
159
}));
160
return keys;
161
};
162
const keys = compare(this.allKeys(), other.allKeys());
163
const overrides: [string, string[]][] = [];
164
const allOverrideIdentifiers = distinct([...this.allOverrideIdentifiers(), ...other.allOverrideIdentifiers()]);
165
for (const overrideIdentifier of allOverrideIdentifiers) {
166
const keys = compare(this.getAllKeysForOverrideIdentifier(overrideIdentifier), other.getAllKeysForOverrideIdentifier(overrideIdentifier), overrideIdentifier);
167
if (keys.length) {
168
overrides.push([overrideIdentifier, keys]);
169
}
170
}
171
return { keys, overrides };
172
}
173
174
}
175
176