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