diff --git a/editors/code/src/tasks.ts b/editors/code/src/tasks.ts index fa1c4a951dd..1366c76d6bd 100644 --- a/editors/code/src/tasks.ts +++ b/editors/code/src/tasks.ts @@ -4,49 +4,80 @@ import * as vscode from 'vscode'; // our configuration should be compatible with it so use the same key. const TASK_TYPE = 'cargo'; -export function activateTaskProvider(target: vscode.WorkspaceFolder): vscode.Disposable { - const provider: vscode.TaskProvider = { +interface CargoTaskDefinition extends vscode.TaskDefinition { + command?: string; + args?: string[]; + cwd?: string; + env?: { [key: string]: string }; +} + +class CargoTaskProvider implements vscode.TaskProvider { + private readonly target: vscode.WorkspaceFolder; + + constructor(target: vscode.WorkspaceFolder) { + this.target = target; + } + + provideTasks(): vscode.Task[] { // Detect Rust tasks. Currently we do not do any actual detection // of tasks (e.g. aliases in .cargo/config) and just return a fixed // set of tasks that always exist. These tasks cannot be removed in // tasks.json - only tweaked. - provideTasks: () => getStandardCargoTasks(target), - // We don't need to implement this. - resolveTask: () => undefined, - }; + return [ + { command: 'build', group: vscode.TaskGroup.Build }, + { command: 'check', group: vscode.TaskGroup.Build }, + { command: 'test', group: vscode.TaskGroup.Test }, + { command: 'clean', group: vscode.TaskGroup.Clean }, + { command: 'run', group: undefined }, + ] + .map(({ command, group }) => { + const vscodeTask = new vscode.Task( + // The contents of this object end up in the tasks.json entries. + { + type: TASK_TYPE, + command, + }, + // The scope of the task - workspace or specific folder (global + // is not supported). + this.target, + // The task name, and task source. These are shown in the UI as + // `${source}: ${name}`, e.g. `rust: cargo build`. + `cargo ${command}`, + 'rust', + // What to do when this command is executed. + new vscode.ShellExecution('cargo', [command]), + // Problem matchers. + ['$rustc'], + ); + vscodeTask.group = group; + return vscodeTask; + }); + } - return vscode.tasks.registerTaskProvider(TASK_TYPE, provider); -} + resolveTask(task: vscode.Task): vscode.Task | undefined { + // VSCode calls this for every cargo task in the user's tasks.json, + // we need to inform VSCode how to execute that command by creating + // a ShellExecution for it. -function getStandardCargoTasks(target: vscode.WorkspaceFolder): vscode.Task[] { - return [ - { command: 'build', group: vscode.TaskGroup.Build }, - { command: 'check', group: vscode.TaskGroup.Build }, - { command: 'test', group: vscode.TaskGroup.Test }, - { command: 'clean', group: vscode.TaskGroup.Clean }, - { command: 'run', group: undefined }, - ] - .map(({ command, group }) => { - const vscodeTask = new vscode.Task( - // The contents of this object end up in the tasks.json entries. - { - type: TASK_TYPE, - command, - }, - // The scope of the task - workspace or specific folder (global - // is not supported). - target, - // The task name, and task source. These are shown in the UI as - // `${source}: ${name}`, e.g. `rust: cargo build`. - `cargo ${command}`, + const definition = task.definition as CargoTaskDefinition; + + if (definition.type === 'cargo' && definition.command) { + const args = [definition.command].concat(definition.args ?? []); + + return new vscode.Task( + definition, + task.name, 'rust', - // What to do when this command is executed. - new vscode.ShellExecution('cargo', [command]), - // Problem matchers. - ['$rustc'], + new vscode.ShellExecution('cargo', args, definition), ); - vscodeTask.group = group; - return vscodeTask; - }); + } + + return undefined; + } } + +export function activateTaskProvider(target: vscode.WorkspaceFolder): vscode.Disposable { + const provider = new CargoTaskProvider(target); + return vscode.tasks.registerTaskProvider(TASK_TYPE, provider); +} \ No newline at end of file