Cherry picked cef3276521ba005fa30af46130dba2836347b1ae
This commit is contained in:
		
							parent
							
								
									cd42f51f1a
								
							
						
					
					
						commit
						8ac09025f5
					
				|  | @ -38,6 +38,7 @@ impl LspProject { | ||||||
|             PropertyTest::DEFAULT_MAX_SUCCESS, |             PropertyTest::DEFAULT_MAX_SUCCESS, | ||||||
|             Tracing::verbose(), |             Tracing::verbose(), | ||||||
|             None, |             None, | ||||||
|  |             false, | ||||||
|         ); |         ); | ||||||
| 
 | 
 | ||||||
|         self.project.restore(checkpoint); |         self.project.restore(checkpoint); | ||||||
|  |  | ||||||
|  | @ -197,11 +197,13 @@ where | ||||||
|         uplc: bool, |         uplc: bool, | ||||||
|         tracing: Tracing, |         tracing: Tracing, | ||||||
|         env: Option<String>, |         env: Option<String>, | ||||||
|  |         json: bool, | ||||||
|     ) -> Result<(), Vec<Error>> { |     ) -> Result<(), Vec<Error>> { | ||||||
|         let options = Options { |         let options = Options { | ||||||
|             code_gen_mode: CodeGenMode::Build(uplc), |             code_gen_mode: CodeGenMode::Build(uplc), | ||||||
|             tracing, |             tracing, | ||||||
|             env, |             env, | ||||||
|  |             json, | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         self.compile(options) |         self.compile(options) | ||||||
|  | @ -225,7 +227,7 @@ where | ||||||
| 
 | 
 | ||||||
|         let mut modules = self.parse_sources(self.config.name.clone())?; |         let mut modules = self.parse_sources(self.config.name.clone())?; | ||||||
| 
 | 
 | ||||||
|         self.type_check(&mut modules, Tracing::silent(), None, false)?; |         self.type_check(&mut modules, Tracing::silent(), None, false, false)?; | ||||||
| 
 | 
 | ||||||
|         let destination = destination.unwrap_or_else(|| self.root.join("docs")); |         let destination = destination.unwrap_or_else(|| self.root.join("docs")); | ||||||
| 
 | 
 | ||||||
|  | @ -267,6 +269,7 @@ where | ||||||
|         property_max_success: usize, |         property_max_success: usize, | ||||||
|         tracing: Tracing, |         tracing: Tracing, | ||||||
|         env: Option<String>, |         env: Option<String>, | ||||||
|  |         json: bool, | ||||||
|     ) -> Result<(), Vec<Error>> { |     ) -> Result<(), Vec<Error>> { | ||||||
|         let options = Options { |         let options = Options { | ||||||
|             tracing, |             tracing, | ||||||
|  | @ -282,6 +285,7 @@ where | ||||||
|                     property_max_success, |                     property_max_success, | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|  |             json: json, | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         self.compile(options) |         self.compile(options) | ||||||
|  | @ -343,6 +347,7 @@ where | ||||||
|                 root: self.root.clone(), |                 root: self.root.clone(), | ||||||
|                 name: self.config.name.to_string(), |                 name: self.config.name.to_string(), | ||||||
|                 version: self.config.version.clone(), |                 version: self.config.version.clone(), | ||||||
|  |                 json: options.json, | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
|         let env = options.env.as_deref(); |         let env = options.env.as_deref(); | ||||||
|  | @ -353,7 +358,7 @@ where | ||||||
| 
 | 
 | ||||||
|         let mut modules = self.parse_sources(self.config.name.clone())?; |         let mut modules = self.parse_sources(self.config.name.clone())?; | ||||||
| 
 | 
 | ||||||
|         self.type_check(&mut modules, options.tracing, env, true)?; |         self.type_check(&mut modules, options.tracing, env, true, options.json)?; | ||||||
| 
 | 
 | ||||||
|         match options.code_gen_mode { |         match options.code_gen_mode { | ||||||
|             CodeGenMode::Build(uplc_dump) => { |             CodeGenMode::Build(uplc_dump) => { | ||||||
|  | @ -400,7 +405,8 @@ where | ||||||
|                     self.collect_tests(verbose, match_tests, exact_match, options.tracing)?; |                     self.collect_tests(verbose, match_tests, exact_match, options.tracing)?; | ||||||
| 
 | 
 | ||||||
|                 if !tests.is_empty() { |                 if !tests.is_empty() { | ||||||
|                     self.event_listener.handle_event(Event::RunningTests); |                     self.event_listener | ||||||
|  |                         .handle_event(Event::RunningTests { json: options.json }); | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 let tests = self.run_tests(tests, seed, property_max_success); |                 let tests = self.run_tests(tests, seed, property_max_success); | ||||||
|  | @ -427,8 +433,11 @@ where | ||||||
|                     }) |                     }) | ||||||
|                     .collect(); |                     .collect(); | ||||||
| 
 | 
 | ||||||
|                 self.event_listener |                 self.event_listener.handle_event(Event::FinishedTests { | ||||||
|                     .handle_event(Event::FinishedTests { seed, tests }); |                     seed, | ||||||
|  |                     tests, | ||||||
|  |                     json: options.json, | ||||||
|  |                 }); | ||||||
| 
 | 
 | ||||||
|                 if !errors.is_empty() { |                 if !errors.is_empty() { | ||||||
|                     Err(errors) |                     Err(errors) | ||||||
|  | @ -637,7 +646,11 @@ where | ||||||
|         Ok(blueprint) |         Ok(blueprint) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn with_dependencies(&mut self, parsed_packages: &mut ParsedModules) -> Result<(), Vec<Error>> { |     fn with_dependencies( | ||||||
|  |         &mut self, | ||||||
|  |         parsed_packages: &mut ParsedModules, | ||||||
|  |         json: bool, | ||||||
|  |     ) -> Result<(), Vec<Error>> { | ||||||
|         let manifest = deps::download(&self.event_listener, &self.root, &self.config)?; |         let manifest = deps::download(&self.event_listener, &self.root, &self.config)?; | ||||||
| 
 | 
 | ||||||
|         for package in manifest.packages { |         for package in manifest.packages { | ||||||
|  | @ -648,6 +661,7 @@ where | ||||||
|                     root: lib.clone(), |                     root: lib.clone(), | ||||||
|                     name: package.name.to_string(), |                     name: package.name.to_string(), | ||||||
|                     version: package.version.clone(), |                     version: package.version.clone(), | ||||||
|  |                     json, | ||||||
|                 }); |                 }); | ||||||
| 
 | 
 | ||||||
|             self.read_package_source_files(&lib.join("lib"))?; |             self.read_package_source_files(&lib.join("lib"))?; | ||||||
|  | @ -836,10 +850,11 @@ where | ||||||
|         tracing: Tracing, |         tracing: Tracing, | ||||||
|         env: Option<&str>, |         env: Option<&str>, | ||||||
|         validate_module_name: bool, |         validate_module_name: bool, | ||||||
|  |         json: bool, | ||||||
|     ) -> Result<(), Vec<Error>> { |     ) -> Result<(), Vec<Error>> { | ||||||
|         let our_modules: BTreeSet<String> = modules.keys().cloned().collect(); |         let our_modules: BTreeSet<String> = modules.keys().cloned().collect(); | ||||||
| 
 | 
 | ||||||
|         self.with_dependencies(modules)?; |         self.with_dependencies(modules, json)?; | ||||||
| 
 | 
 | ||||||
|         for name in modules.sequence(&our_modules)? { |         for name in modules.sequence(&our_modules)? { | ||||||
|             if let Some(module) = modules.remove(&name) { |             if let Some(module) = modules.remove(&name) { | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ pub struct Options { | ||||||
|     pub code_gen_mode: CodeGenMode, |     pub code_gen_mode: CodeGenMode, | ||||||
|     pub tracing: Tracing, |     pub tracing: Tracing, | ||||||
|     pub env: Option<String>, |     pub env: Option<String>, | ||||||
|  |     pub json: bool, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Default for Options { | impl Default for Options { | ||||||
|  | @ -12,6 +13,7 @@ impl Default for Options { | ||||||
|             code_gen_mode: CodeGenMode::NoOp, |             code_gen_mode: CodeGenMode::NoOp, | ||||||
|             tracing: Tracing::silent(), |             tracing: Tracing::silent(), | ||||||
|             env: None, |             env: None, | ||||||
|  |             json: false, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ use aiken_lang::{ | ||||||
|     test_framework::{PropertyTestResult, TestResult, UnitTestResult}, |     test_framework::{PropertyTestResult, TestResult, UnitTestResult}, | ||||||
| }; | }; | ||||||
| use owo_colors::{OwoColorize, Stream::Stderr}; | use owo_colors::{OwoColorize, Stream::Stderr}; | ||||||
|  | use serde_json::json; | ||||||
| use std::{collections::BTreeMap, fmt::Display, path::PathBuf}; | use std::{collections::BTreeMap, fmt::Display, path::PathBuf}; | ||||||
| use uplc::machine::cost_model::ExBudget; | use uplc::machine::cost_model::ExBudget; | ||||||
| 
 | 
 | ||||||
|  | @ -18,6 +19,7 @@ pub enum Event { | ||||||
|         name: String, |         name: String, | ||||||
|         version: String, |         version: String, | ||||||
|         root: PathBuf, |         root: PathBuf, | ||||||
|  |         json: bool, | ||||||
|     }, |     }, | ||||||
|     BuildingDocumentation { |     BuildingDocumentation { | ||||||
|         name: String, |         name: String, | ||||||
|  | @ -37,10 +39,13 @@ pub enum Event { | ||||||
|         name: String, |         name: String, | ||||||
|         path: PathBuf, |         path: PathBuf, | ||||||
|     }, |     }, | ||||||
|     RunningTests, |     RunningTests { | ||||||
|  |         json: bool, | ||||||
|  |     }, | ||||||
|     FinishedTests { |     FinishedTests { | ||||||
|         seed: u32, |         seed: u32, | ||||||
|         tests: Vec<TestResult<UntypedExpr, UntypedExpr>>, |         tests: Vec<TestResult<UntypedExpr, UntypedExpr>>, | ||||||
|  |         json: bool, | ||||||
|     }, |     }, | ||||||
|     WaitingForBuildDirLock, |     WaitingForBuildDirLock, | ||||||
|     ResolvingPackages { |     ResolvingPackages { | ||||||
|  | @ -81,17 +86,20 @@ impl EventListener for Terminal { | ||||||
|                 name, |                 name, | ||||||
|                 version, |                 version, | ||||||
|                 root, |                 root, | ||||||
|  |                 json, | ||||||
|             } => { |             } => { | ||||||
|                 eprintln!( |                 if !json { | ||||||
|                     "{} {} {} ({})", |                     eprintln!( | ||||||
|                     "    Compiling" |                         "{} {} {} ({})", | ||||||
|                         .if_supports_color(Stderr, |s| s.bold()) |                         "    Compiling" | ||||||
|                         .if_supports_color(Stderr, |s| s.purple()), |                             .if_supports_color(Stderr, |s| s.bold()) | ||||||
|                     name.if_supports_color(Stderr, |s| s.bold()), |                             .if_supports_color(Stderr, |s| s.purple()), | ||||||
|                     version, |                         name.if_supports_color(Stderr, |s| s.bold()), | ||||||
|                     root.display() |                         version, | ||||||
|                         .if_supports_color(Stderr, |s| s.bright_blue()) |                         root.display() | ||||||
|                 ); |                             .if_supports_color(Stderr, |s| s.bright_blue()) | ||||||
|  |                     ); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|             Event::BuildingDocumentation { |             Event::BuildingDocumentation { | ||||||
|                 name, |                 name, | ||||||
|  | @ -169,53 +177,70 @@ impl EventListener for Terminal { | ||||||
|                     name.if_supports_color(Stderr, |s| s.bright_blue()), |                     name.if_supports_color(Stderr, |s| s.bright_blue()), | ||||||
|                 ); |                 ); | ||||||
|             } |             } | ||||||
|             Event::RunningTests => { |             Event::RunningTests { json } => { | ||||||
|                 eprintln!( |                 if !json { | ||||||
|                     "{} {}", |                     eprintln!( | ||||||
|                     "      Testing" |                         "{} {}\n", | ||||||
|                         .if_supports_color(Stderr, |s| s.bold()) |                         "      Testing" | ||||||
|                         .if_supports_color(Stderr, |s| s.purple()), |                             .if_supports_color(Stderr, |s| s.bold()) | ||||||
|                     "...".if_supports_color(Stderr, |s| s.bold()) |                             .if_supports_color(Stderr, |s| s.purple()), | ||||||
|                 ); |                         "...".if_supports_color(Stderr, |s| s.bold()) | ||||||
|  |                     ); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|             Event::FinishedTests { seed, tests } => { |             Event::FinishedTests { seed, tests, json } => { | ||||||
|                 let (max_mem, max_cpu, max_iter) = find_max_execution_units(&tests); |                 let (max_mem, max_cpu, max_iter) = find_max_execution_units(&tests); | ||||||
| 
 | 
 | ||||||
|                 for (module, results) in &group_by_module(&tests) { |                 if json { | ||||||
|                     let title = module |                     let json_output = serde_json::json!({ | ||||||
|                         .if_supports_color(Stderr, |s| s.bold()) |                         "seed": seed, | ||||||
|                         .if_supports_color(Stderr, |s| s.blue()) |                         "modules": group_by_module(&tests).iter().map(|(module, results)| { | ||||||
|                         .to_string(); |                             serde_json::json!({ | ||||||
|  |                                 "name": module, | ||||||
|  |                                 "tests": results.iter().map(|r| fmt_test_json(r, max_mem, max_cpu, max_iter)).collect::<Vec<_>>(), | ||||||
|  |                                 "summary": fmt_test_summary_json(results) | ||||||
|  |                             }) | ||||||
|  |                         }).collect::<Vec<_>>(), | ||||||
|  |                         "summary": fmt_overall_summary_json(&tests) | ||||||
|  |                     }); | ||||||
|  |                     println!("{}", serde_json::to_string_pretty(&json_output).unwrap()); | ||||||
|  |                 } else { | ||||||
|  |                     for (module, results) in &group_by_module(&tests) { | ||||||
|  |                         let title = module | ||||||
|  |                             .if_supports_color(Stderr, |s| s.bold()) | ||||||
|  |                             .if_supports_color(Stderr, |s| s.blue()) | ||||||
|  |                             .to_string(); | ||||||
| 
 | 
 | ||||||
|                     let tests = results |                         let tests = results | ||||||
|                         .iter() |                             .iter() | ||||||
|                         .map(|r| fmt_test(r, max_mem, max_cpu, max_iter, true)) |                             .map(|r| fmt_test(r, max_mem, max_cpu, max_iter, true)) | ||||||
|                         .collect::<Vec<String>>() |                             .collect::<Vec<String>>() | ||||||
|                         .join("\n"); |                             .join("\n"); | ||||||
| 
 | 
 | ||||||
|                     let seed_info = if results |                         let seed_info = if results | ||||||
|                         .iter() |                             .iter() | ||||||
|                         .any(|t| matches!(t, TestResult::PropertyTestResult { .. })) |                             .any(|t| matches!(t, TestResult::PropertyTestResult { .. })) | ||||||
|                     { |                         { | ||||||
|                         format!( |                             format!( | ||||||
|                             "with {opt}={seed} → ", |                                 "with {opt}={seed} → ", | ||||||
|                             opt = "--seed".if_supports_color(Stderr, |s| s.bold()), |                                 opt = "--seed".if_supports_color(Stderr, |s| s.bold()), | ||||||
|                             seed = format!("{seed}").if_supports_color(Stderr, |s| s.bold()) |                                 seed = format!("{seed}").if_supports_color(Stderr, |s| s.bold()) | ||||||
|                         ) |                             ) | ||||||
|                     } else { |                         } else { | ||||||
|                         String::new() |                             String::new() | ||||||
|                     }; |                         }; | ||||||
| 
 | 
 | ||||||
|                     let summary = format!("{}{}", seed_info, fmt_test_summary(results, true)); |                         let summary = format!("{}{}", seed_info, fmt_test_summary(results, true)); | ||||||
|                     println!( |                         println!( | ||||||
|                         "\n{}", |                             "{}\n", | ||||||
|                         pretty::indent( |                             pretty::indent( | ||||||
|                             &pretty::open_box(&title, &tests, &summary, |border| border |                                 &pretty::open_box(&title, &tests, &summary, |border| border | ||||||
|                                 .if_supports_color(Stderr, |s| s.bright_black()) |                                     .if_supports_color(Stderr, |s| s.bright_black()) | ||||||
|                                 .to_string()), |                                     .to_string()), | ||||||
|                             4 |                                 4 | ||||||
|                         ) |                             ) | ||||||
|                     ); |                         ); | ||||||
|  |                     } | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 if !tests.is_empty() { |                 if !tests.is_empty() { | ||||||
|  | @ -495,7 +520,105 @@ fn fmt_test_summary<T>(tests: &[&TestResult<T, T>], styled: bool) -> String { | ||||||
|     ) |     ) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn group_by_module<T>(results: &Vec<TestResult<T, T>>) -> BTreeMap<String, Vec<&TestResult<T, T>>> { | fn fmt_test_json( | ||||||
|  |     result: &TestResult<UntypedExpr, UntypedExpr>, | ||||||
|  |     max_mem: usize, | ||||||
|  |     max_cpu: usize, | ||||||
|  |     max_iter: usize, | ||||||
|  | ) -> serde_json::Value { | ||||||
|  |     let mut test = json!({ | ||||||
|  |         "name": result.title(), | ||||||
|  |         "status": if result.is_success() { "PASS" } else { "FAIL" }, | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     match result { | ||||||
|  |         TestResult::UnitTestResult(UnitTestResult { | ||||||
|  |             spent_budget, | ||||||
|  |             assertion, | ||||||
|  |             test: unit_test, | ||||||
|  |             .. | ||||||
|  |         }) => { | ||||||
|  |             test["execution_units"] = json!({ | ||||||
|  |                 "memory": spent_budget.mem, | ||||||
|  |                 "cpu": spent_budget.cpu, | ||||||
|  |             }); | ||||||
|  |             if !result.is_success() { | ||||||
|  |                 if let Some(assertion) = assertion { | ||||||
|  |                     test["assertion"] = json!({ | ||||||
|  |                         "message": assertion.to_string(Stderr, false), | ||||||
|  |                         "expected_to_fail": matches!(unit_test.on_test_failure, OnTestFailure::SucceedEventually | OnTestFailure::SucceedImmediately), | ||||||
|  |                     }); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         TestResult::PropertyTestResult(PropertyTestResult { | ||||||
|  |             iterations, | ||||||
|  |             labels, | ||||||
|  |             counterexample, | ||||||
|  |             .. | ||||||
|  |         }) => { | ||||||
|  |             test["iterations"] = json!(iterations); | ||||||
|  |             test["labels"] = json!(labels); | ||||||
|  |             test["counterexample"] = match counterexample { | ||||||
|  |                 Ok(Some(expr)) => json!(Formatter::new().expr(expr, false).to_pretty_string(60)), | ||||||
|  |                 Ok(None) => json!(null), | ||||||
|  |                 Err(err) => json!({"error": err.to_string()}), | ||||||
|  |             }; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if !result.traces().is_empty() { | ||||||
|  |         test["traces"] = json!(result.traces()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     test | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn fmt_test_summary_json(tests: &[&TestResult<UntypedExpr, UntypedExpr>]) -> serde_json::Value { | ||||||
|  |     let total = tests.len(); | ||||||
|  |     let passed = tests.iter().filter(|t| t.is_success()).count(); | ||||||
|  |     let failed = total - passed; | ||||||
|  | 
 | ||||||
|  |     json!({ | ||||||
|  |         "total": total, | ||||||
|  |         "passed": passed, | ||||||
|  |         "failed": failed, | ||||||
|  |     }) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn fmt_overall_summary_json(tests: &[TestResult<UntypedExpr, UntypedExpr>]) -> serde_json::Value { | ||||||
|  |     let total = tests.len(); | ||||||
|  |     let passed = tests.iter().filter(|t| t.is_success()).count(); | ||||||
|  |     let failed = total - passed; | ||||||
|  | 
 | ||||||
|  |     let modules = group_by_module(tests); | ||||||
|  |     let module_count = modules.len(); | ||||||
|  | 
 | ||||||
|  |     let (max_mem, max_cpu, max_iter) = find_max_execution_units(tests); | ||||||
|  | 
 | ||||||
|  |     json!({ | ||||||
|  |         "total_tests": total, | ||||||
|  |         "passed_tests": passed, | ||||||
|  |         "failed_tests": failed, | ||||||
|  |         "module_count": module_count, | ||||||
|  |         "max_execution_units": { | ||||||
|  |             "memory": max_mem, | ||||||
|  |             "cpu": max_cpu, | ||||||
|  |         }, | ||||||
|  |         "max_iterations": max_iter, | ||||||
|  |         "modules": modules.into_iter().map(|(module, results)| { | ||||||
|  |             json!({ | ||||||
|  |                 "name": module, | ||||||
|  |                 "tests": results.iter().map(|r| fmt_test_json(r, max_mem, max_cpu, max_iter)).collect::<Vec<_>>(), | ||||||
|  |                 "summary": fmt_test_summary_json(&results), | ||||||
|  |             }) | ||||||
|  |         }).collect::<Vec<_>>(), | ||||||
|  |     }) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn group_by_module( | ||||||
|  |     results: &[TestResult<UntypedExpr, UntypedExpr>], | ||||||
|  | ) -> BTreeMap<String, Vec<&TestResult<UntypedExpr, UntypedExpr>>> { | ||||||
|     let mut modules = BTreeMap::new(); |     let mut modules = BTreeMap::new(); | ||||||
|     for r in results { |     for r in results { | ||||||
|         let xs: &mut Vec<&TestResult<_, _>> = modules.entry(r.module().to_string()).or_default(); |         let xs: &mut Vec<&TestResult<_, _>> = modules.entry(r.module().to_string()).or_default(); | ||||||
|  |  | ||||||
|  | @ -88,7 +88,12 @@ pub fn default_filter(evt: &Event) -> bool { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn with_project<A>(directory: Option<&Path>, deny: bool, mut action: A) -> miette::Result<()> | pub fn with_project<A>( | ||||||
|  |     directory: Option<&Path>, | ||||||
|  |     deny: bool, | ||||||
|  |     json: bool, | ||||||
|  |     mut action: A, | ||||||
|  | ) -> miette::Result<()> | ||||||
| where | where | ||||||
|     A: FnMut(&mut Project<Terminal>) -> Result<(), Vec<crate::error::Error>>, |     A: FnMut(&mut Project<Terminal>) -> Result<(), Vec<crate::error::Error>>, | ||||||
| { | { | ||||||
|  | @ -116,36 +121,38 @@ where | ||||||
| 
 | 
 | ||||||
|     let warning_count = warnings.len(); |     let warning_count = warnings.len(); | ||||||
| 
 | 
 | ||||||
|     for warning in &warnings { |     if !json { | ||||||
|         warning.report() |         for warning in &warnings { | ||||||
|     } |             warning.report() | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|     if let Err(errs) = build_result { |         if let Err(errs) = build_result { | ||||||
|         for err in &errs { |             for err in &errs { | ||||||
|             err.report() |                 err.report() | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             eprintln!( | ||||||
|  |                 "{}", | ||||||
|  |                 Summary { | ||||||
|  |                     check_count: project.checks_count, | ||||||
|  |                     warning_count, | ||||||
|  |                     error_count: errs.len(), | ||||||
|  |                 } | ||||||
|  |             ); | ||||||
|  | 
 | ||||||
|  |             return Err(ExitFailure::into_report()); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         eprintln!( |         eprintln!( | ||||||
|             "{}", |             "{}", | ||||||
|             Summary { |             Summary { | ||||||
|                 check_count: project.checks_count, |                 check_count: project.checks_count, | ||||||
|                 warning_count, |                 error_count: 0, | ||||||
|                 error_count: errs.len(), |                 warning_count | ||||||
|             } |             } | ||||||
|         ); |         ); | ||||||
| 
 |  | ||||||
|         return Err(ExitFailure::into_report()); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     eprintln!( |  | ||||||
|         "{}", |  | ||||||
|         Summary { |  | ||||||
|             check_count: project.checks_count, |  | ||||||
|             error_count: 0, |  | ||||||
|             warning_count |  | ||||||
|         } |  | ||||||
|     ); |  | ||||||
| 
 |  | ||||||
|     if warning_count > 0 && deny { |     if warning_count > 0 && deny { | ||||||
|         Err(ExitFailure::into_report()) |         Err(ExitFailure::into_report()) | ||||||
|     } else { |     } else { | ||||||
|  | @ -239,7 +246,7 @@ where | ||||||
|                     .if_supports_color(Stderr, |s| s.bold()) |                     .if_supports_color(Stderr, |s| s.bold()) | ||||||
|                     .if_supports_color(Stderr, |s| s.purple()), |                     .if_supports_color(Stderr, |s| s.purple()), | ||||||
|             ); |             ); | ||||||
|             with_project(directory, false, &mut action).unwrap_or(()) |             with_project(directory, false, false, &mut action).unwrap_or(()) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -33,7 +33,7 @@ pub fn exec( | ||||||
|         mainnet, |         mainnet, | ||||||
|     }: Args, |     }: Args, | ||||||
| ) -> miette::Result<()> { | ) -> miette::Result<()> { | ||||||
|     with_project(directory.as_deref(), false, |p| { |     with_project(directory.as_deref(), false, false, |p| { | ||||||
|         let title = module.as_ref().map(|m| { |         let title = module.as_ref().map(|m| { | ||||||
|             format!( |             format!( | ||||||
|                 "{m}{}", |                 "{m}{}", | ||||||
|  |  | ||||||
|  | @ -54,7 +54,7 @@ pub fn exec( | ||||||
|         validator, |         validator, | ||||||
|     }: Args, |     }: Args, | ||||||
| ) -> miette::Result<()> { | ) -> miette::Result<()> { | ||||||
|     with_project(None, false, |p| { |     with_project(None, false, false, |p| { | ||||||
|         let title = module.as_ref().map(|m| { |         let title = module.as_ref().map(|m| { | ||||||
|             format!( |             format!( | ||||||
|                 "{m}{}", |                 "{m}{}", | ||||||
|  |  | ||||||
|  | @ -23,7 +23,7 @@ pub fn exec( | ||||||
|         validator, |         validator, | ||||||
|     }: Args, |     }: Args, | ||||||
| ) -> miette::Result<()> { | ) -> miette::Result<()> { | ||||||
|     with_project(directory.as_deref(), false, |p| { |     with_project(directory.as_deref(), false, false, |p| { | ||||||
|         let title = module.as_ref().map(|m| { |         let title = module.as_ref().map(|m| { | ||||||
|             format!( |             format!( | ||||||
|                 "{m}{}", |                 "{m}{}", | ||||||
|  |  | ||||||
|  | @ -23,7 +23,7 @@ pub fn exec( | ||||||
|         validator, |         validator, | ||||||
|     }: Args, |     }: Args, | ||||||
| ) -> miette::Result<()> { | ) -> miette::Result<()> { | ||||||
|     with_project(directory.as_deref(), false, |p| { |     with_project(directory.as_deref(), false, false, |p| { | ||||||
|         let title = module.as_ref().map(|m| { |         let title = module.as_ref().map(|m| { | ||||||
|             format!( |             format!( | ||||||
|                 "{m}{}", |                 "{m}{}", | ||||||
|  |  | ||||||
|  | @ -79,10 +79,11 @@ pub fn exec( | ||||||
|                     None => Tracing::All(trace_level), |                     None => Tracing::All(trace_level), | ||||||
|                 }, |                 }, | ||||||
|                 env.clone(), |                 env.clone(), | ||||||
|  |                 false, | ||||||
|             ) |             ) | ||||||
|         }) |         }) | ||||||
|     } else { |     } else { | ||||||
|         with_project(directory.as_deref(), deny, |p| { |         with_project(directory.as_deref(), deny, false, |p| { | ||||||
|             p.build( |             p.build( | ||||||
|                 uplc, |                 uplc, | ||||||
|                 match trace_filter { |                 match trace_filter { | ||||||
|  | @ -90,6 +91,7 @@ pub fn exec( | ||||||
|                     None => Tracing::All(trace_level), |                     None => Tracing::All(trace_level), | ||||||
|                 }, |                 }, | ||||||
|                 env.clone(), |                 env.clone(), | ||||||
|  |                 false, | ||||||
|             ) |             ) | ||||||
|         }) |         }) | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  | @ -84,6 +84,10 @@ pub struct Args { | ||||||
|     /// [optional]
 |     /// [optional]
 | ||||||
|     #[clap(short, long, value_parser=trace_level_parser(), default_value_t=TraceLevel::Verbose, verbatim_doc_comment)] |     #[clap(short, long, value_parser=trace_level_parser(), default_value_t=TraceLevel::Verbose, verbatim_doc_comment)] | ||||||
|     trace_level: TraceLevel, |     trace_level: TraceLevel, | ||||||
|  | 
 | ||||||
|  |     /// Output JSON (useful for scripting & automation)
 | ||||||
|  |     #[clap(long)] | ||||||
|  |     json: bool, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn exec( | pub fn exec( | ||||||
|  | @ -100,6 +104,7 @@ pub fn exec( | ||||||
|         seed, |         seed, | ||||||
|         max_success, |         max_success, | ||||||
|         env, |         env, | ||||||
|  |         json, | ||||||
|     }: Args, |     }: Args, | ||||||
| ) -> miette::Result<()> { | ) -> miette::Result<()> { | ||||||
|     let mut rng = rand::thread_rng(); |     let mut rng = rand::thread_rng(); | ||||||
|  | @ -120,10 +125,11 @@ pub fn exec( | ||||||
|                     None => Tracing::All(trace_level), |                     None => Tracing::All(trace_level), | ||||||
|                 }, |                 }, | ||||||
|                 env.clone(), |                 env.clone(), | ||||||
|  |                 json, | ||||||
|             ) |             ) | ||||||
|         }) |         }) | ||||||
|     } else { |     } else { | ||||||
|         with_project(directory.as_deref(), deny, |p| { |         with_project(directory.as_deref(), deny, json, |p| { | ||||||
|             p.check( |             p.check( | ||||||
|                 skip_tests, |                 skip_tests, | ||||||
|                 match_tests.clone(), |                 match_tests.clone(), | ||||||
|  | @ -136,6 +142,7 @@ pub fn exec( | ||||||
|                     None => Tracing::All(trace_level), |                     None => Tracing::All(trace_level), | ||||||
|                 }, |                 }, | ||||||
|                 env.clone(), |                 env.clone(), | ||||||
|  |                 json, | ||||||
|             ) |             ) | ||||||
|         }) |         }) | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  | @ -38,7 +38,7 @@ pub fn exec( | ||||||
|             p.docs(destination.clone(), include_dependencies) |             p.docs(destination.clone(), include_dependencies) | ||||||
|         }) |         }) | ||||||
|     } else { |     } else { | ||||||
|         with_project(directory.as_deref(), deny, |p| { |         with_project(directory.as_deref(), deny, false, |p| { | ||||||
|             p.docs(destination.clone(), include_dependencies) |             p.docs(destination.clone(), include_dependencies) | ||||||
|         }) |         }) | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  | @ -61,7 +61,7 @@ pub fn exec( | ||||||
|         trace_level, |         trace_level, | ||||||
|     }: Args, |     }: Args, | ||||||
| ) -> miette::Result<()> { | ) -> miette::Result<()> { | ||||||
|     with_project(directory.as_deref(), false, |p| { |     with_project(directory.as_deref(), false, false, |p| { | ||||||
|         p.compile(Options::default())?; |         p.compile(Options::default())?; | ||||||
| 
 | 
 | ||||||
|         let export = p.export( |         let export = p.export( | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Riley-Kilgore
						Riley-Kilgore