From eab19a8e2d1cefbec325f23771d0cbc66a417d66 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 13 Jun 2024 16:22:45 -0700 Subject: [PATCH] Fix panic when doing various cursor movements with a pending mouse selection (#13016) This fixes a panic in the `SelectionsCollection::first_anchor` when there was a pending mouse selection and no other selections. Until recently, this method was only used in vim mode, but as of https://github.com/zed-industries/zed/commit/53b0720d546b6541fbf236d2f9d2dadbce6f126e, it's also used in the normal `move_up` and `move_down` actions. So until recently, the panic that this fixes could only happen in vim mode. Release Notes: - Fixed a crash that could happen when using certain cursor-motion bindings with a pending mouse selection. --- crates/editor/src/editor_tests.rs | 36 ++++++++++++++++++++++ crates/editor/src/selections_collection.rs | 5 ++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 7c825118f1b9a1e73e6e7a543e68b62d031a840b..a38068eb899b9182b0df2aea72e953e135084d86 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -476,6 +476,42 @@ fn test_canceling_pending_selection(cx: &mut TestAppContext) { }); } +#[gpui::test] +fn test_movement_actions_with_pending_selection(cx: &mut TestAppContext) { + init_test(cx, |_| {}); + + let view = cx.add_window(|cx| { + let buffer = MultiBuffer::build_simple("aaaaaa\nbbbbbb\ncccccc\ndddddd\n", cx); + build_editor(buffer, cx) + }); + + _ = view.update(cx, |view, cx| { + view.begin_selection(DisplayPoint::new(DisplayRow(2), 2), false, 1, cx); + assert_eq!( + view.selections.display_ranges(cx), + [DisplayPoint::new(DisplayRow(2), 2)..DisplayPoint::new(DisplayRow(2), 2)] + ); + + view.move_down(&Default::default(), cx); + assert_eq!( + view.selections.display_ranges(cx), + [DisplayPoint::new(DisplayRow(3), 2)..DisplayPoint::new(DisplayRow(3), 2)] + ); + + view.begin_selection(DisplayPoint::new(DisplayRow(2), 2), false, 1, cx); + assert_eq!( + view.selections.display_ranges(cx), + [DisplayPoint::new(DisplayRow(2), 2)..DisplayPoint::new(DisplayRow(2), 2)] + ); + + view.move_up(&Default::default(), cx); + assert_eq!( + view.selections.display_ranges(cx), + [DisplayPoint::new(DisplayRow(1), 2)..DisplayPoint::new(DisplayRow(1), 2)] + ); + }); +} + #[gpui::test] fn test_clone(cx: &mut TestAppContext) { init_test(cx, |_| {}); diff --git a/crates/editor/src/selections_collection.rs b/crates/editor/src/selections_collection.rs index 70af8b9489385519a18de24904020b8f05560916..7a448f0b6cc5feb0ad244f037e601ed2c37a3e98 100644 --- a/crates/editor/src/selections_collection.rs +++ b/crates/editor/src/selections_collection.rs @@ -256,7 +256,10 @@ impl SelectionsCollection { } pub fn first_anchor(&self) -> Selection { - self.disjoint[0].clone() + self.pending + .as_ref() + .map(|pending| pending.selection.clone()) + .unwrap_or_else(|| self.disjoint.first().cloned().unwrap()) } pub fn first>(