diff options
Diffstat (limited to 'cli/tools/coverage.rs')
-rw-r--r-- | cli/tools/coverage.rs | 58 |
1 files changed, 55 insertions, 3 deletions
diff --git a/cli/tools/coverage.rs b/cli/tools/coverage.rs index e3092975f..b7d64e8f2 100644 --- a/cli/tools/coverage.rs +++ b/cli/tools/coverage.rs @@ -6,6 +6,7 @@ use crate::colors; use crate::media_type::MediaType; use crate::module_graph::TypeLib; use crate::program_state::ProgramState; +use crate::source_maps::SourceMapGetter; use deno_core::error::AnyError; use deno_core::serde_json; use deno_core::serde_json::json; @@ -15,6 +16,7 @@ use deno_runtime::inspector::InspectorSession; use deno_runtime::permissions::Permissions; use serde::Deserialize; use serde::Serialize; +use sourcemap::SourceMap; use std::fs; use std::path::PathBuf; use std::sync::Arc; @@ -130,7 +132,15 @@ impl PrettyCoverageReporter { &mut self, script_coverage: &ScriptCoverage, script_source: &str, + maybe_source_map: Option<Vec<u8>>, + maybe_original_source: Option<String>, ) { + let maybe_source_map = if let Some(source_map) = maybe_source_map { + Some(SourceMap::from_slice(&source_map).unwrap()) + } else { + None + }; + let mut ignored_spans: Vec<Span> = Vec::new(); for item in ast::lex("", script_source, &MediaType::JavaScript) { if let TokenOrComment::Token(_) = item.inner { @@ -221,8 +231,39 @@ impl PrettyCoverageReporter { 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 uncovered_lines { + for line_index in output_indices { const WIDTH: usize = 4; const SEPERATOR: &str = "|"; @@ -238,7 +279,7 @@ impl PrettyCoverageReporter { "{:width$} {} {}", line_index + 1, colors::gray(SEPERATOR), - colors::red(&lines[line_index]), + colors::red(&output_lines[line_index]), width = WIDTH ); @@ -354,7 +395,18 @@ pub async fn report_coverages( let module_source = program_state.load(module_specifier.clone(), None)?; let script_source = &module_source.code; - coverage_reporter.visit_coverage(&script_coverage, &script_source); + let maybe_source_map = program_state.get_source_map(&script_coverage.url); + let maybe_cached_source = program_state + .file_fetcher + .get_source(&module_specifier) + .map(|f| f.source); + + coverage_reporter.visit_coverage( + &script_coverage, + &script_source, + maybe_source_map, + maybe_cached_source, + ); } Ok(()) |