atlas_coverage_core/
lib.rs1#[macro_use]
2extern crate serde_derive;
3extern crate serde;
4extern crate serde_json;
5extern crate vlq;
6extern crate xml;
7extern crate globset;
8extern crate lcov_parser;
9extern crate memmap;
10
11pub mod debug;
12pub mod settings;
13
14mod lcov;
15mod lines;
16mod load;
17mod model;
18mod range;
19mod source_map;
20mod vlq_decode;
21mod util;
22
23use std::path::Path;
24
25use lines::calculate_executable_line_mappings;
26use lines::calculate_line_coverage;
27use lines::FileCoverage;
28use lines::ManyCoverage;
29use model::{PuppeteerData, SourceMap};
30use settings::Settings;
31use source_map::*;
32use std::collections::HashMap;
33use std::collections::HashSet;
34use std::env::args;
35use std::io::Write;
36use std::io;
37
38pub fn process_source_map(settings: &Settings, data: PuppeteerData) -> Option<Vec<FileCoverage>> {
39 if let Some(source_mapping_url) = data.get_source_mapping_url() {
40 let source_path = data.url.replace(&settings.public_url_base, &settings.dist_path);
41
42 let source_mapping_url = source_mapping_url.replace("//# sourceMappingURL=", "");
43 let source_mapping_path = Path::new(&source_path)
44 .parent()
45 .unwrap()
46 .join(source_mapping_url);
47
48 println!("Processing source map {}", source_mapping_path.to_string_lossy());
49
50 let source_mapping_path = Path::new(&source_mapping_path);
51 if source_mapping_path.exists() {
52 let source_map: SourceMap = util::deserialize_object(source_mapping_path).unwrap();
53
54 let references = process_references(&settings, &source_map);
55
56 let file_refs = references.iter().map(|s| s.file_path.clone()).collect();
57 let line_refs = calculate_executable_line_mappings(&source_map, references);
58 let mut file_coverage =
59 calculate_line_coverage(data.ranges, line_refs, file_refs, data.text.as_str());
60
61 if let Some(ref reify_against_lcov) = settings.reify_against_lcov {
62 file_coverage = {
63 eprintln!("Reifying against LCOV file");
64
65 let mut file_hash_map: HashMap<_,_> = file_coverage.into_iter().map(|v| (v.path.clone(), v)).collect();
66
67 for line_data in lcov::LcovFilesLines::new(&util::fast_read(&reify_against_lcov).unwrap()) {
68
69 let our_coverage = file_hash_map.get_mut(&line_data.file_path);
70 our_coverage.map(|our_coverage| {
71 let new_lines : HashSet<_> = line_data.lines.into_iter().collect();
72
73 our_coverage.lines.retain(|v| new_lines.contains(&v.line_number));
74 });
75 }
76
77 file_hash_map.into_iter().map(|(_k,v)| v).collect()
78 }
79 }
80
81 Some(file_coverage)
82 } else {
83 None
84 }
85 } else {
86 None
87 }
88}
89
90pub fn run<P: AsRef<Path>, W: Write>(settings: Settings, json_path: Vec<P>, writer: Option<W>) {
91 let values = load::load_items(json_path);
92 let processed: Vec<_> = values
93 .into_iter()
94 .map(|value| process_source_map(&settings, value))
95 .flat_map(|value| value.into_iter())
96 .flat_map(|value| value.into_iter())
97 .collect();
98
99 let many_coverage = ManyCoverage { files: processed };
100
101 if let Some(writer) = writer {
102 many_coverage.write_xml(writer);
103 } else {
104 let stdout = io::stdout();
105 let handle = stdout.lock();
106
107 many_coverage.write_xml(handle);
108 }
109}
110
111#[cfg(test)]
112mod test {
113 use std::path::Path;
114}