From 3966413ecae15d2c8f5da96ae1774ac767f4fd82 Mon Sep 17 00:00:00 2001 From: Andrew Parmet Date: Tue, 5 May 2026 17:22:40 -0400 Subject: [PATCH] Fix UnifiedDiffReader to use correct DeltaType finalizeChunk() previously always created ChangeDelta regardless of whether the hunk contained only insertions, only deletions, or only context lines. This made it impossible for consumers to determine the actual type of change from the delta alone. Now uses InsertDelta when a hunk contains only additions (no context), DeleteDelta when only deletions (no context), EqualDelta when only context, and ChangeDelta otherwise. Hunks with context lines still use ChangeDelta to preserve backward-compatible applyTo behavior. Fixes #201 --- .../unifieddiff/UnifiedDiffReader.java | 56 +++++++++++++------ .../unifieddiff/UnifiedDiffReaderTest.java | 2 +- 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/java-diff-utils/src/main/java/com/github/difflib/unifieddiff/UnifiedDiffReader.java b/java-diff-utils/src/main/java/com/github/difflib/unifieddiff/UnifiedDiffReader.java index 61e1aa4..b457d97 100644 --- a/java-diff-utils/src/main/java/com/github/difflib/unifieddiff/UnifiedDiffReader.java +++ b/java-diff-utils/src/main/java/com/github/difflib/unifieddiff/UnifiedDiffReader.java @@ -15,8 +15,12 @@ */ package com.github.difflib.unifieddiff; +import com.github.difflib.patch.AbstractDelta; import com.github.difflib.patch.ChangeDelta; import com.github.difflib.patch.Chunk; +import com.github.difflib.patch.DeleteDelta; +import com.github.difflib.patch.EqualDelta; +import com.github.difflib.patch.InsertDelta; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; @@ -298,23 +302,41 @@ private void processSimilarityIndex(MatchResult match, String line) { private int delLineIdx = 0; private int addLineIdx = 0; - private void finalizeChunk() { - if (!originalTxt.isEmpty() || !revisedTxt.isEmpty()) { - actualFile - .getPatch() - .addDelta(new ChangeDelta<>( - new Chunk<>(old_ln - 1, originalTxt, delLineIdxList), - new Chunk<>(new_ln - 1, revisedTxt, addLineIdxList))); - old_ln = 0; - new_ln = 0; - originalTxt.clear(); - revisedTxt.clear(); - addLineIdxList.clear(); - delLineIdxList.clear(); - delLineIdx = 0; - addLineIdx = 0; - } - } + private void finalizeChunk() { + if (!originalTxt.isEmpty() || !revisedTxt.isEmpty()) { + boolean hasDeletes = !delLineIdxList.isEmpty(); + boolean hasInserts = !addLineIdxList.isEmpty(); + boolean hasContext = originalTxt.size() != delLineIdxList.size() + || revisedTxt.size() != addLineIdxList.size(); + AbstractDelta delta; + if (hasContext || (hasDeletes && hasInserts)) { + delta = new ChangeDelta<>( + new Chunk<>(old_ln - 1, originalTxt, delLineIdxList), + new Chunk<>(new_ln - 1, revisedTxt, addLineIdxList)); + } else if (hasDeletes) { + delta = new DeleteDelta<>( + new Chunk<>(old_ln - 1, originalTxt, delLineIdxList), + new Chunk<>(new_ln - 1, revisedTxt, addLineIdxList)); + } else if (hasInserts) { + delta = new InsertDelta<>( + new Chunk<>(old_ln - 1, originalTxt, delLineIdxList), + new Chunk<>(new_ln - 1, revisedTxt, addLineIdxList)); + } else { + delta = new EqualDelta<>( + new Chunk<>(old_ln - 1, originalTxt, delLineIdxList), + new Chunk<>(new_ln - 1, revisedTxt, addLineIdxList)); + } + actualFile.getPatch().addDelta(delta); + old_ln = 0; + new_ln = 0; + originalTxt.clear(); + revisedTxt.clear(); + addLineIdxList.clear(); + delLineIdxList.clear(); + delLineIdx = 0; + addLineIdx = 0; + } + } private void processNormalLine(MatchResult match, String line) { String cline = line.substring(1); diff --git a/java-diff-utils/src/test/java/com/github/difflib/unifieddiff/UnifiedDiffReaderTest.java b/java-diff-utils/src/test/java/com/github/difflib/unifieddiff/UnifiedDiffReaderTest.java index fc272ed..ee7e1d9 100644 --- a/java-diff-utils/src/test/java/com/github/difflib/unifieddiff/UnifiedDiffReaderTest.java +++ b/java-diff-utils/src/test/java/com/github/difflib/unifieddiff/UnifiedDiffReaderTest.java @@ -275,7 +275,7 @@ public void testParseIssue104() throws IOException { assertThat(file.getToFile()).isEqualTo("doc/samba_data_tool_path.xml.in"); assertThat(file.getPatch().toString()) - .isEqualTo("Patch{deltas=[[ChangeDelta, position: 0, lines: [] to [@SAMBA_DATA_TOOL@]]]}"); + .isEqualTo("Patch{deltas=[[InsertDelta, position: 0, lines: [@SAMBA_DATA_TOOL@]]]}"); assertThat(diff.getTail()).isEqualTo("2.14.4"); }