From 2b78f0c76f65b189b2689d738827681751b5e93e Mon Sep 17 00:00:00 2001 From: Andras Schmelczer Date: Sat, 5 Apr 2025 13:57:48 +0100 Subject: [PATCH] Remove break_up_raw_operations --- backend/reconcile/src/diffs/myers.rs | 61 ++++++++++++------- ...ile__diffs__myers__tests__delete_only.snap | 4 ++ ...iffs__myers__tests__identical_content.snap | 8 +++ ...ile__diffs__myers__tests__insert_only.snap | 4 ++ ...iffs__myers__tests__prefix_and_suffix.snap | 4 ++ .../operation_transformation/edited_text.rs | 32 +--------- 6 files changed, 61 insertions(+), 52 deletions(-) diff --git a/backend/reconcile/src/diffs/myers.rs b/backend/reconcile/src/diffs/myers.rs index da75404..b7a7c5e 100644 --- a/backend/reconcile/src/diffs/myers.rs +++ b/backend/reconcile/src/diffs/myers.rs @@ -1,4 +1,5 @@ //! Taken from +//! //! Myers' diff algorithm. //! //! * time: `O((N+M)D)` @@ -34,8 +35,7 @@ use crate::{ /// Diff `old`, between indices `old_range` and `new` between indices /// `new_range`. /// -/// This diff is done with an optional deadline that defines the maximal -/// execution time permitted before it bails and falls back to an approximation. +/// The returned RawOperations all have a token count of 1. pub fn diff(old: &[Token], new: &[Token]) -> Vec> where T: PartialEq + Clone + std::fmt::Debug, @@ -44,6 +44,7 @@ where let mut vb = V::new(max_d); let mut vf = V::new(max_d); let mut result: Vec> = vec![]; + conquer( old, 0..old.len(), @@ -53,6 +54,12 @@ where &mut vb, &mut result, ); + + debug_assert!( + result.iter().all(|op| op.tokens().len() == 1), + "All operations should be of length 1" + ); + result } @@ -234,9 +241,11 @@ fn conquer( // Check for common prefix let common_prefix_len = common_prefix_len(old, old_range.clone(), new, new_range.clone()); if common_prefix_len > 0 { - result.push(RawOperation::Equal( - old[old_range.start..old_range.start + common_prefix_len].to_vec(), - )); + result.extend( + old[old_range.start..old_range.start + common_prefix_len] + .iter() + .map(|token| RawOperation::Equal(vec![token.clone()])), + ) } old_range.start += common_prefix_len; new_range.start += common_prefix_len; @@ -251,15 +260,19 @@ fn conquer( new_range.end -= common_suffix_len; if old_range.is_empty() && new_range.is_empty() { - // Do nothing + // do nothing } else if new_range.is_empty() { - result.push(RawOperation::Delete( - old[old_range.start..old_range.start + old_range.len()].to_vec(), - )); + result.extend( + old[old_range.start..old_range.start + old_range.len()] + .iter() + .map(|token| RawOperation::Delete(vec![token.clone()])), + ) } else if old_range.is_empty() { - result.push(RawOperation::Insert( - new[new_range.start..new_range.start + new_range.len()].to_vec(), - )); + result.extend( + new[new_range.start..new_range.start + new_range.len()] + .iter() + .map(|token| RawOperation::Insert(vec![token.clone()])), + ) } else if let Some((x_start, y_start)) = find_middle_snake(old, old_range.clone(), new, new_range.clone(), vf, vb) { @@ -268,18 +281,24 @@ fn conquer( conquer(old, old_a, new, new_a, vf, vb, result); conquer(old, old_b, new, new_b, vf, vb, result); } else { - result.push(RawOperation::Delete( - old[old_range.start..old_range.end].to_vec(), - )); - result.push(RawOperation::Insert( - new[new_range.start..new_range.end].to_vec(), - )); + result.extend( + old[old_range.start..old_range.end] + .iter() + .map(|token| RawOperation::Delete(vec![token.clone()])), + ); + result.extend( + new[new_range.start..new_range.end] + .iter() + .map(|token| RawOperation::Insert(vec![token.clone()])), + ); } if common_suffix_len > 0 { - result.push(RawOperation::Equal( - old[common_suffix.0..common_suffix.0 + common_suffix_len].to_vec(), - )); + result.extend( + old[common_suffix.0..common_suffix.0 + common_suffix_len] + .iter() + .map(|token| RawOperation::Equal(vec![token.clone()])), + ); } } diff --git a/backend/reconcile/src/diffs/snapshots/reconcile__diffs__myers__tests__delete_only.snap b/backend/reconcile/src/diffs/snapshots/reconcile__diffs__myers__tests__delete_only.snap index a4598d0..93bb529 100644 --- a/backend/reconcile/src/diffs/snapshots/reconcile__diffs__myers__tests__delete_only.snap +++ b/backend/reconcile/src/diffs/snapshots/reconcile__diffs__myers__tests__delete_only.snap @@ -12,6 +12,10 @@ snapshot_kind: text is_left_joinable: true, is_right_joinable: true, }, + ], + ), + Delete( + [ Token { normalised: "b", original: "b", diff --git a/backend/reconcile/src/diffs/snapshots/reconcile__diffs__myers__tests__identical_content.snap b/backend/reconcile/src/diffs/snapshots/reconcile__diffs__myers__tests__identical_content.snap index 2fc3317..f82d4ac 100644 --- a/backend/reconcile/src/diffs/snapshots/reconcile__diffs__myers__tests__identical_content.snap +++ b/backend/reconcile/src/diffs/snapshots/reconcile__diffs__myers__tests__identical_content.snap @@ -12,12 +12,20 @@ snapshot_kind: text is_left_joinable: true, is_right_joinable: true, }, + ], + ), + Equal( + [ Token { normalised: "b", original: "b", is_left_joinable: true, is_right_joinable: true, }, + ], + ), + Equal( + [ Token { normalised: "c", original: "c", diff --git a/backend/reconcile/src/diffs/snapshots/reconcile__diffs__myers__tests__insert_only.snap b/backend/reconcile/src/diffs/snapshots/reconcile__diffs__myers__tests__insert_only.snap index e07d844..0f61f3c 100644 --- a/backend/reconcile/src/diffs/snapshots/reconcile__diffs__myers__tests__insert_only.snap +++ b/backend/reconcile/src/diffs/snapshots/reconcile__diffs__myers__tests__insert_only.snap @@ -12,6 +12,10 @@ snapshot_kind: text is_left_joinable: true, is_right_joinable: true, }, + ], + ), + Insert( + [ Token { normalised: "b", original: "b", diff --git a/backend/reconcile/src/diffs/snapshots/reconcile__diffs__myers__tests__prefix_and_suffix.snap b/backend/reconcile/src/diffs/snapshots/reconcile__diffs__myers__tests__prefix_and_suffix.snap index 6b86600..e50984f 100644 --- a/backend/reconcile/src/diffs/snapshots/reconcile__diffs__myers__tests__prefix_and_suffix.snap +++ b/backend/reconcile/src/diffs/snapshots/reconcile__diffs__myers__tests__prefix_and_suffix.snap @@ -22,6 +22,10 @@ snapshot_kind: text is_left_joinable: true, is_right_joinable: true, }, + ], + ), + Delete( + [ Token { normalised: "c", original: "c", diff --git a/backend/reconcile/src/operation_transformation/edited_text.rs b/backend/reconcile/src/operation_transformation/edited_text.rs index fdaa87f..12e0ee8 100644 --- a/backend/reconcile/src/operation_transformation/edited_text.rs +++ b/backend/reconcile/src/operation_transformation/edited_text.rs @@ -63,41 +63,11 @@ where Self::new( original, - Self::cook_operations(Self::elongate_operations(Self::break_up_raw_operations( - diff, - ))) - .collect(), + Self::cook_operations(Self::elongate_operations(diff)).collect(), updated.cursors, ) } - fn break_up_raw_operations(raw_operations: I) -> impl Iterator> - where - I: IntoIterator>, - { - raw_operations.into_iter().flat_map(|raw_operation| { - let mut result: Vec> = Vec::new(); - match raw_operation { - RawOperation::Insert(tokens) => { - for token in tokens { - result.push(RawOperation::Insert(vec![token])); - } - } - RawOperation::Delete(tokens) => { - for token in tokens { - result.push(RawOperation::Delete(vec![token])); - } - } - RawOperation::Equal(tokens) => { - for token in tokens { - result.push(RawOperation::Equal(vec![token])); - } - } - } - result.into_iter() - }) - } - fn elongate_operations(raw_operations: I) -> Vec> where I: IntoIterator>,