From fa68aa770493fe82e90ba057671a3c9fd6391561 Mon Sep 17 00:00:00 2001 From: Ben Kunkle Date: Fri, 30 Jan 2026 09:44:15 -0600 Subject: [PATCH] ep_cli: Further improve reversal ratio (#48028) Closes #ISSUE Release Notes: - N/A *or* Added/Fixed/Improved ... --- .../src/reversal_tracking.rs | 56 +++++++++++++------ 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/crates/edit_prediction_cli/src/reversal_tracking.rs b/crates/edit_prediction_cli/src/reversal_tracking.rs index 6f1be51c79df3d002004a09c5d0977d5f2a215eb..05d2e3b9d386ac20d2ad99b42707a76dd2fa845d 100644 --- a/crates/edit_prediction_cli/src/reversal_tracking.rs +++ b/crates/edit_prediction_cli/src/reversal_tracking.rs @@ -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 { @@ -79,13 +80,22 @@ fn compute_history_addition_ranges(history_edits: &[GranularEdit]) -> Vec Vec { - 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 {