diff options
Diffstat (limited to 'editors/code/src/tasks.ts')
-rw-r--r-- | editors/code/src/tasks.ts | 112 |
1 files changed, 73 insertions, 39 deletions
diff --git a/editors/code/src/tasks.ts b/editors/code/src/tasks.ts index 1366c76d6..14abbd5b7 100644 --- a/editors/code/src/tasks.ts +++ b/editors/code/src/tasks.ts | |||
@@ -1,10 +1,14 @@ | |||
1 | import * as vscode from 'vscode'; | 1 | import * as vscode from 'vscode'; |
2 | import * as toolchain from "./toolchain"; | ||
3 | import { Config } from './config'; | ||
4 | import { log } from './util'; | ||
2 | 5 | ||
3 | // 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 |
4 | // 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. |
5 | const TASK_TYPE = 'cargo'; | 8 | export const TASK_TYPE = 'cargo'; |
9 | export const TASK_SOURCE = 'rust'; | ||
6 | 10 | ||
7 | interface CargoTaskDefinition extends vscode.TaskDefinition { | 11 | export interface CargoTaskDefinition extends vscode.TaskDefinition { |
8 | command?: string; | 12 | command?: string; |
9 | args?: string[]; | 13 | args?: string[]; |
10 | cwd?: string; | 14 | cwd?: string; |
@@ -13,71 +17,101 @@ interface CargoTaskDefinition extends vscode.TaskDefinition { | |||
13 | 17 | ||
14 | class CargoTaskProvider implements vscode.TaskProvider { | 18 | class CargoTaskProvider implements vscode.TaskProvider { |
15 | private readonly target: vscode.WorkspaceFolder; | 19 | private readonly target: vscode.WorkspaceFolder; |
20 | private readonly config: Config; | ||
16 | 21 | ||
17 | constructor(target: vscode.WorkspaceFolder) { | 22 | constructor(target: vscode.WorkspaceFolder, config: Config) { |
18 | this.target = target; | 23 | this.target = target; |
24 | this.config = config; | ||
19 | } | 25 | } |
20 | 26 | ||
21 | provideTasks(): vscode.Task[] { | 27 | async provideTasks(): Promise<vscode.Task[]> { |
22 | // Detect Rust tasks. Currently we do not do any actual detection | 28 | // Detect Rust tasks. Currently we do not do any actual detection |
23 | // 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 |
24 | // 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 |
25 | // tasks.json - only tweaked. | 31 | // tasks.json - only tweaked. |
26 | 32 | ||
27 | return [ | 33 | const defs = [ |
28 | { command: 'build', group: vscode.TaskGroup.Build }, | 34 | { command: 'build', group: vscode.TaskGroup.Build }, |
29 | { command: 'check', group: vscode.TaskGroup.Build }, | 35 | { command: 'check', group: vscode.TaskGroup.Build }, |
30 | { command: 'test', group: vscode.TaskGroup.Test }, | 36 | { command: 'test', group: vscode.TaskGroup.Test }, |
31 | { command: 'clean', group: vscode.TaskGroup.Clean }, | 37 | { command: 'clean', group: vscode.TaskGroup.Clean }, |
32 | { command: 'run', group: undefined }, | 38 | { command: 'run', group: undefined }, |
33 | ] | 39 | ]; |
34 | .map(({ command, group }) => { | 40 | |
35 | const vscodeTask = new vscode.Task( | 41 | const tasks: vscode.Task[] = []; |
36 | // The contents of this object end up in the tasks.json entries. | 42 | for (const def of defs) { |
37 | { | 43 | const vscodeTask = await buildCargoTask(this.target, { type: TASK_TYPE, command: def.command }, `cargo ${def.command}`, [def.command], this.config.cargoRunner); |
38 | type: TASK_TYPE, | 44 | vscodeTask.group = def.group; |
39 | command, | 45 | tasks.push(vscodeTask); |
40 | }, | 46 | } |
41 | // The scope of the task - workspace or specific folder (global | 47 | |
42 | // is not supported). | 48 | return tasks; |
43 | this.target, | ||
44 | // The task name, and task source. These are shown in the UI as | ||
45 | // `${source}: ${name}`, e.g. `rust: cargo build`. | ||
46 | `cargo ${command}`, | ||
47 | 'rust', | ||
48 | // What to do when this command is executed. | ||
49 | new vscode.ShellExecution('cargo', [command]), | ||
50 | // Problem matchers. | ||
51 | ['$rustc'], | ||
52 | ); | ||
53 | vscodeTask.group = group; | ||
54 | return vscodeTask; | ||
55 | }); | ||
56 | } | 49 | } |
57 | 50 | ||
58 | resolveTask(task: vscode.Task): vscode.Task | undefined { | 51 | async resolveTask(task: vscode.Task): Promise<vscode.Task | undefined> { |
59 | // 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, |
60 | // 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 |
61 | // a ShellExecution for it. | 54 | // a ShellExecution for it. |
62 | 55 | ||
63 | const definition = task.definition as CargoTaskDefinition; | 56 | const definition = task.definition as CargoTaskDefinition; |
64 | 57 | ||
65 | if (definition.type === 'cargo' && definition.command) { | 58 | if (definition.type === TASK_TYPE && definition.command) { |
66 | const args = [definition.command].concat(definition.args ?? []); | 59 | const args = [definition.command].concat(definition.args ?? []); |
67 | 60 | ||
68 | return new vscode.Task( | 61 | return await buildCargoTask(this.target, definition, task.name, args, this.config.cargoRunner); |
69 | definition, | ||
70 | task.name, | ||
71 | 'rust', | ||
72 | new vscode.ShellExecution('cargo', args, definition), | ||
73 | ); | ||
74 | } | 62 | } |
75 | 63 | ||
76 | return undefined; | 64 | return undefined; |
77 | } | 65 | } |
78 | } | 66 | } |
79 | 67 | ||
80 | export function activateTaskProvider(target: vscode.WorkspaceFolder): vscode.Disposable { | 68 | export async function buildCargoTask( |
81 | 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 | |||
114 | export function activateTaskProvider(target: vscode.WorkspaceFolder, config: Config): vscode.Disposable { | ||
115 | const provider = new CargoTaskProvider(target, config); | ||
82 | return vscode.tasks.registerTaskProvider(TASK_TYPE, provider); | 116 | return vscode.tasks.registerTaskProvider(TASK_TYPE, provider); |
83 | } \ No newline at end of file | 117 | } |