@@ -55,8 +55,9 @@ use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
5555use rustc_hash:: FxHashMap ;
5656use serde:: { de, Deserialize } ;
5757use span:: Edition ;
58+ use std:: path:: PathBuf ;
5859
59- use crate :: cfg_flag:: CfgFlag ;
60+ use crate :: { cfg_flag:: CfgFlag , TargetKind } ;
6061
6162/// Roots and crates that compose this Rust project.
6263#[ derive( Clone , Debug , Eq , PartialEq ) ]
@@ -87,6 +88,21 @@ pub struct Crate {
8788 pub ( crate ) exclude : Vec < AbsPathBuf > ,
8889 pub ( crate ) is_proc_macro : bool ,
8990 pub ( crate ) repository : Option < String > ,
91+ pub build_info : Option < BuildInfo > ,
92+ }
93+
94+ /// Additional metadata about a crate, used to configure runnables.
95+ #[ derive( Clone , Debug , Eq , PartialEq ) ]
96+ pub struct BuildInfo {
97+ /// The name associated with this crate, according to the custom
98+ /// build system being used.
99+ pub label : String ,
100+ /// What kind of target is this crate? For example, we don't want
101+ /// to offer a 'run' button for library crates.
102+ pub target_kind : TargetKind ,
103+ /// Configuration for shell commands, such as CLI invocations for
104+ /// a check build or a test run.
105+ pub shell_runnables : Vec < ShellRunnableArgs > ,
90106}
91107
92108impl ProjectJson {
@@ -121,6 +137,15 @@ impl ProjectJson {
121137 None => ( vec ! [ root_module. parent( ) . unwrap( ) . to_path_buf( ) ] , Vec :: new ( ) ) ,
122138 } ;
123139
140+ let build_info = match crate_data. build_info {
141+ Some ( build_info) => Some ( BuildInfo {
142+ label : build_info. label ,
143+ target_kind : build_info. target_kind . into ( ) ,
144+ shell_runnables : build_info. shell_runnables ,
145+ } ) ,
146+ None => None ,
147+ } ;
148+
124149 Crate {
125150 display_name : crate_data
126151 . display_name
@@ -149,6 +174,7 @@ impl ProjectJson {
149174 exclude,
150175 is_proc_macro : crate_data. is_proc_macro ,
151176 repository : crate_data. repository ,
177+ build_info,
152178 }
153179 } )
154180 . collect ( ) ,
@@ -172,6 +198,14 @@ impl ProjectJson {
172198 pub fn path ( & self ) -> & AbsPath {
173199 & self . project_root
174200 }
201+
202+ pub fn crate_by_root ( & self , root : & AbsPath ) -> Option < Crate > {
203+ self . crates
204+ . iter ( )
205+ . filter ( |krate| krate. is_workspace_member )
206+ . find ( |krate| & krate. root_module == root)
207+ . cloned ( )
208+ }
175209}
176210
177211#[ derive( Deserialize , Debug , Clone ) ]
@@ -201,6 +235,8 @@ struct CrateData {
201235 is_proc_macro : bool ,
202236 #[ serde( default ) ]
203237 repository : Option < String > ,
238+ #[ serde( default ) ]
239+ build_info : Option < BuildInfoData > ,
204240}
205241
206242#[ derive( Deserialize , Debug , Clone ) ]
@@ -216,6 +252,48 @@ enum EditionData {
216252 Edition2024 ,
217253}
218254
255+ #[ derive( Deserialize , Debug , Clone ) ]
256+ pub struct BuildInfoData {
257+ label : String ,
258+ target_kind : TargetKindData ,
259+ shell_runnables : Vec < ShellRunnableArgs > ,
260+ }
261+
262+ #[ derive( Debug , Clone , PartialEq , Eq , serde:: Deserialize ) ]
263+ #[ serde( rename_all = "camelCase" ) ]
264+ pub struct ShellRunnableArgs {
265+ pub program : String ,
266+ pub args : Vec < String > ,
267+ pub cwd : PathBuf ,
268+ pub kind : ShellRunnableKind ,
269+ }
270+
271+ #[ derive( Debug , Clone , PartialEq , Eq , serde:: Deserialize ) ]
272+ #[ serde( rename_all = "camelCase" ) ]
273+ pub enum ShellRunnableKind {
274+ Check ,
275+ Run ,
276+ }
277+
278+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , serde:: Deserialize ) ]
279+ #[ serde( rename_all = "camelCase" ) ]
280+ pub enum TargetKindData {
281+ Bin ,
282+ /// Any kind of Cargo lib crate-type (dylib, rlib, proc-macro, ...).
283+ Lib ,
284+ Test ,
285+ }
286+
287+ impl From < TargetKindData > for TargetKind {
288+ fn from ( value : TargetKindData ) -> Self {
289+ match value {
290+ TargetKindData :: Bin => TargetKind :: Bin ,
291+ TargetKindData :: Lib => TargetKind :: Lib { is_proc_macro : false } ,
292+ TargetKindData :: Test => TargetKind :: Test ,
293+ }
294+ }
295+ }
296+
219297impl From < EditionData > for Edition {
220298 fn from ( data : EditionData ) -> Self {
221299 match data {
0 commit comments