diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 31497e6409..f079d0fb27 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -6523,6 +6523,10 @@ impl Editor { provider.accept(cx); } + // Store the transaction ID and selections before applying the edit + let transaction_id_prev = + self.buffer.read_with(cx, |b, cx| b.last_transaction_id(cx)); + let snapshot = self.buffer.read(cx).snapshot(cx); let last_edit_end = edits.last().unwrap().0.end.bias_right(&snapshot); @@ -6531,9 +6535,20 @@ impl Editor { }); self.change_selections(None, window, cx, |s| { - s.select_anchor_ranges([last_edit_end..last_edit_end]) + s.select_anchor_ranges([last_edit_end..last_edit_end]); }); + let selections = self.selections.disjoint_anchors(); + if let Some(transaction_id_now) = + self.buffer.read_with(cx, |b, cx| b.last_transaction_id(cx)) + { + let has_new_transaction = transaction_id_prev != Some(transaction_id_now); + if has_new_transaction { + self.selection_history + .insert_transaction(transaction_id_now, selections); + } + } + self.update_visible_inline_completion(window, cx); if self.active_inline_completion.is_none() { self.refresh_inline_completion(true, true, window, cx); diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index e81b72538d..d1ad72234a 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -1,6 +1,7 @@ use super::*; use crate::{ JoinLines, + inline_completion_tests::FakeInlineCompletionProvider, linked_editing_ranges::LinkedEditingRanges, scroll::scroll_amount::ScrollAmount, test::{ @@ -6380,6 +6381,98 @@ async fn test_undo_format_scrolls_to_last_edit_pos(cx: &mut TestAppContext) { "}); } +#[gpui::test] +async fn test_undo_inline_completion_scrolls_to_edit_pos(cx: &mut TestAppContext) { + init_test(cx, |_| {}); + + let mut cx = EditorTestContext::new(cx).await; + + let provider = cx.new(|_| FakeInlineCompletionProvider::default()); + cx.update_editor(|editor, window, cx| { + editor.set_edit_prediction_provider(Some(provider.clone()), window, cx); + }); + + cx.set_state(indoc! {" + line 1 + line 2 + linˇe 3 + line 4 + line 5 + line 6 + line 7 + line 8 + line 9 + line 10 + "}); + + let snapshot = cx.buffer_snapshot(); + let edit_position = snapshot.anchor_after(Point::new(2, 4)); + + cx.update(|_, cx| { + provider.update(cx, |provider, _| { + provider.set_inline_completion(Some(inline_completion::InlineCompletion { + id: None, + edits: vec![(edit_position..edit_position, "X".into())], + edit_preview: None, + })) + }) + }); + + cx.update_editor(|editor, window, cx| editor.update_visible_inline_completion(window, cx)); + cx.update_editor(|editor, window, cx| { + editor.accept_edit_prediction(&crate::AcceptEditPrediction, window, cx) + }); + + cx.assert_editor_state(indoc! {" + line 1 + line 2 + lineXˇ 3 + line 4 + line 5 + line 6 + line 7 + line 8 + line 9 + line 10 + "}); + + cx.update_editor(|editor, window, cx| { + editor.change_selections(None, window, cx, |s| { + s.select_ranges([Point::new(9, 2)..Point::new(9, 2)]); + }); + }); + + cx.assert_editor_state(indoc! {" + line 1 + line 2 + lineX 3 + line 4 + line 5 + line 6 + line 7 + line 8 + line 9 + liˇne 10 + "}); + + cx.update_editor(|editor, window, cx| { + editor.undo(&Default::default(), window, cx); + }); + + cx.assert_editor_state(indoc! {" + line 1 + line 2 + lineˇ 3 + line 4 + line 5 + line 6 + line 7 + line 8 + line 9 + line 10 + "}); +} + #[gpui::test] async fn test_select_next_with_multiple_carets(cx: &mut TestAppContext) { init_test(cx, |_| {}); diff --git a/crates/editor/src/inline_completion_tests.rs b/crates/editor/src/inline_completion_tests.rs index 05d15302d1..5ac34c94f5 100644 --- a/crates/editor/src/inline_completion_tests.rs +++ b/crates/editor/src/inline_completion_tests.rs @@ -302,8 +302,8 @@ fn assign_editor_completion_provider( } #[derive(Default, Clone)] -struct FakeInlineCompletionProvider { - completion: Option, +pub struct FakeInlineCompletionProvider { + pub completion: Option, } impl FakeInlineCompletionProvider {