diff --git a/src/vs/workbench/api/common/extHostDebugService.ts b/src/vs/workbench/api/common/extHostDebugService.ts index 1e1643ee414..b724e831cad 100644 --- a/src/vs/workbench/api/common/extHostDebugService.ts +++ b/src/vs/workbench/api/common/extHostDebugService.ts @@ -1032,7 +1032,7 @@ export class ExtHostVariableResolverService extends AbstractVariableResolverServ } return undefined; } - }, env, !editorService); + }, undefined, env, !editorService); } } diff --git a/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts b/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts index 7fc15ac3615..86f3644cf6f 100644 --- a/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts +++ b/src/vs/workbench/services/configurationResolver/browser/configurationResolverService.ts @@ -5,7 +5,6 @@ import { URI as uri } from 'vs/base/common/uri'; import * as nls from 'vs/nls'; -import * as path from 'vs/base/common/path'; import * as Types from 'vs/base/common/types'; import { Schemas } from 'vs/base/common/network'; import { toResource } from 'vs/workbench/common/editor'; @@ -22,6 +21,7 @@ import { IQuickInputService, IInputOptions, IQuickPickItem, IPickOptions } from import { ConfiguredInput, IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; import { IProcessEnvironment } from 'vs/base/common/platform'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; +import { ILabelService } from 'vs/platform/label/common/label'; export abstract class BaseConfigurationResolverService extends AbstractVariableResolverService { @@ -34,7 +34,8 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR private readonly configurationService: IConfigurationService, private readonly commandService: ICommandService, private readonly workspaceContextService: IWorkspaceContextService, - private readonly quickInputService: IQuickInputService + private readonly quickInputService: IQuickInputService, + private readonly labelService: ILabelService ) { super({ getFolderUri: (folderName: string): uri | undefined => { @@ -55,11 +56,11 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR if (activeEditor instanceof DiffEditorInput) { activeEditor = activeEditor.modifiedInput; } - const fileResource = toResource(activeEditor, { filterByScheme: [Schemas.file, Schemas.userData] }); + const fileResource = toResource(activeEditor, { filterByScheme: [Schemas.file, Schemas.userData, Schemas.vscodeRemote] }); if (!fileResource) { return undefined; } - return path.normalize(fileResource.fsPath); + return this.labelService.getUriLabel(fileResource); }, getSelectedText: (): string | undefined => { const activeTextEditorControl = editorService.activeTextEditorControl; @@ -83,7 +84,7 @@ export abstract class BaseConfigurationResolverService extends AbstractVariableR } return undefined; } - }, envVariables); + }, labelService, envVariables); } public async resolveWithInteractionReplace(folder: IWorkspaceFolder | undefined, config: any, section?: string, variables?: IStringDictionary, target?: ConfigurationTarget): Promise { @@ -347,9 +348,10 @@ export class ConfigurationResolverService extends BaseConfigurationResolverServi @IConfigurationService configurationService: IConfigurationService, @ICommandService commandService: ICommandService, @IWorkspaceContextService workspaceContextService: IWorkspaceContextService, - @IQuickInputService quickInputService: IQuickInputService + @IQuickInputService quickInputService: IQuickInputService, + @ILabelService labelService: ILabelService ) { - super({ getExecPath: () => undefined }, Object.create(null), editorService, configurationService, commandService, workspaceContextService, quickInputService); + super({ getExecPath: () => undefined }, Object.create(null), editorService, configurationService, commandService, workspaceContextService, quickInputService, labelService); } } diff --git a/src/vs/workbench/services/configurationResolver/common/variableResolver.ts b/src/vs/workbench/services/configurationResolver/common/variableResolver.ts index 2ad97f9bc33..e0b143610a7 100644 --- a/src/vs/workbench/services/configurationResolver/common/variableResolver.ts +++ b/src/vs/workbench/services/configurationResolver/common/variableResolver.ts @@ -14,6 +14,7 @@ import { localize } from 'vs/nls'; import { URI as uri } from 'vs/base/common/uri'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; +import { ILabelService } from 'vs/platform/label/common/label'; export interface IVariableResolveContext { getFolderUri(folderName: string): uri | undefined; @@ -32,12 +33,14 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe declare readonly _serviceBrand: undefined; private _context: IVariableResolveContext; + private _labelService?: ILabelService; private _envVariables?: IProcessEnvironment; protected _contributedVariables: Map Promise> = new Map(); - constructor(_context: IVariableResolveContext, _envVariables?: IProcessEnvironment, private _ignoreEditorVariables = false) { + constructor(_context: IVariableResolveContext, _labelService?: ILabelService, _envVariables?: IProcessEnvironment, private _ignoreEditorVariables = false) { this._context = _context; + this._labelService = _labelService; if (_envVariables) { if (isWindows) { // windows env variables are case insensitive @@ -140,6 +143,10 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe return replaced; } + private fsPath(displayUri: uri): string { + return this._labelService ? this._labelService.getUriLabel(displayUri) : displayUri.fsPath; + } + private evaluateSingleVariable(match: string, variable: string, folderUri: uri | undefined, commandValueMapping: IStringDictionary | undefined): string { // try to separate variable arguments from variable name @@ -221,14 +228,14 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe switch (variable) { case 'workspaceRoot': case 'workspaceFolder': - return normalizeDriveLetter(getFolderUri().fsPath); + return normalizeDriveLetter(this.fsPath(getFolderUri())); case 'cwd': - return ((folderUri || argument) ? normalizeDriveLetter(getFolderUri().fsPath) : process.cwd()); + return ((folderUri || argument) ? normalizeDriveLetter(this.fsPath(getFolderUri())) : process.cwd()); case 'workspaceRootFolderName': case 'workspaceFolderBasename': - return paths.basename(getFolderUri().fsPath); + return paths.basename(this.fsPath(getFolderUri())); case 'lineNumber': if (this._ignoreEditorVariables) { @@ -261,7 +268,7 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe return match; } if (folderUri || argument) { - return paths.normalize(paths.relative(getFolderUri().fsPath, getFilePath())); + return paths.relative(this.fsPath(getFolderUri()), getFilePath()); } return getFilePath(); @@ -271,7 +278,7 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe } const dirname = paths.dirname(getFilePath()); if (folderUri || argument) { - return paths.normalize(paths.relative(getFolderUri().fsPath, dirname)); + return paths.relative(this.fsPath(getFolderUri()), dirname); } return dirname; diff --git a/src/vs/workbench/services/configurationResolver/electron-sandbox/configurationResolverService.ts b/src/vs/workbench/services/configurationResolver/electron-sandbox/configurationResolverService.ts index 3d48987346a..a22d0c7cad8 100644 --- a/src/vs/workbench/services/configurationResolver/electron-sandbox/configurationResolverService.ts +++ b/src/vs/workbench/services/configurationResolver/electron-sandbox/configurationResolverService.ts @@ -15,6 +15,7 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IProcessEnvironment } from 'vs/base/common/platform'; import { BaseConfigurationResolverService } from 'vs/workbench/services/configurationResolver/browser/configurationResolverService'; import { process } from 'vs/base/parts/sandbox/electron-sandbox/globals'; +import { ILabelService } from 'vs/platform/label/common/label'; export class ConfigurationResolverService extends BaseConfigurationResolverService { @@ -24,13 +25,14 @@ export class ConfigurationResolverService extends BaseConfigurationResolverServi @IConfigurationService configurationService: IConfigurationService, @ICommandService commandService: ICommandService, @IWorkspaceContextService workspaceContextService: IWorkspaceContextService, - @IQuickInputService quickInputService: IQuickInputService + @IQuickInputService quickInputService: IQuickInputService, + @ILabelService labelService: ILabelService ) { super({ getExecPath: (): string | undefined => { return environmentService.execPath; } - }, process.env as IProcessEnvironment, editorService, configurationService, commandService, workspaceContextService, quickInputService); + }, process.env as IProcessEnvironment, editorService, configurationService, commandService, workspaceContextService, quickInputService, labelService); } } diff --git a/src/vs/workbench/services/configurationResolver/test/electron-browser/configurationResolverService.test.ts b/src/vs/workbench/services/configurationResolver/test/electron-browser/configurationResolverService.test.ts index 596eae837df..53d047f643f 100644 --- a/src/vs/workbench/services/configurationResolver/test/electron-browser/configurationResolverService.test.ts +++ b/src/vs/workbench/services/configurationResolver/test/electron-browser/configurationResolverService.test.ts @@ -4,18 +4,19 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { Event } from 'vs/base/common/event'; +import * as path from 'path'; +import { Emitter, Event } from 'vs/base/common/event'; import { URI as uri } from 'vs/base/common/uri'; import * as platform from 'vs/base/common/platform'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; import { BaseConfigurationResolverService } from 'vs/workbench/services/configurationResolver/browser/configurationResolverService'; -import { Workspace, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; +import { Workspace, IWorkspaceFolder, IWorkspace } from 'vs/platform/workspace/common/workspace'; import { TestEditorService } from 'vs/workbench/test/browser/workbenchTestServices'; import { TestWorkbenchConfiguration } from 'vs/workbench/test/electron-browser/workbenchTestServices'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; -import { Disposable } from 'vs/base/common/lifecycle'; +import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { IQuickInputService, IQuickPickItem, QuickPickInput, IPickOptions, Omit, IInputOptions, IQuickInputButton, IQuickPick, IInputBox, IQuickNavigateConfiguration } from 'vs/platform/quickinput/common/quickInput'; import { CancellationToken } from 'vs/base/common/cancellation'; import * as Types from 'vs/base/common/types'; @@ -24,6 +25,8 @@ import { Selection } from 'vs/editor/common/core/selection'; import { NativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-browser/environmentService'; import { TestContextService } from 'vs/workbench/test/common/workbenchTestServices'; import { testWorkspace } from 'vs/platform/workspace/test/common/testWorkspace'; +import { IFormatterChangeEvent, ILabelService, ResourceLabelFormatter } from 'vs/platform/label/common/label'; +import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; const mockLineNumber = 10; class TestEditorServiceWithActiveEditor extends TestEditorService { @@ -59,15 +62,17 @@ suite('Configuration Resolver Service', () => { let containingWorkspace: Workspace; let workspace: IWorkspaceFolder; let quickInputService: MockQuickInputService; + let labelService: MockLabelService; setup(() => { mockCommandService = new MockCommandService(); editorService = new TestEditorServiceWithActiveEditor(); quickInputService = new MockQuickInputService(); environmentService = new MockWorkbenchEnvironmentService(envVariables); + labelService = new MockLabelService(); containingWorkspace = testWorkspace(uri.parse('file:///VSCode/workspaceLocation')); workspace = containingWorkspace.folders[0]; - configurationResolverService = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, editorService, new MockInputsConfigurationService(), mockCommandService, new TestContextService(containingWorkspace), quickInputService); + configurationResolverService = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, editorService, new MockInputsConfigurationService(), mockCommandService, new TestContextService(containingWorkspace), quickInputService, labelService); }); teardown(() => { @@ -202,7 +207,7 @@ suite('Configuration Resolver Service', () => { } }); - let service = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService); + let service = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService); assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} xyz'), 'abc foo xyz'); }); @@ -219,7 +224,7 @@ suite('Configuration Resolver Service', () => { } }); - let service = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService); + let service = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService); assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${config:terminal.integrated.fontFamily} xyz'), 'abc foo bar xyz'); }); @@ -236,7 +241,7 @@ suite('Configuration Resolver Service', () => { } }); - let service = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService); + let service = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService); if (platform.isWindows) { assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${workspaceFolder} ${env:key1} xyz'), 'abc foo \\VSCode\\workspaceLocation Value for key1 xyz'); } else { @@ -257,7 +262,7 @@ suite('Configuration Resolver Service', () => { } }); - let service = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService); + let service = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService); 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'); } else { @@ -291,7 +296,7 @@ suite('Configuration Resolver Service', () => { } }); - let service = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService); + let service = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService); assert.strictEqual(service.resolve(workspace, 'abc ${config:editor.fontFamily} ${config:editor.lineNumbers} ${config:editor.insertSpaces} xyz'), 'abc foo 123 false xyz'); }); @@ -301,7 +306,7 @@ suite('Configuration Resolver Service', () => { editor: {} }); - let service = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService); + let service = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService); assert.strictEqual(service.resolve(workspace, 'abc ${unknownVariable} xyz'), 'abc ${unknownVariable} xyz'); assert.strictEqual(service.resolve(workspace, 'abc ${env:unknownVariable} xyz'), 'abc xyz'); }); @@ -314,7 +319,7 @@ suite('Configuration Resolver Service', () => { } }); - let service = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService); + let service = new TestConfigurationResolverService({ getExecPath: () => undefined }, environmentService.userEnv, new TestEditorServiceWithActiveEditor(), configurationService, mockCommandService, new TestContextService(), quickInputService, labelService); assert.throws(() => service.resolve(workspace, 'abc ${env} xyz')); assert.throws(() => service.resolve(workspace, 'abc ${env:} xyz')); @@ -647,6 +652,29 @@ class MockQuickInputService implements IQuickInputService { } } +class MockLabelService implements ILabelService { + _serviceBrand: undefined; + getUriLabel(resource: uri, options?: { relative?: boolean | undefined; noPrefix?: boolean | undefined; endWithSeparator?: boolean | undefined; }): string { + return path.normalize(resource.fsPath); + } + getUriBasenameLabel(resource: uri): string { + throw new Error('Method not implemented.'); + } + getWorkspaceLabel(workspace: uri | IWorkspaceIdentifier | IWorkspace, options?: { verbose: boolean; }): string { + throw new Error('Method not implemented.'); + } + getHostLabel(scheme: string, authority?: string): string { + throw new Error('Method not implemented.'); + } + getSeparator(scheme: string, authority?: string): '/' | '\\' { + throw new Error('Method not implemented.'); + } + registerFormatter(formatter: ResourceLabelFormatter): IDisposable { + throw new Error('Method not implemented.'); + } + onDidChangeFormatters: Event = new Emitter().event; +} + class MockInputsConfigurationService extends TestConfigurationService { public getValue(arg1?: any, arg2?: any): any { let configuration;