fn get_coverage()

in src/cobertura.rs [234:329]


fn get_coverage(
    results: &[ResultTuple],
    sources: Vec<String>,
    demangle: bool,
    demangle_options: DemangleOptions,
) -> Coverage {
    let packages: Vec<Package> = results
        .iter()
        .map(|(_, rel_path, result)| {
            let all_lines: Vec<u32> = result.lines.keys().cloned().collect();

            let end: u32 = result.lines.keys().last().unwrap_or(&0) + 1;

            let mut start_indexes: Vec<u32> = Vec::new();
            for function in result.functions.values() {
                start_indexes.push(function.start);
            }
            start_indexes.sort_unstable();

            let line_from_number = |number| {
                let hits = result.lines.get(&number).cloned().unwrap_or_default();
                if let Some(branches) = result.branches.get(&number) {
                    let conditions = branches
                        .iter()
                        .enumerate()
                        .map(|(i, b)| Condition {
                            cond_type: ConditionType::Jump,
                            coverage: if *b { 1.0 } else { 0.0 },
                            number: i,
                        })
                        .collect::<Vec<_>>();
                    Line::Branch {
                        number,
                        hits,
                        conditions,
                    }
                } else {
                    Line::Plain { number, hits }
                }
            };

            let methods: Vec<Method> = result
                .functions
                .iter()
                .map(|(name, function)| {
                    let mut func_end = end;

                    for start in &start_indexes {
                        if *start > function.start {
                            func_end = *start;
                            break;
                        }
                    }

                    let mut lines_in_function: Vec<u32> = Vec::new();
                    for line in all_lines
                        .iter()
                        .filter(|&&x| x >= function.start && x < func_end)
                    {
                        lines_in_function.push(*line);
                    }

                    let lines: Vec<Line> = lines_in_function
                        .into_iter()
                        .map(line_from_number)
                        .collect();

                    Method {
                        name: demangle!(name, demangle, demangle_options),
                        signature: String::new(),
                        lines,
                    }
                })
                .collect();

            let lines: Vec<Line> = all_lines.into_iter().map(line_from_number).collect();
            let class = Class {
                name: rel_path
                    .file_stem()
                    .map(|x| x.to_str().unwrap())
                    .unwrap_or_default()
                    .to_string(),
                file_name: rel_path.to_str().unwrap_or_default().to_string(),
                lines,
                methods,
            };

            Package {
                name: rel_path.to_str().unwrap_or_default().to_string(),
                classes: vec![class],
            }
        })
        .collect();

    Coverage { sources, packages }
}