introduce alternative column syntax for variable replacment

fixes #16064
This commit is contained in:
isidor 2017-02-21 16:42:31 +01:00
parent db8a4cbd78
commit 00104cc62d
3 changed files with 46 additions and 38 deletions

View file

@ -223,6 +223,10 @@ export class Adapter {
description: nls.localize('debugLinuxConfiguration', "Linux specific launch configuration attributes."),
properties: osProperties
};
Object.keys(attributes.properties).forEach(name => {
attributes.properties[name].errorMessage = attributes.properties[name].errorMessage || nls.localize('deprecatedVariables', "'env.', 'config.' and 'command.' are deprecated, use 'env:', 'config:' and 'command:' instead.");
attributes.properties[name].pattern = attributes.properties[name].pattern || '^(?!\\$\\{(env|config|command)\\.)';
});
return attributes;
});

View file

@ -17,6 +17,7 @@ import { ICommonCodeEditor } from 'vs/editor/common/editorCommon';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { toResource } from 'vs/workbench/common/editor';
// TODO@Isidor remove support for env, config. and command. in march
export class ConfigurationResolverService implements IConfigurationResolverService {
_serviceBrand: any;
private _workspaceRoot: string;
@ -34,6 +35,7 @@ export class ConfigurationResolverService implements IConfigurationResolverServi
this._execPath = environmentService.execPath;
Object.keys(envVariables).forEach(key => {
this[`env.${key}`] = envVariables[key];
this[`env:${key}`] = envVariables[key];
});
}
@ -139,7 +141,7 @@ export class ConfigurationResolverService implements IConfigurationResolverServi
if (types.isString(newValue)) {
return newValue;
} else {
return match && match.indexOf('env.') > 0 ? '' : match;
return match && (match.indexOf('env.') > 0 || match.indexOf('env:') > 0) ? '' : match;
}
});
@ -147,8 +149,7 @@ export class ConfigurationResolverService implements IConfigurationResolverServi
}
private resolveConfigVariable(value: string, originalValue: string): string {
let regexp = /\$\{config\.(.+?)\}/g;
return value.replace(regexp, (match: string, name: string) => {
const replacer = (match: string, name: string) => {
let config = this.configurationService.getConfiguration();
let newValue: any;
try {
@ -173,7 +174,9 @@ export class ConfigurationResolverService implements IConfigurationResolverServi
} else {
return this.resolve(newValue) + '';
}
});
};
return value.replace(/\$\{config\.(.+?)\}/g, replacer).replace(/\$\{config:(.+?)\}/g, replacer);
}
private resolveLiteral(values: IStringDictionary<string | IStringDictionary<string> | string[]>): IStringDictionary<string | IStringDictionary<string> | string[]> {
@ -220,7 +223,8 @@ export class ConfigurationResolverService implements IConfigurationResolverServi
if (object[key] && typeof object[key] === 'object') {
findInteractiveVariables(object[key]);
} else if (typeof object[key] === 'string') {
const matches = /\${command.(.+)}/.exec(object[key]);
object[key] = object[key].replace(new RegExp('command.', 'g'), 'command:');
const matches = /\${command:(.+)}/.exec(object[key]);
if (matches && matches.length === 2) {
const interactiveVariable = matches[1];
if (!interactiveVariablesToSubstitutes[interactiveVariable]) {
@ -246,7 +250,7 @@ export class ConfigurationResolverService implements IConfigurationResolverServi
return this.commandService.executeCommand<string>(commandId, configuration).then(result => {
if (result) {
interactiveVariablesToSubstitutes[interactiveVariable].forEach(substitute =>
substitute.object[substitute.key] = substitute.object[substitute.key].replace(`\${command.${interactiveVariable}}`, result)
substitute.object[substitute.key] = substitute.object[substitute.key].replace(`\${command:${interactiveVariable}}`, result)
);
} else {
substitionCanceled = true;

View file

@ -57,17 +57,17 @@ suite('Configuration Resolver Service', () => {
test('substitute one env variable', () => {
if (platform.isWindows) {
assert.strictEqual(configurationResolverService.resolve('abc ${workspaceRoot} ${env.key1} xyz'), 'abc \\VSCode\\workspaceLocation Value for Key1 xyz');
assert.strictEqual(configurationResolverService.resolve('abc ${workspaceRoot} ${env:key1} xyz'), 'abc \\VSCode\\workspaceLocation Value for Key1 xyz');
} else {
assert.strictEqual(configurationResolverService.resolve('abc ${workspaceRoot} ${env.key1} xyz'), 'abc /VSCode/workspaceLocation Value for Key1 xyz');
assert.strictEqual(configurationResolverService.resolve('abc ${workspaceRoot} ${env:key1} xyz'), 'abc /VSCode/workspaceLocation Value for Key1 xyz');
}
});
test('substitute many env variable', () => {
if (platform.isWindows) {
assert.strictEqual(configurationResolverService.resolve('${workspaceRoot} - ${workspaceRoot} ${env.key1} - ${env.key2}'), '\\VSCode\\workspaceLocation - \\VSCode\\workspaceLocation Value for Key1 - Value for Key2');
assert.strictEqual(configurationResolverService.resolve('${workspaceRoot} - ${workspaceRoot} ${env:key1} - ${env:key2}'), '\\VSCode\\workspaceLocation - \\VSCode\\workspaceLocation Value for Key1 - Value for Key2');
} else {
assert.strictEqual(configurationResolverService.resolve('${workspaceRoot} - ${workspaceRoot} ${env.key1} - ${env.key2}'), '/VSCode/workspaceLocation - /VSCode/workspaceLocation Value for Key1 - Value for Key2');
assert.strictEqual(configurationResolverService.resolve('${workspaceRoot} - ${workspaceRoot} ${env:key1} - ${env:key2}'), '/VSCode/workspaceLocation - /VSCode/workspaceLocation Value for Key1 - Value for Key2');
}
});
@ -85,7 +85,7 @@ suite('Configuration Resolver Service', () => {
});
let service = new ConfigurationResolverService(uri.parse('file:///VSCode/workspaceLocation'), envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService);
assert.strictEqual(service.resolve('abc ${config.editor.fontFamily} xyz'), 'abc foo xyz');
assert.strictEqual(service.resolve('abc ${config:editor.fontFamily} xyz'), 'abc foo xyz');
});
test('substitute many configuration variables', () => {
@ -102,14 +102,14 @@ suite('Configuration Resolver Service', () => {
});
let service = new ConfigurationResolverService(uri.parse('file:///VSCode/workspaceLocation'), envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService);
assert.strictEqual(service.resolve('abc ${config.editor.fontFamily} ${config.terminal.integrated.fontFamily} xyz'), 'abc foo bar xyz');
assert.strictEqual(service.resolve('abc ${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} xyz'), 'abc foo bar xyz');
});
test('substitute nested configuration variables', () => {
let configurationService: IConfigurationService;
configurationService = new MockConfigurationService({
editor: {
fontFamily: 'foo ${workspaceRoot} ${config.terminal.integrated.fontFamily}'
fontFamily: 'foo ${workspaceRoot} ${config:terminal.integrated.fontFamily}'
},
terminal: {
integrated: {
@ -120,9 +120,9 @@ suite('Configuration Resolver Service', () => {
let service = new ConfigurationResolverService(uri.parse('file:///VSCode/workspaceLocation'), envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService);
if (platform.isWindows) {
assert.strictEqual(service.resolve('abc ${config.editor.fontFamily} ${config.terminal.integrated.fontFamily} xyz'), 'abc foo \\VSCode\\workspaceLocation bar bar xyz');
assert.strictEqual(service.resolve('abc ${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} xyz'), 'abc foo \\VSCode\\workspaceLocation bar bar xyz');
} else {
assert.strictEqual(service.resolve('abc ${config.editor.fontFamily} ${config.terminal.integrated.fontFamily} xyz'), 'abc foo /VSCode/workspaceLocation bar bar xyz');
assert.strictEqual(service.resolve('abc ${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} xyz'), 'abc foo /VSCode/workspaceLocation bar bar xyz');
}
});
@ -130,7 +130,7 @@ suite('Configuration Resolver Service', () => {
let configurationService: IConfigurationService;
configurationService = new MockConfigurationService({
editor: {
fontFamily: 'foo ${workspaceRoot} ${config.terminal.integrated.fontFamily} ${config.editor.fontFamily}'
fontFamily: 'foo ${workspaceRoot} ${config:terminal.integrated.fontFamily} ${config:editor.fontFamily}'
},
terminal: {
integrated: {
@ -141,9 +141,9 @@ suite('Configuration Resolver Service', () => {
let service = new ConfigurationResolverService(uri.parse('file:///VSCode/workspaceLocation'), envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService);
if (platform.isWindows) {
assert.strictEqual(service.resolve('abc ${config.editor.fontFamily} ${config.terminal.integrated.fontFamily} xyz'), 'abc foo \\VSCode\\workspaceLocation bar bar xyz');
assert.strictEqual(service.resolve('abc ${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} xyz'), 'abc foo \\VSCode\\workspaceLocation bar bar xyz');
} else {
assert.strictEqual(service.resolve('abc ${config.editor.fontFamily} ${config.terminal.integrated.fontFamily} xyz'), 'abc foo /VSCode/workspaceLocation bar bar xyz');
assert.strictEqual(service.resolve('abc ${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} xyz'), 'abc foo /VSCode/workspaceLocation bar bar xyz');
}
});
@ -162,9 +162,9 @@ suite('Configuration Resolver Service', () => {
let service = new ConfigurationResolverService(uri.parse('file:///VSCode/workspaceLocation'), envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService);
if (platform.isWindows) {
assert.strictEqual(service.resolve('abc ${config.editor.fontFamily} ${workspaceRoot} ${env.key1} xyz'), 'abc foo \\VSCode\\workspaceLocation Value for Key1 xyz');
assert.strictEqual(service.resolve('abc ${config:editor.fontFamily} ${workspaceRoot} ${env:key1} xyz'), 'abc foo \\VSCode\\workspaceLocation Value for Key1 xyz');
} else {
assert.strictEqual(service.resolve('abc ${config.editor.fontFamily} ${workspaceRoot} ${env.key1} xyz'), 'abc foo /VSCode/workspaceLocation Value for Key1 xyz');
assert.strictEqual(service.resolve('abc ${config:editor.fontFamily} ${workspaceRoot} ${env:key1} xyz'), 'abc foo /VSCode/workspaceLocation Value for Key1 xyz');
}
});
@ -183,9 +183,9 @@ suite('Configuration Resolver Service', () => {
let service = new ConfigurationResolverService(uri.parse('file:///VSCode/workspaceLocation'), envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService);
if (platform.isWindows) {
assert.strictEqual(service.resolve('${config.editor.fontFamily} ${config.terminal.integrated.fontFamily} ${workspaceRoot} - ${workspaceRoot} ${env.key1} - ${env.key2}'), 'foo bar \\VSCode\\workspaceLocation - \\VSCode\\workspaceLocation Value for Key1 - Value for Key2');
assert.strictEqual(service.resolve('${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} ${workspaceRoot} - ${workspaceRoot} ${env:key1} - ${env:key2}'), 'foo bar \\VSCode\\workspaceLocation - \\VSCode\\workspaceLocation Value for Key1 - Value for Key2');
} else {
assert.strictEqual(service.resolve('${config.editor.fontFamily} ${config.terminal.integrated.fontFamily} ${workspaceRoot} - ${workspaceRoot} ${env.key1} - ${env.key2}'), 'foo bar /VSCode/workspaceLocation - /VSCode/workspaceLocation Value for Key1 - Value for Key2');
assert.strictEqual(service.resolve('${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} ${workspaceRoot} - ${workspaceRoot} ${env:key1} - ${env:key2}'), 'foo bar /VSCode/workspaceLocation - /VSCode/workspaceLocation Value for Key1 - Value for Key2');
}
});
@ -216,7 +216,7 @@ suite('Configuration Resolver Service', () => {
});
let service = new ConfigurationResolverService(uri.parse('file:///VSCode/workspaceLocation'), envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService);
assert.strictEqual(service.resolve('abc ${config.editor.fontFamily} ${config.editor.lineNumbers} ${config.editor.insertSpaces} xyz'), 'abc foo 123 false xyz');
assert.strictEqual(service.resolve('abc ${config:editor.fontFamily} ${config:editor.lineNumbers} ${config:editor.insertSpaces} xyz'), 'abc foo 123 false xyz');
});
test('configuration should not evaluate Javascript', () => {
@ -228,7 +228,7 @@ suite('Configuration Resolver Service', () => {
});
let service = new ConfigurationResolverService(uri.parse('file:///VSCode/workspaceLocation'), envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService);
assert.strictEqual(service.resolve('abc ${config.editor[\'abc\'.substr(0)]} xyz'), 'abc xyz');
assert.strictEqual(service.resolve('abc ${config:editor[\'abc\'.substr(0)]} xyz'), 'abc xyz');
});
test('uses empty string as fallback', () => {
@ -238,10 +238,10 @@ suite('Configuration Resolver Service', () => {
});
let service = new ConfigurationResolverService(uri.parse('file:///VSCode/workspaceLocation'), envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService);
assert.strictEqual(service.resolve('abc ${config.editor.abc} xyz'), 'abc xyz');
assert.strictEqual(service.resolve('abc ${config.editor.abc.def} xyz'), 'abc xyz');
assert.strictEqual(service.resolve('abc ${config.panel} xyz'), 'abc xyz');
assert.strictEqual(service.resolve('abc ${config.panel.abc} xyz'), 'abc xyz');
assert.strictEqual(service.resolve('abc ${config:editor.abc} xyz'), 'abc xyz');
assert.strictEqual(service.resolve('abc ${config:editor.abc.def} xyz'), 'abc xyz');
assert.strictEqual(service.resolve('abc ${config:panel} xyz'), 'abc xyz');
assert.strictEqual(service.resolve('abc ${config:panel.abc} xyz'), 'abc xyz');
});
test('is restricted to own properties', () => {
@ -251,8 +251,8 @@ suite('Configuration Resolver Service', () => {
});
let service = new ConfigurationResolverService(uri.parse('file:///VSCode/workspaceLocation'), envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService);
assert.strictEqual(service.resolve('abc ${config.editor.__proto__} xyz'), 'abc xyz');
assert.strictEqual(service.resolve('abc ${config.editor.toString} xyz'), 'abc xyz');
assert.strictEqual(service.resolve('abc ${config:editor.__proto__} xyz'), 'abc xyz');
assert.strictEqual(service.resolve('abc ${config:editor.toString} xyz'), 'abc xyz');
});
test('configuration variables with invalid accessor', () => {
@ -264,9 +264,9 @@ suite('Configuration Resolver Service', () => {
});
let service = new ConfigurationResolverService(uri.parse('file:///VSCode/workspaceLocation'), envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService);
assert.strictEqual(service.resolve('abc ${config.} xyz'), 'abc ${config.} xyz');
assert.strictEqual(service.resolve('abc ${config.editor..fontFamily} xyz'), 'abc xyz');
assert.strictEqual(service.resolve('abc ${config.editor.none.none2} xyz'), 'abc xyz');
assert.strictEqual(service.resolve('abc ${config:} xyz'), 'abc ${config:} xyz');
assert.strictEqual(service.resolve('abc ${config:editor..fontFamily} xyz'), 'abc xyz');
assert.strictEqual(service.resolve('abc ${config:editor.none.none2} xyz'), 'abc xyz');
});
test('interactive variable simple', () => {
@ -274,7 +274,7 @@ suite('Configuration Resolver Service', () => {
'name': 'Attach to Process',
'type': 'node',
'request': 'attach',
'processId': '${command.interactiveVariable1}',
'processId': '${command:interactiveVariable1}',
'port': 5858,
'sourceMaps': false,
'outDir': null
@ -303,12 +303,12 @@ suite('Configuration Resolver Service', () => {
'name': 'Attach to Process',
'type': 'node',
'request': 'attach',
'processId': '${command.interactiveVariable1}',
'port': '${command.interactiveVariable2}',
'processId': '${command:interactiveVariable1}',
'port': '${command:interactiveVariable2}',
'sourceMaps': false,
'outDir': 'src/${command.interactiveVariable2}',
'outDir': 'src/${command:interactiveVariable2}',
'env': {
'processId': '__${command.interactiveVariable2}__',
'processId': '__${command:interactiveVariable2}__',
}
};
const interactiveVariables = Object.create(null);