@@ -54,9 +54,9 @@ use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
5454use rustc_hash:: FxHashMap ;
5555use serde:: { de, Deserialize , Serialize } ;
5656use span:: Edition ;
57+ use std:: path:: PathBuf ;
5758
58- use crate :: cfg:: CfgFlag ;
59- use crate :: ManifestPath ;
59+ use crate :: { cfg:: CfgFlag , ManifestPath , TargetKind } ;
6060
6161/// Roots and crates that compose this Rust project.
6262#[ derive( Clone , Debug , Eq , PartialEq ) ]
@@ -88,6 +88,23 @@ pub struct Crate {
8888 pub ( crate ) exclude : Vec < AbsPathBuf > ,
8989 pub ( crate ) is_proc_macro : bool ,
9090 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 > ,
91108}
92109
93110impl ProjectJson {
@@ -127,6 +144,16 @@ impl ProjectJson {
127144 None => ( vec ! [ root_module. parent( ) . unwrap( ) . to_path_buf( ) ] , Vec :: new ( ) ) ,
128145 } ;
129146
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+
130157 Crate {
131158 display_name : crate_data
132159 . display_name
@@ -146,6 +173,7 @@ impl ProjectJson {
146173 exclude,
147174 is_proc_macro : crate_data. is_proc_macro ,
148175 repository : crate_data. repository ,
176+ build,
149177 }
150178 } )
151179 . collect ( ) ,
@@ -167,10 +195,23 @@ impl ProjectJson {
167195 & self . project_root
168196 }
169197
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+
170206 /// Returns the path to the project's manifest or root folder, if no manifest exists.
171207 pub fn manifest_or_root ( & self ) -> & AbsPath {
172208 self . manifest . as_ref ( ) . map_or ( & self . project_root , |manifest| manifest. as_ref ( ) )
173209 }
210+
211+ /// Returns the manifest
212+ pub fn manifest ( & self ) -> Option < & ManifestPath > {
213+ self . manifest . as_ref ( )
214+ }
174215}
175216
176217#[ derive( Serialize , Deserialize , Debug , Clone ) ]
@@ -200,6 +241,8 @@ struct CrateData {
200241 is_proc_macro : bool ,
201242 #[ serde( default ) ]
202243 repository : Option < String > ,
244+ #[ serde( default ) ]
245+ build : Option < BuildData > ,
203246}
204247
205248#[ derive( Serialize , Deserialize , Debug , Clone ) ]
@@ -215,6 +258,50 @@ enum EditionData {
215258 Edition2024 ,
216259}
217260
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+
218305impl From < EditionData > for Edition {
219306 fn from ( data : EditionData ) -> Self {
220307 match data {
0 commit comments