mirror of
https://github.com/microsoft/vscode.git
synced 2026-02-15 07:28:05 +00:00
config: fix nested config resolution strings not getting resolved sometimes (#248724)
See https://github.com/microsoft/vscode/issues/245798#issuecomment-2871753176 Fixes #245798
This commit is contained in:
@@ -65,7 +65,7 @@ interface IReplacementLocation {
|
||||
export class ConfigurationResolverExpression<T> implements IConfigurationResolverExpression<T> {
|
||||
public static readonly VARIABLE_LHS = '${';
|
||||
|
||||
private locations = new Map<string, IReplacementLocation>();
|
||||
private readonly locations = new Map<string, IReplacementLocation>();
|
||||
private root: T;
|
||||
private stringRoot: boolean;
|
||||
/**
|
||||
@@ -173,17 +173,14 @@ export class ConfigurationResolverExpression<T> implements IConfigurationResolve
|
||||
}
|
||||
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
this.parseString(obj, key, key, true); // parse key
|
||||
|
||||
if (typeof value === 'string') {
|
||||
this.parseString(obj, key, value);
|
||||
} else {
|
||||
this.parseObject(value);
|
||||
}
|
||||
}
|
||||
|
||||
// only after all values are marked for replacement, we can collect keys that have to be replaced
|
||||
for (const [key] of Object.entries(obj)) {
|
||||
this.parseString(obj, key, key, true);
|
||||
}
|
||||
}
|
||||
|
||||
private parseString(object: any, propertyName: string | number, value: string, replaceKeyName?: boolean, replacementPath?: string[]): void {
|
||||
@@ -281,15 +278,26 @@ export class ConfigurationResolverExpression<T> implements IConfigurationResolve
|
||||
const newKey = propertyName.replaceAll(replacement.id, data.value);
|
||||
delete object[propertyName];
|
||||
object[newKey] = value;
|
||||
this._renameKeyInLocations(object, propertyName, newKey);
|
||||
this.parseString(object, newKey, data.value, true, path);
|
||||
} else {
|
||||
this.parseString(object, propertyName, data.value, false, path);
|
||||
object[propertyName] = object[propertyName].replaceAll(replacement.id, data.value);
|
||||
this.parseString(object, propertyName, data.value, false, path);
|
||||
}
|
||||
|
||||
path.pop();
|
||||
}
|
||||
|
||||
private _renameKeyInLocations(obj: object, oldKey: string, newKey: string) {
|
||||
for (const location of this.locations.values()) {
|
||||
for (const loc of location.locations) {
|
||||
if (loc.object === obj && loc.propertyName === oldKey) {
|
||||
loc.propertyName = newKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public toObject(): T {
|
||||
// If we wrapped a string, unwrap it
|
||||
if (this.stringRoot) {
|
||||
|
||||
@@ -1010,4 +1010,53 @@ suite('ConfigurationResolverExpression', () => {
|
||||
'key that is username: testuser': 'cool!'
|
||||
});
|
||||
});
|
||||
|
||||
test('resolves nested values 2 (#245798)', () => {
|
||||
const expr = ConfigurationResolverExpression.parse({
|
||||
env: {
|
||||
SITE: "${input:site}",
|
||||
TLD: "${input:tld}",
|
||||
HOST: "${input:host}",
|
||||
},
|
||||
});
|
||||
|
||||
for (const r of expr.unresolved()) {
|
||||
if (r.arg === 'site') {
|
||||
expr.resolve(r, 'example');
|
||||
} else if (r.arg === 'tld') {
|
||||
expr.resolve(r, 'com');
|
||||
} else if (r.arg === 'host') {
|
||||
expr.resolve(r, 'local.${input:site}.${input:tld}');
|
||||
}
|
||||
}
|
||||
|
||||
assert.deepStrictEqual(expr.toObject(), {
|
||||
env: {
|
||||
SITE: 'example',
|
||||
TLD: 'com',
|
||||
HOST: 'local.example.com'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('out-of-order key resolution (#248550)', () => {
|
||||
const expr = ConfigurationResolverExpression.parse({
|
||||
'${input:key}': "${input:value}",
|
||||
});
|
||||
|
||||
for (const r of expr.unresolved()) {
|
||||
if (r.arg === 'key') {
|
||||
expr.resolve(r, 'the-key');
|
||||
}
|
||||
}
|
||||
for (const r of expr.unresolved()) {
|
||||
if (r.arg === 'value') {
|
||||
expr.resolve(r, 'the-value');
|
||||
}
|
||||
}
|
||||
|
||||
assert.deepStrictEqual(expr.toObject(), {
|
||||
'the-key': 'the-value'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user