diff: do not add excessive number of context lines to last unified-diff hunk

The last hunk could be truncated instead, but the .peekable() version is easier
to follow. If we truncated lines, we would have to adjust line ranges
accordingly.
This commit is contained in:
Yuya Nishihara 2024-06-30 20:54:49 +09:00
parent ec709e7f8b
commit f9a15ba542
2 changed files with 9 additions and 12 deletions

View file

@ -771,7 +771,8 @@ fn unified_diff_hunks<'content>(
lines: vec![], lines: vec![],
}; };
let diff = Diff::for_tokenizer(&[left_content, right_content], diff::find_line_ranges); let diff = Diff::for_tokenizer(&[left_content, right_content], diff::find_line_ranges);
for hunk in diff.hunks() { let mut diff_hunks = diff.hunks().peekable();
while let Some(hunk) = diff_hunks.next() {
match hunk { match hunk {
DiffHunk::Matching(content) => { DiffHunk::Matching(content) => {
let mut lines = content.split_inclusive(|b| *b == b'\n').fuse(); let mut lines = content.split_inclusive(|b| *b == b'\n').fuse();
@ -779,7 +780,11 @@ fn unified_diff_hunks<'content>(
// The previous hunk line should be either removed/added. // The previous hunk line should be either removed/added.
current_hunk.extend_context_lines(lines.by_ref().take(num_context_lines)); current_hunk.extend_context_lines(lines.by_ref().take(num_context_lines));
} }
let before_lines = lines.by_ref().rev().take(num_context_lines).collect_vec(); let before_lines = if diff_hunks.peek().is_some() {
lines.by_ref().rev().take(num_context_lines).collect()
} else {
vec![] // No more hunks
};
let num_skip_lines = lines.count(); let num_skip_lines = lines.count();
if num_skip_lines > 0 { if num_skip_lines > 0 {
let left_start = current_hunk.left_line_range.end + num_skip_lines; let left_start = current_hunk.left_line_range.end + num_skip_lines;
@ -804,12 +809,7 @@ fn unified_diff_hunks<'content>(
} }
} }
} }
// The last unified hunk might contain redundant "before" context lines. if !current_hunk.lines.is_empty() {
if !current_hunk
.lines
.iter()
.all(|(diff_type, _line)| *diff_type == DiffLineType::Context)
{
hunks.push(current_hunk); hunks.push(current_hunk);
} }
hunks hunks

View file

@ -952,14 +952,13 @@ fn test_diff_leading_trailing_context() {
// N=5 <= 2 * num_context_lines: The last hunk wouldn't be split if // N=5 <= 2 * num_context_lines: The last hunk wouldn't be split if
// trailing diff existed. // trailing diff existed.
// FIXME: trailing context lines should be trimmed
let stdout = test_env.jj_cmd_success(&repo_path, &["diff", "--git", "--context=3"]); let stdout = test_env.jj_cmd_success(&repo_path, &["diff", "--git", "--context=3"]);
insta::assert_snapshot!(stdout, @r###" insta::assert_snapshot!(stdout, @r###"
diff --git a/file1 b/file1 diff --git a/file1 b/file1
index 1bf57dee4a...69b3e1865c 100644 index 1bf57dee4a...69b3e1865c 100644
--- a/file1 --- a/file1
+++ b/file1 +++ b/file1
@@ -3,10 +3,10 @@ @@ -3,8 +3,8 @@
3 3
4 4
5 5
@ -969,8 +968,6 @@ fn test_diff_leading_trailing_context() {
7 7
8 8
9 9
10
11
"###); "###);
// N=5 > 2 * num_context_lines: The last hunk should be split no matter // N=5 > 2 * num_context_lines: The last hunk should be split no matter