my fork of dmp
Fix full overlap elimination for inserts with trailing deletes
In cases where there's a full overlap elimination for a delete (e.g., when there's a delete followed by an insert that ends with a re-insert of the deleted content), the delete should be replaced with an insert of the (new) prefix, and the overlap should be replaced by an equal covering the overlap, and the original insert should be changed to zero-length. There's a bug in the implementation where it fails to identify the overlap correctly and so leaves the original insert in place, which results in duplicated contents. This adds a test for this overlap case and it fixes the big.
Andrew Schamp 8 months ago
parent 00e0e8f · commit 65c526b
-rw-r--r--src/dmp.rs23
1 files changed, 19 insertions, 4 deletions
diff --git a/src/dmp.rs b/src/dmp.rs
index 0aab3d8..3bf1fb5 100644
--- a/src/dmp.rs
+++ b/src/dmp.rs
@@ -1317,7 +1317,7 @@ impl DiffMatchPatch {
diffs[p_prev] = Diff::insert(&insert[..ins_idx_end]);
}
- if p_next < diffs.len() && overlap_2 < delete.len() {
+ if p_next < diffs.len() && overlap_2 <= delete.len() {
diffs[p_next] = Diff::delete(&delete[overlap_2..]);
}
@@ -4460,17 +4460,32 @@ mod tests {
DiffMatchPatch::cleanup_semantic(&mut diffs);
assert_eq!(test, diffs);
- // overlap that fully eliminates an delete
+ // overlap that fully eliminates a delete at the front of an insert
let mut diffs = vec![
Diff::delete(&"abcd".chars().collect::<Vec<_>>()[..]),
Diff::insert(&"abcd1212".chars().collect::<Vec<_>>()[..]),
- Diff::equal(&"wxyz".chars().collect::<Vec<_>>()[..]),
+ Diff::equal(&"wxyz".chars().collect::<Vec<_>>()[..]),
];
let test = vec![
Diff::delete(&"".chars().collect::<Vec<_>>()[..]),
Diff::equal(&"abcd".chars().collect::<Vec<_>>()[..]),
Diff::insert(&"1212".chars().collect::<Vec<_>>()[..]),
- Diff::equal(&"wxyz".chars().collect::<Vec<_>>()[..]),
+ Diff::equal(&"wxyz".chars().collect::<Vec<_>>()[..]),
+ ];
+ DiffMatchPatch::cleanup_semantic(&mut diffs);
+ assert_eq!(test, diffs);
+
+ // overlap that fully eliminates a delete at the tail of an insert
+ let mut diffs = vec![
+ Diff::delete(&"abcd".chars().collect::<Vec<_>>()[..]),
+ Diff::insert(&"1212abcd".chars().collect::<Vec<_>>()[..]),
+ Diff::delete(&"2323".chars().collect::<Vec<_>>()[..]),
+ ];
+ let test = vec![
+ Diff::insert(&"1212".chars().collect::<Vec<_>>()[..]),
+ Diff::equal(&"abcd".chars().collect::<Vec<_>>()[..]),
+ Diff::delete(&"".chars().collect::<Vec<_>>()[..]),
+ Diff::delete(&"2323".chars().collect::<Vec<_>>()[..]),
];
DiffMatchPatch::cleanup_semantic(&mut diffs);
assert_eq!(test, diffs);