@@ -2,17 +2,26 @@ import * as vscode from "vscode";
22import * as toolchain from "./toolchain" ;
33import type { Config } from "./config" ;
44import { log } from "./util" ;
5+ import { unwrapUndefinable } from "./undefinable" ;
56
67// This ends up as the `type` key in tasks.json. RLS also uses `cargo` and
78// our configuration should be compatible with it so use the same key.
89export const TASK_TYPE = "cargo" ;
10+
911export const TASK_SOURCE = "rust" ;
1012
1113export interface CargoTaskDefinition extends vscode . TaskDefinition {
12- program : string ;
13- args : string [ ] ;
14+ // The cargo command, such as "run" or "check".
15+ command : string ;
16+ // Additional arguments passed to the cargo command.
17+ args ?: string [ ] ;
18+ // The working directory to run the cargo command in.
1419 cwd ?: string ;
20+ // The shell environment.
1521 env ?: { [ key : string ] : string } ;
22+ // Override the cargo executable name, such as
23+ // "my_custom_cargo_bin".
24+ overrideCargo ?: string ;
1625}
1726
1827class RustTaskProvider implements vscode . TaskProvider {
@@ -37,14 +46,12 @@ class RustTaskProvider implements vscode.TaskProvider {
3746 { command : "run" , group : undefined } ,
3847 ] ;
3948
40- const cargoPath = await toolchain . cargoPath ( ) ;
41-
4249 const tasks : vscode . Task [ ] = [ ] ;
4350 for ( const workspaceTarget of vscode . workspace . workspaceFolders || [ ] ) {
4451 for ( const def of defs ) {
4552 const vscodeTask = await buildRustTask (
4653 workspaceTarget ,
47- { type : TASK_TYPE , program : cargoPath , args : [ def . command ] } ,
54+ { type : TASK_TYPE , command : def . command } ,
4855 `cargo ${ def . command } ` ,
4956 this . config . problemMatcher ,
5057 this . config . cargoRunner ,
@@ -86,10 +93,32 @@ export async function buildRustTask(
8693 customRunner ?: string ,
8794 throwOnError : boolean = false ,
8895) : Promise < vscode . Task > {
89- let exec : vscode . ProcessExecution | vscode . ShellExecution | undefined = undefined ;
96+ const exec = await cargoToExecution (
97+ definition ,
98+ customRunner ,
99+ throwOnError ,
100+ ) ;
101+
102+ return new vscode . Task (
103+ definition ,
104+ // scope can sometimes be undefined. in these situations we default to the workspace taskscope as
105+ // recommended by the official docs: https://code.visualstudio.com/api/extension-guides/task-provider#task-provider)
106+ scope ?? vscode . TaskScope . Workspace ,
107+ name ,
108+ TASK_SOURCE ,
109+ exec ,
110+ problemMatcher ,
111+ ) ;
112+ }
90113
114+ async function cargoToExecution (
115+ definition : CargoTaskDefinition ,
116+ customRunner : string | undefined ,
117+ throwOnError : boolean ,
118+ ) : Promise < vscode . ProcessExecution | vscode . ShellExecution > {
91119 if ( customRunner ) {
92120 const runnerCommand = `${ customRunner } .buildShellExecution` ;
121+
93122 try {
94123 const runnerArgs = {
95124 kind : TASK_TYPE ,
@@ -100,7 +129,7 @@ export async function buildRustTask(
100129 const customExec = await vscode . commands . executeCommand ( runnerCommand , runnerArgs ) ;
101130 if ( customExec ) {
102131 if ( customExec instanceof vscode . ShellExecution ) {
103- exec = customExec ;
132+ return customExec ;
104133 } else {
105134 log . debug ( "Invalid cargo ShellExecution" , customExec ) ;
106135 throw "Invalid cargo ShellExecution." ;
@@ -113,20 +142,20 @@ export async function buildRustTask(
113142 }
114143 }
115144
116- if ( ! exec ) {
117- exec = new vscode . ProcessExecution ( definition . program , definition . args , definition ) ;
118- }
145+ // Check whether we must use a user-defined substitute for cargo.
146+ // Split on spaces to allow overrides like "wrapper cargo".
147+ const cargoPath = await toolchain . cargoPath ( ) ;
148+ const cargoCommand = definition . overrideCargo ?. split ( " " ) ?? [ cargoPath ] ;
119149
120- return new vscode . Task (
121- definition ,
122- // scope can sometimes be undefined. in these situations we default to the workspace taskscope as
123- // recommended by the official docs: https://code.visualstudio.com/api/extension-guides/task-provider#task-provider)
124- scope ?? vscode . TaskScope . Workspace ,
125- name ,
126- TASK_SOURCE ,
127- exec ,
128- problemMatcher ,
129- ) ;
150+ const args = [ definition . command ] . concat ( definition . args ?? [ ] ) ;
151+ const fullCommand = [ ...cargoCommand , ...args ] ;
152+
153+ const processName = unwrapUndefinable ( fullCommand [ 0 ] ) ;
154+
155+ return new vscode . ProcessExecution ( processName , fullCommand . slice ( 1 ) , {
156+ cwd : definition . cwd ,
157+ env : definition . env ,
158+ } ) ;
130159}
131160
132161export function activateTaskProvider ( config : Config ) : vscode . Disposable {
0 commit comments