@@ -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 ) ]
@@ -68,6 +68,9 @@ pub struct ProjectJson {
6868 project_root : AbsPathBuf ,
6969 manifest : Option < ManifestPath > ,
7070 crates : Vec < Crate > ,
71+ /// Configuration for commands, such as CLI invocations for
72+ /// a check build or a test run.
73+ runnables : Vec < Runnable > ,
7174}
7275
7376/// 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 {
8891 pub ( crate ) exclude : Vec < AbsPathBuf > ,
8992 pub ( crate ) is_proc_macro : bool ,
9093 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 ,
91123}
92124
93125impl ProjectJson {
@@ -109,6 +141,7 @@ impl ProjectJson {
109141 sysroot_src : data. sysroot_src . map ( absolutize_on_base) ,
110142 project_root : base. to_path_buf ( ) ,
111143 manifest,
144+ runnables : data. runnables . into_iter ( ) . map ( Runnable :: from) . collect ( ) ,
112145 crates : data
113146 . crates
114147 . into_iter ( )
@@ -127,6 +160,15 @@ impl ProjectJson {
127160 None => ( vec ! [ root_module. parent( ) . unwrap( ) . to_path_buf( ) ] , Vec :: new ( ) ) ,
128161 } ;
129162
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+
130172 Crate {
131173 display_name : crate_data
132174 . display_name
@@ -146,6 +188,7 @@ impl ProjectJson {
146188 exclude,
147189 is_proc_macro : crate_data. is_proc_macro ,
148190 repository : crate_data. repository ,
191+ build,
149192 }
150193 } )
151194 . collect ( ) ,
@@ -167,7 +210,15 @@ impl ProjectJson {
167210 & self . project_root
168211 }
169212
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.
171222 pub fn manifest ( & self ) -> Option < & ManifestPath > {
172223 self . manifest . as_ref ( )
173224 }
@@ -176,13 +227,19 @@ impl ProjectJson {
176227 pub fn manifest_or_root ( & self ) -> & AbsPath {
177228 self . manifest . as_ref ( ) . map_or ( & self . project_root , |manifest| manifest. as_ref ( ) )
178229 }
230+
231+ pub fn runnables ( & self ) -> & [ Runnable ] {
232+ & self . runnables
233+ }
179234}
180235
181236#[ derive( Serialize , Deserialize , Debug , Clone ) ]
182237pub struct ProjectJsonData {
183238 sysroot : Option < Utf8PathBuf > ,
184239 sysroot_src : Option < Utf8PathBuf > ,
185240 crates : Vec < CrateData > ,
241+ #[ serde( default ) ]
242+ runnables : Vec < RunnableData > ,
186243}
187244
188245#[ derive( Serialize , Deserialize , Debug , Clone ) ]
@@ -205,6 +262,8 @@ struct CrateData {
205262 is_proc_macro : bool ,
206263 #[ serde( default ) ]
207264 repository : Option < String > ,
265+ #[ serde( default ) ]
266+ build : Option < BuildData > ,
208267}
209268
210269#[ derive( Serialize , Deserialize , Debug , Clone ) ]
@@ -220,6 +279,48 @@ enum EditionData {
220279 Edition2024 ,
221280}
222281
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+
223324impl From < EditionData > for Edition {
224325 fn from ( data : EditionData ) -> Self {
225326 match data {
@@ -231,6 +332,22 @@ impl From<EditionData> for Edition {
231332 }
232333}
233334
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+
234351/// Identifies a crate by position in the crates array.
235352///
236353/// This will differ from `CrateId` when multiple `ProjectJson`
0 commit comments