diff --git a/Cargo.lock b/Cargo.lock index 46d6a36338..302fb63d3d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -838,7 +838,7 @@ dependencies = [ "tempfile", "test_util", "text-size", - "text_lines", + "text_lines 0.6.0", "tokio", "tokio-util", "tower-lsp", @@ -881,7 +881,7 @@ dependencies = [ "swc_ecma_transforms_typescript", "swc_ecma_utils", "swc_ecma_visit", - "text_lines", + "text_lines 0.4.1", "url 2.2.2", ] @@ -1370,7 +1370,7 @@ dependencies = [ "dprint-core", "jsonc-parser", "serde", - "text_lines", + "text_lines 0.4.1", ] [[package]] @@ -1412,7 +1412,7 @@ dependencies = [ "swc_common", "swc_ecma_ast", "swc_ecma_parser", - "text_lines", + "text_lines 0.4.1", ] [[package]] @@ -4580,6 +4580,12 @@ dependencies = [ "serde", ] +[[package]] +name = "text_lines" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fd5828de7deaa782e1dd713006ae96b3bee32d3279b79eb67ecf8072c059bcf" + [[package]] name = "textwrap" version = "0.15.0" diff --git a/cli/Cargo.toml b/cli/Cargo.toml index f86ec4ea20..83eb7666d0 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -94,7 +94,7 @@ serde = { version = "=1.0.139", features = ["derive"] } serde_repr = "=0.1.8" shell-escape = "=0.1.5" text-size = "=1.1.0" -text_lines = "=0.4.1" +text_lines = "=0.6.0" tokio = { version = "=1.19", features = ["full"] } tokio-util = "=0.7.2" tower-lsp = "=0.17.0" diff --git a/cli/tests/testdata/coverage/complex_expected.lcov b/cli/tests/testdata/coverage/complex_expected.lcov index 1bb79d2770..7a3cd8d921 100644 --- a/cli/tests/testdata/coverage/complex_expected.lcov +++ b/cli/tests/testdata/coverage/complex_expected.lcov @@ -46,9 +46,9 @@ DA:64,0 DA:65,0 DA:66,0 DA:67,0 -DA:68,1 +DA:68,0 DA:71,0 DA:74,1 -LH:23 +LH:22 LF:38 end_of_record diff --git a/cli/tests/testdata/coverage/complex_expected.out b/cli/tests/testdata/coverage/complex_expected.out index e318e20673..3f7c89e9b7 100644 --- a/cli/tests/testdata/coverage/complex_expected.out +++ b/cli/tests/testdata/coverage/complex_expected.out @@ -1,4 +1,4 @@ -cover [WILDCARD]/coverage/complex.ts ... 60.526% (23/38) +cover [WILDCARD]/coverage/complex.ts ... 57.895% (22/38) 46 | export function unused( 47 | foo: string, 48 | bar: string, @@ -15,5 +15,6 @@ cover [WILDCARD]/coverage/complex.ts ... 60.526% (23/38) 65 | return ( 66 | 0 67 | ); + 68 | } -----|----- 71 | console.log("%s", () => 1); diff --git a/cli/tools/coverage/json_types.rs b/cli/tools/coverage/json_types.rs index 1e46cc7fde..6da17d58f6 100644 --- a/cli/tools/coverage/json_types.rs +++ b/cli/tools/coverage/json_types.rs @@ -6,10 +6,12 @@ use serde::Serialize; #[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)] #[serde(rename_all = "camelCase")] pub struct CoverageRange { - /// Start byte index. - pub start_offset: usize, - /// End byte index. - pub end_offset: usize, + /// Start character index. + #[serde(rename = "startOffset")] + pub start_char_offset: usize, + /// End character index. + #[serde(rename = "endOffset")] + pub end_char_offset: usize, pub count: i64, } diff --git a/cli/tools/coverage/merge.rs b/cli/tools/coverage/merge.rs index b0606e215f..08a695e1d6 100644 --- a/cli/tools/coverage/merge.rs +++ b/cli/tools/coverage/merge.rs @@ -54,15 +54,15 @@ pub fn merge_scripts( let first: &ScriptCoverage = &scripts[0]; (first.script_id.clone(), first.url.clone()) }; - let mut range_to_funcs: BTreeMap> = + let mut range_to_funcs: BTreeMap> = BTreeMap::new(); for script_cov in scripts { for func_cov in script_cov.functions { let root_range = { let root_range_cov: &CoverageRange = &func_cov.ranges[0]; - Range { - start: root_range_cov.start_offset, - end: root_range_cov.end_offset, + CharRange { + start: root_range_cov.start_char_offset, + end: root_range_cov.end_char_offset, } }; range_to_funcs @@ -85,12 +85,12 @@ pub fn merge_scripts( } #[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)] -struct Range { +struct CharRange { start: usize, end: usize, } -impl Ord for Range { +impl Ord for CharRange { fn cmp(&self, other: &Self) -> ::std::cmp::Ordering { if self.start != other.start { self.start.cmp(&other.start) @@ -100,7 +100,7 @@ impl Ord for Range { } } -impl PartialOrd for Range { +impl PartialOrd for CharRange { fn partial_cmp(&self, other: &Self) -> Option<::std::cmp::Ordering> { if self.start != other.start { self.start.partial_cmp(&other.start) @@ -249,7 +249,7 @@ fn merge_range_tree_children<'a>( Vec::with_capacity(parent_trees.len()); let mut wrapped_children: Vec>> = Vec::with_capacity(parent_trees.len()); - let mut open_range: Option = None; + let mut open_range: Option = None; for _parent_tree in parent_trees.iter() { flat_children.push(Vec::new()); @@ -318,7 +318,7 @@ fn merge_range_tree_children<'a>( .push(tree); } start_event_queue.set_pending_offset(open_range_end); - open_range = Some(Range { + open_range = Some(CharRange { start: event.offset, end: open_range_end, }); @@ -452,8 +452,8 @@ mod tests { function_name: String::from("lib"), is_block_coverage: true, ranges: vec![CoverageRange { - start_offset: 0, - end_offset: 9, + start_char_offset: 0, + end_char_offset: 9, count: 1, }], }], @@ -467,8 +467,8 @@ mod tests { function_name: String::from("lib"), is_block_coverage: true, ranges: vec![CoverageRange { - start_offset: 0, - end_offset: 9, + start_char_offset: 0, + end_char_offset: 9, count: 2, }], }], @@ -483,8 +483,8 @@ mod tests { function_name: String::from("lib"), is_block_coverage: true, ranges: vec![CoverageRange { - start_offset: 0, - end_offset: 9, + start_char_offset: 0, + end_char_offset: 9, count: 3, }], }], @@ -506,13 +506,13 @@ mod tests { is_block_coverage: true, ranges: vec![ CoverageRange { - start_offset: 0, - end_offset: 9, + start_char_offset: 0, + end_char_offset: 9, count: 10, }, CoverageRange { - start_offset: 3, - end_offset: 6, + start_char_offset: 3, + end_char_offset: 6, count: 1, }, ], @@ -528,13 +528,13 @@ mod tests { is_block_coverage: true, ranges: vec![ CoverageRange { - start_offset: 0, - end_offset: 9, + start_char_offset: 0, + end_char_offset: 9, count: 20, }, CoverageRange { - start_offset: 3, - end_offset: 6, + start_char_offset: 3, + end_char_offset: 6, count: 2, }, ], @@ -551,13 +551,13 @@ mod tests { is_block_coverage: true, ranges: vec![ CoverageRange { - start_offset: 0, - end_offset: 9, + start_char_offset: 0, + end_char_offset: 9, count: 30, }, CoverageRange { - start_offset: 3, - end_offset: 6, + start_char_offset: 3, + end_char_offset: 6, count: 3, }, ], @@ -580,13 +580,13 @@ mod tests { is_block_coverage: true, ranges: vec![ CoverageRange { - start_offset: 0, - end_offset: 9, + start_char_offset: 0, + end_char_offset: 9, count: 10, }, CoverageRange { - start_offset: 2, - end_offset: 5, + start_char_offset: 2, + end_char_offset: 5, count: 1, }, ], @@ -602,13 +602,13 @@ mod tests { is_block_coverage: true, ranges: vec![ CoverageRange { - start_offset: 0, - end_offset: 9, + start_char_offset: 0, + end_char_offset: 9, count: 20, }, CoverageRange { - start_offset: 4, - end_offset: 7, + start_char_offset: 4, + end_char_offset: 7, count: 2, }, ], @@ -625,23 +625,23 @@ mod tests { is_block_coverage: true, ranges: vec![ CoverageRange { - start_offset: 0, - end_offset: 9, + start_char_offset: 0, + end_char_offset: 9, count: 30, }, CoverageRange { - start_offset: 2, - end_offset: 5, + start_char_offset: 2, + end_char_offset: 5, count: 21, }, CoverageRange { - start_offset: 4, - end_offset: 5, + start_char_offset: 4, + end_char_offset: 5, count: 3, }, CoverageRange { - start_offset: 5, - end_offset: 7, + start_char_offset: 5, + end_char_offset: 7, count: 12, }, ], @@ -664,23 +664,23 @@ mod tests { is_block_coverage: true, ranges: vec![ CoverageRange { - start_offset: 0, - end_offset: 9, + start_char_offset: 0, + end_char_offset: 9, count: 1, }, CoverageRange { - start_offset: 1, - end_offset: 8, + start_char_offset: 1, + end_char_offset: 8, count: 6, }, CoverageRange { - start_offset: 1, - end_offset: 5, + start_char_offset: 1, + end_char_offset: 5, count: 5, }, CoverageRange { - start_offset: 5, - end_offset: 8, + start_char_offset: 5, + end_char_offset: 8, count: 7, }, ], @@ -696,23 +696,23 @@ mod tests { is_block_coverage: true, ranges: vec![ CoverageRange { - start_offset: 0, - end_offset: 9, + start_char_offset: 0, + end_char_offset: 9, count: 4, }, CoverageRange { - start_offset: 1, - end_offset: 8, + start_char_offset: 1, + end_char_offset: 8, count: 8, }, CoverageRange { - start_offset: 1, - end_offset: 5, + start_char_offset: 1, + end_char_offset: 5, count: 9, }, CoverageRange { - start_offset: 5, - end_offset: 8, + start_char_offset: 5, + end_char_offset: 8, count: 7, }, ], @@ -729,13 +729,13 @@ mod tests { is_block_coverage: true, ranges: vec![ CoverageRange { - start_offset: 0, - end_offset: 9, + start_char_offset: 0, + end_char_offset: 9, count: 5, }, CoverageRange { - start_offset: 1, - end_offset: 8, + start_char_offset: 1, + end_char_offset: 8, count: 14, }, ], @@ -758,13 +758,13 @@ mod tests { is_block_coverage: true, ranges: vec![ CoverageRange { - start_offset: 0, - end_offset: 7, + start_char_offset: 0, + end_char_offset: 7, count: 10, }, CoverageRange { - start_offset: 0, - end_offset: 4, + start_char_offset: 0, + end_char_offset: 4, count: 1, }, ], @@ -780,18 +780,18 @@ mod tests { is_block_coverage: true, ranges: vec![ CoverageRange { - start_offset: 0, - end_offset: 7, + start_char_offset: 0, + end_char_offset: 7, count: 20, }, CoverageRange { - start_offset: 1, - end_offset: 6, + start_char_offset: 1, + end_char_offset: 6, count: 11, }, CoverageRange { - start_offset: 2, - end_offset: 5, + start_char_offset: 2, + end_char_offset: 5, count: 2, }, ], @@ -808,23 +808,23 @@ mod tests { is_block_coverage: true, ranges: vec![ CoverageRange { - start_offset: 0, - end_offset: 7, + start_char_offset: 0, + end_char_offset: 7, count: 30, }, CoverageRange { - start_offset: 0, - end_offset: 6, + start_char_offset: 0, + end_char_offset: 6, count: 21, }, CoverageRange { - start_offset: 1, - end_offset: 5, + start_char_offset: 1, + end_char_offset: 5, count: 12, }, CoverageRange { - start_offset: 2, - end_offset: 4, + start_char_offset: 2, + end_char_offset: 4, count: 3, }, ], diff --git a/cli/tools/coverage/mod.rs b/cli/tools/coverage/mod.rs index 0b1a9bc353..bba7271f5c 100644 --- a/cli/tools/coverage/mod.rs +++ b/cli/tools/coverage/mod.rs @@ -202,16 +202,18 @@ fn generate_coverage_report( continue; } - let source_line_index = - text_lines.line_index(function.ranges[0].start_offset); + let dest_line_index = text_lines.line_index( + text_lines + .byte_index_from_char_index(function.ranges[0].start_char_offset), + ); let line_index = if let Some(source_map) = maybe_source_map.as_ref() { source_map .tokens() - .find(|token| token.get_dst_line() as usize == source_line_index) + .find(|token| token.get_dst_line() as usize == dest_line_index) .map(|token| token.get_src_line() as usize) .unwrap_or(0) } else { - source_line_index + dest_line_index }; coverage_report.named_functions.push(FunctionCoverageItem { @@ -224,7 +226,9 @@ fn generate_coverage_report( for (block_number, function) in script_coverage.functions.iter().enumerate() { let block_hits = function.ranges[0].count; for (branch_number, range) in function.ranges[1..].iter().enumerate() { - let source_line_index = text_lines.line_index(range.start_offset); + let source_line_index = text_lines.line_index( + text_lines.byte_index_from_char_index(range.start_char_offset), + ); let line_index = if let Some(source_map) = maybe_source_map.as_ref() { source_map .tokens() @@ -264,11 +268,14 @@ fn generate_coverage_report( // parts of a line in color (word diff style) instead of the entire line. let mut line_counts = Vec::with_capacity(text_lines.lines_count()); for line_index in 0..text_lines.lines_count() { - let line_start_offset = text_lines.line_start(line_index); - let line_end_offset = text_lines.line_end(line_index); + let line_start_byte_offset = text_lines.line_start(line_index); + let line_start_char_offset = text_lines.char_index(line_start_byte_offset); + let line_end_byte_offset = text_lines.line_end(line_index); + let line_end_char_offset = text_lines.char_index(line_end_byte_offset); let ignore = comment_ranges.iter().any(|range| { - range.start <= line_start_offset && range.end >= line_end_offset - }) || script_source[line_start_offset..line_end_offset] + range.start <= line_start_byte_offset && range.end >= line_end_byte_offset + }) || script_source + [line_start_byte_offset..line_end_byte_offset] .trim() .is_empty(); let mut count = 0; @@ -280,8 +287,8 @@ fn generate_coverage_report( // 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 + if range.start_char_offset <= line_start_char_offset + && range.end_char_offset >= line_end_char_offset { count += range.count; } @@ -295,8 +302,8 @@ fn generate_coverage_report( continue; } - let overlaps = range.start_offset < line_end_offset - && range.end_offset > line_start_offset; + let overlaps = range.start_char_offset < line_end_char_offset + && range.end_char_offset > line_start_char_offset; if overlaps { count = 0; } diff --git a/cli/tools/coverage/range_tree.rs b/cli/tools/coverage/range_tree.rs index 24d0a9ffcf..aca8939ee6 100644 --- a/cli/tools/coverage/range_tree.rs +++ b/cli/tools/coverage/range_tree.rs @@ -134,8 +134,8 @@ impl<'rt> RangeTree<'rt> { while let Some((cur, parent_count)) = stack.pop() { let count: i64 = parent_count + cur.delta; ranges.push(CoverageRange { - start_offset: cur.start, - end_offset: cur.end, + start_char_offset: cur.start, + end_char_offset: cur.end, count, }); for child in cur.children.iter().rev() { @@ -165,14 +165,14 @@ impl<'rt> RangeTree<'rt> { ) -> Option<&'a mut RangeTree<'a>> { let has_range: bool = match ranges.peek() { None => false, - Some(range) => range.start_offset < parent_end, + Some(range) => range.start_char_offset < parent_end, }; if !has_range { return None; } let range = ranges.next().unwrap(); - let start: usize = range.start_offset; - let end: usize = range.end_offset; + let start: usize = range.start_char_offset; + let end: usize = range.end_char_offset; let count: i64 = range.count; let delta: i64 = count - parent_count; let mut children: Vec<&mut RangeTree> = Vec::new(); @@ -193,8 +193,8 @@ mod tests { fn from_sorted_ranges_empty() { let rta = RangeTreeArena::new(); let inputs: Vec = vec![CoverageRange { - start_offset: 0, - end_offset: 9, + start_char_offset: 0, + end_char_offset: 9, count: 1, }]; let actual: Option<&mut RangeTree> =