From e89512576db56bb2161d4b3484dd6ec6e25d5051 Mon Sep 17 00:00:00 2001 From: KnorpelSenf Date: Mon, 8 Sep 2025 21:00:54 +0000 Subject: [PATCH 01/17] perf: speed up file diffing This swaps out dissimilar for imara which is substantially faster at diffing strings. Note that this is a proof of concept and I did not have enough time to make the output pretty. I just shows that the diff is fast. Applying colors should be doable without changing much about the perf. Fixes https://github.com/denoland/deno/issues/30634 --- Cargo.lock | 12 +- Cargo.toml | 1 + libs/resolver/Cargo.toml | 2 +- libs/resolver/display.rs | 236 +++++++++++++++------------------------ 4 files changed, 102 insertions(+), 149 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 17fa6028be7996..5e93e4f17ecc3a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2784,9 +2784,9 @@ dependencies = [ "deno_semver", "deno_terminal 0.2.2", "deno_unsync", - "dissimilar", "futures", "http 1.1.0", + "imara-diff", "import_map", "indexmap 2.9.0", "jsonc-parser", @@ -5283,6 +5283,16 @@ dependencies = [ "zune-jpeg", ] +[[package]] +name = "imara-diff" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f01d462f766df78ab820dd06f5eb700233c51f0f4c2e846520eaf4ba6aa5c5c" +dependencies = [ + "hashbrown 0.15.5", + "memchr", +] + [[package]] name = "import_map" version = "0.23.0" diff --git a/Cargo.toml b/Cargo.toml index 528a965102a7ca..1c882addd7a34f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -307,6 +307,7 @@ console_static_text = "=0.8.3" crossterm = "0.28.1" dhat = "0.3.3" dissimilar = "=1.0.9" +imara-diff = "=0.2.0" dprint-core = "=0.67.4" dprint-plugin-json = "=0.20.0" dprint-plugin-jupyter = "=0.2.0" diff --git a/libs/resolver/Cargo.toml b/libs/resolver/Cargo.toml index 2276b19af76541..918dc7aea8d14e 100644 --- a/libs/resolver/Cargo.toml +++ b/libs/resolver/Cargo.toml @@ -48,7 +48,7 @@ deno_permissions = { workspace = true, optional = true } deno_semver.workspace = true deno_terminal.workspace = true deno_unsync.workspace = true -dissimilar.workspace = true +imara-diff.workspace = true futures.workspace = true http = { workspace = true, optional = true } import_map.workspace = true diff --git a/libs/resolver/display.rs b/libs/resolver/display.rs index 01ccccce357570..9d464acfaab2ab 100644 --- a/libs/resolver/display.rs +++ b/libs/resolver/display.rs @@ -3,11 +3,10 @@ //! It would be best to move these utilities out of this //! crate as this is not specific to resolution, but for //! the time being it's fine for this to live here. -use std::fmt::Write as _; - use deno_terminal::colors; -use dissimilar::Chunk; -use dissimilar::diff as difference; +use imara_diff::{ + BasicLineDiffPrinter, Diff, InternedInput, UnifiedDiffConfig, +}; /// Print diff of the same file_path, before and after formatting. /// @@ -25,153 +24,96 @@ pub fn diff(orig_text: &str, edit_text: &str) -> String { return " | Text differed by line endings.\n".to_string(); } - DiffBuilder::build(&orig_text, &edit_text) -} - -struct DiffBuilder { - output: String, - line_number_width: usize, - orig_line: usize, - edit_line: usize, - orig: String, - edit: String, - has_changes: bool, -} - -impl DiffBuilder { - pub fn build(orig_text: &str, edit_text: &str) -> String { - let mut diff_builder = DiffBuilder { - output: String::new(), - orig_line: 1, - edit_line: 1, - orig: String::new(), - edit: String::new(), - has_changes: false, - line_number_width: { - let line_count = std::cmp::max( - orig_text.split('\n').count(), - edit_text.split('\n').count(), - ); - line_count.to_string().chars().count() - }, - }; - - let chunks = difference(orig_text, edit_text); - diff_builder.handle_chunks(chunks); - diff_builder.output - } - - fn handle_chunks<'a>(&'a mut self, chunks: Vec>) { - for chunk in chunks { - match chunk { - Chunk::Delete(s) => { - let split = s.split('\n').enumerate(); - for (i, s) in split { - if i > 0 { - self.orig.push('\n'); - } - self.orig.push_str(&fmt_rem_text_highlight(s)); - } - self.has_changes = true - } - Chunk::Insert(s) => { - let split = s.split('\n').enumerate(); - for (i, s) in split { - if i > 0 { - self.edit.push('\n'); - } - self.edit.push_str(&fmt_add_text_highlight(s)); - } - self.has_changes = true - } - Chunk::Equal(s) => { - let split = s.split('\n').enumerate(); - for (i, s) in split { - if i > 0 { - self.flush_changes(); - } - self.orig.push_str(&fmt_rem_text(s)); - self.edit.push_str(&fmt_add_text(s)); - } - } - } - } - - self.flush_changes(); - } - - fn flush_changes(&mut self) { - if self.has_changes { - self.write_line_diff(); - - self.orig_line += self.orig.split('\n').count(); - self.edit_line += self.edit.split('\n').count(); - self.has_changes = false; - } else { - self.orig_line += 1; - self.edit_line += 1; - } - - self.orig.clear(); - self.edit.clear(); - } - - fn write_line_diff(&mut self) { - let split = self.orig.split('\n').enumerate(); - for (i, s) in split { - write!( - self.output, - "{:width$}{} ", - self.orig_line + i, - colors::gray(" |"), - width = self.line_number_width - ) - .unwrap(); - self.output.push_str(&fmt_rem()); - self.output.push_str(s); - self.output.push('\n'); - } - - let split = self.edit.split('\n').enumerate(); - for (i, s) in split { - write!( - self.output, - "{:width$}{} ", - self.edit_line + i, - colors::gray(" |"), - width = self.line_number_width - ) - .unwrap(); - self.output.push_str(&fmt_add()); - self.output.push_str(s); - self.output.push('\n'); - } - } -} - -fn fmt_add() -> String { - colors::green_bold("+").to_string() -} - -fn fmt_add_text(x: &str) -> String { - colors::green(x).to_string() -} - -fn fmt_add_text_highlight(x: &str) -> String { - colors::black_on_green(x).to_string() -} - -fn fmt_rem() -> String { - colors::red_bold("-").to_string() + build(&orig_text, &edit_text) } -fn fmt_rem_text(x: &str) -> String { - colors::red(x).to_string() +pub fn build(orig_text: &str, edit_text: &str) -> String { + let input = InternedInput::new(orig_text, edit_text); + let mut diff = Diff::compute(imara_diff::Algorithm::Histogram, &input); + diff.postprocess_lines(&input); + + diff + .unified_diff( + &BasicLineDiffPrinter(&input.interner), + UnifiedDiffConfig::default(), + &input, + ) + .to_string() } -fn fmt_rem_text_highlight(x: &str) -> String { - colors::white_on_red(x).to_string() -} +// fn handle_diff(&mut self, diff: &Diff, input: &InternedInput<&str>) { +// let mut old_line = 0u32; +// let mut new_line = 0u32; + +// for hunk in diff.hunks() { +// // Process unchanged lines before this hunk +// if old_line < hunk.before.start || new_line < hunk.after.start { +// let unchanged_start = std::cmp::max(old_line, new_line); +// let unchanged_end = std::cmp::min(hunk.before.start, hunk.after.start); + +// for line_idx in unchanged_start..unchanged_end { +// if line_idx > unchanged_start { +// self.flush_changes(); +// } +// if (line_idx as usize) < input.before.len() { +// let line_text = &input.interner[input.before[line_idx as usize]]; +// self.orig.push_str(&fmt_rem_text(line_text)); +// } +// if (line_idx as usize) < input.after.len() { +// let line_text = &input.interner[input.after[line_idx as usize]]; +// self.edit.push_str(&fmt_add_text(line_text)); +// } +// } +// } + +// // Process deletions (lines only in before) +// if hunk.before.start < hunk.before.end { +// for line_idx in hunk.before.start..hunk.before.end { +// if line_idx > hunk.before.start { +// self.orig.push('\n'); +// } +// let line_text = &input.interner[input.before[line_idx as usize]]; +// self.orig.push_str(&fmt_rem_text_highlight(line_text)); +// } +// self.has_changes = true; +// } + +// // Process insertions (lines only in after) +// if hunk.after.start < hunk.after.end { +// for line_idx in hunk.after.start..hunk.after.end { +// if line_idx > hunk.after.start { +// self.edit.push('\n'); +// } +// let line_text = &input.interner[input.after[line_idx as usize]]; +// self.edit.push_str(&fmt_add_text_highlight(line_text)); +// } +// self.has_changes = true; +// } + +// old_line = hunk.before.end; +// new_line = hunk.after.end; +// } + +// // Process any remaining unchanged lines +// let max_lines = std::cmp::max(input.before.len(), input.after.len()) as u32; +// if old_line < max_lines || new_line < max_lines { +// for line_idx in std::cmp::max(old_line, new_line)..max_lines { +// if line_idx > std::cmp::max(old_line, new_line) { +// self.flush_changes(); +// } +// if (line_idx as usize) < input.before.len() { +// let line_text = &input.interner[input.before[line_idx as usize]]; +// self.orig.push_str(&fmt_rem_text(line_text)); +// } +// if (line_idx as usize) < input.after.len() { +// let line_text = &input.interner[input.after[line_idx as usize]]; +// self.edit.push_str(&fmt_add_text(line_text)); +// } +// } +// } + +// self.flush_changes(); +// } pub struct DisplayTreeNode { pub text: String, From 9aab445490d3b22d30cae8925910a242a2b98a03 Mon Sep 17 00:00:00 2001 From: KnorpelSenf Date: Mon, 8 Sep 2025 21:10:17 +0000 Subject: [PATCH 02/17] style: fix lints --- Cargo.toml | 2 +- libs/resolver/Cargo.toml | 2 +- libs/resolver/display.rs | 7 ++++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1c882addd7a34f..96d30378ee3ab8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -307,7 +307,6 @@ console_static_text = "=0.8.3" crossterm = "0.28.1" dhat = "0.3.3" dissimilar = "=1.0.9" -imara-diff = "=0.2.0" dprint-core = "=0.67.4" dprint-plugin-json = "=0.20.0" dprint-plugin-jupyter = "=0.2.0" @@ -315,6 +314,7 @@ dprint-plugin-markdown = "=0.19.0" dprint-plugin-typescript = "=0.95.11" env_logger = "=0.11.6" fancy-regex = "=0.14.0" +imara-diff = "=0.2.0" libsui = "0.10.0" malva = "=0.12.1" markup_fmt = "=0.22.0" diff --git a/libs/resolver/Cargo.toml b/libs/resolver/Cargo.toml index 918dc7aea8d14e..5b985cf4b6633e 100644 --- a/libs/resolver/Cargo.toml +++ b/libs/resolver/Cargo.toml @@ -48,9 +48,9 @@ deno_permissions = { workspace = true, optional = true } deno_semver.workspace = true deno_terminal.workspace = true deno_unsync.workspace = true -imara-diff.workspace = true futures.workspace = true http = { workspace = true, optional = true } +imara-diff.workspace = true import_map.workspace = true indexmap.workspace = true jsonc-parser.workspace = true diff --git a/libs/resolver/display.rs b/libs/resolver/display.rs index 9d464acfaab2ab..f48dc5d0a4b917 100644 --- a/libs/resolver/display.rs +++ b/libs/resolver/display.rs @@ -4,9 +4,10 @@ //! crate as this is not specific to resolution, but for //! the time being it's fine for this to live here. use deno_terminal::colors; -use imara_diff::{ - BasicLineDiffPrinter, Diff, InternedInput, UnifiedDiffConfig, -}; +use imara_diff::BasicLineDiffPrinter; +use imara_diff::Diff; +use imara_diff::InternedInput; +use imara_diff::UnifiedDiffConfig; /// Print diff of the same file_path, before and after formatting. /// From d257d1aefd70d223ac184b0d1151933c0039a444 Mon Sep 17 00:00:00 2001 From: KnorpelSenf Date: Mon, 8 Sep 2025 21:33:16 +0000 Subject: [PATCH 03/17] build: enabled unified_diff feature for imara --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 69e088548ddbde..6ad5d803fccc0a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -314,7 +314,7 @@ dprint-plugin-markdown = "=0.19.0" dprint-plugin-typescript = "=0.95.11" env_logger = "=0.11.6" fancy-regex = "=0.14.0" -imara-diff = "=0.2.0" +imara-diff = { version = "=0.2.0", features = ["unified_diff"] } libsui = "0.10.0" malva = "=0.12.1" markup_fmt = "=0.22.0" From b834694b83e0d66d9c923ffadb0c403010c3fb7b Mon Sep 17 00:00:00 2001 From: KnorpelSenf Date: Thu, 18 Sep 2025 20:42:44 +0000 Subject: [PATCH 04/17] feat: restore first bits of diff formatting --- libs/resolver/display.rs | 248 +++++++++++++++++++++++++-------------- 1 file changed, 159 insertions(+), 89 deletions(-) diff --git a/libs/resolver/display.rs b/libs/resolver/display.rs index f48dc5d0a4b917..c0e16b58e9b4db 100644 --- a/libs/resolver/display.rs +++ b/libs/resolver/display.rs @@ -3,11 +3,11 @@ //! It would be best to move these utilities out of this //! crate as this is not specific to resolution, but for //! the time being it's fine for this to live here. +use std::fmt::Write as _; + use deno_terminal::colors; -use imara_diff::BasicLineDiffPrinter; use imara_diff::Diff; use imara_diff::InternedInput; -use imara_diff::UnifiedDiffConfig; /// Print diff of the same file_path, before and after formatting. /// @@ -25,96 +25,164 @@ pub fn diff(orig_text: &str, edit_text: &str) -> String { return " | Text differed by line endings.\n".to_string(); } - build(&orig_text, &edit_text) + DiffBuilder::build(&orig_text, &edit_text) } -pub fn build(orig_text: &str, edit_text: &str) -> String { - let input = InternedInput::new(orig_text, edit_text); - let mut diff = Diff::compute(imara_diff::Algorithm::Histogram, &input); - diff.postprocess_lines(&input); - - diff - .unified_diff( - &BasicLineDiffPrinter(&input.interner), - UnifiedDiffConfig::default(), - &input, - ) - .to_string() +struct DiffBuilder<'a> { + input: InternedInput<&'a str>, + output: String, + line_number_width: usize, + orig_line: usize, + edit_line: usize, + orig: String, + edit: String, + has_changes: bool, } -// fn handle_diff(&mut self, diff: &Diff, input: &InternedInput<&str>) { -// let mut old_line = 0u32; -// let mut new_line = 0u32; - -// for hunk in diff.hunks() { -// // Process unchanged lines before this hunk -// if old_line < hunk.before.start || new_line < hunk.after.start { -// let unchanged_start = std::cmp::max(old_line, new_line); -// let unchanged_end = std::cmp::min(hunk.before.start, hunk.after.start); - -// for line_idx in unchanged_start..unchanged_end { -// if line_idx > unchanged_start { -// self.flush_changes(); -// } -// if (line_idx as usize) < input.before.len() { -// let line_text = &input.interner[input.before[line_idx as usize]]; -// self.orig.push_str(&fmt_rem_text(line_text)); -// } -// if (line_idx as usize) < input.after.len() { -// let line_text = &input.interner[input.after[line_idx as usize]]; -// self.edit.push_str(&fmt_add_text(line_text)); -// } -// } -// } - -// // Process deletions (lines only in before) -// if hunk.before.start < hunk.before.end { -// for line_idx in hunk.before.start..hunk.before.end { -// if line_idx > hunk.before.start { -// self.orig.push('\n'); -// } -// let line_text = &input.interner[input.before[line_idx as usize]]; -// self.orig.push_str(&fmt_rem_text_highlight(line_text)); -// } -// self.has_changes = true; -// } - -// // Process insertions (lines only in after) -// if hunk.after.start < hunk.after.end { -// for line_idx in hunk.after.start..hunk.after.end { -// if line_idx > hunk.after.start { -// self.edit.push('\n'); -// } -// let line_text = &input.interner[input.after[line_idx as usize]]; -// self.edit.push_str(&fmt_add_text_highlight(line_text)); -// } -// self.has_changes = true; -// } - -// old_line = hunk.before.end; -// new_line = hunk.after.end; -// } - -// // Process any remaining unchanged lines -// let max_lines = std::cmp::max(input.before.len(), input.after.len()) as u32; -// if old_line < max_lines || new_line < max_lines { -// for line_idx in std::cmp::max(old_line, new_line)..max_lines { -// if line_idx > std::cmp::max(old_line, new_line) { -// self.flush_changes(); -// } -// if (line_idx as usize) < input.before.len() { -// let line_text = &input.interner[input.before[line_idx as usize]]; -// self.orig.push_str(&fmt_rem_text(line_text)); -// } -// if (line_idx as usize) < input.after.len() { -// let line_text = &input.interner[input.after[line_idx as usize]]; -// self.edit.push_str(&fmt_add_text(line_text)); -// } -// } -// } - -// self.flush_changes(); -// } +impl<'a> DiffBuilder<'a> { + pub fn build(orig_text: &'a str, edit_text: &'a str) -> String { + let input = InternedInput::new(orig_text, edit_text); + let mut diff = Diff::compute(imara_diff::Algorithm::Histogram, &input); + diff.postprocess_lines(&input); + + let diff_builder = DiffBuilder { + input, + output: String::new(), + orig_line: 1, + edit_line: 1, + orig: String::new(), + edit: String::new(), + has_changes: false, + line_number_width: { + let line_count = std::cmp::max( + orig_text.split('\n').count(), + edit_text.split('\n').count(), + ); + line_count.to_string().chars().count() + }, + }; + diff_builder.handle_diff(diff) + } + + fn handle_diff(mut self, diff: Diff) -> String { + for hunk in diff.hunks() { + if !hunk.before.is_empty() || !hunk.after.is_empty() { + self.has_changes = true; + } + // TODO: add leading lines for context + // Chunk::Equal(s) => { + // let split = s.split('\n').enumerate(); + // for (i, s) in split { + // if i > 0 { + // self.flush_changes(); + // } + // self.orig.push_str(&fmt_rem_text(s)); + // self.edit.push_str(&fmt_add_text(s)); + // } + // } + for (i, del) in hunk.before.enumerate() { + let s = self.input.interner[self.input.before[del as usize]]; + if i > 0 { + self.orig.push('\n'); + } + self.orig.push_str(&fmt_rem_text_highlight(s)); + } + for (i, ins) in hunk.after.enumerate() { + let s = self.input.interner[self.input.after[ins as usize]]; + if i > 0 { + self.edit.push('\n'); + } + self.edit.push_str(&fmt_add_text_highlight(s)); + } + // TODO: add trailing lines for context + // Chunk::Equal(s) => { + // let split = s.split('\n').enumerate(); + // for (i, s) in split { + // if i > 0 { + // self.flush_changes(); + // } + // self.orig.push_str(&fmt_rem_text(s)); + // self.edit.push_str(&fmt_add_text(s)); + // } + // } + } + + self.flush_changes(); + self.output + } + + fn flush_changes(&mut self) { + if self.has_changes { + self.write_line_diff(); + + self.orig_line += self.orig.split('\n').count(); + self.edit_line += self.edit.split('\n').count(); + self.has_changes = false; + } else { + self.orig_line += 1; + self.edit_line += 1; + } + + self.orig.clear(); + self.edit.clear(); + } + + fn write_line_diff(&mut self) { + let split = self.orig.split('\n').enumerate(); + for (i, s) in split { + write!( + self.output, + "{:width$}{} ", + self.orig_line + i, + colors::gray(" |"), + width = self.line_number_width + ) + .unwrap(); + self.output.push_str(&fmt_rem()); + self.output.push_str(s); + self.output.push('\n'); + } + + let split = self.edit.split('\n').enumerate(); + for (i, s) in split { + write!( + self.output, + "{:width$}{} ", + self.edit_line + i, + colors::gray(" |"), + width = self.line_number_width + ) + .unwrap(); + self.output.push_str(&fmt_add()); + self.output.push_str(s); + self.output.push('\n'); + } + } +} + +fn fmt_add() -> String { + colors::green_bold("+").to_string() +} + +fn fmt_add_text(x: &str) -> String { + colors::green(x).to_string() +} + +fn fmt_add_text_highlight(x: &str) -> String { + colors::black_on_green(x).to_string() +} + +fn fmt_rem() -> String { + colors::red_bold("-").to_string() +} + +fn fmt_rem_text(x: &str) -> String { + colors::red(x).to_string() +} + +fn fmt_rem_text_highlight(x: &str) -> String { + colors::white_on_red(x).to_string() +} pub struct DisplayTreeNode { pub text: String, @@ -240,7 +308,9 @@ mod tests { fn run_test(diff_text1: &str, diff_text2: &str, expected_output: &str) { assert_eq!( - test_util::strip_ansi_codes(&diff(diff_text1, diff_text2,)), + test_util::strip_ansi_codes( + &diff_lines(diff_text1, diff_text2,).collect::() + ), expected_output, ); } From 7a863b444807698815fb77df35a8cdcdb5d607e5 Mon Sep 17 00:00:00 2001 From: KnorpelSenf Date: Thu, 18 Sep 2025 20:43:50 +0000 Subject: [PATCH 05/17] build: disable unused imara diff feature --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 75778164a90eb9..46d760cc4b36f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -314,7 +314,7 @@ dprint-plugin-markdown = "=0.19.0" dprint-plugin-typescript = "=0.95.11" env_logger = "=0.11.6" fancy-regex = "=0.14.0" -imara-diff = { version = "=0.2.0", features = ["unified_diff"] } +imara-diff = "=0.2.0" libsui = "0.10.0" malva = "=0.12.1" markup_fmt = "=0.22.0" From 0332a9a836606a008b8e8a81232ef3756c94a996 Mon Sep 17 00:00:00 2001 From: KnorpelSenf Date: Thu, 18 Sep 2025 20:46:05 +0000 Subject: [PATCH 06/17] test: revert temporary changes --- libs/resolver/display.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libs/resolver/display.rs b/libs/resolver/display.rs index c0e16b58e9b4db..ce32aa6fd2ce8e 100644 --- a/libs/resolver/display.rs +++ b/libs/resolver/display.rs @@ -308,9 +308,7 @@ mod tests { fn run_test(diff_text1: &str, diff_text2: &str, expected_output: &str) { assert_eq!( - test_util::strip_ansi_codes( - &diff_lines(diff_text1, diff_text2,).collect::() - ), + test_util::strip_ansi_codes(&diff_lines(diff_text1, diff_text2,)), expected_output, ); } From 85057cad11d63e62961d16838c40617ece6569cc Mon Sep 17 00:00:00 2001 From: KnorpelSenf Date: Thu, 18 Sep 2025 20:46:47 +0000 Subject: [PATCH 07/17] fix: bad rename --- libs/resolver/display.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/resolver/display.rs b/libs/resolver/display.rs index ce32aa6fd2ce8e..fd9f57e1fa1878 100644 --- a/libs/resolver/display.rs +++ b/libs/resolver/display.rs @@ -308,7 +308,7 @@ mod tests { fn run_test(diff_text1: &str, diff_text2: &str, expected_output: &str) { assert_eq!( - test_util::strip_ansi_codes(&diff_lines(diff_text1, diff_text2,)), + test_util::strip_ansi_codes(&diff(diff_text1, diff_text2,)), expected_output, ); } From ed4188a596131aeb9ec966b90465fa02f653a0ea Mon Sep 17 00:00:00 2001 From: KnorpelSenf Date: Thu, 18 Sep 2025 20:55:34 +0000 Subject: [PATCH 08/17] fix: lints --- libs/resolver/display.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libs/resolver/display.rs b/libs/resolver/display.rs index fd9f57e1fa1878..a0c8574e91c7b3 100644 --- a/libs/resolver/display.rs +++ b/libs/resolver/display.rs @@ -164,9 +164,9 @@ fn fmt_add() -> String { colors::green_bold("+").to_string() } -fn fmt_add_text(x: &str) -> String { - colors::green(x).to_string() -} +// fn fmt_add_text(x: &str) -> String { +// colors::green(x).to_string() +// } fn fmt_add_text_highlight(x: &str) -> String { colors::black_on_green(x).to_string() @@ -176,9 +176,9 @@ fn fmt_rem() -> String { colors::red_bold("-").to_string() } -fn fmt_rem_text(x: &str) -> String { - colors::red(x).to_string() -} +// fn fmt_rem_text(x: &str) -> String { +// colors::red(x).to_string() +// } fn fmt_rem_text_highlight(x: &str) -> String { colors::white_on_red(x).to_string() From c1518927e068d62525e92439c37f59ec5285717a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Thu, 12 Mar 2026 12:00:39 +0100 Subject: [PATCH 09/17] fix: properly handle multi-hunk diffs and line number tracking Simplify DiffBuilder to directly write lines per hunk instead of buffering. This fixes: - Missing flush between hunks causing all changes to merge into one block - Incorrect line numbers when unchanged lines exist between hunks - Token trailing newlines being duplicated in output Also fix pre-existing sys_traits dev-dependency missing getrandom feature and remove dead commented-out code. Co-Authored-By: Claude Opus 4.6 --- libs/resolver/Cargo.toml | 2 +- libs/resolver/display.rs | 146 +++++++++++++-------------------------- 2 files changed, 49 insertions(+), 99 deletions(-) diff --git a/libs/resolver/Cargo.toml b/libs/resolver/Cargo.toml index 7e9437971b780f..cb3392c56805dd 100644 --- a/libs/resolver/Cargo.toml +++ b/libs/resolver/Cargo.toml @@ -69,5 +69,5 @@ url.workspace = true [dev-dependencies] node_resolver.workspace = true -sys_traits = { workspace = true, features = ["memory", "real", "serde_json"] } +sys_traits = { workspace = true, features = ["getrandom", "memory", "real", "serde_json"] } test_util.workspace = true diff --git a/libs/resolver/display.rs b/libs/resolver/display.rs index bd2a555f4f8776..69cf173a4758d9 100644 --- a/libs/resolver/display.rs +++ b/libs/resolver/display.rs @@ -34,9 +34,6 @@ struct DiffBuilder<'a> { line_number_width: usize, orig_line: usize, edit_line: usize, - orig: String, - edit: String, - has_changes: bool, } impl<'a> DiffBuilder<'a> { @@ -50,9 +47,6 @@ impl<'a> DiffBuilder<'a> { output: String::new(), orig_line: 1, edit_line: 1, - orig: String::new(), - edit: String::new(), - has_changes: false, line_number_width: { let line_count = std::cmp::max( orig_text.split('\n').count(), @@ -65,98 +59,64 @@ impl<'a> DiffBuilder<'a> { } fn handle_diff(mut self, diff: Diff) -> String { + let mut prev_before_end: u32 = 0; + let mut prev_after_end: u32 = 0; + for hunk in diff.hunks() { - if !hunk.before.is_empty() || !hunk.after.is_empty() { - self.has_changes = true; - } - // TODO: add leading lines for context - // Chunk::Equal(s) => { - // let split = s.split('\n').enumerate(); - // for (i, s) in split { - // if i > 0 { - // self.flush_changes(); - // } - // self.orig.push_str(&fmt_rem_text(s)); - // self.edit.push_str(&fmt_add_text(s)); - // } - // } - for (i, del) in hunk.before.enumerate() { + // Skip unchanged lines between hunks + self.orig_line += + (hunk.before.start - prev_before_end) as usize; + self.edit_line += + (hunk.after.start - prev_after_end) as usize; + + // Write deleted lines + for del in hunk.before.clone() { let s = self.input.interner[self.input.before[del as usize]]; - if i > 0 { - self.orig.push('\n'); - } - self.orig.push_str(&fmt_rem_text_highlight(s)); + self.write_rem_line(s); } - for (i, ins) in hunk.after.enumerate() { + // Write inserted lines + for ins in hunk.after.clone() { let s = self.input.interner[self.input.after[ins as usize]]; - if i > 0 { - self.edit.push('\n'); - } - self.edit.push_str(&fmt_add_text_highlight(s)); + self.write_add_line(s); } - // TODO: add trailing lines for context - // Chunk::Equal(s) => { - // let split = s.split('\n').enumerate(); - // for (i, s) in split { - // if i > 0 { - // self.flush_changes(); - // } - // self.orig.push_str(&fmt_rem_text(s)); - // self.edit.push_str(&fmt_add_text(s)); - // } - // } + + prev_before_end = hunk.before.end; + prev_after_end = hunk.after.end; } - self.flush_changes(); self.output } - fn flush_changes(&mut self) { - if self.has_changes { - self.write_line_diff(); - - self.orig_line += self.orig.split('\n').count(); - self.edit_line += self.edit.split('\n').count(); - self.has_changes = false; - } else { - self.orig_line += 1; - self.edit_line += 1; - } - - self.orig.clear(); - self.edit.clear(); + fn write_rem_line(&mut self, text: &str) { + let text = text.strip_suffix('\n').unwrap_or(text); + write!( + self.output, + "{:width$}{} ", + self.orig_line, + colors::gray(" |"), + width = self.line_number_width + ) + .unwrap(); + self.output.push_str(&fmt_rem()); + self.output.push_str(&fmt_rem_text_highlight(text)); + self.output.push('\n'); + self.orig_line += 1; } - fn write_line_diff(&mut self) { - let split = self.orig.split('\n').enumerate(); - for (i, s) in split { - write!( - self.output, - "{:width$}{} ", - self.orig_line + i, - colors::gray(" |"), - width = self.line_number_width - ) - .unwrap(); - self.output.push_str(&fmt_rem()); - self.output.push_str(s); - self.output.push('\n'); - } - - let split = self.edit.split('\n').enumerate(); - for (i, s) in split { - write!( - self.output, - "{:width$}{} ", - self.edit_line + i, - colors::gray(" |"), - width = self.line_number_width - ) - .unwrap(); - self.output.push_str(&fmt_add()); - self.output.push_str(s); - self.output.push('\n'); - } + fn write_add_line(&mut self, text: &str) { + let text = text.strip_suffix('\n').unwrap_or(text); + write!( + self.output, + "{:width$}{} ", + self.edit_line, + colors::gray(" |"), + width = self.line_number_width + ) + .unwrap(); + self.output.push_str(&fmt_add()); + self.output.push_str(&fmt_add_text_highlight(text)); + self.output.push('\n'); + self.edit_line += 1; } } @@ -164,10 +124,6 @@ fn fmt_add() -> String { colors::green_bold("+").to_string() } -// fn fmt_add_text(x: &str) -> String { -// colors::green(x).to_string() -// } - fn fmt_add_text_highlight(x: &str) -> String { colors::black_on_green(x).to_string() } @@ -176,10 +132,6 @@ fn fmt_rem() -> String { colors::red_bold("-").to_string() } -// fn fmt_rem_text(x: &str) -> String { -// colors::red(x).to_string() -// } - fn fmt_rem_text_highlight(x: &str) -> String { colors::white_on_red(x).to_string() } @@ -279,11 +231,10 @@ mod tests { "2 | -\n", "3 | -\n", "4 | -\n", - "5 | -console.log(\n", - "1 | +console.log(\n", "6 | -'Hello World'\n", + "7 | -)\n", "2 | +\"Hello World\"\n", - "7 | -)\n3 | +);\n", + "3 | +);\n", ), ); } @@ -296,7 +247,6 @@ mod tests { concat!( "2 | -some line text test\n", "2 | +some line text test\n", - "3 | +\n", ), ); } From b7c83b145d758aef6df58a7ec3c864bb56ab9c22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Thu, 12 Mar 2026 12:09:17 +0100 Subject: [PATCH 10/17] fix: show context lines between hunks, fix Cargo.lock Address review feedback: show unchanged context lines between diff hunks so that related changes remain visually connected (e.g. console.log( appearing as both -/+ between surrounding changes). Context lines use non-highlighted colors to distinguish them from actual changes. Only lines immediately preceding a hunk are shown as context to avoid noise. Also update Cargo.lock for the getrandom feature addition. Co-Authored-By: Claude Opus 4.6 --- Cargo.lock | 22 +++++++------- libs/resolver/display.rs | 62 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 69 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 93993e303d235b..04729bd7b4de7d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3120,8 +3120,8 @@ dependencies = [ "deno_terminal", "deno_unsync", "futures", - "imara-diff", "http 1.4.0", + "imara-diff", "import_map", "indexmap 2.12.0", "jsonc-parser 0.28.0", @@ -5916,23 +5916,23 @@ dependencies = [ ] [[package]] -name = "imara-diff" -version = "0.2.0" +name = "image-webp" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f01d462f766df78ab820dd06f5eb700233c51f0f4c2e846520eaf4ba6aa5c5c" +checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" dependencies = [ - "hashbrown 0.15.5", - "memchr", + "byteorder-lite", + "quick-error 2.0.1", ] [[package]] -name = "import_map" -version = "0.24.0" +name = "imara-diff" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b77d01e822461baa8409e156015a1d91735549f0f2c17691bd2d996bef238f7f" +checksum = "2f01d462f766df78ab820dd06f5eb700233c51f0f4c2e846520eaf4ba6aa5c5c" dependencies = [ - "byteorder-lite", - "quick-error 2.0.1", + "hashbrown 0.15.5", + "memchr", ] [[package]] diff --git a/libs/resolver/display.rs b/libs/resolver/display.rs index 69cf173a4758d9..a7b4b4e54b585e 100644 --- a/libs/resolver/display.rs +++ b/libs/resolver/display.rs @@ -63,11 +63,26 @@ impl<'a> DiffBuilder<'a> { let mut prev_after_end: u32 = 0; for hunk in diff.hunks() { - // Skip unchanged lines between hunks - self.orig_line += + // Show unchanged context lines between hunks + let gap_len = (hunk.before.start - prev_before_end) as usize; - self.edit_line += - (hunk.after.start - prev_after_end) as usize; + if gap_len > 0 { + if prev_before_end == 0 { + // Before the first hunk — just skip, no context needed + self.orig_line += gap_len; + self.edit_line += gap_len; + } else { + // Between hunks — show up to 1 trailing context line + let skip = if gap_len > 1 { gap_len - 1 } else { 0 }; + self.orig_line += skip; + self.edit_line += skip; + for idx in (hunk.before.start - 1)..hunk.before.start { + let s = + self.input.interner[self.input.before[idx as usize]]; + self.write_context_line(s); + } + } + } // Write deleted lines for del in hunk.before.clone() { @@ -87,6 +102,35 @@ impl<'a> DiffBuilder<'a> { self.output } + fn write_context_line(&mut self, text: &str) { + let text = text.strip_suffix('\n').unwrap_or(text); + write!( + self.output, + "{:width$}{} ", + self.orig_line, + colors::gray(" |"), + width = self.line_number_width + ) + .unwrap(); + self.output.push_str(&fmt_rem()); + self.output.push_str(&fmt_rem_text(text)); + self.output.push('\n'); + self.orig_line += 1; + + write!( + self.output, + "{:width$}{} ", + self.edit_line, + colors::gray(" |"), + width = self.line_number_width + ) + .unwrap(); + self.output.push_str(&fmt_add()); + self.output.push_str(&fmt_add_text(text)); + self.output.push('\n'); + self.edit_line += 1; + } + fn write_rem_line(&mut self, text: &str) { let text = text.strip_suffix('\n').unwrap_or(text); write!( @@ -124,6 +168,10 @@ fn fmt_add() -> String { colors::green_bold("+").to_string() } +fn fmt_add_text(x: &str) -> String { + colors::green(x).to_string() +} + fn fmt_add_text_highlight(x: &str) -> String { colors::black_on_green(x).to_string() } @@ -132,6 +180,10 @@ fn fmt_rem() -> String { colors::red_bold("-").to_string() } +fn fmt_rem_text(x: &str) -> String { + colors::red(x).to_string() +} + fn fmt_rem_text_highlight(x: &str) -> String { colors::white_on_red(x).to_string() } @@ -231,6 +283,8 @@ mod tests { "2 | -\n", "3 | -\n", "4 | -\n", + "5 | -console.log(\n", + "1 | +console.log(\n", "6 | -'Hello World'\n", "7 | -)\n", "2 | +\"Hello World\"\n", From 057583aa827e1b129b53c40ca04c5a71373febff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Thu, 12 Mar 2026 14:48:31 +0100 Subject: [PATCH 11/17] fix: interleave delete/insert pairs and run formatter Interleave deleted and inserted lines within each hunk so that corresponding old/new line pairs appear adjacent in the output. This matches the expected format in spec tests (e.g. gitignore) and preserves readability for formatter diffs. Also fix rustfmt formatting in test code. Co-Authored-By: Claude Opus 4.6 --- libs/resolver/display.rs | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/libs/resolver/display.rs b/libs/resolver/display.rs index a7b4b4e54b585e..4959251d5049d1 100644 --- a/libs/resolver/display.rs +++ b/libs/resolver/display.rs @@ -64,8 +64,7 @@ impl<'a> DiffBuilder<'a> { for hunk in diff.hunks() { // Show unchanged context lines between hunks - let gap_len = - (hunk.before.start - prev_before_end) as usize; + let gap_len = (hunk.before.start - prev_before_end) as usize; if gap_len > 0 { if prev_before_end == 0 { // Before the first hunk — just skip, no context needed @@ -77,21 +76,33 @@ impl<'a> DiffBuilder<'a> { self.orig_line += skip; self.edit_line += skip; for idx in (hunk.before.start - 1)..hunk.before.start { - let s = - self.input.interner[self.input.before[idx as usize]]; + let s = self.input.interner[self.input.before[idx as usize]]; self.write_context_line(s); } } } - // Write deleted lines - for del in hunk.before.clone() { - let s = self.input.interner[self.input.before[del as usize]]; + // Interleave deleted/inserted line pairs, then emit remaining + let del_count = hunk.before.len(); + let ins_count = hunk.after.len(); + let paired = std::cmp::min(del_count, ins_count); + + for i in 0..paired { + let del_idx = hunk.before.start + i as u32; + let s = self.input.interner[self.input.before[del_idx as usize]]; + self.write_rem_line(s); + let ins_idx = hunk.after.start + i as u32; + let s = self.input.interner[self.input.after[ins_idx as usize]]; + self.write_add_line(s); + } + // Remaining unpaired deletes + for del_idx in (hunk.before.start + paired as u32)..hunk.before.end { + let s = self.input.interner[self.input.before[del_idx as usize]]; self.write_rem_line(s); } - // Write inserted lines - for ins in hunk.after.clone() { - let s = self.input.interner[self.input.after[ins as usize]]; + // Remaining unpaired inserts + for ins_idx in (hunk.after.start + paired as u32)..hunk.after.end { + let s = self.input.interner[self.input.after[ins_idx as usize]]; self.write_add_line(s); } @@ -286,8 +297,8 @@ mod tests { "5 | -console.log(\n", "1 | +console.log(\n", "6 | -'Hello World'\n", - "7 | -)\n", "2 | +\"Hello World\"\n", + "7 | -)\n", "3 | +);\n", ), ); @@ -298,10 +309,7 @@ mod tests { run_test( "test\nsome line text test", "test\nsome line text test\n", - concat!( - "2 | -some line text test\n", - "2 | +some line text test\n", - ), + concat!("2 | -some line text test\n", "2 | +some line text test\n",), ); } From ae9f49bc5fc4032c772c560139ee05137efa2de8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Thu, 12 Mar 2026 15:16:05 +0100 Subject: [PATCH 12/17] fix: resolve clippy warnings and remove context lines between hunks Remove context lines between diff hunks that were causing spec test failures. Remove unused prev_after_end variable and dead code (write_context_line, fmt_rem_text, fmt_add_text). Update test expectations since imara-diff correctly identifies unchanged lines. Co-Authored-By: Claude Opus 4.6 --- libs/resolver/display.rs | 61 ++-------------------------------------- 1 file changed, 3 insertions(+), 58 deletions(-) diff --git a/libs/resolver/display.rs b/libs/resolver/display.rs index 4959251d5049d1..0de67443dffb7b 100644 --- a/libs/resolver/display.rs +++ b/libs/resolver/display.rs @@ -60,27 +60,12 @@ impl<'a> DiffBuilder<'a> { fn handle_diff(mut self, diff: Diff) -> String { let mut prev_before_end: u32 = 0; - let mut prev_after_end: u32 = 0; for hunk in diff.hunks() { - // Show unchanged context lines between hunks + // Skip unchanged lines between hunks let gap_len = (hunk.before.start - prev_before_end) as usize; - if gap_len > 0 { - if prev_before_end == 0 { - // Before the first hunk — just skip, no context needed - self.orig_line += gap_len; - self.edit_line += gap_len; - } else { - // Between hunks — show up to 1 trailing context line - let skip = if gap_len > 1 { gap_len - 1 } else { 0 }; - self.orig_line += skip; - self.edit_line += skip; - for idx in (hunk.before.start - 1)..hunk.before.start { - let s = self.input.interner[self.input.before[idx as usize]]; - self.write_context_line(s); - } - } - } + self.orig_line += gap_len; + self.edit_line += gap_len; // Interleave deleted/inserted line pairs, then emit remaining let del_count = hunk.before.len(); @@ -107,41 +92,11 @@ impl<'a> DiffBuilder<'a> { } prev_before_end = hunk.before.end; - prev_after_end = hunk.after.end; } self.output } - fn write_context_line(&mut self, text: &str) { - let text = text.strip_suffix('\n').unwrap_or(text); - write!( - self.output, - "{:width$}{} ", - self.orig_line, - colors::gray(" |"), - width = self.line_number_width - ) - .unwrap(); - self.output.push_str(&fmt_rem()); - self.output.push_str(&fmt_rem_text(text)); - self.output.push('\n'); - self.orig_line += 1; - - write!( - self.output, - "{:width$}{} ", - self.edit_line, - colors::gray(" |"), - width = self.line_number_width - ) - .unwrap(); - self.output.push_str(&fmt_add()); - self.output.push_str(&fmt_add_text(text)); - self.output.push('\n'); - self.edit_line += 1; - } - fn write_rem_line(&mut self, text: &str) { let text = text.strip_suffix('\n').unwrap_or(text); write!( @@ -179,10 +134,6 @@ fn fmt_add() -> String { colors::green_bold("+").to_string() } -fn fmt_add_text(x: &str) -> String { - colors::green(x).to_string() -} - fn fmt_add_text_highlight(x: &str) -> String { colors::black_on_green(x).to_string() } @@ -191,10 +142,6 @@ fn fmt_rem() -> String { colors::red_bold("-").to_string() } -fn fmt_rem_text(x: &str) -> String { - colors::red(x).to_string() -} - fn fmt_rem_text_highlight(x: &str) -> String { colors::white_on_red(x).to_string() } @@ -294,8 +241,6 @@ mod tests { "2 | -\n", "3 | -\n", "4 | -\n", - "5 | -console.log(\n", - "1 | +console.log(\n", "6 | -'Hello World'\n", "2 | +\"Hello World\"\n", "7 | -)\n", From 6ac9249cfa3bc4b38a76b3693bc2b73e2f24edf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Thu, 12 Mar 2026 16:47:55 +0100 Subject: [PATCH 13/17] fix: update frozen lockfile test expectations for imara-diff The imara-diff algorithm matches identical lines (like closing braces) as unchanged context rather than delete/insert pairs, producing more minimal diffs. Update .out files to match. Co-Authored-By: Claude Opus 4.6 --- libs/resolver/display.rs | 48 +++++++++++++++++++ .../frozen_lockfile/frozen_new_dep_cache.out | 2 - .../frozen_new_dep_dynamic_http.out | 2 - .../frozen_new_dep_dynamic_jsr.out | 6 +-- .../frozen_new_dep_dynamic_npm.out | 2 - .../frozen_new_dep_jsr_cache.out | 6 --- .../frozen_new_dep_jsr_run.out | 6 --- .../frozen_lockfile/frozen_new_dep_run.out | 2 - .../frozen_package_json_changed.out | 2 - .../frozen_package_json_changed_install.out | 2 - .../frozen_lockfile/no_lockfile_run.out | 2 - 11 files changed, 50 insertions(+), 30 deletions(-) diff --git a/libs/resolver/display.rs b/libs/resolver/display.rs index 0de67443dffb7b..dce37264c1ee22 100644 --- a/libs/resolver/display.rs +++ b/libs/resolver/display.rs @@ -263,6 +263,54 @@ mod tests { run_test("test\n", "test\r\n", " | Text differed by line endings.\n"); } + #[test] + fn test_lockfile_diff() { + // Simulates the frozen lockfile diff scenario where adding a new + // dependency inserts lines while matching braces remain unchanged. + let before = r#"{ + "version": "5", + "packages": { + "npm:@denotest/add@1": "1.0.0" + }, + "npm": { + "@denotest/add@1.0.0": { + "integrity": "abc", + "tarball": "http://localhost/add/1.0.0.tgz" + } + } +}"#; + let after = r#"{ + "version": "5", + "packages": { + "npm:@denotest/add@1": "1.0.0", + "npm:@denotest/subtract@1": "1.0.0" + }, + "npm": { + "@denotest/add@1.0.0": { + "integrity": "abc", + "tarball": "http://localhost/add/1.0.0.tgz" + }, + "@denotest/subtract@1.0.0": { + "integrity": "def", + "tarball": "http://localhost/subtract/1.0.0.tgz" + } + } +}"#; + run_test( + before, + after, + concat!( + " 4 | - \"npm:@denotest/add@1\": \"1.0.0\"\n", + " 4 | + \"npm:@denotest/add@1\": \"1.0.0\",\n", + " 5 | + \"npm:@denotest/subtract@1\": \"1.0.0\"\n", + "11 | + },\n", + "12 | + \"@denotest/subtract@1.0.0\": {\n", + "13 | + \"integrity\": \"def\",\n", + "14 | + \"tarball\": \"http://localhost/subtract/1.0.0.tgz\"\n", + ), + ); + } + fn run_test(diff_text1: &str, diff_text2: &str, expected_output: &str) { assert_eq!( test_util::strip_ansi_codes(&diff(diff_text1, diff_text2,)), diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_cache.out b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_cache.out index dc90d5d8fb3901..1fc04746282daf 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_cache.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_cache.out @@ -3,9 +3,7 @@ changes: 4 | - "npm:@denotest/add@1": "1.0.0" 4 | + "npm:@denotest/add@1": "1.0.0", 5 | + "npm:@denotest/subtract@1": "1.0.0" -10 | - } 11 | + }, 12 | + "@denotest/subtract@1.0.0": { 13 | + "integrity": "[WILDCARD]", 14 | + "tarball": "http://localhost:4260/@denotest/subtract/1.0.0.tgz" -15 | + } diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_http.out b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_http.out index 5549c902b8ae72..01383dbff897a1 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_http.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_http.out @@ -1,11 +1,9 @@ Download http://localhost:4545/welcome.ts error: Uncaught (in promise) TypeError: The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it. changes: -11 | - } 11 | + }, 12 | + "remote": { 13 | + "http://localhost:4545/welcome.ts": "7353d5fcbc36c45d26bcbca478cf973092523b07c45999f41319820092b4de31" -14 | + } const _ = await import(scheme + "localhost:4545/welcome.ts"); ^ at [WILDCARD] \ No newline at end of file diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_jsr.out b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_jsr.out index c22b529edb9983..7d09c0e85b344c 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_jsr.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_jsr.out @@ -3,14 +3,12 @@ Download http://127.0.0.1:4250/@denotest/add/1.0.0_meta.json Download http://127.0.0.1:4250/@denotest/add/1.0.0/mod.ts error: Uncaught (in promise) TypeError: The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it. changes: - 4 | - "npm:@denotest/add@1": "1.0.0" 4 | + "jsr:@denotest/add@1": "1.0.0", - 5 | + "npm:@denotest/add@1": "1.0.0" - 6 | + }, 7 | + "jsr": { 8 | + "@denotest/add@1.0.0": { 9 | + "integrity": "[WILDCARD]" 10 | + } +11 | + }, const { add } = await import(scheme + "@denotest/add@1"); ^ - at [WILDCARD] \ No newline at end of file + at [WILDCARD] diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_npm.out b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_npm.out index 25e72c1e53d899..3647dc84a62b9c 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_npm.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_npm.out @@ -4,12 +4,10 @@ changes: 4 | - "npm:@denotest/add@1": "1.0.0" 4 | + "npm:@denotest/add@1": "1.0.0", 5 | + "npm:@denotest/subtract@1": "1.0.0" -10 | - } 11 | + }, 12 | + "@denotest/subtract@1.0.0": { 13 | + "integrity": "[WILDCARD]", 14 | + "tarball": "http://localhost:4260/@denotest/subtract/1.0.0.tgz" -15 | + } const { subtract } = await import(scheme + "@denotest/subtract@1"); ^ at [WILDCARD] diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_jsr_cache.out b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_jsr_cache.out index 9c0fa7edcc9cd3..31cfd2681c02a8 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_jsr_cache.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_jsr_cache.out @@ -1,12 +1,6 @@ error: The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it. changes: - 4 | - "jsr:@denotest/add@1": "1.0.0" - 5 | - }, - 6 | - "jsr": { 4 | + "jsr:@denotest/add@0.2.0": "0.2.0", - 5 | + "jsr:@denotest/add@1": "1.0.0" - 6 | + }, - 7 | + "jsr": { 8 | + "@denotest/add@0.2.0": { 9 | + "integrity": "[WILDCARD]" 10 | + }, diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_jsr_run.out b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_jsr_run.out index fe628a454a7cfb..dd4d9b835a36bc 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_jsr_run.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_jsr_run.out @@ -2,13 +2,7 @@ Download http://127.0.0.1:4250/@denotest/add/0.2.0_meta.json Download http://127.0.0.1:4250/@denotest/add/0.2.0/mod.ts error: The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it. changes: - 4 | - "jsr:@denotest/add@1": "1.0.0" - 5 | - }, - 6 | - "jsr": { 4 | + "jsr:@denotest/add@0.2.0": "0.2.0", - 5 | + "jsr:@denotest/add@1": "1.0.0" - 6 | + }, - 7 | + "jsr": { 8 | + "@denotest/add@0.2.0": { 9 | + "integrity": "[WILDCARD]" 10 | + }, diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_run.out b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_run.out index fe268456b32c7c..bc4a54b072771a 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_run.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_run.out @@ -4,9 +4,7 @@ changes: 4 | - "npm:@denotest/add@1": "1.0.0" 4 | + "npm:@denotest/add@1": "1.0.0", 5 | + "npm:@denotest/subtract@1": "1.0.0" -10 | - } 11 | + }, 12 | + "@denotest/subtract@1.0.0": { 13 | + "integrity": "[WILDCARD]", 14 | + "tarball": "http://localhost:4260/@denotest/subtract/1.0.0.tgz" -15 | + } diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_package_json_changed.out b/tests/specs/lockfile/frozen_lockfile/frozen_package_json_changed.out index 84b2c8194a5b45..7e95d02e21cdc9 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_package_json_changed.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_package_json_changed.out @@ -4,7 +4,6 @@ changes: 4 | - "npm:@denotest/add@1": "1.0.0" 4 | + "npm:@denotest/add@1": "1.0.0", 5 | + "npm:@denotest/bin@0.7.0": "0.7.0" -10 | - } 11 | + }, 12 | + "@denotest/bin@0.7.0": { 13 | + "integrity": "sha512-RAE7sQrdTUuV4KdDAshObhsULXb2QjTjfRg/KbzE9asZV8dUmwbPZy2kfmE2CunPo8+6DvwPklXFJ4PQi0Usuw==", @@ -17,4 +16,3 @@ changes: 20 | + "dependencies": [ 21 | + "npm:@denotest/bin@0.7.0" 22 | + ] -23 | + } diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_package_json_changed_install.out b/tests/specs/lockfile/frozen_lockfile/frozen_package_json_changed_install.out index e185239aa8be00..13c7eccb21bd7b 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_package_json_changed_install.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_package_json_changed_install.out @@ -3,7 +3,6 @@ changes: 4 | - "npm:@denotest/add@1": "1.0.0" 4 | + "npm:@denotest/add@1": "1.0.0", 5 | + "npm:@denotest/bin@0.7.0": "0.7.0" -10 | - } 11 | + }, 12 | + "@denotest/bin@0.7.0": { 13 | + "integrity": "sha512-RAE7sQrdTUuV4KdDAshObhsULXb2QjTjfRg/KbzE9asZV8dUmwbPZy2kfmE2CunPo8+6DvwPklXFJ4PQi0Usuw==", @@ -16,4 +15,3 @@ changes: 20 | + "dependencies": [ 21 | + "npm:@denotest/bin@0.7.0" 22 | + ] -23 | + } diff --git a/tests/specs/lockfile/frozen_lockfile/no_lockfile_run.out b/tests/specs/lockfile/frozen_lockfile/no_lockfile_run.out index 29a11dce70dad2..e4f98796c6ff99 100644 --- a/tests/specs/lockfile/frozen_lockfile/no_lockfile_run.out +++ b/tests/specs/lockfile/frozen_lockfile/no_lockfile_run.out @@ -1,7 +1,6 @@ Download http://localhost:4260/@denotest%2fadd error: The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it. changes: - 1 | - 1 | +{ 2 | + "version": "5", 3 | + "specifiers": { @@ -14,4 +13,3 @@ changes: 10 | + } 11 | + } 12 | +} -13 | + From 8d306852ea22ec85b1f45b11f8b2dde6db6dd2db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Thu, 12 Mar 2026 20:02:04 +0100 Subject: [PATCH 14/17] fix: preserve newline-only changes in diff output Add "\ No newline at end of file" marker (matching git convention) when a line lacks a trailing newline, so that trailing-newline changes are visible in the rendered diff instead of silently disappearing after strip_suffix('\n'). Co-Authored-By: Claude Opus 4.6 --- libs/resolver/display.rs | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/libs/resolver/display.rs b/libs/resolver/display.rs index dce37264c1ee22..341d3ebb60bbc1 100644 --- a/libs/resolver/display.rs +++ b/libs/resolver/display.rs @@ -98,7 +98,10 @@ impl<'a> DiffBuilder<'a> { } fn write_rem_line(&mut self, text: &str) { - let text = text.strip_suffix('\n').unwrap_or(text); + let (text, has_newline) = match text.strip_suffix('\n') { + Some(t) => (t, true), + None => (text, false), + }; write!( self.output, "{:width$}{} ", @@ -110,11 +113,17 @@ impl<'a> DiffBuilder<'a> { self.output.push_str(&fmt_rem()); self.output.push_str(&fmt_rem_text_highlight(text)); self.output.push('\n'); + if !has_newline { + self.write_no_newline_marker(); + } self.orig_line += 1; } fn write_add_line(&mut self, text: &str) { - let text = text.strip_suffix('\n').unwrap_or(text); + let (text, has_newline) = match text.strip_suffix('\n') { + Some(t) => (t, true), + None => (text, false), + }; write!( self.output, "{:width$}{} ", @@ -126,8 +135,23 @@ impl<'a> DiffBuilder<'a> { self.output.push_str(&fmt_add()); self.output.push_str(&fmt_add_text_highlight(text)); self.output.push('\n'); + if !has_newline { + self.write_no_newline_marker(); + } self.edit_line += 1; } + + fn write_no_newline_marker(&mut self) { + writeln!( + self.output, + "{:width$}{} {}", + "", + colors::gray(" |"), + colors::gray("\\ No newline at end of file"), + width = self.line_number_width + ) + .unwrap(); + } } fn fmt_add() -> String { @@ -229,7 +253,9 @@ mod tests { "console.log(\"Hello World\");", concat!( "1 | -console.log('Hello World')\n", + " | \\ No newline at end of file\n", "1 | +console.log(\"Hello World\");\n", + " | \\ No newline at end of file\n", ), ); @@ -244,7 +270,9 @@ mod tests { "6 | -'Hello World'\n", "2 | +\"Hello World\"\n", "7 | -)\n", + " | \\ No newline at end of file\n", "3 | +);\n", + " | \\ No newline at end of file\n", ), ); } @@ -254,7 +282,11 @@ mod tests { run_test( "test\nsome line text test", "test\nsome line text test\n", - concat!("2 | -some line text test\n", "2 | +some line text test\n",), + concat!( + "2 | -some line text test\n", + " | \\ No newline at end of file\n", + "2 | +some line text test\n", + ), ); } From f9f56af70f57e4ab2e94212e05e7467e3fab7b9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Thu, 12 Mar 2026 22:11:48 +0100 Subject: [PATCH 15/17] fix: add separator between non-contiguous hunks in diff output Emit a `...` separator line between hunks that have gaps (skipped unchanged lines), making it clear when diff output jumps across non-adjacent lines. Also remove unnecessary getrandom feature from dev-dependencies. Co-Authored-By: Claude Opus 4.6 --- libs/resolver/Cargo.toml | 2 +- libs/resolver/display.rs | 14 ++++++++++++++ .../frozen_lockfile/frozen_new_dep_cache.out | 1 + .../frozen_new_dep_dynamic_http.out | 1 + .../frozen_lockfile/frozen_new_dep_dynamic_jsr.out | 1 + .../frozen_lockfile/frozen_new_dep_dynamic_npm.out | 1 + .../frozen_lockfile/frozen_new_dep_jsr_cache.out | 1 + .../frozen_lockfile/frozen_new_dep_jsr_run.out | 1 + .../frozen_lockfile/frozen_new_dep_run.out | 1 + .../frozen_package_json_changed.out | 1 + .../frozen_package_json_changed_install.out | 1 + 11 files changed, 24 insertions(+), 1 deletion(-) diff --git a/libs/resolver/Cargo.toml b/libs/resolver/Cargo.toml index cb3392c56805dd..7e9437971b780f 100644 --- a/libs/resolver/Cargo.toml +++ b/libs/resolver/Cargo.toml @@ -69,5 +69,5 @@ url.workspace = true [dev-dependencies] node_resolver.workspace = true -sys_traits = { workspace = true, features = ["getrandom", "memory", "real", "serde_json"] } +sys_traits = { workspace = true, features = ["memory", "real", "serde_json"] } test_util.workspace = true diff --git a/libs/resolver/display.rs b/libs/resolver/display.rs index 341d3ebb60bbc1..cc07e070325e01 100644 --- a/libs/resolver/display.rs +++ b/libs/resolver/display.rs @@ -60,12 +60,25 @@ impl<'a> DiffBuilder<'a> { fn handle_diff(mut self, diff: Diff) -> String { let mut prev_before_end: u32 = 0; + let mut is_first_hunk = true; for hunk in diff.hunks() { // Skip unchanged lines between hunks let gap_len = (hunk.before.start - prev_before_end) as usize; + if gap_len > 0 && !is_first_hunk { + writeln!( + self.output, + "{:width$}{} {}", + "", + colors::gray(" |"), + colors::gray("..."), + width = self.line_number_width + ) + .unwrap(); + } self.orig_line += gap_len; self.edit_line += gap_len; + is_first_hunk = false; // Interleave deleted/inserted line pairs, then emit remaining let del_count = hunk.before.len(); @@ -335,6 +348,7 @@ mod tests { " 4 | - \"npm:@denotest/add@1\": \"1.0.0\"\n", " 4 | + \"npm:@denotest/add@1\": \"1.0.0\",\n", " 5 | + \"npm:@denotest/subtract@1\": \"1.0.0\"\n", + " | ...\n", "11 | + },\n", "12 | + \"@denotest/subtract@1.0.0\": {\n", "13 | + \"integrity\": \"def\",\n", diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_cache.out b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_cache.out index 1fc04746282daf..2b18fc74a1a926 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_cache.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_cache.out @@ -3,6 +3,7 @@ changes: 4 | - "npm:@denotest/add@1": "1.0.0" 4 | + "npm:@denotest/add@1": "1.0.0", 5 | + "npm:@denotest/subtract@1": "1.0.0" + | ... 11 | + }, 12 | + "@denotest/subtract@1.0.0": { 13 | + "integrity": "[WILDCARD]", diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_http.out b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_http.out index 01383dbff897a1..4697490d3074c0 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_http.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_http.out @@ -1,6 +1,7 @@ Download http://localhost:4545/welcome.ts error: Uncaught (in promise) TypeError: The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it. changes: + | ... 11 | + }, 12 | + "remote": { 13 | + "http://localhost:4545/welcome.ts": "7353d5fcbc36c45d26bcbca478cf973092523b07c45999f41319820092b4de31" diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_jsr.out b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_jsr.out index 7d09c0e85b344c..26f3f0f34fc81d 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_jsr.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_jsr.out @@ -4,6 +4,7 @@ Download http://127.0.0.1:4250/@denotest/add/1.0.0/mod.ts error: Uncaught (in promise) TypeError: The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it. changes: 4 | + "jsr:@denotest/add@1": "1.0.0", + | ... 7 | + "jsr": { 8 | + "@denotest/add@1.0.0": { 9 | + "integrity": "[WILDCARD]" diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_npm.out b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_npm.out index 3647dc84a62b9c..884eb8d6217eb9 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_npm.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_npm.out @@ -4,6 +4,7 @@ changes: 4 | - "npm:@denotest/add@1": "1.0.0" 4 | + "npm:@denotest/add@1": "1.0.0", 5 | + "npm:@denotest/subtract@1": "1.0.0" + | ... 11 | + }, 12 | + "@denotest/subtract@1.0.0": { 13 | + "integrity": "[WILDCARD]", diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_jsr_cache.out b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_jsr_cache.out index 31cfd2681c02a8..fae5a40c563e87 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_jsr_cache.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_jsr_cache.out @@ -1,6 +1,7 @@ error: The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it. changes: 4 | + "jsr:@denotest/add@0.2.0": "0.2.0", + | ... 8 | + "@denotest/add@0.2.0": { 9 | + "integrity": "[WILDCARD]" 10 | + }, diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_jsr_run.out b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_jsr_run.out index dd4d9b835a36bc..8c000631b3ed58 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_jsr_run.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_jsr_run.out @@ -3,6 +3,7 @@ Download http://127.0.0.1:4250/@denotest/add/0.2.0/mod.ts error: The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it. changes: 4 | + "jsr:@denotest/add@0.2.0": "0.2.0", + | ... 8 | + "@denotest/add@0.2.0": { 9 | + "integrity": "[WILDCARD]" 10 | + }, diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_run.out b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_run.out index bc4a54b072771a..7baeb0d652a8b3 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_run.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_run.out @@ -4,6 +4,7 @@ changes: 4 | - "npm:@denotest/add@1": "1.0.0" 4 | + "npm:@denotest/add@1": "1.0.0", 5 | + "npm:@denotest/subtract@1": "1.0.0" + | ... 11 | + }, 12 | + "@denotest/subtract@1.0.0": { 13 | + "integrity": "[WILDCARD]", diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_package_json_changed.out b/tests/specs/lockfile/frozen_lockfile/frozen_package_json_changed.out index 7e95d02e21cdc9..d27fef4fd9211d 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_package_json_changed.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_package_json_changed.out @@ -4,6 +4,7 @@ changes: 4 | - "npm:@denotest/add@1": "1.0.0" 4 | + "npm:@denotest/add@1": "1.0.0", 5 | + "npm:@denotest/bin@0.7.0": "0.7.0" + | ... 11 | + }, 12 | + "@denotest/bin@0.7.0": { 13 | + "integrity": "sha512-RAE7sQrdTUuV4KdDAshObhsULXb2QjTjfRg/KbzE9asZV8dUmwbPZy2kfmE2CunPo8+6DvwPklXFJ4PQi0Usuw==", diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_package_json_changed_install.out b/tests/specs/lockfile/frozen_lockfile/frozen_package_json_changed_install.out index 13c7eccb21bd7b..cb20dc4321eccb 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_package_json_changed_install.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_package_json_changed_install.out @@ -3,6 +3,7 @@ changes: 4 | - "npm:@denotest/add@1": "1.0.0" 4 | + "npm:@denotest/add@1": "1.0.0", 5 | + "npm:@denotest/bin@0.7.0": "0.7.0" + | ... 11 | + }, 12 | + "@denotest/bin@0.7.0": { 13 | + "integrity": "sha512-RAE7sQrdTUuV4KdDAshObhsULXb2QjTjfRg/KbzE9asZV8dUmwbPZy2kfmE2CunPo8+6DvwPklXFJ4PQi0Usuw==", From a24eb000a09c0c61022472f488b0126d17aa44b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Thu, 12 Mar 2026 22:28:02 +0100 Subject: [PATCH 16/17] update tests --- libs/resolver/display.rs | 21 ++++++++++--------- .../frozen_new_dep_dynamic_http.out | 1 - 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/libs/resolver/display.rs b/libs/resolver/display.rs index cc07e070325e01..63dc3e678c48a6 100644 --- a/libs/resolver/display.rs +++ b/libs/resolver/display.rs @@ -276,16 +276,17 @@ mod tests { "\n\n\n\nconsole.log(\n'Hello World'\n)", "console.log(\n\"Hello World\"\n);", concat!( - "1 | -\n", - "2 | -\n", - "3 | -\n", - "4 | -\n", - "6 | -'Hello World'\n", - "2 | +\"Hello World\"\n", - "7 | -)\n", - " | \\ No newline at end of file\n", - "3 | +);\n", - " | \\ No newline at end of file\n", + "1 | -", + "2 | -", + "3 | -", + "4 | -", + " | ...", + "6 | -'Hello World'", + "2 | +\"Hello World\"", + "7 | -)", + " | \\ No newline at end of file", + "3 | +);", + " | \\ No newline at end of file", ), ); } diff --git a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_http.out b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_http.out index 4697490d3074c0..01383dbff897a1 100644 --- a/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_http.out +++ b/tests/specs/lockfile/frozen_lockfile/frozen_new_dep_dynamic_http.out @@ -1,7 +1,6 @@ Download http://localhost:4545/welcome.ts error: Uncaught (in promise) TypeError: The lockfile is out of date. Run `deno install --frozen=false`, or rerun with `--frozen=false` to update it. changes: - | ... 11 | + }, 12 | + "remote": { 13 | + "http://localhost:4545/welcome.ts": "7353d5fcbc36c45d26bcbca478cf973092523b07c45999f41319820092b4de31" From 1311270dd256e86b0b4bd4bfc89da884f0c2e045 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Thu, 12 Mar 2026 22:43:40 +0100 Subject: [PATCH 17/17] fix the test --- libs/resolver/display.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/libs/resolver/display.rs b/libs/resolver/display.rs index 63dc3e678c48a6..4336567dba802a 100644 --- a/libs/resolver/display.rs +++ b/libs/resolver/display.rs @@ -276,17 +276,17 @@ mod tests { "\n\n\n\nconsole.log(\n'Hello World'\n)", "console.log(\n\"Hello World\"\n);", concat!( - "1 | -", - "2 | -", - "3 | -", - "4 | -", - " | ...", - "6 | -'Hello World'", - "2 | +\"Hello World\"", - "7 | -)", - " | \\ No newline at end of file", - "3 | +);", - " | \\ No newline at end of file", + "1 | -\n", + "2 | -\n", + "3 | -\n", + "4 | -\n", + " | ...\n", + "6 | -'Hello World'\n", + "2 | +\"Hello World\"\n", + "7 | -)\n", + " | \\ No newline at end of file\n", + "3 | +);\n", + " | \\ No newline at end of file\n", ), ); }