qlty_coverage/parser/
jacoco.rs

1use crate::Parser;
2use anyhow::{Context, Result};
3use qlty_types::tests::v1::FileCoverage;
4use serde::Deserialize;
5use serde_xml_rs;
6
7#[derive(Debug, Deserialize)]
8#[serde(rename = "report")]
9struct JacocoSource {
10    package: Vec<Package>,
11}
12
13#[derive(Debug, Deserialize)]
14struct Package {
15    name: String,
16    sourcefile: Vec<Sourcefile>,
17}
18
19#[derive(Debug, Deserialize)]
20struct Sourcefile {
21    name: String,
22    line: Vec<Line>,
23}
24
25#[derive(Debug, Deserialize)]
26struct Line {
27    nr: i64,
28    ci: i64,
29}
30
31pub struct Jacoco {}
32
33impl Jacoco {
34    pub fn new() -> Self {
35        Self {}
36    }
37}
38
39impl Parser for Jacoco {
40    fn parse_text(&self, text: &str) -> Result<Vec<FileCoverage>> {
41        let source: JacocoSource =
42            serde_xml_rs::from_str(text).with_context(|| "Failed to parse XML text")?;
43        let mut file_coverages: Vec<FileCoverage> = vec![];
44
45        for package in source.package.iter() {
46            for sourcefile in package.sourcefile.iter() {
47                let mut line_hits = Vec::new();
48                for line in sourcefile.line.iter() {
49                    // Fill in any missing lines with -1 to indicate that are omitted
50                    for _x in (line_hits.len() as i64)..(line.nr - 1) {
51                        line_hits.push(-1)
52                    }
53
54                    line_hits.push(line.ci);
55                }
56
57                let path = format!("{}/{}", package.name, sourcefile.name);
58
59                let file_coverage = FileCoverage {
60                    path,
61                    hits: line_hits,
62                    ..Default::default()
63                };
64
65                file_coverages.push(file_coverage);
66            }
67        }
68
69        Ok(file_coverages)
70    }
71}