mirror of
https://github.com/microsoft/vscode.git
synced 2026-09-28 08:04:00 +01:00
Better variable resolve on remote
Part of microsoft/vscode-remote-release#2619
This commit is contained in:
@@ -1032,7 +1032,7 @@ export class ExtHostVariableResolverService extends AbstractVariableResolverServ
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}, env, !editorService);
|
||||
}, undefined, env, !editorService);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
-7
@@ -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<string>, target?: ConfigurationTarget): Promise<any> {
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<string, () => Promise<string | undefined>> = 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<string> | 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;
|
||||
|
||||
|
||||
+4
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+39
-11
@@ -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<IFormatterChangeEvent> = new Emitter<IFormatterChangeEvent>().event;
|
||||
}
|
||||
|
||||
class MockInputsConfigurationService extends TestConfigurationService {
|
||||
public getValue(arg1?: any, arg2?: any): any {
|
||||
let configuration;
|
||||
|
||||
Reference in New Issue
Block a user