1
1
//! Support for compiling [foundry_compilers::Project]
2
2
3
- use crate :: { term:: SpinnerReporter , TestFunctionExt } ;
3
+ use crate :: {
4
+ reports:: { report_kind, ReportKind } ,
5
+ shell,
6
+ term:: SpinnerReporter ,
7
+ TestFunctionExt ,
8
+ } ;
4
9
use comfy_table:: { presets:: ASCII_MARKDOWN , Attribute , Cell , CellAlignment , Color , Table } ;
5
10
use eyre:: Result ;
6
11
use foundry_block_explorers:: contract:: Metadata ;
@@ -181,11 +186,13 @@ impl ProjectCompiler {
181
186
}
182
187
183
188
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
+ }
189
196
}
190
197
191
198
self . handle_output ( & output) ;
@@ -205,26 +212,32 @@ impl ProjectCompiler {
205
212
for ( name, ( _, version) ) in output. versioned_artifacts ( ) {
206
213
artifacts. entry ( version) . or_default ( ) . push ( name) ;
207
214
}
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
+ }
217
229
}
218
230
}
219
231
}
220
232
221
233
if print_sizes {
222
234
// add extra newline if names were already printed
223
- if print_names {
235
+ if print_names && !shell :: is_json ( ) {
224
236
let _ = sh_println ! ( ) ;
225
237
}
226
238
227
- let mut size_report = SizeReport { contracts : BTreeMap :: new ( ) } ;
239
+ let mut size_report =
240
+ SizeReport { report_kind : report_kind ( ) , contracts : BTreeMap :: new ( ) } ;
228
241
229
242
let artifacts: BTreeMap < _ , _ > = output
230
243
. artifact_ids ( )
@@ -278,6 +291,8 @@ const CONTRACT_INITCODE_SIZE_LIMIT: usize = 49152;
278
291
279
292
/// Contracts with info about their size
280
293
pub struct SizeReport {
294
+ /// What kind of report to generate.
295
+ report_kind : ReportKind ,
281
296
/// `contract name -> info`
282
297
pub contracts : BTreeMap < String , ContractInfo > ,
283
298
}
@@ -316,6 +331,43 @@ impl SizeReport {
316
331
317
332
impl Display for SizeReport {
318
333
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 {
319
371
let mut table = Table :: new ( ) ;
320
372
table. load_preset ( ASCII_MARKDOWN ) ;
321
373
table. set_header ( [
@@ -366,8 +418,7 @@ impl Display for SizeReport {
366
418
] ) ;
367
419
}
368
420
369
- writeln ! ( f, "{table}" ) ?;
370
- Ok ( ( ) )
421
+ table
371
422
}
372
423
}
373
424
@@ -476,7 +527,7 @@ pub fn etherscan_project(
476
527
/// Configures the reporter and runs the given closure.
477
528
pub fn with_compilation_reporter < O > ( quiet : bool , f : impl FnOnce ( ) -> O ) -> O {
478
529
#[ allow( clippy:: collapsible_else_if) ]
479
- let reporter = if quiet {
530
+ let reporter = if quiet || shell :: is_json ( ) {
480
531
Report :: new ( NoReporter :: default ( ) )
481
532
} else {
482
533
if std:: io:: stdout ( ) . is_terminal ( ) {
0 commit comments