aboutsummaryrefslogtreecommitdiff
path: root/editors/code/src/tasks.ts
diff options
context:
space:
mode:
Diffstat (limited to 'editors/code/src/tasks.ts')
-rw-r--r--editors/code/src/tasks.ts111
1 files changed, 71 insertions, 40 deletions
diff --git a/editors/code/src/tasks.ts b/editors/code/src/tasks.ts
index 9748824df..14abbd5b7 100644
--- a/editors/code/src/tasks.ts
+++ b/editors/code/src/tasks.ts
@@ -1,11 +1,14 @@
1import * as vscode from 'vscode'; 1import * as vscode from 'vscode';
2import * as toolchain from "./toolchain"; 2import * as toolchain from "./toolchain";
3import { Config } from './config';
4import { log } from './util';
3 5
4// This ends up as the `type` key in tasks.json. RLS also uses `cargo` and 6// This ends up as the `type` key in tasks.json. RLS also uses `cargo` and
5// our configuration should be compatible with it so use the same key. 7// our configuration should be compatible with it so use the same key.
6const TASK_TYPE = 'cargo'; 8export const TASK_TYPE = 'cargo';
9export const TASK_SOURCE = 'rust';
7 10
8interface CargoTaskDefinition extends vscode.TaskDefinition { 11export interface CargoTaskDefinition extends vscode.TaskDefinition {
9 command?: string; 12 command?: string;
10 args?: string[]; 13 args?: string[];
11 cwd?: string; 14 cwd?: string;
@@ -14,73 +17,101 @@ interface CargoTaskDefinition extends vscode.TaskDefinition {
14 17
15class CargoTaskProvider implements vscode.TaskProvider { 18class CargoTaskProvider implements vscode.TaskProvider {
16 private readonly target: vscode.WorkspaceFolder; 19 private readonly target: vscode.WorkspaceFolder;
20 private readonly config: Config;
17 21
18 constructor(target: vscode.WorkspaceFolder) { 22 constructor(target: vscode.WorkspaceFolder, config: Config) {
19 this.target = target; 23 this.target = target;
24 this.config = config;
20 } 25 }
21 26
22 provideTasks(): vscode.Task[] { 27 async provideTasks(): Promise<vscode.Task[]> {
23 // Detect Rust tasks. Currently we do not do any actual detection 28 // Detect Rust tasks. Currently we do not do any actual detection
24 // of tasks (e.g. aliases in .cargo/config) and just return a fixed 29 // of tasks (e.g. aliases in .cargo/config) and just return a fixed
25 // set of tasks that always exist. These tasks cannot be removed in 30 // set of tasks that always exist. These tasks cannot be removed in
26 // tasks.json - only tweaked. 31 // tasks.json - only tweaked.
27 32
28 const cargoPath = toolchain.cargoPath(); 33 const defs = [
29
30 return [
31 { command: 'build', group: vscode.TaskGroup.Build }, 34 { command: 'build', group: vscode.TaskGroup.Build },
32 { command: 'check', group: vscode.TaskGroup.Build }, 35 { command: 'check', group: vscode.TaskGroup.Build },
33 { command: 'test', group: vscode.TaskGroup.Test }, 36 { command: 'test', group: vscode.TaskGroup.Test },
34 { command: 'clean', group: vscode.TaskGroup.Clean }, 37 { command: 'clean', group: vscode.TaskGroup.Clean },
35 { command: 'run', group: undefined }, 38 { command: 'run', group: undefined },
36 ] 39 ];
37 .map(({ command, group }) => { 40
38 const vscodeTask = new vscode.Task( 41 const tasks: vscode.Task[] = [];
39 // The contents of this object end up in the tasks.json entries. 42 for (const def of defs) {
40 { 43 const vscodeTask = await buildCargoTask(this.target, { type: TASK_TYPE, command: def.command }, `cargo ${def.command}`, [def.command], this.config.cargoRunner);
41 type: TASK_TYPE, 44 vscodeTask.group = def.group;
42 command, 45 tasks.push(vscodeTask);
43 }, 46 }
44 // The scope of the task - workspace or specific folder (global 47
45 // is not supported). 48 return tasks;
46 this.target,
47 // The task name, and task source. These are shown in the UI as
48 // `${source}: ${name}`, e.g. `rust: cargo build`.
49 `cargo ${command}`,
50 'rust',
51 // What to do when this command is executed.
52 new vscode.ShellExecution(cargoPath, [command]),
53 // Problem matchers.
54 ['$rustc'],
55 );
56 vscodeTask.group = group;
57 return vscodeTask;
58 });
59 } 49 }
60 50
61 resolveTask(task: vscode.Task): vscode.Task | undefined { 51 async resolveTask(task: vscode.Task): Promise<vscode.Task | undefined> {
62 // VSCode calls this for every cargo task in the user's tasks.json, 52 // VSCode calls this for every cargo task in the user's tasks.json,
63 // we need to inform VSCode how to execute that command by creating 53 // we need to inform VSCode how to execute that command by creating
64 // a ShellExecution for it. 54 // a ShellExecution for it.
65 55
66 const definition = task.definition as CargoTaskDefinition; 56 const definition = task.definition as CargoTaskDefinition;
67 57
68 if (definition.type === 'cargo' && definition.command) { 58 if (definition.type === TASK_TYPE && definition.command) {
69 const args = [definition.command].concat(definition.args ?? []); 59 const args = [definition.command].concat(definition.args ?? []);
70 60
71 return new vscode.Task( 61 return await buildCargoTask(this.target, definition, task.name, args, this.config.cargoRunner);
72 definition,
73 task.name,
74 'rust',
75 new vscode.ShellExecution('cargo', args, definition),
76 );
77 } 62 }
78 63
79 return undefined; 64 return undefined;
80 } 65 }
81} 66}
82 67
83export function activateTaskProvider(target: vscode.WorkspaceFolder): vscode.Disposable { 68export async function buildCargoTask(
84 const provider = new CargoTaskProvider(target); 69 target: vscode.WorkspaceFolder,
70 definition: CargoTaskDefinition,
71 name: string,
72 args: string[],
73 customRunner?: string,
74 throwOnError: boolean = false
75): Promise<vscode.Task> {
76
77 let exec: vscode.ShellExecution | undefined = undefined;
78
79 if (customRunner) {
80 const runnerCommand = `${customRunner}.buildShellExecution`;
81 try {
82 const runnerArgs = { kind: TASK_TYPE, args, cwd: definition.cwd, env: definition.env };
83 const customExec = await vscode.commands.executeCommand(runnerCommand, runnerArgs);
84 if (customExec) {
85 if (customExec instanceof vscode.ShellExecution) {
86 exec = customExec;
87 } else {
88 log.debug("Invalid cargo ShellExecution", customExec);
89 throw "Invalid cargo ShellExecution.";
90 }
91 }
92 // fallback to default processing
93
94 } catch (e) {
95 if (throwOnError) throw `Cargo runner '${customRunner}' failed! ${e}`;
96 // fallback to default processing
97 }
98 }
99
100 if (!exec) {
101 exec = new vscode.ShellExecution(toolchain.cargoPath(), args, definition);
102 }
103
104 return new vscode.Task(
105 definition,
106 target,
107 name,
108 TASK_SOURCE,
109 exec,
110 ['$rustc']
111 );
112}
113
114export function activateTaskProvider(target: vscode.WorkspaceFolder, config: Config): vscode.Disposable {
115 const provider = new CargoTaskProvider(target, config);
85 return vscode.tasks.registerTaskProvider(TASK_TYPE, provider); 116 return vscode.tasks.registerTaskProvider(TASK_TYPE, provider);
86} 117}