Skip to content

Commit

Permalink
refactor variable resolving
Browse files Browse the repository at this point in the history
  • Loading branch information
weinand committed Jun 13, 2018
1 parent 2d45960 commit cb0f976
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 136 deletions.
49 changes: 13 additions & 36 deletions src/vs/workbench/api/node/extHostDebugService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,12 @@ import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/node/extHostDocumen
import { IAdapterExecutable, ITerminalSettings, IDebuggerContribution, IConfig, IDebugAdapter } from 'vs/workbench/parts/debug/common/debug';
import { getTerminalLauncher, hasChildprocesses, prepareCommand } from 'vs/workbench/parts/debug/node/terminals';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { VariableResolver } from 'vs/workbench/services/configurationResolver/node/variableResolver';
import { IStringDictionary } from 'vs/base/common/collections';
import { AbstractVariableResolverService } from 'vs/workbench/services/configurationResolver/node/variableResolver';
import { ExtHostConfiguration } from './extHostConfiguration';
import { convertToVSCPaths, convertToDAPaths } from 'vs/workbench/parts/debug/common/debugUtils';
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
import { ExtHostTerminalService } from 'vs/workbench/api/node/extHostTerminalService';
import { IDisposable } from 'vs/base/common/lifecycle';
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';


export class ExtHostDebugService implements ExtHostDebugServiceShape {
Expand Down Expand Up @@ -176,7 +175,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
throw new Error('Not implemented');
}
};
return asWinJsPromise(token => DebugAdapter.substituteVariables(ws, config, this._variableResolver));
return asWinJsPromise(token => this._variableResolver.resolveAny(ws, config));
}

public $startDASession(handle: number, debugType: string, adpaterExecutable: IAdapterExecutable | null, debugPort: number): TPromise<void> {
Expand Down Expand Up @@ -588,32 +587,29 @@ export class ExtHostDebugConsole implements vscode.DebugConsole {
}
}

export class ExtHostVariableResolverService implements IConfigurationResolverService {

_serviceBrand: any;
_variableResolver: VariableResolver;
export class ExtHostVariableResolverService extends AbstractVariableResolverService {

constructor(workspace: ExtHostWorkspace, editors: ExtHostDocumentsAndEditors, configuration: ExtHostConfiguration) {
this._variableResolver = new VariableResolver({
constructor(workspaceService: ExtHostWorkspace, editorService: ExtHostDocumentsAndEditors, configurationService: ExtHostConfiguration) {
super({
getFolderUri: (folderName: string): URI => {
const folders = workspace.getWorkspaceFolders();
const folders = workspaceService.getWorkspaceFolders();
const found = folders.filter(f => f.name === folderName);
if (found && found.length > 0) {
return found[0].uri;
}
return undefined;
},
getWorkspaceFolderCount: (): number => {
return workspace.getWorkspaceFolders().length;
return workspaceService.getWorkspaceFolders().length;
},
getConfigurationValue: (folderUri: URI, section: string) => {
return configuration.getConfiguration(undefined, folderUri).get<string>(section);
return configurationService.getConfiguration(undefined, folderUri).get<string>(section);
},
getExecPath: (): string | undefined => {
return undefined; // does not exist in EH
},
getFilePath: (): string | undefined => {
const activeEditor = editors.activeEditor();
const activeEditor = editorService.activeEditor();
if (activeEditor) {
const resource = activeEditor.document.uri;
if (resource.scheme === Schemas.file) {
Expand All @@ -623,38 +619,19 @@ export class ExtHostVariableResolverService implements IConfigurationResolverSer
return undefined;
},
getSelectedText: (): string | undefined => {
const activeEditor = editors.activeEditor();
const activeEditor = editorService.activeEditor();
if (activeEditor && !activeEditor.selection.isEmpty) {
return activeEditor.document.getText(activeEditor.selection);
}
return undefined;
},
getLineNumber: (): string => {
const activeEditor = editors.activeEditor();
const activeEditor = editorService.activeEditor();
if (activeEditor) {
return String(activeEditor.selection.end.line + 1);
}
return undefined;
}
}, process.env);
}

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 {
return this._variableResolver.resolveAny(root ? root.uri : undefined, value);
}

public resolveAny<T>(root: IWorkspaceFolder, value: T, commandMapping?: IStringDictionary<string>): T {
return this._variableResolver.resolveAny(root ? root.uri : undefined, value, commandMapping);
}

public executeCommandVariables(configuration: any, variables: IStringDictionary<string>): TPromise<IStringDictionary<string>> {
throw new Error('findAndExecuteCommandVariables not implemented.');
}

public resolveWithCommands(folder: IWorkspaceFolder, config: any): TPromise<any> {
throw new Error('resolveWithCommands not implemented.');
});
}
}
27 changes: 1 addition & 26 deletions src/vs/workbench/parts/debug/node/debugAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { ExtensionsChannelId } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { IOutputService } from 'vs/workbench/parts/output/common/output';
import { IDebugAdapter, IAdapterExecutable, IDebuggerContribution, IPlatformSpecificAdapterContribution, IConfig } from 'vs/workbench/parts/debug/common/debug';
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { IStringDictionary } from 'vs/base/common/collections';
import { IDebugAdapter, IAdapterExecutable, IDebuggerContribution, IPlatformSpecificAdapterContribution } from 'vs/workbench/parts/debug/common/debug';

/**
* Abstract implementation of the low level API for a debug adapter.
Expand Down Expand Up @@ -440,26 +437,4 @@ export class DebugAdapter extends StreamDebugAdapter {
};
}
}

static substituteVariables(workspaceFolder: IWorkspaceFolder, config: IConfig, resolverService: IConfigurationResolverService, commandValueMapping?: IStringDictionary<string>): IConfig {

const result = objects.deepClone(config) as IConfig;

// hoist platform specific attributes to top level
if (platform.isWindows && result.windows) {
Object.keys(result.windows).forEach(key => result[key] = result.windows[key]);
} else if (platform.isMacintosh && result.osx) {
Object.keys(result.osx).forEach(key => result[key] = result.osx[key]);
} else if (platform.isLinux && result.linux) {
Object.keys(result.linux).forEach(key => result[key] = result.linux[key]);
}

// delete all platform specific sections
delete result.windows;
delete result.osx;
delete result.linux;

// substitute all variables in string values
return resolverService.resolveAny(workspaceFolder, result, commandValueMapping);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,20 @@ export const IConfigurationResolverService = createDecorator<IConfigurationResol
export interface IConfigurationResolverService {
_serviceBrand: any;

resolve(root: IWorkspaceFolder, value: string): string;
resolve(root: IWorkspaceFolder, value: string[]): string[];
resolve(root: IWorkspaceFolder, value: IStringDictionary<string>): IStringDictionary<string>;
resolveAny<T>(root: IWorkspaceFolder, value: T, commandMapping?: IStringDictionary<string>): T;
resolve(folder: IWorkspaceFolder, value: string): string;
resolve(folder: IWorkspaceFolder, value: string[]): string[];
resolve(folder: IWorkspaceFolder, value: IStringDictionary<string>): IStringDictionary<string>;

/**
* Recursively resolves all variables in the given config and returns a copy of it with substituted values.
* Command variables are only substituted if a "commandValueMapping" dictionary is given and if it contains an entry for the command.
*/
resolveAny(folder: IWorkspaceFolder, config: any, commandValueMapping?: IStringDictionary<string>): any;

/**
* Recursively resolves all variables (including commands) in the given config and returns a copy of it with substituted values.
* If a "variables" dictionary (with names -> command ids) is given,
* command variables are first mapped through it before being resolved.
*/
resolveWithCommands(folder: IWorkspaceFolder, config: any, variables?: IStringDictionary<string>): TPromise<any>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,22 @@ import uri from 'vs/base/common/uri';
import * as nls from 'vs/nls';
import * as paths from 'vs/base/common/paths';
import * as platform from 'vs/base/common/platform';
import * as objects from 'vs/base/common/objects';
import { Schemas } from 'vs/base/common/network';
import { TPromise } from 'vs/base/common/winjs.base';
import { sequence } from 'vs/base/common/async';
import { toResource } from 'vs/workbench/common/editor';
import { IStringDictionary, size } from 'vs/base/common/collections';
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
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, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { VariableResolver } from 'vs/workbench/services/configurationResolver/node/variableResolver';
import { AbstractVariableResolverService } from 'vs/workbench/services/configurationResolver/node/variableResolver';
import { isCodeEditor } from 'vs/editor/browser/editorBrowser';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { isUndefinedOrNull } from 'vs/base/common/types';

export class ConfigurationResolverService implements IConfigurationResolverService {

_serviceBrand: any;
private resolver: VariableResolver;
export class ConfigurationResolverService extends AbstractVariableResolverService {

constructor(
envVariables: platform.IProcessEnvironment,
Expand All @@ -37,7 +32,7 @@ export class ConfigurationResolverService implements IConfigurationResolverServi
@ICommandService private commandService: ICommandService,
@IWorkspaceContextService workspaceContextService: IWorkspaceContextService
) {
this.resolver = new VariableResolver({
super({
getFolderUri: (folderName: string): uri => {
const folder = workspaceContextService.getWorkspace().folders.filter(f => f.name === folderName).pop();
return folder ? folder.uri : undefined;
Expand Down Expand Up @@ -84,21 +79,10 @@ export class ConfigurationResolverService implements IConfigurationResolverServi
}, envVariables);
}

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 {
return this.resolver.resolveAny(root ? root.uri : undefined, value);
}

public resolveAny(root: IWorkspaceFolder, value: any, commandValueMapping?: IStringDictionary<string>): any {
return this.resolver.resolveAny(root ? root.uri : undefined, value, commandValueMapping);
}

public resolveWithCommands(folder: IWorkspaceFolder, config: any, variables?: IStringDictionary<string>): TPromise<any> {

// then substitute remaining variables in VS Code core
config = this.substituteVariables(folder, config);
config = this.resolveAny(folder, config);

// now evaluate command variables (which might have a UI)
return this.executeCommandVariables(config, variables).then(commandValueMapping => {
Expand All @@ -109,37 +93,18 @@ export class ConfigurationResolverService implements IConfigurationResolverServi

// finally substitute evaluated command variables (if there are any)
if (size<string>(commandValueMapping) > 0) {
return this.substituteVariables(folder, config, commandValueMapping);
return this.resolveAny(folder, config, commandValueMapping);
} else {
return config;
}
});
}

private substituteVariables(workspaceFolder: IWorkspaceFolder, config: any, commandValueMapping?: IStringDictionary<string>): any {

const result = objects.deepClone(config) as any;

// hoist platform specific attributes to top level
if (platform.isWindows && result.windows) {
Object.keys(result.windows).forEach(key => result[key] = result.windows[key]);
} else if (platform.isMacintosh && result.osx) {
Object.keys(result.osx).forEach(key => result[key] = result.osx[key]);
} else if (platform.isLinux && result.linux) {
Object.keys(result.linux).forEach(key => result[key] = result.linux[key]);
}

// delete all platform specific sections
delete result.windows;
delete result.osx;
delete result.linux;

// substitute all variables in string values
return this.resolveAny(workspaceFolder, result, commandValueMapping);
}

/**
* Finds and executes all command variables (see #6569)
* Finds and executes all command variables in the given configuration and returns their values as a dictionary.
* Please note: this method does not substitute the command variables (so the configuration is not modified).
* The returned dictionary can be passed to "resolvePlatform" for the substitution.
* See #6569.
*/
private executeCommandVariables(configuration: any, variableToCommandMap: IStringDictionary<string>): TPromise<IStringDictionary<string>> {

Expand Down
Loading

0 comments on commit cb0f976

Please sign in to comment.