dry4rust/cli/
check_command.rs1use std::io::Write;
7
8use crate::analysis::AnalysisResult;
9use crate::cli::checking::ceiling::Ceiling;
10use crate::cli::checking::check_thresholds::CheckThresholds;
11use crate::cli::cli_error::CliError;
12use crate::cli::cli_error::CliResult;
13use crate::config::Config;
14use crate::grouper::DuplicateGroup;
15use crate::output::check_breach::CheckBreach;
16use crate::output::reporter::Reporter;
17
18pub struct CheckCommand<'a> {
23 config: &'a Config,
24 result: &'a AnalysisResult,
25 reporter: &'a dyn Reporter,
26 thresholds: &'a CheckThresholds,
27}
28
29impl<'a> CheckCommand<'a> {
30 #[must_use]
31 pub const fn new(
32 config: &'a Config,
33 result: &'a AnalysisResult,
34 reporter: &'a dyn Reporter,
35 thresholds: &'a CheckThresholds,
36 ) -> Self {
37 Self {
38 config,
39 result,
40 reporter,
41 thresholds,
42 }
43 }
44
45 pub fn run(&self, writer: &mut impl Write) -> CliResult {
55 let breaches = self.breaches();
56 self.reporter
57 .report_check(&self.result.stats, &breaches, writer)?;
58 if breaches.is_empty() {
59 Ok(())
60 } else {
61 Err(CliError::CheckFailed)
62 }
63 }
64
65 fn breaches(&self) -> Vec<CheckBreach<'a>> {
66 self.ceilings()
67 .into_iter()
68 .filter_map(|(ceiling, of_exact)| {
69 ceiling
70 .breach()
71 .map(|message| CheckBreach::new(message, self.offenders(of_exact), of_exact))
72 })
73 .collect()
74 }
75
76 const fn offenders(&self, of_exact: bool) -> &'a [DuplicateGroup] {
77 if of_exact {
78 self.result.exact_groups.as_slice()
79 } else {
80 self.result.near_groups.as_slice()
81 }
82 }
83
84 fn ceilings(&self) -> [(Ceiling, bool); 4] {
85 let stats = &self.result.stats;
86 [
87 (
88 Ceiling::count(
89 self.thresholds
90 .max_exact
91 .or(self.config.max_exact_duplicates),
92 stats.exact_duplicate_groups,
93 "exact duplicate groups",
94 ),
95 true,
96 ),
97 (
98 Ceiling::count(
99 self.thresholds.max_near.or(self.config.max_near_duplicates),
100 stats.near_duplicate_groups,
101 "near duplicate groups",
102 ),
103 false,
104 ),
105 (
106 Ceiling::percent(
107 self.thresholds
108 .max_exact_percent
109 .or(self.config.max_exact_percent),
110 stats.exact_duplicate_percent(),
111 "exact duplicate lines",
112 ),
113 true,
114 ),
115 (
116 Ceiling::percent(
117 self.thresholds
118 .max_near_percent
119 .or(self.config.max_near_percent),
120 stats.near_duplicate_percent(),
121 "near duplicate lines",
122 ),
123 false,
124 ),
125 ]
126 }
127}