@@ -57,6 +57,7 @@ struct HistoryAdditionRange {
#[derive(Debug, Clone)]
struct HistoryDeletionRange {
deleted_text: String,
+ position_in_current: usize,
}
fn compute_history_addition_ranges(history_edits: &[GranularEdit]) -> Vec<HistoryAdditionRange> {
@@ -79,13 +80,22 @@ fn compute_history_addition_ranges(history_edits: &[GranularEdit]) -> Vec<Histor
}
fn compute_history_deletion_ranges(history_edits: &[GranularEdit]) -> Vec<HistoryDeletionRange> {
- history_edits
- .iter()
- .filter(|edit| !edit.old_text.is_empty())
- .map(|edit| HistoryDeletionRange {
- deleted_text: edit.old_text.clone(),
- })
- .collect()
+ let mut result = Vec::new();
+ let mut offset_delta: isize = 0;
+
+ for edit in history_edits {
+ if !edit.old_text.is_empty() {
+ let position_in_current = (edit.range.start as isize + offset_delta) as usize;
+ result.push(HistoryDeletionRange {
+ deleted_text: edit.old_text.clone(),
+ position_in_current,
+ });
+ }
+
+ offset_delta += edit.new_text.len() as isize - edit.old_text.len() as isize;
+ }
+
+ result
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
@@ -214,17 +224,23 @@ fn compute_restored_deletions(
history_deletion_ranges: &[HistoryDeletionRange],
prediction_edits: &[GranularEdit],
) -> usize {
- let history_deleted_text: String = history_deletion_ranges
- .iter()
- .map(|r| r.deleted_text.as_str())
- .collect();
+ let mut restored = 0;
- let prediction_added_text: String = prediction_edits
- .iter()
- .map(|e| e.new_text.as_str())
- .collect();
+ for pred_edit in prediction_edits {
+ if pred_edit.new_text.is_empty() {
+ continue;
+ }
- compute_lcs_length(&history_deleted_text, &prediction_added_text)
+ for deletion in history_deletion_ranges {
+ if pred_edit.range.contains(&deletion.position_in_current)
+ || deletion.position_in_current == pred_edit.range.start
+ {
+ restored += compute_lcs_length(&deletion.deleted_text, &pred_edit.new_text);
+ }
+ }
+ }
+
+ restored
}
fn compute_lcs_length(a: &str, b: &str) -> usize {
@@ -524,6 +540,14 @@ mod tests {
expected_reversal_chars: 1,
expected_total_chars: 1,
},
+ Case {
+ name: "multiple insertions no reversal",
+ original: "print(\"Hello, World!\")",
+ current: "sys.(\"Hello, World!\")",
+ predicted: "sys.stdout.write(\"Hello, World!\n\")",
+ expected_reversal_chars: 0,
+ expected_total_chars: 13,
+ },
];
for case in &cases {