qlty_coverage/parser/
lcov.rs1use crate::Parser;
2use anyhow::Result;
3use qlty_types::tests::v1::FileCoverage;
4use std::collections::HashMap;
5
6#[derive(Debug, Clone, PartialEq, Eq, Default)]
7pub struct Lcov {}
8
9impl Lcov {
10 pub fn new() -> Self {
11 Self {}
12 }
13}
14
15impl Parser for Lcov {
16 fn parse_text(&self, text: &str) -> Result<Vec<FileCoverage>> {
17 let mut file_coverages = vec![];
18 let mut lcov_lines = text.lines();
19
20 while let Some(lcov_line) = lcov_lines.next() {
21 if let Some(path_string) = lcov_line.strip_prefix(SF) {
22 let file_coverage_path = path_string.to_string();
23
24 let mut file_coverage = FileCoverage {
25 path: file_coverage_path,
26 ..Default::default()
27 };
28
29 let mut line_numbers_to_hits = HashMap::new();
30
31 for lcov_line in lcov_lines.by_ref() {
32 if let Some(lcov_line) = lcov_line.strip_prefix(DA) {
33 let mut split = lcov_line.split(',');
34
35 let line_number = split.next().unwrap();
36 let line_number = line_number.parse::<u32>().unwrap();
37
38 let hits_count = split.next().unwrap();
39 let hits_count = hits_count.parse::<u64>().unwrap();
40
41 *line_numbers_to_hits.entry(line_number).or_insert(0) += hits_count;
42 } else if lcov_line.starts_with(END_OF_RECORD) {
43 break;
44 }
45 }
46
47 let maximum_line_number = line_numbers_to_hits.keys().max().unwrap();
48 let mut line_hits: Vec<i64> = vec![-1; *maximum_line_number as usize];
49
50 for (line_number, hits) in line_numbers_to_hits {
51 line_hits[(line_number - 1) as usize] = hits as i64;
52 }
53
54 file_coverage.hits = line_hits;
55 file_coverages.push(file_coverage);
56 }
57 }
58
59 Ok(file_coverages)
60 }
61}
62
63const SF: &str = "SF:";
64const DA: &str = "DA:";
65const END_OF_RECORD: &str = "end_of_record";
66
67#[cfg(test)]
68mod test {
69 use super::*;
70
71 #[test]
72 fn simple() {
73 let input = r#"
74SF:src/lib.rs
75DA:1,1
76DA:2,0
77DA:5,10
78"#;
79
80 insta::assert_yaml_snapshot!(Lcov::new().parse_text(input).unwrap(), @r#"
81 - path: src/lib.rs
82 hits:
83 - "1"
84 - "0"
85 - "-1"
86 - "-1"
87 - "10"
88 "#);
89 }
90}