@@ -54,9 +54,9 @@ use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
54
54
use rustc_hash:: FxHashMap ;
55
55
use serde:: { de, Deserialize , Serialize } ;
56
56
use span:: Edition ;
57
+ use std:: path:: PathBuf ;
57
58
58
- use crate :: cfg:: CfgFlag ;
59
- use crate :: ManifestPath ;
59
+ use crate :: { cfg:: CfgFlag , ManifestPath , TargetKind } ;
60
60
61
61
/// Roots and crates that compose this Rust project.
62
62
#[ derive( Clone , Debug , Eq , PartialEq ) ]
@@ -68,6 +68,9 @@ pub struct ProjectJson {
68
68
project_root : AbsPathBuf ,
69
69
manifest : Option < ManifestPath > ,
70
70
crates : Vec < Crate > ,
71
+ /// Configuration for commands, such as CLI invocations for
72
+ /// a check build or a test run.
73
+ runnables : Vec < Runnable > ,
71
74
}
72
75
73
76
/// A crate points to the root module of a crate and lists the dependencies of the crate. This is
@@ -88,6 +91,35 @@ pub struct Crate {
88
91
pub ( crate ) exclude : Vec < AbsPathBuf > ,
89
92
pub ( crate ) is_proc_macro : bool ,
90
93
pub ( crate ) repository : Option < String > ,
94
+ pub build : Option < Build > ,
95
+ }
96
+
97
+ /// Additional metadata about a crate, used to configure runnables.
98
+ #[ derive( Clone , Debug , Eq , PartialEq ) ]
99
+ pub struct Build {
100
+ /// The name associated with this crate, according to the custom
101
+ /// build system being used.
102
+ pub label : String ,
103
+ /// Path corresponding to the build system-specific file defining the crate.
104
+ pub build_file : PathBuf ,
105
+ /// What kind of target is this crate? For example, we don't want
106
+ /// to offer a 'run' button for library crates.
107
+ pub target_kind : TargetKind ,
108
+ }
109
+
110
+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
111
+ pub struct Runnable {
112
+ pub program : String ,
113
+ pub args : Vec < String > ,
114
+ pub cwd : PathBuf ,
115
+ pub kind : RunnableKind ,
116
+ }
117
+
118
+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
119
+ pub enum RunnableKind {
120
+ Check ,
121
+ Run ,
122
+ TestOne ,
91
123
}
92
124
93
125
impl ProjectJson {
@@ -109,6 +141,7 @@ impl ProjectJson {
109
141
sysroot_src : data. sysroot_src . map ( absolutize_on_base) ,
110
142
project_root : base. to_path_buf ( ) ,
111
143
manifest,
144
+ runnables : data. runnables . into_iter ( ) . map ( Runnable :: from) . collect ( ) ,
112
145
crates : data
113
146
. crates
114
147
. into_iter ( )
@@ -127,6 +160,15 @@ impl ProjectJson {
127
160
None => ( vec ! [ root_module. parent( ) . unwrap( ) . to_path_buf( ) ] , Vec :: new ( ) ) ,
128
161
} ;
129
162
163
+ let build = match crate_data. build {
164
+ Some ( build) => Some ( Build {
165
+ label : build. label ,
166
+ build_file : build. build_file ,
167
+ target_kind : build. target_kind . into ( ) ,
168
+ } ) ,
169
+ None => None ,
170
+ } ;
171
+
130
172
Crate {
131
173
display_name : crate_data
132
174
. display_name
@@ -146,6 +188,7 @@ impl ProjectJson {
146
188
exclude,
147
189
is_proc_macro : crate_data. is_proc_macro ,
148
190
repository : crate_data. repository ,
191
+ build,
149
192
}
150
193
} )
151
194
. collect ( ) ,
@@ -167,7 +210,15 @@ impl ProjectJson {
167
210
& self . project_root
168
211
}
169
212
170
- /// Returns the path to the project's manifest file, if it exists.
213
+ pub fn crate_by_root ( & self , root : & AbsPath ) -> Option < Crate > {
214
+ self . crates
215
+ . iter ( )
216
+ . filter ( |krate| krate. is_workspace_member )
217
+ . find ( |krate| krate. root_module == root)
218
+ . cloned ( )
219
+ }
220
+
221
+ /// Returns the path to the project's manifest, if it exists.
171
222
pub fn manifest ( & self ) -> Option < & ManifestPath > {
172
223
self . manifest . as_ref ( )
173
224
}
@@ -176,13 +227,19 @@ impl ProjectJson {
176
227
pub fn manifest_or_root ( & self ) -> & AbsPath {
177
228
self . manifest . as_ref ( ) . map_or ( & self . project_root , |manifest| manifest. as_ref ( ) )
178
229
}
230
+
231
+ pub fn runnables ( & self ) -> & [ Runnable ] {
232
+ & self . runnables
233
+ }
179
234
}
180
235
181
236
#[ derive( Serialize , Deserialize , Debug , Clone ) ]
182
237
pub struct ProjectJsonData {
183
238
sysroot : Option < Utf8PathBuf > ,
184
239
sysroot_src : Option < Utf8PathBuf > ,
185
240
crates : Vec < CrateData > ,
241
+ #[ serde( default ) ]
242
+ runnables : Vec < RunnableData > ,
186
243
}
187
244
188
245
#[ derive( Serialize , Deserialize , Debug , Clone ) ]
@@ -205,6 +262,8 @@ struct CrateData {
205
262
is_proc_macro : bool ,
206
263
#[ serde( default ) ]
207
264
repository : Option < String > ,
265
+ #[ serde( default ) ]
266
+ build : Option < BuildData > ,
208
267
}
209
268
210
269
#[ derive( Serialize , Deserialize , Debug , Clone ) ]
@@ -220,6 +279,48 @@ enum EditionData {
220
279
Edition2024 ,
221
280
}
222
281
282
+ #[ derive( Serialize , Deserialize , Debug , Clone ) ]
283
+ pub struct BuildData {
284
+ label : String ,
285
+ build_file : PathBuf ,
286
+ target_kind : TargetKindData ,
287
+ }
288
+
289
+ #[ derive( Debug , Clone , PartialEq , Eq , Serialize , Deserialize ) ]
290
+ pub struct RunnableData {
291
+ pub program : String ,
292
+ pub args : Vec < String > ,
293
+ pub cwd : PathBuf ,
294
+ pub kind : RunnableKindData ,
295
+ }
296
+
297
+ #[ derive( Debug , Clone , PartialEq , Eq , Deserialize , Serialize ) ]
298
+ #[ serde( rename_all = "camelCase" ) ]
299
+ pub enum RunnableKindData {
300
+ Check ,
301
+ Run ,
302
+ TestOne ,
303
+ }
304
+
305
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , Deserialize , Serialize ) ]
306
+ #[ serde( rename_all = "camelCase" ) ]
307
+ pub enum TargetKindData {
308
+ Bin ,
309
+ /// Any kind of Cargo lib crate-type (dylib, rlib, proc-macro, ...).
310
+ Lib ,
311
+ Test ,
312
+ }
313
+
314
+ impl From < TargetKindData > for TargetKind {
315
+ fn from ( data : TargetKindData ) -> Self {
316
+ match data {
317
+ TargetKindData :: Bin => TargetKind :: Bin ,
318
+ TargetKindData :: Lib => TargetKind :: Lib { is_proc_macro : false } ,
319
+ TargetKindData :: Test => TargetKind :: Test ,
320
+ }
321
+ }
322
+ }
323
+
223
324
impl From < EditionData > for Edition {
224
325
fn from ( data : EditionData ) -> Self {
225
326
match data {
@@ -231,6 +332,22 @@ impl From<EditionData> for Edition {
231
332
}
232
333
}
233
334
335
+ impl From < RunnableData > for Runnable {
336
+ fn from ( data : RunnableData ) -> Self {
337
+ Runnable { program : data. program , args : data. args , cwd : data. cwd , kind : data. kind . into ( ) }
338
+ }
339
+ }
340
+
341
+ impl From < RunnableKindData > for RunnableKind {
342
+ fn from ( data : RunnableKindData ) -> Self {
343
+ match data {
344
+ RunnableKindData :: Check => RunnableKind :: Check ,
345
+ RunnableKindData :: Run => RunnableKind :: Run ,
346
+ RunnableKindData :: TestOne => RunnableKind :: TestOne ,
347
+ }
348
+ }
349
+ }
350
+
234
351
/// Identifies a crate by position in the crates array.
235
352
///
236
353
/// This will differ from `CrateId` when multiple `ProjectJson`
0 commit comments