summaryrefslogtreecommitdiff
path: root/cli/tools/coverage.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/tools/coverage.rs')
-rw-r--r--cli/tools/coverage.rs186
1 files changed, 97 insertions, 89 deletions
diff --git a/cli/tools/coverage.rs b/cli/tools/coverage.rs
index b7d64e8f2..b06f4d2be 100644
--- a/cli/tools/coverage.rs
+++ b/cli/tools/coverage.rs
@@ -151,119 +151,127 @@ impl PrettyCoverageReporter {
}
let lines = script_source.split('\n').collect::<Vec<_>>();
- let mut covered_lines: Vec<usize> = Vec::new();
- let mut uncovered_lines: Vec<usize> = Vec::new();
- let mut line_start_offset = 0;
- for (index, line) in lines.iter().enumerate() {
- let line_end_offset = line_start_offset + line.len();
+ let line_offsets = {
+ let mut offsets: Vec<(usize, usize)> = Vec::new();
+ let mut index = 0;
- let mut count = 0;
+ for line in &lines {
+ offsets.push((index, index + line.len() + 1));
+ index += line.len() + 1;
+ }
- let ignore = ignored_spans.iter().any(|span| {
- (span.lo.0 as usize) <= line_start_offset
- && (span.hi.0 as usize) >= line_end_offset
- });
+ offsets
+ };
- if ignore {
- covered_lines.push(index);
- continue;
- }
+ let line_counts = line_offsets
+ .iter()
+ .enumerate()
+ .map(|(index, (line_start_offset, line_end_offset))| {
+ let ignore = ignored_spans.iter().any(|span| {
+ (span.lo.0 as usize) <= *line_start_offset
+ && (span.hi.0 as usize) >= *line_end_offset
+ });
+
+ if ignore {
+ return (index, 1);
+ }
+
+ let mut count = 0;
- // Count the hits of ranges that include the entire line which will always be at-least one
- // as long as the code has been evaluated.
- for function in &script_coverage.functions {
- for range in &function.ranges {
- if range.start_offset <= line_start_offset
- && range.end_offset >= line_end_offset
- {
- count += range.count;
+ // Count the hits of ranges that include the entire line which will always be at-least one
+ // as long as the code has been evaluated.
+ for function in &script_coverage.functions {
+ for range in &function.ranges {
+ if range.start_offset <= *line_start_offset
+ && range.end_offset >= *line_end_offset
+ {
+ count += range.count;
+ }
}
}
- }
- // Reset the count if any block intersects with the current line has a count of
- // zero.
- //
- // We check for intersection instead of inclusion here because a block may be anywhere
- // inside a line.
- for function in &script_coverage.functions {
- for range in &function.ranges {
- if range.count > 0 {
- continue;
- }
+ // Reset the count if any block intersects with the current line has a count of
+ // zero.
+ //
+ // We check for intersection instead of inclusion here because a block may be anywhere
+ // inside a line.
+ for function in &script_coverage.functions {
+ for range in &function.ranges {
+ if range.count > 0 {
+ continue;
+ }
- if (range.start_offset < line_start_offset
- && range.end_offset > line_start_offset)
- || (range.start_offset < line_end_offset
- && range.end_offset > line_end_offset)
- {
- count = 0;
+ if (range.start_offset < *line_start_offset
+ && range.end_offset > *line_start_offset)
+ || (range.start_offset < *line_end_offset
+ && range.end_offset > *line_end_offset)
+ {
+ count = 0;
+ }
}
}
- }
- if count > 0 {
- covered_lines.push(index);
- } else {
- uncovered_lines.push(index);
- }
+ (index, count)
+ })
+ .collect::<Vec<(usize, usize)>>();
- line_start_offset += line.len() + 1;
- }
+ let lines = if let Some(original_source) = maybe_original_source.as_ref() {
+ original_source.split('\n').collect::<Vec<_>>()
+ } else {
+ lines
+ };
+
+ let line_counts = if let Some(source_map) = maybe_source_map.as_ref() {
+ let mut line_counts = line_counts
+ .iter()
+ .map(|(index, count)| {
+ source_map
+ .tokens()
+ .filter(move |token| token.get_dst_line() as usize == *index)
+ .map(move |token| (token.get_src_line() as usize, *count))
+ })
+ .flatten()
+ .collect::<Vec<(usize, usize)>>();
+
+ line_counts.sort_unstable_by_key(|(index, _)| *index);
+ line_counts.dedup_by_key(|(index, _)| *index);
+
+ line_counts
+ } else {
+ line_counts
+ };
if !self.quiet {
print!("cover {} ... ", script_coverage.url);
- let line_coverage_ratio = covered_lines.len() as f32 / lines.len() as f32;
- let line_coverage = format!(
- "{:.3}% ({}/{})",
- line_coverage_ratio * 100.0,
- covered_lines.len(),
- lines.len()
- );
+ let hit_lines = line_counts
+ .iter()
+ .filter(|(_, count)| *count != 0)
+ .map(|(index, _)| *index);
- if line_coverage_ratio >= 0.9 {
+ let missed_lines = line_counts
+ .iter()
+ .filter(|(_, count)| *count == 0)
+ .map(|(index, _)| *index);
+
+ let lines_found = line_counts.len();
+ let lines_hit = hit_lines.count();
+ let line_ratio = lines_hit as f32 / lines_found as f32;
+
+ let line_coverage =
+ format!("{:.3}% ({}/{})", line_ratio * 100.0, lines_hit, lines_found,);
+
+ if line_ratio >= 0.9 {
println!("{}", colors::green(&line_coverage));
- } else if line_coverage_ratio >= 0.75 {
+ } else if line_ratio >= 0.75 {
println!("{}", colors::yellow(&line_coverage));
} else {
println!("{}", colors::red(&line_coverage));
}
- let output_lines =
- if let Some(original_source) = maybe_original_source.as_ref() {
- original_source.split('\n').collect::<Vec<_>>()
- } else {
- lines
- };
-
- let output_indices = if let Some(source_map) = maybe_source_map.as_ref() {
- // The compiled executable source lines have to be mapped to all the original source lines that they
- // came from; this happens in a couple of emit scenarios, the most common example being function
- // declarations where the compiled JavaScript code only takes a line but the original
- // TypeScript source spans 10 lines.
- let mut indices = uncovered_lines
- .iter()
- .map(|i| {
- source_map
- .tokens()
- .filter(move |token| token.get_dst_line() as usize == *i)
- .map(|token| token.get_src_line() as usize)
- })
- .flatten()
- .collect::<Vec<usize>>();
-
- indices.sort_unstable();
- indices.dedup();
-
- indices
- } else {
- uncovered_lines
- };
-
let mut last_line = None;
- for line_index in output_indices {
+ for line_index in missed_lines {
const WIDTH: usize = 4;
const SEPERATOR: &str = "|";
@@ -279,7 +287,7 @@ impl PrettyCoverageReporter {
"{:width$} {} {}",
line_index + 1,
colors::gray(SEPERATOR),
- colors::red(&output_lines[line_index]),
+ colors::red(&lines[line_index]),
width = WIDTH
);