Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7f5c3fa

Browse filesBrowse files
committed
Merge origin/master
2 parents 527e83c + b5b7dac commit 7f5c3fa
Copy full SHA for 7f5c3fa

File tree

5 files changed

+207
-2
lines changed
Filter options

5 files changed

+207
-2
lines changed

‎README.md

Copy file name to clipboardExpand all lines: README.md
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ Just add the code below to your maven dependencies:
125125
<dependency>
126126
<groupId>io.github.java-diff-utils</groupId>
127127
<artifactId>java-diff-utils</artifactId>
128-
<version>4.12</version>
128+
<version>4.15</version>
129129
</dependency>
130130
```
131131

‎java-diff-utils/src/main/java/com/github/difflib/text/DiffRowGenerator.java

Copy file name to clipboardExpand all lines: java-diff-utils/src/main/java/com/github/difflib/text/DiffRowGenerator.java
+30-1Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import com.github.difflib.patch.InsertDelta;
2525
import com.github.difflib.patch.Patch;
2626
import com.github.difflib.text.DiffRow.Tag;
27+
import com.github.difflib.text.deltamerge.DeltaMergeUtils;
28+
import com.github.difflib.text.deltamerge.InlineDeltaMergeInfo;
2729
import java.util.*;
2830
import java.util.function.BiFunction;
2931
import java.util.function.BiPredicate;
@@ -75,6 +77,14 @@ public final class DiffRowGenerator {
7577
public static final Function<String, List<String>> SPLITTER_BY_WORD = line -> splitStringPreserveDelimiter(line, SPLIT_BY_WORD_PATTERN);
7678
public static final Pattern WHITESPACE_PATTERN = Pattern.compile("\\s+");
7779

80+
public static final Function<InlineDeltaMergeInfo, List<AbstractDelta<String>>> DEFAULT_INLINE_DELTA_MERGER = InlineDeltaMergeInfo::getDeltas;
81+
82+
/**
83+
* Merge diffs which are separated by equalities consisting of whitespace only.
84+
*/
85+
public static final Function<InlineDeltaMergeInfo, List<AbstractDelta<String>>> WHITESPACE_EQUALITIES_MERGER = deltaMergeInfo -> DeltaMergeUtils
86+
.mergeInlineDeltas(deltaMergeInfo, (equalities -> equalities.stream().allMatch(String::isBlank)));
87+
7888
public static Builder create() {
7989
return new Builder();
8090
}
@@ -170,6 +180,7 @@ static void wrapInTag(List<String> sequence, int startPosition,
170180
private final boolean reportLinesUnchanged;
171181
private final Function<String, String> lineNormalizer;
172182
private final Function<String, String> processDiffs;
183+
private final Function<InlineDeltaMergeInfo, List<AbstractDelta<String>>> inlineDeltaMerger;
173184

174185
private final boolean showInlineDiffs;
175186
private final boolean replaceOriginalLinefeedInChangesWithSpaces;
@@ -194,11 +205,13 @@ private DiffRowGenerator(Builder builder) {
194205
reportLinesUnchanged = builder.reportLinesUnchanged;
195206
lineNormalizer = builder.lineNormalizer;
196207
processDiffs = builder.processDiffs;
208+
inlineDeltaMerger = builder.inlineDeltaMerger;
197209

198210
replaceOriginalLinefeedInChangesWithSpaces = builder.replaceOriginalLinefeedInChangesWithSpaces;
199211

200212
Objects.requireNonNull(inlineDiffSplitter);
201213
Objects.requireNonNull(lineNormalizer);
214+
Objects.requireNonNull(inlineDeltaMerger);
202215
}
203216

204217
/**
@@ -370,7 +383,10 @@ private List<DiffRow> generateInlineDiffs(AbstractDelta<String> delta) {
370383
origList = inlineDiffSplitter.apply(joinedOrig);
371384
revList = inlineDiffSplitter.apply(joinedRev);
372385

373-
List<AbstractDelta<String>> inlineDeltas = DiffUtils.diff(origList, revList, equalizer).getDeltas();
386+
List<AbstractDelta<String>> originalInlineDeltas = DiffUtils.diff(origList, revList, equalizer)
387+
.getDeltas();
388+
List<AbstractDelta<String>> inlineDeltas = inlineDeltaMerger
389+
.apply(new InlineDeltaMergeInfo(originalInlineDeltas, origList, revList));
374390

375391
Collections.reverse(inlineDeltas);
376392
for (AbstractDelta<String> inlineDelta : inlineDeltas) {
@@ -465,6 +481,7 @@ public static class Builder {
465481
private Function<String, String> processDiffs = null;
466482
private BiPredicate<String, String> equalizer = null;
467483
private boolean replaceOriginalLinefeedInChangesWithSpaces = false;
484+
private Function<InlineDeltaMergeInfo, List<AbstractDelta<String>>> inlineDeltaMerger = DEFAULT_INLINE_DELTA_MERGER;
468485

469486
private Builder() {
470487
}
@@ -673,5 +690,17 @@ public Builder replaceOriginalLinefeedInChangesWithSpaces(boolean replace) {
673690
this.replaceOriginalLinefeedInChangesWithSpaces = replace;
674691
return this;
675692
}
693+
694+
/**
695+
* Provide an inline delta merger for use case specific delta optimizations.
696+
*
697+
* @param inlineDeltaMerger
698+
* @return
699+
*/
700+
public Builder inlineDeltaMerger(
701+
Function<InlineDeltaMergeInfo, List<AbstractDelta<String>>> inlineDeltaMerger) {
702+
this.inlineDeltaMerger = inlineDeltaMerger;
703+
return this;
704+
}
676705
}
677706
}
+79Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright 2009-2024 java-diff-utils.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.github.difflib.text.deltamerge;
17+
18+
import java.util.ArrayList;
19+
import java.util.List;
20+
import java.util.function.Predicate;
21+
22+
import com.github.difflib.patch.AbstractDelta;
23+
import com.github.difflib.patch.ChangeDelta;
24+
import com.github.difflib.patch.Chunk;
25+
26+
/**
27+
* Provides utility features for merge inline deltas
28+
*
29+
* @author <a href="christian.meier@epictec.ch">Christian Meier</a>
30+
*/
31+
final public class DeltaMergeUtils {
32+
33+
public static List<AbstractDelta<String>> mergeInlineDeltas(InlineDeltaMergeInfo deltaMergeInfo,
34+
Predicate<List<String>> replaceEquality) {
35+
final List<AbstractDelta<String>> originalDeltas = deltaMergeInfo.getDeltas();
36+
if (originalDeltas.size() < 2) {
37+
return originalDeltas;
38+
}
39+
40+
final List<AbstractDelta<String>> newDeltas = new ArrayList<>();
41+
newDeltas.add(originalDeltas.get(0));
42+
for (int i = 1; i < originalDeltas.size(); i++) {
43+
final AbstractDelta<String> previousDelta = newDeltas.getLast();
44+
final AbstractDelta<String> currentDelta = originalDeltas.get(i);
45+
46+
final List<String> equalities = deltaMergeInfo.getOrigList().subList(
47+
previousDelta.getSource().getPosition() + previousDelta.getSource().size(),
48+
currentDelta.getSource().getPosition());
49+
50+
if (replaceEquality.test(equalities)) {
51+
// Merge the previous delta, the equality and the current delta into one
52+
// ChangeDelta and replace the previous delta by this new ChangeDelta.
53+
final List<String> allSourceLines = new ArrayList<>();
54+
allSourceLines.addAll(previousDelta.getSource().getLines());
55+
allSourceLines.addAll(equalities);
56+
allSourceLines.addAll(currentDelta.getSource().getLines());
57+
58+
final List<String> allTargetLines = new ArrayList<>();
59+
allTargetLines.addAll(previousDelta.getTarget().getLines());
60+
allTargetLines.addAll(equalities);
61+
allTargetLines.addAll(currentDelta.getTarget().getLines());
62+
63+
final ChangeDelta<String> replacement = new ChangeDelta<>(
64+
new Chunk<>(previousDelta.getSource().getPosition(), allSourceLines),
65+
new Chunk<>(previousDelta.getTarget().getPosition(), allTargetLines));
66+
67+
newDeltas.removeLast();
68+
newDeltas.add(replacement);
69+
} else {
70+
newDeltas.add(currentDelta);
71+
}
72+
}
73+
74+
return newDeltas;
75+
}
76+
77+
private DeltaMergeUtils() {
78+
}
79+
}
+51Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright 2009-2024 java-diff-utils.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.github.difflib.text.deltamerge;
17+
18+
import java.util.List;
19+
20+
import com.github.difflib.patch.AbstractDelta;
21+
22+
/**
23+
* Holds the information required to merge deltas originating from an inline
24+
* diff
25+
*
26+
* @author <a href="christian.meier@epictec.ch">Christian Meier</a>
27+
*/
28+
public final class InlineDeltaMergeInfo {
29+
30+
private final List<AbstractDelta<String>> deltas;
31+
private final List<String> origList;
32+
private final List<String> revList;
33+
34+
public InlineDeltaMergeInfo(List<AbstractDelta<String>> deltas, List<String> origList, List<String> revList) {
35+
this.deltas = deltas;
36+
this.origList = origList;
37+
this.revList = revList;
38+
}
39+
40+
public List<AbstractDelta<String>> getDeltas() {
41+
return deltas;
42+
}
43+
44+
public List<String> getOrigList() {
45+
return origList;
46+
}
47+
48+
public List<String> getRevList() {
49+
return revList;
50+
}
51+
}

‎java-diff-utils/src/test/java/com/github/difflib/text/DiffRowGeneratorTest.java

Copy file name to clipboardExpand all lines: java-diff-utils/src/test/java/com/github/difflib/text/DiffRowGeneratorTest.java
+46Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.util.Arrays;
1313
import java.util.Collections;
1414
import java.util.List;
15+
import java.util.function.Function;
1516
import java.util.regex.Pattern;
1617
import static java.util.stream.Collectors.joining;
1718
import static java.util.stream.Collectors.toList;
@@ -20,6 +21,10 @@
2021
import static org.junit.jupiter.api.Assertions.assertTrue;
2122
import org.junit.jupiter.api.Test;
2223

24+
import com.github.difflib.patch.AbstractDelta;
25+
import com.github.difflib.text.deltamerge.DeltaMergeUtils;
26+
import com.github.difflib.text.deltamerge.InlineDeltaMergeInfo;
27+
2328
public class DiffRowGeneratorTest {
2429

2530
@Test
@@ -791,6 +796,47 @@ public void testIssue129SkipWhitespaceChanges() throws IOException {
791796
.forEach(System.out::println);
792797
}
793798

799+
@Test
800+
public void testGeneratorWithWhitespaceDeltaMerge() {
801+
final DiffRowGenerator generator = DiffRowGenerator.create().showInlineDiffs(true).mergeOriginalRevised(true)
802+
.inlineDiffByWord(true).oldTag(f -> "~").newTag(f -> "**") //
803+
.lineNormalizer(StringUtils::htmlEntites) // do not replace tabs
804+
.inlineDeltaMerger(DiffRowGenerator.WHITESPACE_EQUALITIES_MERGER).build();
805+
806+
assertInlineDiffResult(generator, "No diff", "No diff", "No diff");
807+
assertInlineDiffResult(generator, " x whitespace before diff", " y whitespace before diff",
808+
" ~x~**y** whitespace before diff");
809+
assertInlineDiffResult(generator, "Whitespace after diff x ", "Whitespace after diff y ",
810+
"Whitespace after diff ~x~**y** ");
811+
assertInlineDiffResult(generator, "Diff x x between", "Diff y y between", "Diff ~x x~**y y** between");
812+
assertInlineDiffResult(generator, "Hello \t world", "Hi \t universe", "~Hello \t world~**Hi \t universe**");
813+
assertInlineDiffResult(generator, "The quick brown fox jumps over the lazy dog", "A lazy dog jumps over a fox",
814+
"~The quick brown fox ~**A lazy dog **jumps over ~the lazy dog~**a fox**");
815+
}
816+
817+
@Test
818+
public void testGeneratorWithMergingDeltasForShortEqualities() {
819+
final Function<InlineDeltaMergeInfo, List<AbstractDelta<String>>> shortEqualitiesMerger = deltaMergeInfo -> DeltaMergeUtils
820+
.mergeInlineDeltas(deltaMergeInfo,
821+
(equalities -> equalities.stream().mapToInt(String::length).sum() < 6));
822+
823+
final DiffRowGenerator generator = DiffRowGenerator.create().showInlineDiffs(true).mergeOriginalRevised(true)
824+
.inlineDiffByWord(true).oldTag(f -> "~").newTag(f -> "**").inlineDeltaMerger(shortEqualitiesMerger)
825+
.build();
826+
827+
assertInlineDiffResult(generator, "No diff", "No diff", "No diff");
828+
assertInlineDiffResult(generator, "aaa bbb ccc", "xxx bbb zzz", "~aaa bbb ccc~**xxx bbb zzz**");
829+
assertInlineDiffResult(generator, "aaa bbbb ccc", "xxx bbbb zzz", "~aaa~**xxx** bbbb ~ccc~**zzz**");
830+
}
831+
832+
private void assertInlineDiffResult(DiffRowGenerator generator, String original, String revised, String expected) {
833+
final List<DiffRow> rows = generator.generateDiffRows(Arrays.asList(original), Arrays.asList(revised));
834+
print(rows);
835+
836+
assertEquals(1, rows.size());
837+
assertEquals(expected, rows.get(0).getOldLine().toString());
838+
}
839+
794840
@Test
795841
public void testIssue188HangOnExamples() throws IOException, URISyntaxException {
796842
try (FileSystem zipFs = FileSystems.newFileSystem(Paths.get("target/test-classes/com/github/difflib/text/test.zip"), null);) {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.