Merge VS Code 1.21 source code (#1067)

* Initial VS Code 1.21 file copy with patches

* A few more merges

* Post npm install

* Fix batch of build breaks

* Fix more build breaks

* Fix more build errors

* Fix more build breaks

* Runtime fixes 1

* Get connection dialog working with some todos

* Fix a few packaging issues

* Copy several node_modules to package build to fix loader issues

* Fix breaks from master

* A few more fixes

* Make tests pass

* First pass of license header updates

* Second pass of license header updates

* Fix restore dialog issues

* Remove add additional themes menu items

* fix select box issues where the list doesn't show up

* formatting

* Fix editor dispose issue

* Copy over node modules to correct location on all platforms
This commit is contained in:
Karl Burtram
2018-04-04 15:27:51 -07:00
committed by GitHub
parent 5fba3e31b4
commit dafb780987
9412 changed files with 141255 additions and 98813 deletions

View File

@@ -13,7 +13,6 @@ export const IConfigurationResolverService = createDecorator<IConfigurationResol
export interface IConfigurationResolverService {
_serviceBrand: any;
// TODO@Isidor improve this API
resolve(root: IWorkspaceFolder, value: string): string;
resolve(root: IWorkspaceFolder, value: string[]): string[];
resolve(root: IWorkspaceFolder, value: IStringDictionary<string>): IStringDictionary<string>;

View File

@@ -12,85 +12,149 @@ import { IConfigurationResolverService } from 'vs/workbench/services/configurati
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { IWorkspaceFolder, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { toResource } from 'vs/workbench/common/editor';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { relative } from 'path';
import { IProcessEnvironment, isWindows } from 'vs/base/common/platform';
import { normalizeDriveLetter } from 'vs/base/common/labels';
import { Schemas } from 'vs/base/common/network';
export class ConfigurationResolverService implements IConfigurationResolverService {
_serviceBrand: any;
private _execPath: string;
private _lastWorkspaceFolder: IWorkspaceFolder;
class VariableResolver {
static VARIABLE_REGEXP = /\$\{(.*?)\}/g;
private envVariables: IProcessEnvironment;
constructor(
envVariables: { [key: string]: string },
@IWorkbenchEditorService private editorService: IWorkbenchEditorService,
@IEnvironmentService environmentService: IEnvironmentService,
@IConfigurationService private configurationService: IConfigurationService,
@ICommandService private commandService: ICommandService,
envVariables: IProcessEnvironment,
private configurationService: IConfigurationService,
private editorService: IWorkbenchEditorService,
private environmentService: IEnvironmentService,
private workspaceContextService: IWorkspaceContextService
) {
this._execPath = environmentService.execPath;
Object.keys(envVariables).forEach(key => {
this[`env:${key}`] = envVariables[key];
});
}
private get execPath(): string {
return this._execPath;
}
private get cwd(): string {
if (this.workspaceRoot) {
return this.workspaceRoot;
if (isWindows) {
this.envVariables = Object.create(null);
Object.keys(envVariables).forEach(key => {
this.envVariables[key.toLowerCase()] = envVariables[key];
});
} else {
return process.cwd();
this.envVariables = envVariables;
}
}
private get workspaceRoot(): string {
return this._lastWorkspaceFolder ? this._lastWorkspaceFolder.uri.fsPath : undefined;
resolve(context: IWorkspaceFolder, value: string): string {
const filePath = this.getFilePath();
return value.replace(VariableResolver.VARIABLE_REGEXP, (match: string, variable: string) => {
const parts = variable.split(':');
let sufix: string;
if (parts && parts.length > 1) {
variable = parts[0];
sufix = parts[1];
}
switch (variable) {
case 'env': {
if (sufix) {
if (isWindows) {
sufix = sufix.toLowerCase();
}
const env = this.envVariables[sufix];
if (types.isString(env)) {
return env;
}
}
}
case 'config': {
if (sufix) {
const config = this.configurationService.getValue<string>(sufix, context ? { resource: context.uri } : undefined);
if (!types.isUndefinedOrNull(config) && !types.isObject(config)) {
return config;
}
}
}
default: {
if (sufix) {
const folder = this.workspaceContextService.getWorkspace().folders.filter(f => f.name === sufix).pop();
if (folder) {
context = folder;
}
}
switch (variable) {
case 'workspaceRoot':
case 'workspaceFolder':
return context ? normalizeDriveLetter(context.uri.fsPath) : match;
case 'cwd':
return context ? normalizeDriveLetter(context.uri.fsPath) : process.cwd();
case 'workspaceRootFolderName':
case 'workspaceFolderBasename':
return context ? paths.basename(context.uri.fsPath) : match;
case 'lineNumber':
return this.getLineNumber() || match;
case 'selectedText':
return this.getSelectedText() || match;
case 'file':
return filePath || match;
case 'relativeFile':
return context ? paths.normalize(relative(context.uri.fsPath, filePath)) : filePath || match;
case 'fileDirname':
return filePath ? paths.dirname(filePath) : match;
case 'fileExtname':
return filePath ? paths.extname(filePath) : match;
case 'fileBasename':
return filePath ? paths.basename(filePath) : match;
case 'fileBasenameNoExtension': {
if (!filePath) {
return match;
}
const basename = paths.basename(filePath);
return basename.slice(0, basename.length - paths.extname(basename).length);
}
case 'execPath':
return this.environmentService.execPath;
default:
return match;
}
}
}
});
}
private get workspaceFolder(): string {
return this.workspaceRoot;
private getSelectedText(): string {
const activeEditor = this.editorService.getActiveEditor();
if (activeEditor) {
const editorControl = (<ICodeEditor>activeEditor.getControl());
if (editorControl) {
const editorModel = editorControl.getModel();
const editorSelection = editorControl.getSelection();
if (editorModel && editorSelection) {
return editorModel.getValueInRange(editorSelection);
}
}
}
return undefined;
}
private get workspaceRootFolderName(): string {
return this.workspaceFolderBasename;
private getFilePath(): string {
let input = this.editorService.getActiveEditorInput();
if (input instanceof DiffEditorInput) {
input = input.modifiedInput;
}
const fileResource = toResource(input, { filter: Schemas.file });
if (!fileResource) {
return undefined;
}
return paths.normalize(fileResource.fsPath, true);
}
private get workspaceFolderBasename(): string {
return this.workspaceRoot ? paths.basename(this.workspaceRoot) : '';
}
private get file(): string {
return this.getFilePath();
}
private get relativeFile(): string {
return (this.workspaceRoot) ? paths.normalize(relative(this.workspaceRoot, this.file)) : this.file;
}
private get fileBasename(): string {
return paths.basename(this.getFilePath());
}
private get fileBasenameNoExtension(): string {
const basename = this.fileBasename;
return basename.slice(0, basename.length - paths.extname(basename).length);
}
private get fileDirname(): string {
return paths.dirname(this.getFilePath());
}
private get fileExtname(): string {
return paths.extname(this.getFilePath());
}
private get lineNumber(): string {
private getLineNumber(): string {
const activeEditor = this.editorService.getActiveEditor();
if (activeEditor) {
const editorControl = (<ICodeEditor>activeEditor.getControl());
@@ -100,133 +164,58 @@ export class ConfigurationResolverService implements IConfigurationResolverServi
}
}
return '';
return undefined;
}
}
private getFilePath(): string {
let input = this.editorService.getActiveEditorInput();
if (input instanceof DiffEditorInput) {
input = input.modifiedInput;
}
if (!input) {
return '';
}
export class ConfigurationResolverService implements IConfigurationResolverService {
_serviceBrand: any;
private resolver: VariableResolver;
const fileResource = toResource(input, { filter: 'file' });
if (!fileResource) {
return '';
}
return paths.normalize(fileResource.fsPath, true);
constructor(
envVariables: IProcessEnvironment,
@IWorkbenchEditorService editorService: IWorkbenchEditorService,
@IEnvironmentService environmentService: IEnvironmentService,
@IConfigurationService configurationService: IConfigurationService,
@ICommandService private commandService: ICommandService,
@IWorkspaceContextService workspaceContextService: IWorkspaceContextService
) {
this.resolver = new VariableResolver(envVariables, configurationService, editorService, environmentService, workspaceContextService);
}
public resolve(root: IWorkspaceFolder, value: string): string;
public resolve(root: IWorkspaceFolder, value: string[]): string[];
public resolve(root: IWorkspaceFolder, value: IStringDictionary<string>): IStringDictionary<string>;
public resolve(root: IWorkspaceFolder, value: any): any {
try {
this._lastWorkspaceFolder = root;
if (types.isString(value)) {
return this.resolveString(root, value);
} else if (types.isArray(value)) {
return this.resolveArray(root, value);
} else if (types.isObject(value)) {
return this.resolveLiteral(root, value);
}
return value;
} finally {
this._lastWorkspaceFolder = undefined;
if (types.isString(value)) {
return this.resolver.resolve(root, value);
} else if (types.isArray(value)) {
return value.map(s => this.resolver.resolve(root, s));
} else if (types.isObject(value)) {
let result: IStringDictionary<string | IStringDictionary<string> | string[]> = Object.create(null);
Object.keys(value).forEach(key => {
result[key] = this.resolve(root, value[key]);
});
return result;
}
return value;
}
public resolveAny<T>(root: IWorkspaceFolder, value: T): T;
public resolveAny(root: IWorkspaceFolder, value: any): any {
try {
this._lastWorkspaceFolder = root;
if (types.isString(value)) {
return this.resolveString(root, value);
} else if (types.isArray(value)) {
return this.resolveAnyArray(root, value);
} else if (types.isObject(value)) {
return this.resolveAnyLiteral(root, value);
}
return value;
} finally {
this._lastWorkspaceFolder = undefined;
if (types.isString(value)) {
return this.resolver.resolve(root, value);
} else if (types.isArray(value)) {
return value.map(s => this.resolveAny(root, s));
} else if (types.isObject(value)) {
let result: IStringDictionary<string | IStringDictionary<string> | string[]> = Object.create(null);
Object.keys(value).forEach(key => {
result[key] = this.resolveAny(root, value[key]);
});
return result;
}
}
private resolveString(root: IWorkspaceFolder, value: string): string {
let regexp = /\$\{(.*?)\}/g;
const originalValue = value;
const resolvedString = value.replace(regexp, (match: string, name: string) => {
let newValue = (<any>this)[name];
if (types.isString(newValue)) {
return newValue;
} else {
return match && match.indexOf('env:') > 0 ? '' : match;
}
});
return this.resolveConfigVariable(root, resolvedString, originalValue);
}
private resolveConfigVariable(root: IWorkspaceFolder, value: string, originalValue: string): string {
const replacer = (match: string, name: string) => {
let config = this.configurationService.getValue<any>({ resource: root.uri });
let newValue: any;
try {
const keys: string[] = name.split('.');
if (!keys || keys.length <= 0) {
return '';
}
while (keys.length > 1) {
const key = keys.shift();
if (!config || !config.hasOwnProperty(key)) {
return '';
}
config = config[key];
}
newValue = config && config.hasOwnProperty(keys[0]) ? config[keys[0]] : '';
} catch (e) {
return '';
}
if (types.isString(newValue)) {
// Prevent infinite recursion and also support nested references (or tokens)
return newValue === originalValue ? '' : this.resolveString(root, newValue);
} else {
return this.resolve(root, newValue) + '';
}
};
return value.replace(/\$\{config:(.+?)\}/g, replacer);
}
private resolveLiteral(root: IWorkspaceFolder, values: IStringDictionary<string | IStringDictionary<string> | string[]>): IStringDictionary<string | IStringDictionary<string> | string[]> {
let result: IStringDictionary<string | IStringDictionary<string> | string[]> = Object.create(null);
Object.keys(values).forEach(key => {
let value = values[key];
result[key] = <any>this.resolve(root, <any>value);
});
return result;
}
private resolveAnyLiteral<T>(root: IWorkspaceFolder, values: T): T;
private resolveAnyLiteral(root: IWorkspaceFolder, values: any): any {
let result: IStringDictionary<string | IStringDictionary<string> | string[]> = Object.create(null);
Object.keys(values).forEach(key => {
let value = values[key];
result[key] = <any>this.resolveAny(root, <any>value);
});
return result;
}
private resolveArray(root: IWorkspaceFolder, value: string[]): string[] {
return value.map(s => this.resolveString(root, s));
}
private resolveAnyArray<T>(root: IWorkspaceFolder, value: T[]): T[];
private resolveAnyArray(root: IWorkspaceFolder, value: any[]): any[] {
return value.map(s => this.resolveAny(root, s));
return value;
}
/**
@@ -239,7 +228,7 @@ export class ConfigurationResolverService implements IConfigurationResolverServi
// We need a map from interactive variables to keys because we only want to trigger an command once per key -
// even though it might occur multiple times in configuration #7026.
const interactiveVariablesToSubstitutes: { [interactiveVariable: string]: { object: any, key: string }[] } = {};
const interactiveVariablesToSubstitutes: { [interactiveVariable: string]: { object: any, key: string }[] } = Object.create(null);
const findInteractiveVariables = (object: any) => {
Object.keys(object).forEach(key => {
if (object[key] && typeof object[key] === 'object') {

View File

@@ -12,17 +12,16 @@ import { ICommandService } from 'vs/platform/commands/common/commands';
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
import { ConfigurationResolverService } from 'vs/workbench/services/configurationResolver/electron-browser/configurationResolverService';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { TestEnvironmentService, TestEditorService } from 'vs/workbench/test/workbenchTestServices';
import { TestEnvironmentService, TestEditorService, TestContextService } from 'vs/workbench/test/workbenchTestServices';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
suite('Configuration Resolver Service', () => {
let configurationResolverService: IConfigurationResolverService;
let envVariables: { [key: string]: string } = { key1: 'Value for Key1', key2: 'Value for Key2' };
let envVariables: { [key: string]: string } = { key1: 'Value for key1', key2: 'Value for key2' };
let mockCommandService: MockCommandService;
let editorService: TestEditorService;
let workspace: IWorkspaceFolder;
setup(() => {
mockCommandService = new MockCommandService();
editorService = new TestEditorService();
@@ -32,14 +31,13 @@ suite('Configuration Resolver Service', () => {
index: 0,
toResource: () => null
};
configurationResolverService = new ConfigurationResolverService(envVariables, editorService, TestEnvironmentService, new TestConfigurationService(), mockCommandService);
configurationResolverService = new ConfigurationResolverService(envVariables, editorService, TestEnvironmentService, new TestConfigurationService(), mockCommandService, new TestContextService());
});
teardown(() => {
configurationResolverService = null;
});
test('substitute one', () => {
if (platform.isWindows) {
assert.strictEqual(configurationResolverService.resolve(workspace, 'abc ${workspaceFolder} xyz'), 'abc \\VSCode\\workspaceLocation xyz');
@@ -56,6 +54,10 @@ suite('Configuration Resolver Service', () => {
assert.strictEqual(configurationResolverService.resolve(workspace, 'abc ${lineNumber} xyz'), `abc ${editorService.mockLineNumber} xyz`);
});
test('current selected text', () => {
assert.strictEqual(configurationResolverService.resolve(workspace, 'abc ${selectedText} xyz'), `abc ${editorService.mockSelectedText} xyz`);
});
test('substitute many', () => {
if (platform.isWindows) {
assert.strictEqual(configurationResolverService.resolve(workspace, '${workspaceFolder} - ${workspaceFolder}'), '\\VSCode\\workspaceLocation - \\VSCode\\workspaceLocation');
@@ -66,17 +68,25 @@ suite('Configuration Resolver Service', () => {
test('substitute one env variable', () => {
if (platform.isWindows) {
assert.strictEqual(configurationResolverService.resolve(workspace, 'abc ${workspaceFolder} ${env:key1} xyz'), 'abc \\VSCode\\workspaceLocation Value for Key1 xyz');
assert.strictEqual(configurationResolverService.resolve(workspace, 'abc ${workspaceFolder} ${env:key1} xyz'), 'abc \\VSCode\\workspaceLocation Value for key1 xyz');
} else {
assert.strictEqual(configurationResolverService.resolve(workspace, 'abc ${workspaceFolder} ${env:key1} xyz'), 'abc /VSCode/workspaceLocation Value for Key1 xyz');
assert.strictEqual(configurationResolverService.resolve(workspace, 'abc ${workspaceFolder} ${env:key1} xyz'), 'abc /VSCode/workspaceLocation Value for key1 xyz');
}
});
test('substitute many env variable', () => {
if (platform.isWindows) {
assert.strictEqual(configurationResolverService.resolve(workspace, '${workspaceFolder} - ${workspaceFolder} ${env:key1} - ${env:key2}'), '\\VSCode\\workspaceLocation - \\VSCode\\workspaceLocation Value for Key1 - Value for Key2');
assert.strictEqual(configurationResolverService.resolve(workspace, '${workspaceFolder} - ${workspaceFolder} ${env:key1} - ${env:key2}'), '\\VSCode\\workspaceLocation - \\VSCode\\workspaceLocation Value for key1 - Value for key2');
} else {
assert.strictEqual(configurationResolverService.resolve(workspace, '${workspaceFolder} - ${workspaceFolder} ${env:key1} - ${env:key2}'), '/VSCode/workspaceLocation - /VSCode/workspaceLocation Value for Key1 - Value for Key2');
assert.strictEqual(configurationResolverService.resolve(workspace, '${workspaceFolder} - ${workspaceFolder} ${env:key1} - ${env:key2}'), '/VSCode/workspaceLocation - /VSCode/workspaceLocation Value for key1 - Value for key2');
}
});
test('substitute one env variable using platform case sensitivity', () => {
if (platform.isWindows) {
assert.strictEqual(configurationResolverService.resolve(workspace, '${env:key1} - ${env:Key1}'), 'Value for key1 - Value for key1');
} else {
assert.strictEqual(configurationResolverService.resolve(workspace, '${env:key1} - ${env:Key1}'), 'Value for key1 - ${env:Key1}');
}
});
@@ -93,7 +103,7 @@ suite('Configuration Resolver Service', () => {
}
});
let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService);
let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService, new TestContextService());
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} xyz'), 'abc foo xyz');
});
@@ -110,52 +120,10 @@ suite('Configuration Resolver Service', () => {
}
});
let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService);
let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService, new TestContextService());
assert.strictEqual(service.resolve(workspace, '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 ${workspaceFolder} ${config:terminal.integrated.fontFamily}'
},
terminal: {
integrated: {
fontFamily: 'bar'
}
}
});
let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService);
if (platform.isWindows) {
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} xyz'), 'abc foo \\VSCode\\workspaceLocation bar bar xyz');
} else {
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} xyz'), 'abc foo /VSCode/workspaceLocation bar bar xyz');
}
});
test('substitute accidental self referenced configuration variables', () => {
let configurationService: IConfigurationService;
configurationService = new MockConfigurationService({
editor: {
fontFamily: 'foo ${workspaceFolder} ${config:terminal.integrated.fontFamily} ${config:editor.fontFamily}'
},
terminal: {
integrated: {
fontFamily: 'bar'
}
}
});
let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService);
if (platform.isWindows) {
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} xyz'), 'abc foo \\VSCode\\workspaceLocation bar bar xyz');
} else {
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} xyz'), 'abc foo /VSCode/workspaceLocation bar bar xyz');
}
});
test('substitute one env variable and a configuration variable', () => {
let configurationService: IConfigurationService;
configurationService = new MockConfigurationService({
@@ -169,11 +137,11 @@ suite('Configuration Resolver Service', () => {
}
});
let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService);
let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService, new TestContextService());
if (platform.isWindows) {
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${workspaceFolder} ${env:key1} xyz'), 'abc foo \\VSCode\\workspaceLocation Value for Key1 xyz');
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${workspaceFolder} ${env:key1} xyz'), 'abc foo \\VSCode\\workspaceLocation Value for key1 xyz');
} else {
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${workspaceFolder} ${env:key1} xyz'), 'abc foo /VSCode/workspaceLocation Value for Key1 xyz');
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${workspaceFolder} ${env:key1} xyz'), 'abc foo /VSCode/workspaceLocation Value for key1 xyz');
}
});
@@ -190,11 +158,11 @@ suite('Configuration Resolver Service', () => {
}
});
let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService);
let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService, new TestContextService());
if (platform.isWindows) {
assert.strictEqual(service.resolve(workspace, '${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} ${workspaceFolder} - ${workspaceFolder} ${env:key1} - ${env:key2}'), 'foo bar \\VSCode\\workspaceLocation - \\VSCode\\workspaceLocation Value for Key1 - Value for Key2');
assert.strictEqual(service.resolve(workspace, '${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} ${workspaceFolder} - ${workspaceFolder} ${env:key1} - ${env:key2}'), 'foo bar \\VSCode\\workspaceLocation - \\VSCode\\workspaceLocation Value for key1 - Value for key2');
} else {
assert.strictEqual(service.resolve(workspace, '${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} ${workspaceFolder} - ${workspaceFolder} ${env:key1} - ${env:key2}'), 'foo bar /VSCode/workspaceLocation - /VSCode/workspaceLocation Value for Key1 - Value for Key2');
assert.strictEqual(service.resolve(workspace, '${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} ${workspaceFolder} - ${workspaceFolder} ${env:key1} - ${env:key2}'), 'foo bar /VSCode/workspaceLocation - /VSCode/workspaceLocation Value for key1 - Value for key2');
}
});
@@ -224,7 +192,7 @@ suite('Configuration Resolver Service', () => {
}
});
let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService);
let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService, new TestContextService());
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${config:editor.lineNumbers} ${config:editor.insertSpaces} xyz'), 'abc foo 123 false xyz');
});
@@ -236,32 +204,21 @@ suite('Configuration Resolver Service', () => {
}
});
let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService);
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor[\'abc\'.substr(0)]} xyz'), 'abc xyz');
let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService, new TestContextService());
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor[\'abc\'.substr(0)]} xyz'), 'abc ${config:editor[\'abc\'.substr(0)]} xyz');
});
test('uses empty string as fallback', () => {
test('uses original variable as fallback', () => {
let configurationService: IConfigurationService;
configurationService = new MockConfigurationService({
editor: {}
});
let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService);
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.abc} xyz'), 'abc xyz');
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.abc.def} xyz'), 'abc xyz');
assert.strictEqual(service.resolve(workspace, 'abc ${config:panel} xyz'), 'abc xyz');
assert.strictEqual(service.resolve(workspace, 'abc ${config:panel.abc} xyz'), 'abc xyz');
});
test('is restricted to own properties', () => {
let configurationService: IConfigurationService;
configurationService = new MockConfigurationService({
editor: {}
});
let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService);
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.__proto__} xyz'), 'abc xyz');
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.toString} xyz'), 'abc xyz');
let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService, new TestContextService());
assert.strictEqual(service.resolve(workspace, 'abc ${invalidVariable} xyz'), 'abc ${invalidVariable} xyz');
assert.strictEqual(service.resolve(workspace, 'abc ${env:invalidVariable} xyz'), 'abc ${env:invalidVariable} xyz');
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.abc.def} xyz'), 'abc ${config:editor.abc.def} xyz');
assert.strictEqual(service.resolve(workspace, 'abc ${config:panel.abc} xyz'), 'abc ${config:panel.abc} xyz');
});
test('configuration variables with invalid accessor', () => {
@@ -272,10 +229,10 @@ suite('Configuration Resolver Service', () => {
}
});
let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService);
let service = new ConfigurationResolverService(envVariables, new TestEditorService(), TestEnvironmentService, configurationService, mockCommandService, new TestContextService());
assert.strictEqual(service.resolve(workspace, 'abc ${config:} xyz'), 'abc ${config:} xyz');
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor..fontFamily} xyz'), 'abc xyz');
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.none.none2} xyz'), 'abc xyz');
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor..fontFamily} xyz'), 'abc ${config:editor..fontFamily} xyz');
assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.none.none2} xyz'), 'abc ${config:editor.none.none2} xyz');
});
test('interactive variable simple', () => {
@@ -350,7 +307,20 @@ class MockConfigurationService implements IConfigurationService {
public constructor(private configuration: any = {}) { }
public inspect<T>(key: string, overrides?: IConfigurationOverrides): any { return { value: getConfigurationValue<T>(this.getValue(), key), default: getConfigurationValue<T>(this.getValue(), key), user: getConfigurationValue<T>(this.getValue(), key), workspaceFolder: void 0, folder: void 0 }; }
public keys() { return { default: [], user: [], workspace: [], workspaceFolder: [] }; }
public getValue(): any { return this.configuration; }
public getValue(): any;
public getValue(value: string): any;
public getValue(value?: any): any {
if (!value) {
return this.configuration;
}
const valuePath = (<string>value).split('.');
let object = this.configuration;
while (valuePath.length && object) {
object = object[valuePath.shift()];
}
return object;
}
public updateValue(): TPromise<void> { return null; }
public getConfigurationData(): any { return null; }
public onDidChangeConfiguration() { return { dispose() { } }; }