diff --git a/src/vs/workbench/electron-browser/workbench.ts b/src/vs/workbench/electron-browser/workbench.ts index b8bf77dc373..3d99ed4063b 100644 --- a/src/vs/workbench/electron-browser/workbench.ts +++ b/src/vs/workbench/electron-browser/workbench.ts @@ -53,6 +53,8 @@ import {IActivityService} from 'vs/workbench/services/activity/common/activitySe import {IViewletService} from 'vs/workbench/services/viewlet/common/viewletService'; import {FileService} from 'vs/workbench/services/files/electron-browser/fileService'; import {IFileService} from 'vs/platform/files/common/files'; +import {IConfigurationResolverService} from 'vs/workbench/services/configurationResolver/common/configurationResolver'; +import {ConfigurationResolverService} from 'vs/workbench/services/configurationResolver/node/configurationResolverService'; import {IPanelService} from 'vs/workbench/services/panel/common/panelService'; import {WorkbenchMessageService} from 'vs/workbench/services/message/browser/messageService'; import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService'; @@ -388,6 +390,10 @@ export class Workbench implements IPartService { // Configuration Editing serviceCollection.set(IConfigurationEditingService, this.instantiationService.createInstance(ConfigurationEditingService)); + // Configuration Resolver + const configurationResolverService = this.instantiationService.createInstance(ConfigurationResolverService); + serviceCollection.set(IConfigurationResolverService, configurationResolverService); + // Quick open service (quick open controller) this.quickOpen = this.instantiationService.createInstance(QuickOpenController); this.toDispose.push(this.quickOpen); diff --git a/src/vs/workbench/services/configurationResolver/common/configurationResolver.ts b/src/vs/workbench/services/configurationResolver/common/configurationResolver.ts new file mode 100644 index 00000000000..9aed75fd631 --- /dev/null +++ b/src/vs/workbench/services/configurationResolver/common/configurationResolver.ts @@ -0,0 +1,20 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import {IStringDictionary} from 'vs/base/common/collections'; +import {createDecorator} from 'vs/platform/instantiation/common/instantiation'; + +export const IConfigurationResolverService = createDecorator('configurationResolverService'); + +export interface IConfigurationResolverService { + _serviceBrand: any; + + resolve(value: string): string; + resolve(value: string[]): string[]; + resolve(value: IStringDictionary): IStringDictionary; + resolve(value: IStringDictionary): IStringDictionary; + resolve(value: IStringDictionary>): IStringDictionary>; + resolveAny(value: T): T; +} diff --git a/src/vs/workbench/services/configurationResolver/node/configurationResolverService.ts b/src/vs/workbench/services/configurationResolver/node/configurationResolverService.ts new file mode 100644 index 00000000000..ebd7109a841 --- /dev/null +++ b/src/vs/workbench/services/configurationResolver/node/configurationResolverService.ts @@ -0,0 +1,148 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as paths from 'vs/base/common/paths'; +import * as types from 'vs/base/common/types'; +import {IStringDictionary} from 'vs/base/common/collections'; +import {IConfigurationResolverService} from 'vs/workbench/services/configurationResolver/common/configurationResolver'; +import {IWorkspaceContextService} from 'vs/platform/workspace/common/workspace'; +import {IEnvironmentService} from 'vs/platform/environment/common/environment'; +import {IWorkbenchEditorService} from 'vs/workbench/services/editor/common/editorService'; +import {asFileEditorInput} from 'vs/workbench/common/editor'; + +export class ConfigurationResolverService implements IConfigurationResolverService { + _serviceBrand: any; + private _workspaceRoot: string; + private _execPath: string; + + constructor( + @IWorkbenchEditorService private editorService: IWorkbenchEditorService, + @IWorkspaceContextService private contextService: IWorkspaceContextService, + @IEnvironmentService private environmentService: IEnvironmentService + ) { + const workspace = contextService.getWorkspace(); + const fsPath = workspace ? workspace.resource.fsPath : ''; + this._workspaceRoot = paths.normalize(fsPath, true); + this._execPath = environmentService.execPath; + Object.keys(process.env).forEach(key => { + this[`env.${key}`] = process.env[key]; + }); + } + + private get execPath(): string { + return this._execPath; + } + + private get cwd(): string { + return this.workspaceRoot; + } + + private get workspaceRoot(): string { + return this._workspaceRoot; + } + + private get file(): string { + return this.getFilePath(); + } + + private get relativeFile(): string { + return (this.workspaceRoot) ? paths.relative(this.workspaceRoot, this.file) : this.file; + } + + private get fileBasename(): string { + return paths.basename(this.getFilePath()); + } + + private get fileDirname(): string { + return paths.dirname(this.getFilePath()); + } + + private get fileExtname(): string { + return paths.extname(this.getFilePath()); + } + + private getFilePath(): string { + let input = this.editorService.getActiveEditorInput(); + if (!input) { + return ''; + } + let fileEditorInput = asFileEditorInput(input); + if (!fileEditorInput) { + return ''; + } + let resource = fileEditorInput.getResource(); + return paths.normalize(resource.fsPath, true); + } + + public resolve(value: string): string; + public resolve(value: string[]): string[]; + public resolve(value: IStringDictionary): IStringDictionary; + public resolve(value: IStringDictionary): IStringDictionary; + public resolve(value: IStringDictionary>): IStringDictionary>; + public resolve(value: any): any { + if (types.isString(value)) { + return this.resolveString(value); + } else if (types.isArray(value)) { + return this.__resolveArray(value); + } else if (types.isObject(value)) { + return this.__resolveLiteral(value); + } + + return value; + } + + public resolveAny(value: T): T; + public resolveAny(value: any): any { + if (types.isString(value)) { + return this.resolveString(value); + } else if (types.isArray(value)) { + return this.__resolveAnyArray(value); + } else if (types.isObject(value)) { + return this.__resolveAnyLiteral(value); + } + + return value; + } + + protected resolveString(value: string): string { + let regexp = /\$\{(.*?)\}/g; + return value.replace(regexp, (match: string, name: string) => { + let newValue = (this)[name]; + if (types.isString(newValue)) { + return newValue; + } else { + return match && match.indexOf('env.') > 0 ? '' : match; + } + }); + } + + private __resolveLiteral(values: IStringDictionary | string[]>): IStringDictionary | string[]> { + let result: IStringDictionary | string[]> = Object.create(null); + Object.keys(values).forEach(key => { + let value = values[key]; + result[key] = this.resolve(value); + }); + return result; + } + + private __resolveAnyLiteral(values: T): T; + private __resolveAnyLiteral(values: any): any { + let result: IStringDictionary | string[]> = Object.create(null); + Object.keys(values).forEach(key => { + let value = values[key]; + result[key] = this.resolveAny(value); + }); + return result; + } + + private __resolveArray(value: string[]): string[] { + return value.map(s => this.resolveString(s)); + } + + private __resolveAnyArray(value: T[]): T[]; + private __resolveAnyArray(value: any[]): any[] { + return value.map(s => this.resolveAny(s)); + } +} diff --git a/src/vs/workbench/services/configurationResolver/test/node/configurationResolverService.test.ts b/src/vs/workbench/services/configurationResolver/test/node/configurationResolverService.test.ts new file mode 100644 index 00000000000..cdd8f723993 --- /dev/null +++ b/src/vs/workbench/services/configurationResolver/test/node/configurationResolverService.test.ts @@ -0,0 +1,12 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import assert = require('assert'); + +suite('Configuration Resolver Service', () => { + test('fake', () => { + assert.equal(true, true); + }); +});