1
1
import * as vscode from "vscode" ;
2
2
import type { Config } from "./config" ;
3
- import { log , unwrapUndefinable } from "./util" ;
4
3
import * as toolchain from "./toolchain" ;
5
4
6
5
// This ends up as the `type` key in tasks.json. RLS also uses `cargo` and
@@ -10,21 +9,21 @@ export const SHELL_TASK_TYPE = "shell";
10
9
11
10
export const RUST_TASK_SOURCE = "rust" ;
12
11
13
- export type RustTargetDefinition = {
12
+ export type TaskDefinition = vscode . TaskDefinition & {
14
13
readonly type : typeof CARGO_TASK_TYPE | typeof SHELL_TASK_TYPE ;
15
- } & vscode . TaskDefinition &
16
- RustTarget ;
17
- export type RustTarget = {
18
- // The command to run, usually `cargo`.
19
- command : string ;
20
- // Additional arguments passed to the command.
21
14
args ?: string [ ] ;
22
- // The working directory to run the command in.
23
- cwd ?: string ;
24
- // The shell environment.
25
- env ?: { [ key : string ] : string } ;
15
+ command : string ;
26
16
} ;
27
17
18
+ export type CargoTaskDefinition = {
19
+ env ?: Record < string , string > ;
20
+ type : typeof CARGO_TASK_TYPE ;
21
+ } & TaskDefinition ;
22
+
23
+ function isCargoTask ( definition : vscode . TaskDefinition ) : definition is CargoTaskDefinition {
24
+ return definition . type === CARGO_TASK_TYPE ;
25
+ }
26
+
28
27
class RustTaskProvider implements vscode . TaskProvider {
29
28
private readonly config : Config ;
30
29
@@ -58,13 +57,13 @@ class RustTaskProvider implements vscode.TaskProvider {
58
57
for ( const workspaceTarget of vscode . workspace . workspaceFolders ) {
59
58
for ( const def of defs ) {
60
59
const definition = {
61
- command : cargo ,
62
- args : [ def . command ] ,
63
- } ;
64
- const exec = await targetToExecution ( definition , this . config . cargoRunner ) ;
60
+ command : def . command ,
61
+ type : CARGO_TASK_TYPE ,
62
+ } as const ;
63
+ const exec = await targetToExecution ( definition , { } , cargo ) ;
65
64
const vscodeTask = await buildRustTask (
66
65
workspaceTarget ,
67
- { ... definition , type : CARGO_TASK_TYPE } ,
66
+ definition ,
68
67
`cargo ${ def . command } ` ,
69
68
this . config . problemMatcher ,
70
69
exec ,
@@ -81,23 +80,13 @@ class RustTaskProvider implements vscode.TaskProvider {
81
80
// VSCode calls this for every cargo task in the user's tasks.json,
82
81
// we need to inform VSCode how to execute that command by creating
83
82
// a ShellExecution for it.
84
- if ( task . definition . type === CARGO_TASK_TYPE ) {
85
- const taskDefinition = task . definition as RustTargetDefinition ;
86
- const cargo = await toolchain . cargoPath ( ) ;
87
- const exec = await targetToExecution (
88
- {
89
- command : cargo ,
90
- args : [ taskDefinition . command ] . concat ( taskDefinition . args || [ ] ) ,
91
- cwd : taskDefinition . cwd ,
92
- env : taskDefinition . env ,
93
- } ,
94
- this . config . cargoRunner ,
95
- ) ;
96
- return await buildRustTask (
83
+ if ( isCargoTask ( task . definition ) ) {
84
+ const exec = await targetToExecution ( task . definition , { env : task . definition . env } ) ;
85
+ return buildRustTask (
97
86
task . scope ,
98
- taskDefinition ,
87
+ task . definition ,
99
88
task . name ,
100
- this . config . problemMatcher ,
89
+ task . problemMatchers ,
101
90
exec ,
102
91
) ;
103
92
}
@@ -108,7 +97,7 @@ class RustTaskProvider implements vscode.TaskProvider {
108
97
109
98
export async function buildRustTask (
110
99
scope : vscode . WorkspaceFolder | vscode . TaskScope | undefined ,
111
- definition : RustTargetDefinition ,
100
+ definition : TaskDefinition ,
112
101
name : string ,
113
102
problemMatcher : string [ ] ,
114
103
exec : vscode . ProcessExecution | vscode . ShellExecution ,
@@ -126,40 +115,23 @@ export async function buildRustTask(
126
115
}
127
116
128
117
export async function targetToExecution (
129
- definition : RustTarget ,
130
- customRunner ?: string ,
131
- throwOnError : boolean = false ,
118
+ definition : TaskDefinition ,
119
+ options ?: {
120
+ env ?: { [ key : string ] : string } ;
121
+ cwd ?: string ;
122
+ } ,
123
+ cargo ?: string ,
132
124
) : Promise < vscode . ProcessExecution | vscode . ShellExecution > {
133
- if ( customRunner ) {
134
- const runnerCommand = `${ customRunner } .buildShellExecution` ;
135
-
136
- try {
137
- const runnerArgs = {
138
- kind : CARGO_TASK_TYPE ,
139
- args : definition . args ,
140
- cwd : definition . cwd ,
141
- env : definition . env ,
142
- } ;
143
- const customExec = await vscode . commands . executeCommand ( runnerCommand , runnerArgs ) ;
144
- if ( customExec ) {
145
- if ( customExec instanceof vscode . ShellExecution ) {
146
- return customExec ;
147
- } else {
148
- log . debug ( "Invalid cargo ShellExecution" , customExec ) ;
149
- throw "Invalid cargo ShellExecution." ;
150
- }
151
- }
152
- // fallback to default processing
153
- } catch ( e ) {
154
- if ( throwOnError ) throw `Cargo runner '${ customRunner } ' failed! ${ e } ` ;
155
- // fallback to default processing
156
- }
125
+ let command , args ;
126
+ if ( isCargoTask ( definition ) ) {
127
+ // FIXME: The server should provide cargo
128
+ command = cargo || ( await toolchain . cargoPath ( ) ) ;
129
+ args = [ definition . command ] . concat ( definition . args || [ ] ) ;
130
+ } else {
131
+ command = definition . command ;
132
+ args = definition . args || [ ] ;
157
133
}
158
- const args = unwrapUndefinable ( definition . args ) ;
159
- return new vscode . ProcessExecution ( definition . command , args , {
160
- cwd : definition . cwd ,
161
- env : definition . env ,
162
- } ) ;
134
+ return new vscode . ProcessExecution ( command , args , options ) ;
163
135
}
164
136
165
137
export function activateTaskProvider ( config : Config ) : vscode . Disposable {
0 commit comments