stern4rust/
json_printer.rs1use std::collections::BTreeSet;
6
7use serde_json::json;
8
9use crate::offence::Offence;
10use crate::offence_threshold::OffenceThreshold;
11
12pub struct JsonPrinter {
20 files_scanned: usize,
21 threshold: OffenceThreshold,
22 applied: Vec<String>,
23 skipped: Vec<String>,
24 unconfigured: Vec<String>,
25}
26
27impl JsonPrinter {
28 pub fn new(files_scanned: usize) -> Self {
29 Self {
30 files_scanned,
31 threshold: OffenceThreshold::default(),
32 applied: Vec::new(),
33 skipped: Vec::new(),
34 unconfigured: Vec::new(),
35 }
36 }
37
38 pub fn with_rules(
42 self,
43 applied: Vec<String>,
44 skipped: Vec<String>,
45 unconfigured: Vec<String>,
46 ) -> Self {
47 Self {
48 applied,
49 skipped,
50 unconfigured,
51 ..self
52 }
53 }
54
55 pub fn with_threshold(self, threshold: OffenceThreshold) -> Self {
56 Self { threshold, ..self }
57 }
58
59 pub fn render(&self, offences: &[Offence]) -> String {
66 let broken: BTreeSet<&str> = offences.iter().map(|offence| offence.rule).collect();
67 let shown = self.threshold.kept(offences);
68 let document = json!({
69 "files_scanned": self.files_scanned,
70 "offences_found": offences.len(),
71 "offences_reported": shown.len(),
72 "offences_omitted": self.threshold.omitted(offences),
73 "offence_threshold": self.threshold.limit(),
74 "rules_broken": broken.len(),
75 "rules_applied": self.applied,
76 "rules_skipped": self.skipped,
77 "rules_unconfigured": self.unconfigured,
78 "offences": shown,
79 });
80 serde_json::to_string_pretty(&document).unwrap_or_default()
81 }
82
83 pub fn print(&self, offences: &[Offence]) {
84 println!("{}", self.render(offences));
85 }
86}