Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inspect shall show the real values #161327

Merged
merged 2 commits into from
Sep 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 74 additions & 40 deletions src/vs/platform/configuration/common/configurationModels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,32 @@ export class ConfigurationModel implements IConfigurationModel {
constructor(
private readonly _contents: any = {},
private readonly _keys: string[] = [],
private readonly _overrides: IOverrides[] = []
private readonly _overrides: IOverrides[] = [],
readonly raw?: ReadonlyArray<IStringDictionary<any> | ConfigurationModel>
) {
}

private _rawConfiguration: ConfigurationModel | undefined;
private get rawConfiguration(): ConfigurationModel {
if (!this._rawConfiguration) {
if (this.raw?.length) {
const rawConfigurationModels = this.raw.map(raw => {
if (raw instanceof ConfigurationModel) {
return raw;
}
const parser = new ConfigurationModelParser('');
parser.parseRaw(raw);
return parser.configurationModel;
});
this._rawConfiguration = rawConfigurationModels.reduce((previous, current) => current === previous ? current : previous.merge(current), rawConfigurationModels[0]);
} else {
// raw is same as current
this._rawConfiguration = this;
}
}
return this._rawConfiguration;
}

get contents(): any {
return this.checkAndFreeze(this._contents);
}
Expand All @@ -55,6 +77,13 @@ export class ConfigurationModel implements IConfigurationModel {
return section ? getConfigurationValue<any>(this.contents, section) : this.contents;
}

inspect<V>(section: string | undefined, overrideIdentifier?: string | null): { value?: V; override?: V; merged?: V } {
const value = this.rawConfiguration.getValue<V>(section);
const override = overrideIdentifier ? this.rawConfiguration.getOverrideValue<V>(section, overrideIdentifier) : undefined;
const merged = overrideIdentifier ? this.rawConfiguration.override(overrideIdentifier).getValue<V>(section) : value;
return { value, override, merged };
}

getOverrideValue<V>(section: string | undefined, overrideIdentifier: string): V | undefined {
const overrideContents = this.getContentsForOverrideIdentifer(overrideIdentifier);
return overrideContents
Expand Down Expand Up @@ -93,8 +122,10 @@ export class ConfigurationModel implements IConfigurationModel {
const contents = objects.deepClone(this.contents);
const overrides = objects.deepClone(this.overrides);
const keys = [...this.keys];
const raws = this.raw?.length ? [...this.raw] : [this];

for (const other of others) {
raws.push(...(other.raw?.length ? other.raw : [other]));
if (other.isEmpty()) {
continue;
}
Expand All @@ -116,7 +147,7 @@ export class ConfigurationModel implements IConfigurationModel {
}
}
}
return new ConfigurationModel(contents, keys, overrides);
return new ConfigurationModel(contents, keys, overrides, raws.every(raw => raw instanceof ConfigurationModel) ? undefined : raws);
}

freeze(): ConfigurationModel {
Expand Down Expand Up @@ -284,8 +315,8 @@ export class ConfigurationModelParser {

public parseRaw(raw: any, options?: ConfigurationParseOptions): void {
this._raw = raw;
const { contents, keys, overrides, restricted } = this.doParseRaw(raw, options);
this._configurationModel = new ConfigurationModel(contents, keys, overrides);
const { contents, keys, overrides, restricted, hasExcludedProperties } = this.doParseRaw(raw, options);
this._configurationModel = new ConfigurationModel(contents, keys, overrides, hasExcludedProperties ? [raw] : undefined /* raw has not changed */);
this._restrictedConfigurations = restricted || [];
}

Expand Down Expand Up @@ -346,26 +377,28 @@ export class ConfigurationModelParser {
return raw;
}

protected doParseRaw(raw: any, options?: ConfigurationParseOptions): IConfigurationModel & { restricted?: string[] } {
protected doParseRaw(raw: any, options?: ConfigurationParseOptions): IConfigurationModel & { restricted?: string[]; hasExcludedProperties?: boolean } {
const configurationProperties = Registry.as<IConfigurationRegistry>(Extensions.Configuration).getConfigurationProperties();
const filtered = this.filter(raw, configurationProperties, true, options);
raw = filtered.raw;
const contents = toValuesTree(raw, message => console.error(`Conflict in settings file ${this._name}: ${message}`));
const keys = Object.keys(raw);
const overrides = this.toOverrides(raw, message => console.error(`Conflict in settings file ${this._name}: ${message}`));
return { contents, keys, overrides, restricted: filtered.restricted };
return { contents, keys, overrides, restricted: filtered.restricted, hasExcludedProperties: filtered.hasExcludedProperties };
}

private filter(properties: any, configurationProperties: { [qualifiedKey: string]: IConfigurationPropertySchema | undefined }, filterOverriddenProperties: boolean, options?: ConfigurationParseOptions): { raw: {}; restricted: string[] } {
private filter(properties: any, configurationProperties: { [qualifiedKey: string]: IConfigurationPropertySchema | undefined }, filterOverriddenProperties: boolean, options?: ConfigurationParseOptions): { raw: {}; restricted: string[]; hasExcludedProperties: boolean } {
let hasExcludedProperties = false;
if (!options?.scopes && !options?.skipRestricted) {
return { raw: properties, restricted: [] };
return { raw: properties, restricted: [], hasExcludedProperties };
}
const raw: any = {};
const restricted: string[] = [];
for (const key in properties) {
if (OVERRIDE_PROPERTY_REGEX.test(key) && filterOverriddenProperties) {
const result = this.filter(properties[key], configurationProperties, false, options);
raw[key] = result.raw;
hasExcludedProperties = hasExcludedProperties || result.hasExcludedProperties;
restricted.push(...result.restricted);
} else {
const propertySchema = configurationProperties[key];
Expand All @@ -374,14 +407,15 @@ export class ConfigurationModelParser {
restricted.push(key);
}
// Load unregistered configurations always.
if (scope === undefined || options.scopes === undefined || options.scopes.includes(scope)) {
if (!(options.skipRestricted && propertySchema?.restricted)) {
raw[key] = properties[key];
}
if ((scope === undefined || options.scopes === undefined || options.scopes.includes(scope)) // Check scopes
&& !(options.skipRestricted && propertySchema?.restricted)) { // Check restricted
raw[key] = properties[key];
} else {
hasExcludedProperties = true;
}
}
}
return { raw, restricted };
return { raw, restricted, hasExcludedProperties };
}

private toOverrides(raw: any, conflictReporter: (message: string) => void): IOverrides[] {
Expand Down Expand Up @@ -501,39 +535,39 @@ export class Configuration {
const folderConfigurationModel = this.getFolderConfigurationModelForResource(overrides.resource, workspace);
const memoryConfigurationModel = overrides.resource ? this._memoryConfigurationByResource.get(overrides.resource) || this._memoryConfiguration : this._memoryConfiguration;

const defaultValue = overrides.overrideIdentifier ? this._defaultConfiguration.freeze().override(overrides.overrideIdentifier).getValue<C>(key) : this._defaultConfiguration.freeze().getValue<C>(key);
const policyValue = this._policyConfiguration.isEmpty() ? undefined : this._policyConfiguration.freeze().getValue<C>(key);
const applicationValue = this.applicationConfiguration.isEmpty() ? undefined : this.applicationConfiguration.freeze().getValue<C>(key);
const userValue = overrides.overrideIdentifier ? this.userConfiguration.freeze().override(overrides.overrideIdentifier).getValue<C>(key) : this.userConfiguration.freeze().getValue<C>(key);
const userLocalValue = overrides.overrideIdentifier ? this.localUserConfiguration.freeze().override(overrides.overrideIdentifier).getValue<C>(key) : this.localUserConfiguration.freeze().getValue<C>(key);
const userRemoteValue = overrides.overrideIdentifier ? this.remoteUserConfiguration.freeze().override(overrides.overrideIdentifier).getValue<C>(key) : this.remoteUserConfiguration.freeze().getValue<C>(key);
const workspaceValue = workspace ? overrides.overrideIdentifier ? this._workspaceConfiguration.freeze().override(overrides.overrideIdentifier).getValue<C>(key) : this._workspaceConfiguration.freeze().getValue<C>(key) : undefined; //Check on workspace exists or not because _workspaceConfiguration is never null
const workspaceFolderValue = folderConfigurationModel ? overrides.overrideIdentifier ? folderConfigurationModel.freeze().override(overrides.overrideIdentifier).getValue<C>(key) : folderConfigurationModel.freeze().getValue<C>(key) : undefined;
const memoryValue = overrides.overrideIdentifier ? memoryConfigurationModel.override(overrides.overrideIdentifier).getValue<C>(key) : memoryConfigurationModel.getValue<C>(key);
const defaultInspectValue = this._defaultConfiguration.inspect<C>(key, overrides.overrideIdentifier);
const policyInspectValue = this._policyConfiguration.isEmpty() ? undefined : this._policyConfiguration.freeze().inspect<C>(key);
const applicationInspectValue = this.applicationConfiguration.isEmpty() ? undefined : this.applicationConfiguration.freeze().inspect<C>(key);
const userInspectValue = this.userConfiguration.freeze().inspect<C>(key, overrides.overrideIdentifier);
const userLocalInspectValue = this.localUserConfiguration.freeze().inspect<C>(key, overrides.overrideIdentifier);
const userRemoteInspectValue = this.remoteUserConfiguration.freeze().inspect<C>(key, overrides.overrideIdentifier);
const workspaceInspectValue = workspace ? this._workspaceConfiguration.freeze().inspect<C>(key, overrides.overrideIdentifier) : undefined; //Check on workspace exists or not because _workspaceConfiguration is never null
const workspaceFolderInspectValue = folderConfigurationModel ? folderConfigurationModel.freeze().inspect<C>(key, overrides.overrideIdentifier) : undefined;
const memoryInspectValue = memoryConfigurationModel.inspect<C>(key, overrides.overrideIdentifier);
const value = consolidateConfigurationModel.getValue<C>(key);
const overrideIdentifiers: string[] = arrays.distinct(consolidateConfigurationModel.overrides.map(override => override.identifiers).flat()).filter(overrideIdentifier => consolidateConfigurationModel.getOverrideValue(key, overrideIdentifier) !== undefined);

return {
defaultValue,
policyValue,
applicationValue,
userValue,
userLocalValue,
userRemoteValue,
workspaceValue,
workspaceFolderValue,
memoryValue,
defaultValue: defaultInspectValue ? defaultInspectValue.merged : undefined,
policyValue: policyInspectValue ? policyInspectValue.merged : undefined,
applicationValue: applicationInspectValue ? applicationInspectValue.merged : undefined,
userValue: userInspectValue ? userInspectValue.merged : undefined,
userLocalValue: userLocalInspectValue ? userLocalInspectValue.merged : undefined,
userRemoteValue: userRemoteInspectValue ? userRemoteInspectValue.merged : undefined,
workspaceValue: workspaceInspectValue ? workspaceInspectValue.merged : undefined,
workspaceFolderValue: workspaceFolderInspectValue ? workspaceFolderInspectValue.merged : undefined,
memoryValue: memoryInspectValue ? memoryInspectValue.merged : undefined,
value,

default: defaultValue !== undefined ? { value: this._defaultConfiguration.freeze().getValue(key), override: overrides.overrideIdentifier ? this._defaultConfiguration.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,
policy: policyValue !== undefined ? { value: policyValue } : undefined,
application: applicationValue !== undefined ? { value: applicationValue, override: overrides.overrideIdentifier ? this.applicationConfiguration.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,
user: userValue !== undefined ? { value: this.userConfiguration.freeze().getValue(key), override: overrides.overrideIdentifier ? this.userConfiguration.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,
userLocal: userLocalValue !== undefined ? { value: this.localUserConfiguration.freeze().getValue(key), override: overrides.overrideIdentifier ? this.localUserConfiguration.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,
userRemote: userRemoteValue !== undefined ? { value: this.remoteUserConfiguration.freeze().getValue(key), override: overrides.overrideIdentifier ? this.remoteUserConfiguration.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,
workspace: workspaceValue !== undefined ? { value: this._workspaceConfiguration.freeze().getValue(key), override: overrides.overrideIdentifier ? this._workspaceConfiguration.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,
workspaceFolder: workspaceFolderValue !== undefined ? { value: folderConfigurationModel?.freeze().getValue(key), override: overrides.overrideIdentifier ? folderConfigurationModel?.freeze().getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,
memory: memoryValue !== undefined ? { value: memoryConfigurationModel.getValue(key), override: overrides.overrideIdentifier ? memoryConfigurationModel.getOverrideValue(key, overrides.overrideIdentifier) : undefined } : undefined,
default: defaultInspectValue.value !== undefined || defaultInspectValue.override !== undefined ? { value: defaultInspectValue.value, override: defaultInspectValue.override } : undefined,
policy: policyInspectValue?.value !== undefined ? { value: policyInspectValue.value } : undefined,
application: applicationInspectValue?.value !== undefined || applicationInspectValue?.override !== undefined ? { value: applicationInspectValue.value, override: applicationInspectValue.override } : undefined,
user: userInspectValue.value !== undefined || userInspectValue.override !== undefined ? { value: userInspectValue.value, override: userInspectValue.override } : undefined,
userLocal: userLocalInspectValue.value !== undefined || userLocalInspectValue.override !== undefined ? { value: userLocalInspectValue.value, override: userLocalInspectValue.override } : undefined,
userRemote: userRemoteInspectValue.value !== undefined || userRemoteInspectValue.override !== undefined ? { value: userRemoteInspectValue.value, override: userRemoteInspectValue.override } : undefined,
workspace: workspaceInspectValue?.value !== undefined || workspaceInspectValue?.override !== undefined ? { value: workspaceInspectValue.value, override: workspaceInspectValue.override } : undefined,
workspaceFolder: workspaceFolderInspectValue?.value !== undefined || workspaceFolderInspectValue?.override !== undefined ? { value: workspaceFolderInspectValue.value, override: workspaceFolderInspectValue.override } : undefined,
memory: memoryInspectValue.value !== undefined || memoryInspectValue.override !== undefined ? { value: memoryInspectValue.value, override: memoryInspectValue.override } : undefined,

overrideIdentifiers: overrideIdentifiers.length ? overrideIdentifiers : undefined
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,67 @@ suite('ConfigurationModel', () => {
{ identifiers: ['x'], contents: { 'a': 3, 'b': 2 }, keys: ['a', 'b'] },
]);
});

test('inspect when raw is same', () => {
const testObject = new ConfigurationModel({ 'a': 1, 'c': 1 }, ['a', 'c'], [{ identifiers: ['x', 'y'], contents: { 'a': 2, 'b': 1 }, keys: ['a'] }]);

assert.deepStrictEqual(testObject.inspect('a'), { value: 1, override: undefined, merged: 1 });
assert.deepStrictEqual(testObject.inspect('a', 'x'), { value: 1, override: 2, merged: 2 });
assert.deepStrictEqual(testObject.inspect('b', 'x'), { value: undefined, override: 1, merged: 1 });
assert.deepStrictEqual(testObject.inspect('d'), { value: undefined, override: undefined, merged: undefined });
});

test('inspect when raw is not same', () => {
const testObject = new ConfigurationModel({ 'a': 1, 'c': 1 }, ['a', 'c'], [{ identifiers: ['x', 'y'], contents: { 'a': 2, }, keys: ['a'] }], [{
'a': 1,
'b': 2,
'c': 1,
'd': 3,
'[x][y]': {
'a': 2,
'b': 1
}
}]);

assert.deepStrictEqual(testObject.inspect('a'), { value: 1, override: undefined, merged: 1 });
assert.deepStrictEqual(testObject.inspect('a', 'x'), { value: 1, override: 2, merged: 2 });
assert.deepStrictEqual(testObject.inspect('b', 'x'), { value: 2, override: 1, merged: 1 });
assert.deepStrictEqual(testObject.inspect('d'), { value: 3, override: undefined, merged: 3 });
assert.deepStrictEqual(testObject.inspect('e'), { value: undefined, override: undefined, merged: undefined });
});

test('inspect in merged configuration when raw is same', () => {
const target1 = new ConfigurationModel({ 'a': 1 }, ['a'], [{ identifiers: ['x', 'y'], contents: { 'a': 2, }, keys: ['a'] }]);
const target2 = new ConfigurationModel({ 'b': 3 }, ['b'], []);
const testObject = target1.merge(target2);

assert.deepStrictEqual(testObject.inspect('a'), { value: 1, override: undefined, merged: 1 });
assert.deepStrictEqual(testObject.inspect('a', 'x'), { value: 1, override: 2, merged: 2 });
assert.deepStrictEqual(testObject.inspect('b'), { value: 3, override: undefined, merged: 3 });
assert.deepStrictEqual(testObject.inspect('b', 'y'), { value: 3, override: undefined, merged: 3 });
assert.deepStrictEqual(testObject.inspect('c'), { value: undefined, override: undefined, merged: undefined });
});

test('inspect in merged configuration when raw is not same for one model', () => {
const target1 = new ConfigurationModel({ 'a': 1 }, ['a'], [{ identifiers: ['x', 'y'], contents: { 'a': 2, }, keys: ['a'] }], [{
'a': 1,
'b': 2,
'c': 3,
'[x][y]': {
'a': 2,
'b': 4,
}
}]);
const target2 = new ConfigurationModel({ 'b': 3 }, ['b'], []);
const testObject = target1.merge(target2);

assert.deepStrictEqual(testObject.inspect('a'), { value: 1, override: undefined, merged: 1 });
assert.deepStrictEqual(testObject.inspect('a', 'x'), { value: 1, override: 2, merged: 2 });
assert.deepStrictEqual(testObject.inspect('b'), { value: 3, override: undefined, merged: 3 });
assert.deepStrictEqual(testObject.inspect('b', 'y'), { value: 3, override: 4, merged: 4 });
assert.deepStrictEqual(testObject.inspect('c'), { value: 3, override: undefined, merged: 3 });
});

});

suite('CustomConfigurationModel', () => {
Expand Down
Loading