diff options
Diffstat (limited to 'cli/tools/coverage.rs')
-rw-r--r-- | cli/tools/coverage.rs | 186 |
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 ); |