From a758e349bca3eb3ab8b775c51bd8c797869395b9 Mon Sep 17 00:00:00 2001 From: Wilfred Hughes Date: Thu, 28 Mar 2024 15:25:05 -0700 Subject: [PATCH] Document CargoTaskDefinition and factor out converting TaskDefinition to Execution --- editors/code/src/run.ts | 17 ++----- editors/code/src/tasks.ts | 95 ++++++++++++++++++++++++--------------- 2 files changed, 63 insertions(+), 49 deletions(-) diff --git a/editors/code/src/run.ts b/editors/code/src/run.ts index 87f7e50b76..4470689cd8 100644 --- a/editors/code/src/run.ts +++ b/editors/code/src/run.ts @@ -2,7 +2,6 @@ import * as vscode from "vscode"; import type * as lc from "vscode-languageclient"; import * as ra from "./lsp_ext"; import * as tasks from "./tasks"; -import * as toolchain from "./toolchain"; import type { CtxInit } from "./ctx"; import { makeDebugConfig } from "./debug"; @@ -112,22 +111,12 @@ export async function createTask(runnable: ra.Runnable, config: Config): Promise throw `Unexpected runnable kind: ${runnable.kind}`; } - let program: string; - let args = createArgs(runnable); - if (runnable.args.overrideCargo) { - // Split on spaces to allow overrides like "wrapper cargo". - const cargoParts = runnable.args.overrideCargo.split(" "); - - program = unwrapUndefinable(cargoParts[0]); - args = [...cargoParts.slice(1), ...args]; - } else { - program = await toolchain.cargoPath(); - } + const args = createArgs(runnable); const definition: tasks.CargoTaskDefinition = { type: tasks.TASK_TYPE, - program, - args, + command: unwrapUndefinable(args[0]), // run, test, etc... + args: args.slice(1), cwd: runnable.args.workspaceRoot || ".", env: prepareEnv(runnable, config.runnablesExtraEnv), overrideCargo: runnable.args.overrideCargo, diff --git a/editors/code/src/tasks.ts b/editors/code/src/tasks.ts index 00b644d5cc..2b3abc5d65 100644 --- a/editors/code/src/tasks.ts +++ b/editors/code/src/tasks.ts @@ -2,17 +2,26 @@ import * as vscode from "vscode"; import * as toolchain from "./toolchain"; import type { Config } from "./config"; import { log } from "./util"; +import { unwrapUndefinable } from "./undefinable"; // 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 TASK_SOURCE = "rust"; export interface CargoTaskDefinition extends vscode.TaskDefinition { - program: string; - args: string[]; + // The cargo command, such as "run" or "check". + command: string; + // Additional arguments passed to the cargo command. + args?: string[]; + // The working directory to run the cargo 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 { @@ -37,14 +46,12 @@ class RustTaskProvider implements vscode.TaskProvider { { command: "run", group: undefined }, ]; - const cargoPath = await toolchain.cargoPath(); - const tasks: vscode.Task[] = []; for (const workspaceTarget of vscode.workspace.workspaceFolders || []) { for (const def of defs) { const vscodeTask = await buildRustTask( workspaceTarget, - { type: TASK_TYPE, program: cargoPath, args: [def.command] }, + { type: TASK_TYPE, command: def.command }, `cargo ${def.command}`, this.config.problemMatcher, this.config.cargoRunner, @@ -86,36 +93,7 @@ export async function buildRustTask( customRunner?: string, throwOnError: boolean = false, ): Promise { - let exec: vscode.ProcessExecution | vscode.ShellExecution | undefined = undefined; - - if (customRunner) { - const runnerCommand = `${customRunner}.buildShellExecution`; - try { - const runnerArgs = { - kind: TASK_TYPE, - args: definition.args, - cwd: definition.cwd, - env: definition.env, - }; - const customExec = await vscode.commands.executeCommand(runnerCommand, runnerArgs); - if (customExec) { - if (customExec instanceof vscode.ShellExecution) { - exec = customExec; - } else { - log.debug("Invalid cargo ShellExecution", customExec); - throw "Invalid cargo ShellExecution."; - } - } - // fallback to default processing - } catch (e) { - if (throwOnError) throw `Cargo runner '${customRunner}' failed! ${e}`; - // fallback to default processing - } - } - - if (!exec) { - exec = new vscode.ProcessExecution(definition.program, definition.args, definition); - } + const exec = await cargoToExecution(definition, customRunner, throwOnError); return new vscode.Task( definition, @@ -129,6 +107,53 @@ export async function buildRustTask( ); } +async function cargoToExecution( + definition: CargoTaskDefinition, + customRunner: string | undefined, + throwOnError: boolean, +): Promise { + if (customRunner) { + const runnerCommand = `${customRunner}.buildShellExecution`; + + try { + const runnerArgs = { + kind: TASK_TYPE, + args: definition.args, + cwd: definition.cwd, + env: definition.env, + }; + const customExec = await vscode.commands.executeCommand(runnerCommand, runnerArgs); + if (customExec) { + if (customExec instanceof vscode.ShellExecution) { + return customExec; + } else { + log.debug("Invalid cargo ShellExecution", customExec); + throw "Invalid cargo ShellExecution."; + } + } + // fallback to default processing + } catch (e) { + if (throwOnError) throw `Cargo runner '${customRunner}' failed! ${e}`; + // 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), { + cwd: definition.cwd, + env: definition.env, + }); +} + export function activateTaskProvider(config: Config): vscode.Disposable { const provider = new RustTaskProvider(config); return vscode.tasks.registerTaskProvider(TASK_TYPE, provider);