Skip to content
This repository was archived by the owner on Nov 18, 2022. It is now read-only.

Commit 901f5df

Browse files
committed
Fix auto-detected Cargo tasks
We now provide following auto-detected tasks: - cargo build - cargo check - cargo test - cargo clean Also we no longer provide extra params to the spawn options as Tasks v2 API allows to cleanly override args/env/cwd via tasks.json already.
1 parent ab60c00 commit 901f5df

File tree

3 files changed

+82
-124
lines changed

3 files changed

+82
-124
lines changed

package.json

+4-15
Original file line numberDiff line numberDiff line change
@@ -111,23 +111,12 @@
111111
"taskDefinitions": [
112112
{
113113
"type": "cargo",
114-
"required": [
115-
"command"
116-
],
117114
"properties": {
118-
"label": {
119-
"type": "string"
120-
},
121-
"command": {
122-
"type": "string"
123-
},
124-
"args": {
125-
"type": "array"
126-
},
127-
"env": {
128-
"type": "object"
115+
"subcommand": {
116+
"type":"string"
129117
}
130-
}
118+
},
119+
"required": ["subcommand"]
131120
}
132121
],
133122
"problemMatchers": [

src/extension.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import { RLSConfiguration } from './configuration';
2929
import { SignatureHelpProvider } from './providers/signatureHelpProvider';
3030
import { checkForRls, ensureToolchain, rustupUpdate } from './rustup';
3131
import { startSpinner, stopSpinner } from './spinner';
32-
import { activateTaskProvider, Execution, runCargoCommand } from './tasks';
32+
import { activateTaskProvider, Execution, runRlsCommand } from './tasks';
3333
import { withWsl } from './utils/child_process';
3434
import { uriWindowsToWsl, uriWslToWindows } from './utils/wslpath';
3535

@@ -352,7 +352,7 @@ class ClientWorkspace {
352352

353353
this.disposables.push(
354354
commands.registerCommand('rls.run', (cmd: Execution) =>
355-
runCargoCommand(this.folder, cmd),
355+
runRlsCommand(this.folder, cmd),
356356
),
357357
);
358358
}

src/tasks.ts

+76-107
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,23 @@ import {
33
Disposable,
44
ShellExecution,
55
Task,
6-
TaskDefinition,
76
TaskGroup,
8-
TaskPanelKind,
9-
TaskPresentationOptions,
107
TaskProvider,
11-
TaskRevealKind,
128
tasks,
139
workspace,
1410
WorkspaceFolder,
1511
} from 'vscode';
1612

13+
/**
14+
* Displayed identifier associated with each task.
15+
*/
16+
const TASK_SOURCE = 'Rust';
17+
/**
18+
* Internal VSCode task type (namespace) under which extensions register their
19+
* tasks. We only use `cargo` task type.
20+
*/
21+
const TASK_TYPE = 'cargo';
22+
1723
/**
1824
* Command execution parameters sent by the RLS (as of 1.35).
1925
*/
@@ -31,119 +37,82 @@ export interface Execution {
3137
cwd?: string;
3238
}
3339

40+
/**
41+
* Creates a Task-used `ShellExecution` from a unified `Execution` interface.
42+
*/
43+
function createShellExecution(execution: Execution): ShellExecution {
44+
const { binary, command, args, cwd, env } = execution;
45+
const cmdLine = `${command || binary} ${args.join(' ')}`;
46+
return new ShellExecution(cmdLine, { cwd, env });
47+
}
48+
3449
export function activateTaskProvider(target: WorkspaceFolder): Disposable {
3550
const provider: TaskProvider = {
36-
provideTasks: () => {
37-
// npm or others parse their task definitions. So they need to provide 'autoDetect' feature.
38-
// e,g, https://github.com/Microsoft/vscode/blob/de7e216e9ebcad74f918a025fc5fe7bdbe0d75b2/extensions/npm/src/main.ts
39-
// However, cargo.toml does not support to define a new task like them.
40-
// So we are not 'autoDetect' feature and the setting for it.
41-
return createDefaultTasks(target);
42-
},
51+
// Tasks returned by this function are treated as 'auto-detected' [1] and
52+
// are treated a bit differently. They are always available and can be
53+
// only tweaked (and not removed) in tasks.json.
54+
// This is to support npm-style scripts, which store project-specific
55+
// scripts in the project manifest. However, Cargo.toml does not support
56+
// anything like that, so we just try our best to help the user and present
57+
// them with most commonly used `cargo` subcommands (e.g. `build`).
58+
// Since typically they would need to parse their task definitions, an
59+
// optional `autoDetect` configuration is usually provided, which we don't.
60+
//
61+
// [1]: https://code.visualstudio.com/docs/editor/tasks#_task-autodetection
62+
provideTasks: () => detectCargoTasks(target),
63+
// NOTE: Currently unused by VSCode
4364
resolveTask: () => undefined,
4465
};
4566

46-
return tasks.registerTaskProvider('cargo', provider);
47-
}
48-
49-
const TASK_SOURCE = 'Rust';
50-
51-
interface TaskConfigItem {
52-
label: string;
53-
definition: TaskDefinition;
54-
execution: Execution;
55-
problemMatchers: string[];
56-
group?: TaskGroup;
57-
presentationOptions?: TaskPresentationOptions;
58-
}
59-
60-
function createDefaultTasks(target: WorkspaceFolder): Task[] {
61-
return createTaskConfigItem().map(def => createCargoTask(def, target));
62-
}
63-
64-
function createCargoTask(cfg: TaskConfigItem, target: WorkspaceFolder): Task {
65-
const { binary, command, args, cwd, env } = cfg.execution;
66-
const cmdLine = `${command || binary} ${args.join(' ')}`;
67-
const execution = new ShellExecution(cmdLine, { cwd, env });
68-
69-
const { definition, problemMatchers, presentationOptions, group } = cfg;
70-
return {
71-
definition,
72-
scope: target,
73-
name: definition.label,
74-
source: TASK_SOURCE,
75-
execution,
76-
isBackground: false,
77-
problemMatchers,
78-
presentationOptions: presentationOptions || {},
79-
runOptions: {},
80-
...{ group },
81-
};
67+
return tasks.registerTaskProvider(TASK_TYPE, provider);
8268
}
8369

84-
function createTaskConfigItem(): TaskConfigItem[] {
85-
const common = {
86-
definition: { type: 'cargo' },
87-
problemMatchers: ['$rustc'],
88-
presentationOptions: {
89-
reveal: TaskRevealKind.Always,
90-
panel: TaskPanelKind.Dedicated,
91-
},
92-
};
93-
70+
function detectCargoTasks(target: WorkspaceFolder): Task[] {
9471
return [
95-
{
96-
label: 'cargo build',
97-
execution: { command: 'cargo', args: ['build'] },
98-
group: TaskGroup.Build,
99-
...common,
100-
},
101-
{
102-
label: 'cargo check',
103-
execution: { command: 'cargo', args: ['check'] },
104-
group: TaskGroup.Build,
105-
...common,
106-
},
107-
{
108-
label: 'cargo run',
109-
execution: { command: 'cargo', args: ['run'] },
110-
...common,
111-
},
112-
{
113-
label: 'cargo test',
114-
execution: { command: 'cargo', args: ['test'] },
115-
group: TaskGroup.Test,
116-
...common,
117-
},
118-
{
119-
label: 'cargo bench',
120-
execution: { command: 'cargo', args: ['+nightly', 'bench'] },
121-
group: TaskGroup.Test,
122-
...common,
123-
},
124-
{
125-
label: 'cargo clean',
126-
execution: { command: 'cargo', args: ['clean'] },
127-
...common,
128-
},
129-
];
72+
{ subcommand: 'build', group: TaskGroup.Build },
73+
{ subcommand: 'check', group: TaskGroup.Build },
74+
{ subcommand: 'test', group: TaskGroup.Test },
75+
{ subcommand: 'clean', group: TaskGroup.Clean },
76+
]
77+
.map(({ subcommand, group }) => ({
78+
definition: { subcommand, type: TASK_TYPE },
79+
label: `cargo ${subcommand}`,
80+
execution: createShellExecution({ command: 'cargo', args: [subcommand] }),
81+
group,
82+
problemMatchers: ['$rustc'],
83+
}))
84+
.map(task => {
85+
// NOTE: It's important to solely use the VSCode-provided constructor (and
86+
// *not* use object spread operator!) - otherwise the task will not be picked
87+
// up by VSCode.
88+
const vscodeTask = new Task(
89+
task.definition,
90+
target,
91+
task.label,
92+
TASK_SOURCE,
93+
task.execution,
94+
task.problemMatchers,
95+
);
96+
vscodeTask.group = task.group;
97+
return vscodeTask;
98+
});
13099
}
131100

132101
// NOTE: `execution` parameters here are sent by the RLS.
133-
export function runCargoCommand(folder: WorkspaceFolder, execution: Execution) {
134-
const config: TaskConfigItem = {
135-
label: 'run Cargo command',
136-
definition: { type: 'cargo' },
137-
execution,
138-
problemMatchers: ['$rustc'],
139-
group: TaskGroup.Build,
140-
presentationOptions: {
141-
reveal: TaskRevealKind.Always,
142-
panel: TaskPanelKind.Dedicated,
143-
},
144-
};
145-
const task = createCargoTask(config, folder);
146-
return tasks.executeTask(task);
102+
export function runRlsCommand(folder: WorkspaceFolder, execution: Execution) {
103+
const shellExecution = createShellExecution(execution);
104+
const problemMatchers = ['$rustc'];
105+
106+
return tasks.executeTask(
107+
new Task(
108+
{ type: 'shell' },
109+
folder,
110+
'External RLS command',
111+
TASK_SOURCE,
112+
shellExecution,
113+
problemMatchers,
114+
),
115+
);
147116
}
148117

149118
/**
@@ -160,7 +129,7 @@ export async function runTaskCommand(
160129
const uniqueId = crypto.randomBytes(20).toString();
161130

162131
const task = new Task(
163-
{ label: uniqueId, type: 'setup' },
132+
{ label: uniqueId, type: 'shell' },
164133
folder ? folder : workspace.workspaceFolders![0],
165134
displayName,
166135
TASK_SOURCE,

0 commit comments

Comments
 (0)