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