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