@@ -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 ) ]
@@ -88,6 +88,23 @@ pub struct Crate {
88
88
pub ( crate ) exclude : Vec < AbsPathBuf > ,
89
89
pub ( crate ) is_proc_macro : bool ,
90
90
pub ( crate ) repository : Option < String > ,
91
+ pub build : Option < Build > ,
92
+ }
93
+
94
+ /// Additional metadata about a crate, used to configure runnables.
95
+ #[ derive( Clone , Debug , Eq , PartialEq ) ]
96
+ pub struct Build {
97
+ /// The name associated with this crate, according to the custom
98
+ /// build system being used.
99
+ pub label : String ,
100
+ /// Path corresponding to the build-system-specific file defining the crate.
101
+ pub build_file : PathBuf ,
102
+ /// What kind of target is this crate? For example, we don't want
103
+ /// to offer a 'run' button for library crates.
104
+ pub target_kind : TargetKind ,
105
+ /// Configuration for shell commands, such as CLI invocations for
106
+ /// a check build or a test run.
107
+ pub runnables : Vec < Runnables > ,
91
108
}
92
109
93
110
impl ProjectJson {
@@ -127,6 +144,16 @@ impl ProjectJson {
127
144
None => ( vec ! [ root_module. parent( ) . unwrap( ) . to_path_buf( ) ] , Vec :: new ( ) ) ,
128
145
} ;
129
146
147
+ let build = match crate_data. build {
148
+ Some ( build) => Some ( Build {
149
+ label : build. label ,
150
+ build_file : build. build_file ,
151
+ target_kind : build. target_kind . into ( ) ,
152
+ runnables : build. runnables ,
153
+ } ) ,
154
+ None => None ,
155
+ } ;
156
+
130
157
Crate {
131
158
display_name : crate_data
132
159
. display_name
@@ -146,6 +173,7 @@ impl ProjectJson {
146
173
exclude,
147
174
is_proc_macro : crate_data. is_proc_macro ,
148
175
repository : crate_data. repository ,
176
+ build,
149
177
}
150
178
} )
151
179
. collect ( ) ,
@@ -167,10 +195,23 @@ impl ProjectJson {
167
195
& self . project_root
168
196
}
169
197
198
+ pub fn crate_by_root ( & self , root : & AbsPath ) -> Option < Crate > {
199
+ self . crates
200
+ . iter ( )
201
+ . filter ( |krate| krate. is_workspace_member )
202
+ . find ( |krate| krate. root_module == root)
203
+ . cloned ( )
204
+ }
205
+
170
206
/// Returns the path to the project's manifest or root folder, if no manifest exists.
171
207
pub fn manifest_or_root ( & self ) -> & AbsPath {
172
208
self . manifest . as_ref ( ) . map_or ( & self . project_root , |manifest| manifest. as_ref ( ) )
173
209
}
210
+
211
+ /// Returns the manifest
212
+ pub fn manifest ( & self ) -> Option < & ManifestPath > {
213
+ self . manifest . as_ref ( )
214
+ }
174
215
}
175
216
176
217
#[ derive( Serialize , Deserialize , Debug , Clone ) ]
@@ -200,6 +241,8 @@ struct CrateData {
200
241
is_proc_macro : bool ,
201
242
#[ serde( default ) ]
202
243
repository : Option < String > ,
244
+ #[ serde( default ) ]
245
+ build : Option < BuildData > ,
203
246
}
204
247
205
248
#[ derive( Serialize , Deserialize , Debug , Clone ) ]
@@ -215,6 +258,50 @@ enum EditionData {
215
258
Edition2024 ,
216
259
}
217
260
261
+ #[ derive( Serialize , Deserialize , Debug , Clone ) ]
262
+ pub struct BuildData {
263
+ label : String ,
264
+ build_file : PathBuf ,
265
+ target_kind : TargetKindData ,
266
+ runnables : Vec < Runnables > ,
267
+ }
268
+
269
+ #[ derive( Debug , Clone , PartialEq , Eq , serde:: Deserialize , serde:: Serialize ) ]
270
+ #[ serde( rename_all = "camelCase" ) ]
271
+ pub struct Runnables {
272
+ pub program : String ,
273
+ pub args : Vec < String > ,
274
+ pub cwd : PathBuf ,
275
+ pub kind : RunnableKind ,
276
+ }
277
+
278
+ #[ derive( Debug , Clone , PartialEq , Eq , serde:: Deserialize , serde:: Serialize ) ]
279
+ #[ serde( rename_all = "camelCase" ) ]
280
+ pub enum RunnableKind {
281
+ Check ,
282
+ Run ,
283
+ TestOne ,
284
+ }
285
+
286
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , serde:: Deserialize , serde:: Serialize ) ]
287
+ #[ serde( rename_all = "camelCase" ) ]
288
+ pub enum TargetKindData {
289
+ Bin ,
290
+ /// Any kind of Cargo lib crate-type (dylib, rlib, proc-macro, ...).
291
+ Lib ,
292
+ Test ,
293
+ }
294
+
295
+ impl From < TargetKindData > for TargetKind {
296
+ fn from ( value : TargetKindData ) -> Self {
297
+ match value {
298
+ TargetKindData :: Bin => TargetKind :: Bin ,
299
+ TargetKindData :: Lib => TargetKind :: Lib { is_proc_macro : false } ,
300
+ TargetKindData :: Test => TargetKind :: Test ,
301
+ }
302
+ }
303
+ }
304
+
218
305
impl From < EditionData > for Edition {
219
306
fn from ( data : EditionData ) -> Self {
220
307
match data {
0 commit comments