shape_vm/feature_tests/
coverage.rs1use std::collections::{BTreeMap, BTreeSet};
7
8use super::PEST_RULES;
9use super::all_feature_tests;
10
11pub fn analyze_coverage() -> CoverageReport {
17 let grammar: BTreeSet<&str> = PEST_RULES.iter().copied().collect();
18
19 let mut covered: BTreeSet<&str> = BTreeSet::new();
21 let mut test_coverage: BTreeMap<&str, Vec<&str>> = BTreeMap::new();
22
23 for test in all_feature_tests() {
24 for &feature in test.covers {
25 covered.insert(feature);
26 test_coverage.entry(feature).or_default().push(test.name);
27 }
28 }
29
30 let uncovered: Vec<&str> = grammar.difference(&covered).copied().collect();
32
33 let unknown: Vec<&str> = covered.difference(&grammar).copied().collect();
35
36 let coverage_pct = if grammar.is_empty() {
37 0.0
38 } else {
39 (covered.intersection(&grammar).count() as f64 / grammar.len() as f64) * 100.0
40 };
41
42 CoverageReport {
43 total_grammar_features: grammar.len(),
44 covered_features: covered.intersection(&grammar).count(),
45 uncovered_features: uncovered,
46 unknown_features: unknown,
47 test_coverage,
48 coverage_pct,
49 }
50}
51
52#[derive(Debug)]
53pub struct CoverageReport {
54 pub total_grammar_features: usize,
55 pub covered_features: usize,
56 pub uncovered_features: Vec<&'static str>,
57 pub unknown_features: Vec<&'static str>,
58 pub test_coverage: BTreeMap<&'static str, Vec<&'static str>>,
59 pub coverage_pct: f64,
60}
61
62impl std::fmt::Display for CoverageReport {
63 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64 writeln!(f, "Feature Coverage Report")?;
65 writeln!(f, "======================")?;
66 writeln!(
67 f,
68 "Coverage: {:.1}% ({}/{} grammar rules)",
69 self.coverage_pct, self.covered_features, self.total_grammar_features
70 )?;
71 writeln!(f)?;
72
73 if !self.uncovered_features.is_empty() {
74 writeln!(
75 f,
76 "Uncovered Grammar Rules ({}):",
77 self.uncovered_features.len()
78 )?;
79 for feature in &self.uncovered_features {
80 writeln!(f, " - {}", feature)?;
81 }
82 writeln!(f)?;
83 }
84
85 if !self.unknown_features.is_empty() {
86 writeln!(
87 f,
88 "Test features not in grammar ({}):",
89 self.unknown_features.len()
90 )?;
91 for feature in &self.unknown_features {
92 writeln!(f, " - {}", feature)?;
93 }
94 }
95
96 Ok(())
97 }
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103
104 #[test]
105 fn test_coverage_report() {
106 let report = analyze_coverage();
107 println!("{}", report);
108 assert!(
109 report.total_grammar_features > 0,
110 "Expected grammar features to be extracted from pest"
111 );
112 }
113}