11//! Support for compiling [foundry_compilers::Project]
22
3- use crate :: { term:: SpinnerReporter , TestFunctionExt } ;
3+ use crate :: {
4+ reports:: { report_kind, ReportKind } ,
5+ shell,
6+ term:: SpinnerReporter ,
7+ TestFunctionExt ,
8+ } ;
49use comfy_table:: { presets:: ASCII_MARKDOWN , Attribute , Cell , CellAlignment , Color , Table } ;
510use eyre:: Result ;
611use foundry_block_explorers:: contract:: Metadata ;
@@ -181,11 +186,13 @@ impl ProjectCompiler {
181186 }
182187
183188 if !quiet {
184- if output. is_unchanged ( ) {
185- sh_println ! ( "No files changed, compilation skipped" ) ?;
186- } else {
187- // print the compiler output / warnings
188- sh_println ! ( "{output}" ) ?;
189+ if !shell:: is_json ( ) {
190+ if output. is_unchanged ( ) {
191+ sh_println ! ( "No files changed, compilation skipped" ) ?;
192+ } else {
193+ // print the compiler output / warnings
194+ sh_println ! ( "{output}" ) ?;
195+ }
189196 }
190197
191198 self . handle_output ( & output) ;
@@ -205,26 +212,32 @@ impl ProjectCompiler {
205212 for ( name, ( _, version) ) in output. versioned_artifacts ( ) {
206213 artifacts. entry ( version) . or_default ( ) . push ( name) ;
207214 }
208- for ( version, names) in artifacts {
209- let _ = sh_println ! (
210- " compiler version: {}.{}.{}" ,
211- version. major,
212- version. minor,
213- version. patch
214- ) ;
215- for name in names {
216- let _ = sh_println ! ( " - {name}" ) ;
215+
216+ if shell:: is_json ( ) {
217+ let _ = sh_println ! ( "{}" , serde_json:: to_string( & artifacts) . unwrap( ) ) ;
218+ } else {
219+ for ( version, names) in artifacts {
220+ let _ = sh_println ! (
221+ " compiler version: {}.{}.{}" ,
222+ version. major,
223+ version. minor,
224+ version. patch
225+ ) ;
226+ for name in names {
227+ let _ = sh_println ! ( " - {name}" ) ;
228+ }
217229 }
218230 }
219231 }
220232
221233 if print_sizes {
222234 // add extra newline if names were already printed
223- if print_names {
235+ if print_names && !shell :: is_json ( ) {
224236 let _ = sh_println ! ( ) ;
225237 }
226238
227- let mut size_report = SizeReport { contracts : BTreeMap :: new ( ) } ;
239+ let mut size_report =
240+ SizeReport { report_kind : report_kind ( ) , contracts : BTreeMap :: new ( ) } ;
228241
229242 let artifacts: BTreeMap < _ , _ > = output
230243 . artifact_ids ( )
@@ -278,6 +291,8 @@ const CONTRACT_INITCODE_SIZE_LIMIT: usize = 49152;
278291
279292/// Contracts with info about their size
280293pub struct SizeReport {
294+ /// What kind of report to generate.
295+ report_kind : ReportKind ,
281296 /// `contract name -> info`
282297 pub contracts : BTreeMap < String , ContractInfo > ,
283298}
@@ -316,6 +331,43 @@ impl SizeReport {
316331
317332impl Display for SizeReport {
318333 fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> Result < ( ) , std:: fmt:: Error > {
334+ match self . report_kind {
335+ ReportKind :: Markdown => {
336+ let table = self . format_table_output ( ) ;
337+ writeln ! ( f, "{table}" ) ?;
338+ }
339+ ReportKind :: JSON => {
340+ writeln ! ( f, "{}" , self . format_json_output( ) ) ?;
341+ }
342+ }
343+
344+ Ok ( ( ) )
345+ }
346+ }
347+
348+ impl SizeReport {
349+ fn format_json_output ( & self ) -> String {
350+ let contracts = self
351+ . contracts
352+ . iter ( )
353+ . filter ( |( _, c) | !c. is_dev_contract && ( c. runtime_size > 0 || c. init_size > 0 ) )
354+ . map ( |( name, contract) | {
355+ (
356+ name. clone ( ) ,
357+ serde_json:: json!( {
358+ "runtime_size" : contract. runtime_size,
359+ "init_size" : contract. init_size,
360+ "runtime_margin" : CONTRACT_RUNTIME_SIZE_LIMIT as isize - contract. runtime_size as isize ,
361+ "init_margin" : CONTRACT_INITCODE_SIZE_LIMIT as isize - contract. init_size as isize ,
362+ } ) ,
363+ )
364+ } )
365+ . collect :: < serde_json:: Map < _ , _ > > ( ) ;
366+
367+ serde_json:: to_string ( & contracts) . unwrap ( )
368+ }
369+
370+ fn format_table_output ( & self ) -> Table {
319371 let mut table = Table :: new ( ) ;
320372 table. load_preset ( ASCII_MARKDOWN ) ;
321373 table. set_header ( [
@@ -366,8 +418,7 @@ impl Display for SizeReport {
366418 ] ) ;
367419 }
368420
369- writeln ! ( f, "{table}" ) ?;
370- Ok ( ( ) )
421+ table
371422 }
372423}
373424
@@ -476,7 +527,7 @@ pub fn etherscan_project(
476527/// Configures the reporter and runs the given closure.
477528pub fn with_compilation_reporter < O > ( quiet : bool , f : impl FnOnce ( ) -> O ) -> O {
478529 #[ allow( clippy:: collapsible_else_if) ]
479- let reporter = if quiet {
530+ let reporter = if quiet || shell :: is_json ( ) {
480531 Report :: new ( NoReporter :: default ( ) )
481532 } else {
482533 if std:: io:: stdout ( ) . is_terminal ( ) {
0 commit comments