Merge VS Code 1.31.1 (#4283)

This commit is contained in:
Matt Irvine
2019-03-15 13:09:45 -07:00
committed by GitHub
parent 7d31575149
commit 86bac90001
1716 changed files with 53308 additions and 48375 deletions

View File

@@ -3,7 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { TPromise } from 'vs/base/common/winjs.base';
import { IStringDictionary } from 'vs/base/common/collections';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
@@ -26,29 +25,39 @@ export interface IConfigurationResolverService {
/**
* Recursively resolves all variables (including commands and user input) 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.
* @param folder
* @param config
*
* @param section For example, 'tasks' or 'debug'. Used for resolving inputs.
* @param variables Aliases for commands.
*/
resolveWithInteractionReplace(folder: IWorkspaceFolder, config: any, section?: string, variables?: IStringDictionary<string>): TPromise<any>;
resolveWithInteractionReplace(folder: IWorkspaceFolder, config: any, section?: string, variables?: IStringDictionary<string>): Promise<any>;
/**
* Similar to resolveWithInteractionReplace, except without the replace. Returns a map of variables and their resolution.
* Keys in the map will be of the format input:variableName or command:variableName.
*/
resolveWithInteraction(folder: IWorkspaceFolder, config: any, section?: string, variables?: IStringDictionary<string>): TPromise<Map<string, string>>;
resolveWithInteraction(folder: IWorkspaceFolder, config: any, section?: string, variables?: IStringDictionary<string>): Promise<Map<string, string>>;
}
export const enum ConfiguredInputType {
PromptString,
PickString
}
export interface ConfiguredInput {
export interface PromptStringInputInfo {
id: string;
type: 'promptString';
description: string;
default?: string;
type: ConfiguredInputType;
options?: string[];
}
}
export interface PickStringInputInfo {
id: string;
type: 'pickString';
description: string;
options: string[];
default?: string;
}
export interface CommandInputInfo {
id: string;
type: 'command';
command: string;
args?: any;
}
export type ConfiguredInput = PromptStringInputInfo | PickStringInputInfo | CommandInputInfo;

View File

@@ -5,41 +5,109 @@
import * as nls from 'vs/nls';
import { IJSONSchema } from 'vs/base/common/jsonSchema';
const idDescription = nls.localize('JsonSchema.input.id', "The input's id is used to associate an input with a variable of the form ${input:id}.");
const typeDescription = nls.localize('JsonSchema.input.type', "The type of user input prompt to use.");
const descriptionDescription = nls.localize('JsonSchema.input.description', "The description is shown when the user is prompted for input.");
const defaultDescription = nls.localize('JsonSchema.input.default', "The default value for the input.");
export const inputsSchema: IJSONSchema = {
definitions: {
inputs: {
type: 'array',
description: nls.localize('JsonSchema.inputs', 'User inputs. Used for defining user input prompts, such as free string input or a choice from several options.'),
items: {
type: 'object',
required: ['id', 'type', 'description'],
additionalProperties: false,
properties: {
id: {
type: 'string',
description: nls.localize('JsonSchema.input.id', "The input\'s id is used to specify inputs as ${input:id}.")
oneOf: [
{
type: 'object',
required: ['id', 'type', 'description'],
additionalProperties: false,
properties: {
id: {
type: 'string',
description: idDescription
},
type: {
type: 'string',
description: typeDescription,
enum: ['promptString'],
enumDescriptions: [
nls.localize('JsonSchema.input.type.promptString', "The 'promptString' type opens an input box to ask the user for input."),
]
},
description: {
type: 'string',
description: descriptionDescription
},
default: {
type: 'string',
description: defaultDescription
},
}
},
type: {
type: 'string',
description: nls.localize('JsonSchema.input.type', 'The promptString type opens an input box to ask the user for input. The pickString type shows a selection list.'),
enum: ['promptString', 'pickString']
{
type: 'object',
required: ['id', 'type', 'description', 'options'],
additionalProperties: false,
properties: {
id: {
type: 'string',
description: idDescription
},
type: {
type: 'string',
description: typeDescription,
enum: ['pickString'],
enumDescriptions: [
nls.localize('JsonSchema.input.type.pickString', "The 'pickString' type shows a selection list."),
]
},
description: {
type: 'string',
description: descriptionDescription
},
default: {
type: 'string',
description: defaultDescription
},
options: {
type: 'array',
description: nls.localize('JsonSchema.input.options', 'An array of strings that defines the options for a quick pick.'),
items: {
type: 'string'
}
}
}
},
description: {
type: 'string',
description: nls.localize('JsonSchema.input.description', 'The description is shown when the user is prompted for input.'),
},
default: {
type: 'string',
description: nls.localize('JsonSchema.input.default', 'The default value for the input.'),
},
options: {
type: 'array',
description: nls.localize('JsonSchema.input.options', 'An array of strings that defines the options for a quick pick.'),
items: {
type: 'string'
{
type: 'object',
required: ['id', 'type', 'command'],
additionalProperties: false,
properties: {
id: {
type: 'string',
description: idDescription
},
type: {
type: 'string',
description: typeDescription,
enum: ['command'],
enumDescriptions: [
nls.localize('JsonSchema.input.type.command', "The 'command' type executes a command."),
]
},
command: {
type: 'string',
description: nls.localize('JsonSchema.input.command.command', "The command to execute for this input variable.")
},
args: {
type: 'object',
description: nls.localize('JsonSchema.input.command.args', "Optional arguments passed to the command.")
}
}
}
}
]
}
}
}

View File

@@ -7,11 +7,8 @@ import { URI as 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 * as Types from 'vs/base/common/types';
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, forEach, fromMap } from 'vs/base/common/collections';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
@@ -23,18 +20,20 @@ import { AbstractVariableResolverService } from 'vs/workbench/services/configura
import { isCodeEditor } from 'vs/editor/browser/editorBrowser';
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
import { IQuickInputService, IInputOptions, IQuickPickItem, IPickOptions } from 'vs/platform/quickinput/common/quickInput';
import { ConfiguredInput, ConfiguredInputType } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
import { ConfiguredInput } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
export class ConfigurationResolverService extends AbstractVariableResolverService {
static INPUT_OR_COMMAND_VARIABLES_PATTERN = /\${((input|command):(.*?))}/g;
constructor(
envVariables: platform.IProcessEnvironment,
@IEditorService editorService: IEditorService,
@IEnvironmentService environmentService: IEnvironmentService,
@IConfigurationService private configurationService: IConfigurationService,
@ICommandService private commandService: ICommandService,
@IWorkspaceContextService private workspaceContextService: IWorkspaceContextService,
@IQuickInputService private quickInputService: IQuickInputService
@IConfigurationService private readonly configurationService: IConfigurationService,
@ICommandService private readonly commandService: ICommandService,
@IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService,
@IQuickInputService private readonly quickInputService: IQuickInputService
) {
super({
getFolderUri: (folderName: string): uri => {
@@ -83,7 +82,7 @@ export class ConfigurationResolverService extends AbstractVariableResolverServic
}, envVariables);
}
public resolveWithInteractionReplace(folder: IWorkspaceFolder, config: any, section?: string, variables?: IStringDictionary<string>): TPromise<any> {
public resolveWithInteractionReplace(folder: IWorkspaceFolder, config: any, section?: string, variables?: IStringDictionary<string>): Promise<any> {
// resolve any non-interactive variables
config = this.resolveAny(folder, config);
@@ -100,26 +99,18 @@ export class ConfigurationResolverService extends AbstractVariableResolverServic
});
}
public resolveWithInteraction(folder: IWorkspaceFolder, config: any, section?: string, variables?: IStringDictionary<string>): TPromise<Map<string, string>> {
public resolveWithInteraction(folder: IWorkspaceFolder, config: any, section?: string, variables?: IStringDictionary<string>): Promise<Map<string, string>> {
// resolve any non-interactive variables
const resolved = this.resolveAnyMap(folder, config);
config = resolved.newConfig;
const allVariableMapping: Map<string, string> = resolved.resolvedVariables;
// resolve input variables in the order in which they are encountered
return this.resolveWithInputs(folder, config, section).then(inputMapping => {
if (!this.updateMapping(inputMapping, allVariableMapping)) {
return undefined;
}
// resolve commands in the order in which they are encountered
return this.resolveWithCommands(config, variables).then(commandMapping => {
if (!this.updateMapping(commandMapping, allVariableMapping)) {
return undefined;
}
// resolve input and command variables in the order in which they are encountered
return this.resolveWithInputAndCommands(folder, config, variables, section).then(inputOrCommandMapping => {
if (this.updateMapping(inputOrCommandMapping, allVariableMapping)) {
return allVariableMapping;
});
}
return undefined;
});
}
@@ -137,199 +128,163 @@ export class ConfigurationResolverService extends AbstractVariableResolverServic
}
/**
* 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.
* Finds and executes all input and command variables in the given configuration and returns their values as a dictionary.
* Please note: this method does not substitute the input or command variables (so the configuration is not modified).
* The returned dictionary can be passed to "resolvePlatform" for the actual substitution.
* See #6569.
* @param configuration
*
* @param variableToCommandMap Aliases for commands
*/
private resolveWithCommands(configuration: any, variableToCommandMap: IStringDictionary<string>): TPromise<IStringDictionary<string>> {
private async resolveWithInputAndCommands(folder: IWorkspaceFolder, configuration: any, variableToCommandMap: IStringDictionary<string>, section: string): Promise<IStringDictionary<string>> {
if (!configuration) {
return TPromise.as(undefined);
}
// use an array to preserve order of first appearance
const cmd_var = /\${command:(.*?)}/g;
const commands: string[] = [];
this.findVariables(cmd_var, configuration, commands);
let cancelled = false;
const commandValueMapping: IStringDictionary<string> = Object.create(null);
const factory: { (): TPromise<any> }[] = commands.map(commandVariable => {
return () => {
let commandId = variableToCommandMap ? variableToCommandMap[commandVariable] : undefined;
if (!commandId) {
// Just launch any command if the interactive variable is not contributed by the adapter #12735
commandId = commandVariable;
}
return this.commandService.executeCommand<string>(commandId, configuration).then(result => {
if (typeof result === 'string') {
commandValueMapping['command:' + commandVariable] = result;
} else if (Types.isUndefinedOrNull(result)) {
cancelled = true;
} else {
throw new Error(nls.localize('stringsOnlySupported', "Command '{0}' did not return a string result. Only strings are supported as results for commands used for variable substitution.", commandVariable));
}
});
};
});
return sequence(factory).then(() => cancelled ? undefined : commandValueMapping);
}
/**
* Resolves all inputs in a configuration and returns a map that maps the unresolved input to the resolved input.
* Does not do replacement of inputs.
* @param folder
* @param config
* @param section
*/
public resolveWithInputs(folder: IWorkspaceFolder, config: any, section: string): Promise<IStringDictionary<string>> {
if (!config) {
return Promise.resolve(undefined);
} else if (folder && section) {
// Get all the possible inputs
let result = this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY
? Objects.deepClone(this.configurationService.getValue<any>(section, { resource: folder.uri }))
: undefined;
let inputsArray = result ? this.parseConfigurationInputs(result.inputs) : undefined;
const inputs = new Map<string, ConfiguredInput>();
if (inputsArray) {
inputsArray.forEach(input => {
inputs.set(input.id, input);
});
}
// use an array to preserve order of first appearance
const input_var = /\${input:(.*?)}/g;
const commands: string[] = [];
this.findVariables(input_var, config, commands);
let cancelled = false;
const commandValueMapping: IStringDictionary<string> = Object.create(null);
const factory: { (): Promise<any> }[] = commands.map(commandVariable => {
return () => {
return this.showUserInput(commandVariable, inputs).then(resolvedValue => {
if (resolvedValue) {
commandValueMapping['input:' + commandVariable] = resolvedValue;
} else {
cancelled = true;
}
});
};
}, reason => {
return Promise.reject(reason);
});
return sequence(factory).then(() => cancelled ? undefined : commandValueMapping);
// get all "inputs"
let inputs: ConfiguredInput[] = undefined;
if (folder && this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY) {
let result = this.configurationService.getValue<any>(section, { resource: folder.uri });
if (result) {
inputs = result.inputs;
}
}
return Promise.resolve(Object.create(null));
}
// extract and dedupe all "input" and "command" variables and preserve their order in an array
const variables: string[] = [];
this.findVariables(configuration, variables);
/**
* Takes the provided input info and shows the quick pick so the user can provide the value for the input
* @param commandVariable Name of the input.
* @param inputs Information about each possible input.
* @param commandValueMapping
*/
private showUserInput(commandVariable: string, inputs: Map<string, ConfiguredInput>): Promise<string> {
if (inputs && inputs.has(commandVariable)) {
const input = inputs.get(commandVariable);
if (input.type === ConfiguredInputType.PromptString) {
let inputOptions: IInputOptions = { prompt: input.description };
if (input.default) {
inputOptions.value = input.default;
}
const variableValues: IStringDictionary<string> = Object.create(null);
return this.quickInputService.input(inputOptions).then(resolvedInput => {
return resolvedInput ? resolvedInput : undefined;
});
} else { // input.type === ConfiguredInputType.pick
let picks = new Array<IQuickPickItem>();
if (input.options) {
input.options.forEach(pickOption => {
let item: IQuickPickItem = { label: pickOption };
if (input.default && (pickOption === input.default)) {
item.description = nls.localize('defaultInputValue', "Default");
picks.unshift(item);
} else {
picks.push(item);
}
});
}
let pickOptions: IPickOptions<IQuickPickItem> = { placeHolder: input.description };
return this.quickInputService.pick(picks, pickOptions, undefined).then(resolvedInput => {
return resolvedInput ? resolvedInput.label : undefined;
});
for (const variable of variables) {
const [type, name] = variable.split(':', 2);
let result: string | undefined | null;
switch (type) {
case 'input':
result = await this.showUserInput(name, inputs);
break;
case 'command':
// use the name as a command ID #12735
const commandId = (variableToCommandMap ? variableToCommandMap[name] : undefined) || name;
result = await this.commandService.executeCommand(commandId, configuration);
if (typeof result !== 'string' && !Types.isUndefinedOrNull(result)) {
throw new Error(nls.localize('commandVariable.noStringType', "Cannot substitute command variable '{0}' because command did not return a result of type string.", commandId));
}
break;
}
if (typeof result === 'string') {
variableValues[variable] = result;
} else {
return undefined;
}
}
return Promise.reject(new Error(nls.localize('undefinedInputVariable', "Undefined input variable {0} encountered. Remove or define {0} to continue.", commandVariable)));
return variableValues;
}
/**
* Finds all variables in object using cmdVar and pushes them into commands.
* @param cmdVar Regex to use for finding variables.
* Recursively finds all command or input variables in object and pushes them into variables.
* @param object object is searched for variables.
* @param commands All found variables are returned in commands.
* @param variables All found variables are returned in variables.
*/
private findVariables(cmdVar: RegExp, object: any, commands: string[]) {
if (!object) {
return;
} else if (typeof object === 'string') {
private findVariables(object: any, variables: string[]) {
if (typeof object === 'string') {
let matches;
while ((matches = cmdVar.exec(object)) !== null) {
if (matches.length === 2) {
while ((matches = ConfigurationResolverService.INPUT_OR_COMMAND_VARIABLES_PATTERN.exec(object)) !== null) {
if (matches.length === 4) {
const command = matches[1];
if (commands.indexOf(command) < 0) {
commands.push(command);
if (variables.indexOf(command) < 0) {
variables.push(command);
}
}
}
} else if (Types.isArray(object)) {
object.forEach(value => {
this.findVariables(cmdVar, value, commands);
this.findVariables(value, variables);
});
} else {
} else if (object) {
Object.keys(object).forEach(key => {
const value = object[key];
this.findVariables(cmdVar, value, commands);
this.findVariables(value, variables);
});
}
}
/**
* Converts an array of inputs into an actaul array of typed, ConfiguredInputs.
* @param object Array of something that should look like inputs.
* Takes the provided input info and shows the quick pick so the user can provide the value for the input
* @param variable Name of the input variable.
* @param inputInfos Information about each possible input variable.
*/
private parseConfigurationInputs(object: any[]): ConfiguredInput[] | undefined {
let inputs = new Array<ConfiguredInput>();
if (object) {
object.forEach(item => {
if (Types.isString(item.id) && Types.isString(item.description) && Types.isString(item.type)) {
let type: ConfiguredInputType;
switch (item.type) {
case 'promptString': type = ConfiguredInputType.PromptString; break;
case 'pickString': type = ConfiguredInputType.PickString; break;
default: {
throw new Error(nls.localize('unknownInputTypeProvided', "Input '{0}' can only be of type 'promptString' or 'pickString'.", item.id));
}
}
let options: string[];
if (type === ConfiguredInputType.PickString) {
if (Types.isStringArray(item.options)) {
options = item.options;
} else {
throw new Error(nls.localize('pickStringRequiresOptions', "Input '{0}' is of type 'pickString' and must include 'options'.", item.id));
}
}
inputs.push({ id: item.id, description: item.description, type, default: item.default, options });
}
});
}
private showUserInput(variable: string, inputInfos: ConfiguredInput[]): Promise<string> {
return inputs;
// find info for the given input variable
const info = inputInfos.filter(item => item.id === variable).pop();
if (info) {
const missingAttribute = (attrName: string) => {
throw new Error(nls.localize('inputVariable.missingAttribute', "Input variable '{0}' is of type '{1}' and must include '{2}'.", variable, info.type, attrName));
};
switch (info.type) {
case 'promptString': {
if (!Types.isString(info.description)) {
missingAttribute('description');
}
const inputOptions: IInputOptions = { prompt: info.description };
if (info.default) {
inputOptions.value = info.default;
}
return this.quickInputService.input(inputOptions).then(resolvedInput => {
return resolvedInput ? resolvedInput : undefined;
});
}
case 'pickString': {
if (!Types.isString(info.description)) {
missingAttribute('description');
}
if (!Types.isStringArray(info.options)) {
missingAttribute('options');
}
const picks = new Array<IQuickPickItem>();
info.options.forEach(pickOption => {
const item: IQuickPickItem = { label: pickOption };
if (pickOption === info.default) {
item.description = nls.localize('inputVariable.defaultInputValue', "Default");
picks.unshift(item);
} else {
picks.push(item);
}
});
const pickOptions: IPickOptions<IQuickPickItem> = { placeHolder: info.description };
return this.quickInputService.pick(picks, pickOptions, undefined).then(resolvedInput => {
return resolvedInput ? resolvedInput.label : undefined;
});
}
case 'command': {
if (!Types.isString(info.command)) {
missingAttribute('command');
}
return this.commandService.executeCommand<string>(info.command, info.args).then(result => {
if (typeof result === 'string' || Types.isUndefinedOrNull(result)) {
return result;
}
throw new Error(nls.localize('inputVariable.command.noStringType', "Cannot substitute input variable '{0}' because command '{1}' did not return a result of type string.", variable, info.command));
});
}
default:
throw new Error(nls.localize('inputVariable.unknownType', "Input variable '{0}' can only be of type 'promptString', 'pickString', or 'command'.", variable));
}
}
return Promise.reject(new Error(nls.localize('inputVariable.undefinedVariable', "Undefined input variable '{0}' encountered. Remove or define '{0}' to continue.", variable)));
}
}

View File

@@ -14,7 +14,6 @@ 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 { TPromise } from 'vs/base/common/winjs.base';
export interface IVariableResolveContext {
getFolderUri(folderName: string): uri | undefined;
@@ -83,11 +82,11 @@ export class AbstractVariableResolverService implements IConfigurationResolverSe
return { newConfig, resolvedVariables };
}
public resolveWithInteractionReplace(folder: IWorkspaceFolder, config: any): TPromise<any> {
public resolveWithInteractionReplace(folder: IWorkspaceFolder, config: any): Promise<any> {
throw new Error('resolveWithInteractionReplace not implemented.');
}
public resolveWithInteraction(folder: IWorkspaceFolder, config: any): TPromise<any> {
public resolveWithInteraction(folder: IWorkspaceFolder, config: any): Promise<any> {
throw new Error('resolveWithInteraction not implemented.');
}

View File

@@ -416,6 +416,33 @@ suite('Configuration Resolver Service', () => {
assert.equal(0, mockCommandService.callCount);
});
});
test('a single command input variable', () => {
const configuration = {
'name': 'Attach to Process',
'type': 'node',
'request': 'attach',
'processId': '${input:input4}',
'port': 5858,
'sourceMaps': false,
'outDir': null
};
return configurationResolverService.resolveWithInteractionReplace(workspace, configuration, 'tasks').then(result => {
assert.deepEqual(result, {
'name': 'Attach to Process',
'type': 'node',
'request': 'attach',
'processId': 'arg for command',
'port': 5858,
'sourceMaps': false,
'outDir': null
});
assert.equal(1, mockCommandService.callCount);
});
});
test('several input variables and command', () => {
const configuration = {
@@ -423,6 +450,7 @@ suite('Configuration Resolver Service', () => {
'type': '${command:command1}',
'request': '${input:input1}',
'processId': '${input:input2}',
'command': '${input:input4}',
'port': 5858,
'sourceMaps': false,
'outDir': null
@@ -435,12 +463,13 @@ suite('Configuration Resolver Service', () => {
'type': 'command1-result',
'request': 'resolvedEnterinput1',
'processId': 'selectedPick',
'command': 'arg for command',
'port': 5858,
'sourceMaps': false,
'outDir': null
});
assert.equal(1, mockCommandService.callCount);
assert.equal(2, mockCommandService.callCount);
});
});
});
@@ -450,7 +479,7 @@ class MockConfigurationService implements IConfigurationService {
public _serviceBrand: any;
public serviceId = 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 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: undefined, folder: undefined }; }
public keys() { return { default: [], user: [], workspace: [], workspaceFolder: [] }; }
public getValue(): any;
public getValue(value: string): any;
@@ -495,9 +524,9 @@ class MockCommandService implements ICommandService {
class MockQuickInputService implements IQuickInputService {
_serviceBrand: any;
public pick<T extends IQuickPickItem>(picks: Thenable<QuickPickInput<T>[]> | QuickPickInput<T>[], options?: IPickOptions<T> & { canPickMany: true }, token?: CancellationToken): Promise<T[]>;
public pick<T extends IQuickPickItem>(picks: Thenable<QuickPickInput<T>[]> | QuickPickInput<T>[], options?: IPickOptions<T> & { canPickMany: false }, token?: CancellationToken): Promise<T>;
public pick<T extends IQuickPickItem>(picks: Thenable<QuickPickInput<T>[]> | QuickPickInput<T>[], options?: Omit<IPickOptions<T>, 'canPickMany'>, token?: CancellationToken): Promise<T> {
public pick<T extends IQuickPickItem>(picks: Promise<QuickPickInput<T>[]> | QuickPickInput<T>[], options?: IPickOptions<T> & { canPickMany: true }, token?: CancellationToken): Promise<T[]>;
public pick<T extends IQuickPickItem>(picks: Promise<QuickPickInput<T>[]> | QuickPickInput<T>[], options?: IPickOptions<T> & { canPickMany: false }, token?: CancellationToken): Promise<T>;
public pick<T extends IQuickPickItem>(picks: Promise<QuickPickInput<T>[]> | QuickPickInput<T>[], options?: Omit<IPickOptions<T>, 'canPickMany'>, token?: CancellationToken): Promise<T> {
if (Types.isArray(picks)) {
return Promise.resolve(<T>{ label: 'selectedPick', description: 'pick description' });
} else {
@@ -568,6 +597,14 @@ class MockInputsConfigurationService extends TestConfigurationService {
type: 'promptString',
description: 'Enterinput3',
default: 'default input3'
},
{
id: 'input4',
type: 'command',
command: 'command1',
args: {
value: 'arg for command'
}
}
]
};