@@ -3,17 +3,23 @@ import {
3
3
Disposable ,
4
4
ShellExecution ,
5
5
Task ,
6
- TaskDefinition ,
7
6
TaskGroup ,
8
- TaskPanelKind ,
9
- TaskPresentationOptions ,
10
7
TaskProvider ,
11
- TaskRevealKind ,
12
8
tasks ,
13
9
workspace ,
14
10
WorkspaceFolder ,
15
11
} from 'vscode' ;
16
12
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
+
17
23
/**
18
24
* Command execution parameters sent by the RLS (as of 1.35).
19
25
*/
@@ -31,119 +37,82 @@ export interface Execution {
31
37
cwd ?: string ;
32
38
}
33
39
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
+
34
49
export function activateTaskProvider ( target : WorkspaceFolder ) : Disposable {
35
50
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
43
64
resolveTask : ( ) => undefined ,
44
65
} ;
45
66
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 ) ;
82
68
}
83
69
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 [ ] {
94
71
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
+ } ) ;
130
99
}
131
100
132
101
// 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
+ ) ;
147
116
}
148
117
149
118
/**
@@ -160,7 +129,7 @@ export async function runTaskCommand(
160
129
const uniqueId = crypto . randomBytes ( 20 ) . toString ( ) ;
161
130
162
131
const task = new Task (
163
- { label : uniqueId , type : 'setup ' } ,
132
+ { label : uniqueId , type : 'shell ' } ,
164
133
folder ? folder : workspace . workspaceFolders ! [ 0 ] ,
165
134
displayName ,
166
135
TASK_SOURCE ,
0 commit comments