fn parse_jacoco_report_package()

in src/parser.rs [733:823]


fn parse_jacoco_report_package<T: BufRead>(
    parser: &mut Reader<T>,
    buf: &mut Vec<u8>,
    package: &str,
) -> Result<Vec<(String, CovResult)>, ParserError> {
    let mut results_map: FxHashMap<String, CovResult> = FxHashMap::default();

    loop {
        match parser.read_event_into(buf) {
            Ok(Event::Start(ref e)) => {
                match e.local_name().into_inner() {
                    b"class" => {
                        let fq_class = get_xml_attribute(parser, e, "name")?;
                        // Class name: "Person$Age"
                        let class = fq_class
                            .split('/')
                            .next_back()
                            .expect("Failed to parse class name");
                        // Class name "Person"
                        let top_class = class
                            .split('$')
                            .next()
                            .expect("Failed to parse top class name");
                        // Fully qualified class name: "org/example/Person$Age"
                        // Generally, we will use the filename if its present,
                        // but if it isn't, fallback to the top level class name
                        let file = get_xml_attribute(parser, e, "sourcefilename")
                            .unwrap_or(format!("{}.java", top_class));

                        // Process all <method /> and <counter /> for this class
                        let functions = parse_jacoco_report_class(parser, buf, class)?;

                        match results_map.entry(file.to_string()) {
                            hash_map::Entry::Occupied(obj) => {
                                obj.into_mut().functions.extend(functions);
                            }
                            hash_map::Entry::Vacant(v) => {
                                v.insert(CovResult {
                                    functions,
                                    lines: BTreeMap::new(),
                                    branches: BTreeMap::new(),
                                });
                            }
                        };
                    }
                    b"sourcefile" => {
                        // Fully qualified class name: "org/example/Person$Age"
                        let file = get_xml_attribute(parser, e, "name")?;

                        let JacocoReport { lines, branches } =
                            parse_jacoco_report_sourcefile(parser, buf)?;

                        match results_map.entry(file.to_string()) {
                            hash_map::Entry::Occupied(obj) => {
                                let obj = obj.into_mut();
                                obj.lines = lines;
                                obj.branches = branches;
                            }
                            hash_map::Entry::Vacant(v) => {
                                v.insert(CovResult {
                                    functions: FxHashMap::default(),
                                    lines,
                                    branches,
                                });
                            }
                        };
                    }
                    &_ => {}
                }
            }
            Ok(Event::End(ref e)) if e.local_name().into_inner() == b"package" => break,
            Err(e) => return Err(ParserError::Parse(e.to_string())),
            _ => {}
        }
    }

    // Change all keys from the class name to the file name and turn the result into a Vec.
    // If package is the empty string, we have to trim the leading '/' in order to obtain a
    // relative path.
    Ok(results_map
        .into_iter()
        .map(|(class, result)| {
            (
                format!("{}/{}", package, class)
                    .trim_start_matches('/')
                    .to_string(),
                result,
            )
        })
        .collect())
}