1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
use crate::coverage::{PackageCoverage, TotalCoverage};
use crate::error::*;
use crate::rule::{default_rules, Rule, SourceCode};
pub struct CoverageFixer {
rules: Vec<Box<dyn Rule>>,
}
impl CoverageFixer {
pub fn new() -> Self {
Self {
rules: default_rules(),
}
}
pub fn with_rules<I: Into<Vec<Box<dyn Rule>>>>(rules: I) -> Self {
Self {
rules: rules.into(),
}
}
pub fn fix(&self, data: &mut PackageCoverage) -> Result<(), Error> {
if self.rules.is_empty() {
debugln!("Skipping fix because rules are empty");
}
let old = CoverageSummary::new(data);
debugln!("Fixing package coverage");
for file_cov in &mut data.file_coverages {
file_cov.line_coverages.sort_by_key(|v| v.line_number);
file_cov.branch_coverages.sort_by_key(|v| v.line_number);
let path = file_cov.path();
debugln!("Processing file {:?}", path);
let source = SourceCode::new(path)?;
for rule in self.rules.iter() {
rule.fix_file_coverage(&source, file_cov);
}
file_cov.line_coverages.retain(|v| v.count.is_some());
file_cov.branch_coverages.retain(|v| v.taken.is_some());
}
let new = CoverageSummary::new(data);
infoln!("Coverages are fixed successfully!");
infoln!(
" line: {:.2}% ({} of {} lines) => {:.2}% ({} of {} lines)",
old.line_percent(),
old.line_executed,
old.line_total,
new.line_percent(),
new.line_executed,
new.line_total,
);
infoln!(
" branch: {:.2}% ({} of {} branches) => {:.2}% ({} of {} branches)\n",
old.branch_percent(),
old.branch_executed,
old.branch_total,
new.branch_percent(),
new.branch_executed,
new.branch_total,
);
Ok(())
}
}
impl Default for CoverageFixer {
fn default() -> Self {
Self::new()
}
}
struct CoverageSummary {
line_executed: usize,
line_total: usize,
branch_executed: usize,
branch_total: usize,
}
impl CoverageSummary {
fn new(data: &PackageCoverage) -> Self {
Self {
line_executed: data.line_executed(),
line_total: data.line_total(),
branch_executed: data.branch_executed(),
branch_total: data.branch_total(),
}
}
fn line_percent(&self) -> f64 {
(self.line_executed as f64) / (self.line_total as f64) * 100.0
}
fn branch_percent(&self) -> f64 {
(self.branch_executed as f64) / (self.branch_total as f64) * 100.0
}
}