@@ -2,17 +2,26 @@ import * as vscode from "vscode";
2
2
import * as toolchain from "./toolchain" ;
3
3
import type { Config } from "./config" ;
4
4
import { log } from "./util" ;
5
+ import { unwrapUndefinable } from "./undefinable" ;
5
6
6
7
// This ends up as the `type` key in tasks.json. RLS also uses `cargo` and
7
8
// our configuration should be compatible with it so use the same key.
8
9
export const TASK_TYPE = "cargo" ;
10
+
9
11
export const TASK_SOURCE = "rust" ;
10
12
11
13
export 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.
14
19
cwd ?: string ;
20
+ // The shell environment.
15
21
env ?: { [ key : string ] : string } ;
22
+ // Override the cargo executable name, such as
23
+ // "my_custom_cargo_bin".
24
+ overrideCargo ?: string ;
16
25
}
17
26
18
27
class RustTaskProvider implements vscode . TaskProvider {
@@ -37,14 +46,12 @@ class RustTaskProvider implements vscode.TaskProvider {
37
46
{ command : "run" , group : undefined } ,
38
47
] ;
39
48
40
- const cargoPath = await toolchain . cargoPath ( ) ;
41
-
42
49
const tasks : vscode . Task [ ] = [ ] ;
43
50
for ( const workspaceTarget of vscode . workspace . workspaceFolders || [ ] ) {
44
51
for ( const def of defs ) {
45
52
const vscodeTask = await buildRustTask (
46
53
workspaceTarget ,
47
- { type : TASK_TYPE , program : cargoPath , args : [ def . command ] } ,
54
+ { type : TASK_TYPE , command : def . command } ,
48
55
`cargo ${ def . command } ` ,
49
56
this . config . problemMatcher ,
50
57
this . config . cargoRunner ,
@@ -86,10 +93,32 @@ export async function buildRustTask(
86
93
customRunner ?: string ,
87
94
throwOnError : boolean = false ,
88
95
) : 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
+ }
90
113
114
+ async function cargoToExecution (
115
+ definition : CargoTaskDefinition ,
116
+ customRunner : string | undefined ,
117
+ throwOnError : boolean ,
118
+ ) : Promise < vscode . ProcessExecution | vscode . ShellExecution > {
91
119
if ( customRunner ) {
92
120
const runnerCommand = `${ customRunner } .buildShellExecution` ;
121
+
93
122
try {
94
123
const runnerArgs = {
95
124
kind : TASK_TYPE ,
@@ -100,7 +129,7 @@ export async function buildRustTask(
100
129
const customExec = await vscode . commands . executeCommand ( runnerCommand , runnerArgs ) ;
101
130
if ( customExec ) {
102
131
if ( customExec instanceof vscode . ShellExecution ) {
103
- exec = customExec ;
132
+ return customExec ;
104
133
} else {
105
134
log . debug ( "Invalid cargo ShellExecution" , customExec ) ;
106
135
throw "Invalid cargo ShellExecution." ;
@@ -113,20 +142,20 @@ export async function buildRustTask(
113
142
}
114
143
}
115
144
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 ] ;
119
149
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
+ } ) ;
130
159
}
131
160
132
161
export function activateTaskProvider ( config : Config ) : vscode . Disposable {
0 commit comments