qlty_coverage/parser/
coverprofile.rs1use crate::Parser;
2use anyhow::Result;
3use qlty_types::tests::v1::FileCoverage;
4use regex::Regex;
5use std::collections::BTreeMap;
6
7pub struct Coverprofile {}
8
9impl Coverprofile {
10 pub fn new() -> Self {
11 Self {}
12 }
13
14 fn push_line_hits(
15 &self,
16 line_count_map: &BTreeMap<i64, i64>,
17 file_name: &str,
18 file_coverages: &mut Vec<FileCoverage>,
19 ) {
20 let mut line_hits: Vec<i64> = Vec::new();
21 if let Some(last_line) = line_count_map.last_key_value() {
22 if *last_line.0 > 0 {
23 for x in 1..=*last_line.0 {
24 if line_count_map.contains_key(&x) {
25 line_hits.push(*line_count_map.get(&x).unwrap());
26 } else {
27 line_hits.push(-1);
28 }
29 }
30 }
31 }
32 let file_coverage = FileCoverage {
33 path: file_name.to_string(),
34 hits: line_hits,
35 ..Default::default()
36 };
37
38 file_coverages.push(file_coverage);
39 }
40}
41
42impl Parser for Coverprofile {
43 fn parse_text(&self, text: &str) -> Result<Vec<FileCoverage>> {
44 let mut file_coverages: Vec<FileCoverage> = vec![];
45 let mut current_file_name = "";
46 let re = Regex::new(r"(?<start_line>\d+)\.?\d+,(?<end_line>\d+)\.?\d+ ?\d+ (?<count>\d+)")
47 .unwrap();
48
49 let mut line_count_map: BTreeMap<i64, i64> = BTreeMap::new();
51
52 text.split("\n").skip(1).for_each(|line| {
53 if line.is_empty() {
54 return;
55 }
56
57 let tokens: Vec<_> = line.split(":").collect();
58 let file_name = tokens[0];
59 let line_info = tokens[1];
60
61 if current_file_name != file_name {
62 if current_file_name != "" {
63 self.push_line_hits(&line_count_map, current_file_name, &mut file_coverages);
64 line_count_map = BTreeMap::new();
65 }
66
67 current_file_name = file_name;
68 }
69
70 let regex_capture = re.captures(line_info).unwrap();
71 let start_line = regex_capture
72 .name("start_line")
73 .unwrap()
74 .as_str()
75 .parse::<i64>()
76 .unwrap();
77 let end_line = regex_capture
78 .name("end_line")
79 .unwrap()
80 .as_str()
81 .parse::<i64>()
82 .unwrap();
83 let count = regex_capture
84 .name("count")
85 .unwrap()
86 .as_str()
87 .parse::<i64>()
88 .unwrap();
89
90 for x in start_line..(end_line + 1) {
91 line_count_map.insert(x, count);
92 }
93 });
94
95 self.push_line_hits(&line_count_map, current_file_name, &mut file_coverages);
96
97 Ok(file_coverages)
98 }
99}