Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'editors/code/src/tasks.ts')
| -rw-r--r-- | editors/code/src/tasks.ts | 100 |
1 files changed, 54 insertions, 46 deletions
diff --git a/editors/code/src/tasks.ts b/editors/code/src/tasks.ts index 2b3abc5d65..6f4fbf9188 100644 --- a/editors/code/src/tasks.ts +++ b/editors/code/src/tasks.ts @@ -1,28 +1,29 @@ import * as vscode from "vscode"; -import * as toolchain from "./toolchain"; import type { Config } from "./config"; -import { log } from "./util"; -import { unwrapUndefinable } from "./undefinable"; +import { log, unwrapUndefinable } from "./util"; +import * as toolchain from "./toolchain"; // This ends up as the `type` key in tasks.json. RLS also uses `cargo` and // our configuration should be compatible with it so use the same key. -export const TASK_TYPE = "cargo"; +export const CARGO_TASK_TYPE = "cargo"; +export const SHELL_TASK_TYPE = "shell"; -export const TASK_SOURCE = "rust"; +export const RUST_TASK_SOURCE = "rust"; -export interface CargoTaskDefinition extends vscode.TaskDefinition { - // The cargo command, such as "run" or "check". +export type RustTargetDefinition = { + readonly type: typeof CARGO_TASK_TYPE | typeof SHELL_TASK_TYPE; +} & vscode.TaskDefinition & + RustTarget; +export type RustTarget = { + // The command to run, usually `cargo`. command: string; - // Additional arguments passed to the cargo command. + // Additional arguments passed to the command. args?: string[]; - // The working directory to run the cargo command in. + // The working directory to run the command in. cwd?: string; // The shell environment. env?: { [key: string]: string }; - // Override the cargo executable name, such as - // "my_custom_cargo_bin". - overrideCargo?: string; -} +}; class RustTaskProvider implements vscode.TaskProvider { private readonly config: Config; @@ -32,6 +33,10 @@ class RustTaskProvider implements vscode.TaskProvider { } async provideTasks(): Promise<vscode.Task[]> { + if (!vscode.workspace.workspaceFolders) { + return []; + } + // 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 @@ -46,15 +51,23 @@ class RustTaskProvider implements vscode.TaskProvider { { command: "run", group: undefined }, ]; + // FIXME: The server should provide this + const cargo = await toolchain.cargoPath(); + const tasks: vscode.Task[] = []; - for (const workspaceTarget of vscode.workspace.workspaceFolders || []) { + for (const workspaceTarget of vscode.workspace.workspaceFolders) { for (const def of defs) { + const definition = { + command: cargo, + args: [def.command], + }; + const exec = await targetToExecution(definition, this.config.cargoRunner); const vscodeTask = await buildRustTask( workspaceTarget, - { type: TASK_TYPE, command: def.command }, + { ...definition, type: CARGO_TASK_TYPE }, `cargo ${def.command}`, this.config.problemMatcher, - this.config.cargoRunner, + exec, ); vscodeTask.group = def.group; tasks.push(vscodeTask); @@ -68,16 +81,24 @@ class RustTaskProvider implements vscode.TaskProvider { // 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. - - const definition = task.definition as CargoTaskDefinition; - - if (definition.type === TASK_TYPE) { + if (task.definition.type === CARGO_TASK_TYPE) { + const taskDefinition = task.definition as RustTargetDefinition; + const cargo = await toolchain.cargoPath(); + const exec = await targetToExecution( + { + command: cargo, + args: [taskDefinition.command].concat(taskDefinition.args || []), + cwd: taskDefinition.cwd, + env: taskDefinition.env, + }, + this.config.cargoRunner, + ); return await buildRustTask( task.scope, - definition, + taskDefinition, task.name, this.config.problemMatcher, - this.config.cargoRunner, + exec, ); } @@ -87,37 +108,34 @@ class RustTaskProvider implements vscode.TaskProvider { export async function buildRustTask( scope: vscode.WorkspaceFolder | vscode.TaskScope | undefined, - definition: CargoTaskDefinition, + definition: RustTargetDefinition, name: string, problemMatcher: string[], - customRunner?: string, - throwOnError: boolean = false, + exec: vscode.ProcessExecution | vscode.ShellExecution, ): Promise<vscode.Task> { - const exec = await cargoToExecution(definition, customRunner, throwOnError); - return new vscode.Task( definition, // scope can sometimes be undefined. in these situations we default to the workspace taskscope as // recommended by the official docs: https://code.visualstudio.com/api/extension-guides/task-provider#task-provider) scope ?? vscode.TaskScope.Workspace, name, - TASK_SOURCE, + RUST_TASK_SOURCE, exec, problemMatcher, ); } -async function cargoToExecution( - definition: CargoTaskDefinition, - customRunner: string | undefined, - throwOnError: boolean, +export async function targetToExecution( + definition: RustTarget, + customRunner?: string, + throwOnError: boolean = false, ): Promise<vscode.ProcessExecution | vscode.ShellExecution> { if (customRunner) { const runnerCommand = `${customRunner}.buildShellExecution`; try { const runnerArgs = { - kind: TASK_TYPE, + kind: CARGO_TASK_TYPE, args: definition.args, cwd: definition.cwd, env: definition.env, @@ -137,18 +155,8 @@ async function cargoToExecution( // fallback to default processing } } - - // Check whether we must use a user-defined substitute for cargo. - // Split on spaces to allow overrides like "wrapper cargo". - const cargoPath = await toolchain.cargoPath(); - const cargoCommand = definition.overrideCargo?.split(" ") ?? [cargoPath]; - - const args = [definition.command].concat(definition.args ?? []); - const fullCommand = [...cargoCommand, ...args]; - - const processName = unwrapUndefinable(fullCommand[0]); - - return new vscode.ProcessExecution(processName, fullCommand.slice(1), { + const args = unwrapUndefinable(definition.args); + return new vscode.ProcessExecution(definition.command, args, { cwd: definition.cwd, env: definition.env, }); @@ -156,5 +164,5 @@ async function cargoToExecution( export function activateTaskProvider(config: Config): vscode.Disposable { const provider = new RustTaskProvider(config); - return vscode.tasks.registerTaskProvider(TASK_TYPE, provider); + return vscode.tasks.registerTaskProvider(CARGO_TASK_TYPE, provider); } |