From 7fa6145f76c4005f4e27bc342356b1ccce6f91ba Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Wed, 17 Sep 2025 17:10:05 +0200 Subject: [PATCH] editor: Fix `unwrap_syntax_node` panicking by not setting selections (#38329) Fixes ZED-11T Release Notes: - N/A *or* Added/Fixed/Improved ... --- crates/agent_ui/src/text_thread_editor.rs | 4 +- crates/editor/src/editor.rs | 90 +++++++++++-------- crates/editor/src/element.rs | 12 ++- crates/editor/src/items.rs | 8 +- crates/editor/src/jsx_tag_auto_close.rs | 2 +- crates/editor/src/lsp_ext.rs | 2 +- crates/editor/src/mouse_context_menu.rs | 7 +- crates/editor/src/rust_analyzer_ext.rs | 6 +- crates/editor/src/selections_collection.rs | 42 +++++---- crates/editor/src/test/editor_test_context.rs | 2 +- crates/git_ui/src/text_diff_view.rs | 2 +- crates/vim/src/command.rs | 4 +- crates/vim/src/normal/mark.rs | 2 +- crates/vim/src/surrounds.rs | 2 +- crates/vim/src/vim.rs | 10 +-- crates/vim/src/visual.rs | 2 +- 16 files changed, 112 insertions(+), 85 deletions(-) diff --git a/crates/agent_ui/src/text_thread_editor.rs b/crates/agent_ui/src/text_thread_editor.rs index d979db5e0468b696d32ed755aec1ef47e2fd3df3..df904b2416cc9b66371a3557b04ff97246f25a41 100644 --- a/crates/agent_ui/src/text_thread_editor.rs +++ b/crates/agent_ui/src/text_thread_editor.rs @@ -477,7 +477,7 @@ impl TextThreadEditor { return; } - let selections = self.editor.read(cx).selections.disjoint_anchors(); + let selections = self.editor.read(cx).selections.disjoint_anchors_arc(); let mut commands_by_range = HashMap::default(); let workspace = self.workspace.clone(); self.context.update(cx, |context, cx| { @@ -1823,7 +1823,7 @@ impl TextThreadEditor { fn split(&mut self, _: &Split, _window: &mut Window, cx: &mut Context) { self.context.update(cx, |context, cx| { - let selections = self.editor.read(cx).selections.disjoint_anchors(); + let selections = self.editor.read(cx).selections.disjoint_anchors_arc(); for selection in selections.as_ref() { let buffer = self.editor.read(cx).buffer().read(cx).snapshot(cx); let range = selection diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index b71a8313626bc716003062559c56c248c085fd73..06b643115b3350a53c3ad9101c911a53f4f85341 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -2414,14 +2414,10 @@ impl Editor { pub fn is_range_selected(&mut self, range: &Range, cx: &mut Context) -> bool { if self .selections - .pending - .as_ref() + .pending_anchor() .is_some_and(|pending_selection| { let snapshot = self.buffer().read(cx).snapshot(cx); - pending_selection - .selection - .range() - .includes(range, &snapshot) + pending_selection.range().includes(range, &snapshot) }) { return true; @@ -3054,7 +3050,7 @@ impl Editor { } } - let selection_anchors = self.selections.disjoint_anchors(); + let selection_anchors = self.selections.disjoint_anchors_arc(); if self.focus_handle.is_focused(window) && self.leader_id.is_none() { self.buffer.update(cx, |buffer, cx| { @@ -3170,7 +3166,7 @@ impl Editor { self.blink_manager.update(cx, BlinkManager::pause_blinking); cx.emit(EditorEvent::SelectionsChanged { local }); - let selections = &self.selections.disjoint; + let selections = &self.selections.disjoint_anchors_arc(); if selections.len() == 1 { cx.emit(SearchEvent::ActiveMatchChanged) } @@ -3282,14 +3278,14 @@ impl Editor { other: Entity, cx: &mut Context, ) -> gpui::Subscription { - let other_selections = other.read(cx).selections.disjoint.to_vec(); + let other_selections = other.read(cx).selections.disjoint_anchors().to_vec(); self.selections.change_with(cx, |selections| { selections.select_anchors(other_selections); }); let other_subscription = cx.subscribe(&other, |this, other, other_evt, cx| { if let EditorEvent::SelectionsChanged { local: true } = other_evt { - let other_selections = other.read(cx).selections.disjoint.to_vec(); + let other_selections = other.read(cx).selections.disjoint_anchors().to_vec(); if other_selections.is_empty() { return; } @@ -3301,7 +3297,7 @@ impl Editor { let this_subscription = cx.subscribe_self::(move |this, this_evt, cx| { if let EditorEvent::SelectionsChanged { local: true } = this_evt { - let these_selections = this.selections.disjoint.to_vec(); + let these_selections = this.selections.disjoint_anchors().to_vec(); if these_selections.is_empty() { return; } @@ -3339,7 +3335,7 @@ impl Editor { effects, old_cursor_position: self.selections.newest_anchor().head(), history_entry: SelectionHistoryEntry { - selections: self.selections.disjoint_anchors(), + selections: self.selections.disjoint_anchors_arc(), select_next_state: self.select_next_state.clone(), select_prev_state: self.select_prev_state.clone(), add_selections_state: self.add_selections_state.clone(), @@ -3499,6 +3495,7 @@ impl Editor { let mut pending_selection = self .selections .pending_anchor() + .cloned() .expect("extend_selection not called with pending selection"); if position >= tail { pending_selection.start = tail_anchor; @@ -3520,7 +3517,7 @@ impl Editor { }; self.change_selections(effects, window, cx, |s| { - s.set_pending(pending_selection, pending_mode) + s.set_pending(pending_selection.clone(), pending_mode) }); } @@ -3595,7 +3592,7 @@ impl Editor { Some(selected_points[0].id) } else { let clicked_point_already_selected = - self.selections.disjoint.iter().find(|selection| { + self.selections.disjoint_anchors().iter().find(|selection| { selection.start.to_point(buffer) == start.to_point(buffer) || selection.end.to_point(buffer) == end.to_point(buffer) }); @@ -3700,7 +3697,7 @@ impl Editor { if self.columnar_selection_state.is_some() { self.select_columns(position, goal_column, &display_map, window, cx); - } else if let Some(mut pending) = self.selections.pending_anchor() { + } else if let Some(mut pending) = self.selections.pending_anchor().cloned() { let buffer = &display_map.buffer_snapshot; let head; let tail; @@ -3776,7 +3773,7 @@ impl Editor { } self.change_selections(SelectionEffects::no_scroll(), window, cx, |s| { - s.set_pending(pending, mode); + s.set_pending(pending.clone(), mode); }); } else { log::error!("update_selection dispatched with no pending selection"); @@ -3885,7 +3882,8 @@ impl Editor { }; pending_nonempty_selection - || (self.columnar_selection_state.is_some() && self.selections.disjoint.len() > 1) + || (self.columnar_selection_state.is_some() + && self.selections.disjoint_anchors().len() > 1) } pub fn has_pending_selection(&self) -> bool { @@ -6065,7 +6063,7 @@ impl Editor { editor.refresh_edit_prediction(true, false, window, cx); }); - self.invalidate_autoclose_regions(&self.selections.disjoint_anchors(), &snapshot); + self.invalidate_autoclose_regions(&self.selections.disjoint_anchors_arc(), &snapshot); let show_new_completions_on_confirm = completion .confirm @@ -7473,7 +7471,7 @@ impl Editor { s.select_anchor_ranges([last_edit_end..last_edit_end]); }); - let selections = self.selections.disjoint_anchors(); + let selections = self.selections.disjoint_anchors_arc(); if let Some(transaction_id_now) = self.buffer.read(cx).last_transaction_id(cx) { let has_new_transaction = transaction_id_prev != Some(transaction_id_now); if has_new_transaction { @@ -7718,7 +7716,7 @@ impl Editor { let Some(mode) = Self::columnar_selection_mode(modifiers, cx) else { return; }; - if self.selections.pending.is_none() { + if self.selections.pending_anchor().is_none() { return; } @@ -10513,7 +10511,7 @@ impl Editor { fn enable_wrap_selections_in_tag(&self, cx: &App) -> bool { let snapshot = self.buffer.read(cx).snapshot(cx); - for selection in self.selections.disjoint_anchors().iter() { + for selection in self.selections.disjoint_anchors_arc().iter() { if snapshot .language_at(selection.start) .and_then(|lang| lang.config().wrap_characters.as_ref()) @@ -10847,7 +10845,7 @@ impl Editor { let snapshot = self.snapshot(window, cx); let cursors = self .selections - .disjoint_anchors() + .disjoint_anchors_arc() .iter() .map(|selection| { let cursor_position: Point = selection.head().to_point(&snapshot.buffer_snapshot); @@ -14538,7 +14536,7 @@ impl Editor { window: &mut Window, cx: &mut Context, ) -> Result<()> { - let selections = self.selections.disjoint_anchors(); + let selections = self.selections.disjoint_anchors_arc(); match selections.first() { Some(first) if selections.len() >= 2 => { self.change_selections(Default::default(), window, cx, |s| { @@ -14562,7 +14560,7 @@ impl Editor { window: &mut Window, cx: &mut Context, ) -> Result<()> { - let selections = self.selections.disjoint_anchors(); + let selections = self.selections.disjoint_anchors_arc(); match selections.last() { Some(last) if selections.len() >= 2 => { self.change_selections(Default::default(), window, cx, |s| { @@ -15115,11 +15113,9 @@ impl Editor { let full_edits = selections .into_iter() .filter_map(|selection| { - // Only requires two branches once if-let-chains stabilize (#53667) - let child = if !selection.is_empty() { - selection.range() - } else if let Some((_, ancestor_range)) = - buffer.syntax_ancestor(selection.start..selection.end) + let child = if selection.is_empty() + && let Some((_, ancestor_range)) = + buffer.syntax_ancestor(selection.start..selection.end) { ancestor_range } else { @@ -15141,6 +15137,9 @@ impl Editor { Some((selection.id, parent, text)) }) .collect::>(); + if full_edits.is_empty() { + return; + } self.transact(window, cx, |this, window, cx| { this.buffer.update(cx, |buffer, cx| { @@ -15649,7 +15648,7 @@ impl Editor { cx: &mut Context, ) { - let selections = self.selections.disjoint_anchors(); + let selections = self.selections.disjoint_anchors_arc(); let lines = if lines == 0 { EditorSettings::get_global(cx).expand_excerpt_lines @@ -17108,7 +17107,7 @@ impl Editor { .transaction(transaction_id_prev) .map(|t| t.0.clone()) }) - .unwrap_or_else(|| self.selections.disjoint_anchors()); + .unwrap_or_else(|| self.selections.disjoint_anchors_arc()); let mut timeout = cx.background_executor().timer(FORMAT_TIMEOUT).fuse(); let format = project.update(cx, |project, cx| { @@ -17648,7 +17647,7 @@ impl Editor { .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx)) { self.selection_history - .insert_transaction(tx_id, self.selections.disjoint_anchors()); + .insert_transaction(tx_id, self.selections.disjoint_anchors_arc()); cx.emit(EditorEvent::TransactionBegun { transaction_id: tx_id, }); @@ -17670,7 +17669,7 @@ impl Editor { if let Some((_, end_selections)) = self.selection_history.transaction_mut(transaction_id) { - *end_selections = Some(self.selections.disjoint_anchors()); + *end_selections = Some(self.selections.disjoint_anchors_arc()); } else { log::error!("unexpectedly ended a transaction that wasn't started by this editor"); } @@ -18340,7 +18339,12 @@ impl Editor { _window: &mut Window, cx: &mut Context, ) { - let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect(); + let ranges: Vec<_> = self + .selections + .disjoint_anchors() + .iter() + .map(|s| s.range()) + .collect(); self.toggle_diff_hunks_in_ranges(ranges, cx); } @@ -18378,7 +18382,12 @@ impl Editor { cx: &mut Context, ) { let snapshot = self.buffer.read(cx).snapshot(cx); - let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect(); + let ranges: Vec<_> = self + .selections + .disjoint_anchors() + .iter() + .map(|s| s.range()) + .collect(); let stage = self.has_stageable_diff_hunks_in_ranges(&ranges, &snapshot); self.stage_or_unstage_diff_hunks(stage, ranges, cx); } @@ -18542,7 +18551,12 @@ impl Editor { } pub fn expand_selected_diff_hunks(&mut self, cx: &mut Context) { - let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect(); + let ranges: Vec<_> = self + .selections + .disjoint_anchors() + .iter() + .map(|s| s.range()) + .collect(); self.buffer .update(cx, |buffer, cx| buffer.expand_diff_hunks(ranges, cx)) } @@ -21262,7 +21276,7 @@ impl Editor { buffer.finalize_last_transaction(cx); if self.leader_id.is_none() { buffer.set_active_selections( - &self.selections.disjoint_anchors(), + &self.selections.disjoint_anchors_arc(), self.selections.line_mode, self.cursor_shape, cx, @@ -23558,7 +23572,7 @@ impl EntityInputHandler for Editor { let marked_ranges = { let snapshot = this.buffer.read(cx).read(cx); this.selections - .disjoint_anchors() + .disjoint_anchors_arc() .iter() .map(|selection| { selection.start.bias_left(&snapshot)..selection.end.bias_right(&snapshot) diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 928c092b58cd99ac2a4fdf91ac52b20f84c2e645..37ae90d70b91017016e46b409f67c7000c2b0f91 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1060,7 +1060,7 @@ impl EditorElement { ); if mouse_down_time.elapsed() >= drag_and_drop_delay { let drop_cursor = Selection { - id: post_inc(&mut editor.selections.next_selection_id), + id: post_inc(&mut editor.selections.next_selection_id()), start: drop_anchor, end: drop_anchor, reversed: false, @@ -1547,9 +1547,13 @@ impl EditorElement { // Local cursors if !skip_local { let color = cx.theme().players().local().cursor; - editor.selections.disjoint.iter().for_each(|selection| { - add_cursor(selection.head(), color); - }); + editor + .selections + .disjoint_anchors() + .iter() + .for_each(|selection| { + add_cursor(selection.head(), color); + }); if let Some(ref selection) = editor.selections.pending_anchor() { add_cursor(selection.head(), color); } diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index 253d0c27518107dc1cad3733cefbfef5bc12b807..bf21d6b461e6fdc082fdd1431f13b8daae730824 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -187,7 +187,7 @@ impl FollowableItem for Editor { } else if self.focus_handle.is_focused(window) { self.buffer.update(cx, |buffer, cx| { buffer.set_active_selections( - &self.selections.disjoint_anchors(), + &self.selections.disjoint_anchors_arc(), self.selections.line_mode, self.cursor_shape, cx, @@ -231,7 +231,7 @@ impl FollowableItem for Editor { scroll_y: scroll_anchor.offset.y, selections: self .selections - .disjoint_anchors() + .disjoint_anchors_arc() .iter() .map(|s| serialize_selection(s, &snapshot)) .collect(), @@ -310,7 +310,7 @@ impl FollowableItem for Editor { let snapshot = self.buffer.read(cx).snapshot(cx); update.selections = self .selections - .disjoint_anchors() + .disjoint_anchors_arc() .iter() .map(|s| serialize_selection(s, &snapshot)) .collect(); @@ -1675,7 +1675,7 @@ impl SearchableItem for Editor { cx: &mut Context, ) -> usize { let buffer = self.buffer().read(cx).snapshot(cx); - let current_index_position = if self.selections.disjoint_anchors().len() == 1 { + let current_index_position = if self.selections.disjoint_anchors_arc().len() == 1 { self.selections.newest_anchor().head() } else { matches[current_index].start diff --git a/crates/editor/src/jsx_tag_auto_close.rs b/crates/editor/src/jsx_tag_auto_close.rs index e6c518beae3ecf3741b5f74be6087628f5231c8c..c1c6ccf2f549042a3defc84d8628f7f614244d44 100644 --- a/crates/editor/src/jsx_tag_auto_close.rs +++ b/crates/editor/src/jsx_tag_auto_close.rs @@ -507,7 +507,7 @@ pub(crate) fn handle_from( { let selections = this - .read_with(cx, |this, _| this.selections.disjoint_anchors()) + .read_with(cx, |this, _| this.selections.disjoint_anchors_arc()) .ok()?; for selection in selections.iter() { let Some(selection_buffer_offset_head) = diff --git a/crates/editor/src/lsp_ext.rs b/crates/editor/src/lsp_ext.rs index 18ad2d71c835e5ec7e3bbd540de21f7e38425c39..0c4760f5684acf450b793a1deac54be983dcafd0 100644 --- a/crates/editor/src/lsp_ext.rs +++ b/crates/editor/src/lsp_ext.rs @@ -35,7 +35,7 @@ where let project = editor.project.clone()?; editor .selections - .disjoint_anchors() + .disjoint_anchors_arc() .iter() .filter_map(|selection| Some((selection.head(), selection.head().buffer_id?))) .unique_by(|(_, buffer_id)| *buffer_id) diff --git a/crates/editor/src/mouse_context_menu.rs b/crates/editor/src/mouse_context_menu.rs index 3bc334c54c2f58e6dda2b404039369907c275422..78b12945afd1c2fcd359181afb030fc235c60a18 100644 --- a/crates/editor/src/mouse_context_menu.rs +++ b/crates/editor/src/mouse_context_menu.rs @@ -130,12 +130,9 @@ fn display_ranges<'a>( display_map: &'a DisplaySnapshot, selections: &'a SelectionsCollection, ) -> impl Iterator> + 'a { - let pending = selections - .pending - .as_ref() - .map(|pending| &pending.selection); + let pending = selections.pending_anchor(); selections - .disjoint + .disjoint_anchors() .iter() .chain(pending) .map(move |s| s.start.to_display_point(display_map)..s.end.to_display_point(display_map)) diff --git a/crates/editor/src/rust_analyzer_ext.rs b/crates/editor/src/rust_analyzer_ext.rs index f4059ca03d2ad70106aa958b4fe0c545cb4988ea..ffa0c017c0eb157df776cc49e0dba51e617e3379 100644 --- a/crates/editor/src/rust_analyzer_ext.rs +++ b/crates/editor/src/rust_analyzer_ext.rs @@ -319,7 +319,7 @@ fn cancel_flycheck_action( }; let buffer_id = editor .selections - .disjoint_anchors() + .disjoint_anchors_arc() .iter() .find_map(|selection| { let buffer_id = selection.start.buffer_id.or(selection.end.buffer_id)?; @@ -344,7 +344,7 @@ fn run_flycheck_action( }; let buffer_id = editor .selections - .disjoint_anchors() + .disjoint_anchors_arc() .iter() .find_map(|selection| { let buffer_id = selection.start.buffer_id.or(selection.end.buffer_id)?; @@ -369,7 +369,7 @@ fn clear_flycheck_action( }; let buffer_id = editor .selections - .disjoint_anchors() + .disjoint_anchors_arc() .iter() .find_map(|selection| { let buffer_id = selection.start.buffer_id.or(selection.end.buffer_id)?; diff --git a/crates/editor/src/selections_collection.rs b/crates/editor/src/selections_collection.rs index 0a02390b641e1020aff8d9cf0167b44485baf489..e562be10e92344c1c892878ab674cba39beb74c2 100644 --- a/crates/editor/src/selections_collection.rs +++ b/crates/editor/src/selections_collection.rs @@ -28,13 +28,13 @@ pub struct PendingSelection { pub struct SelectionsCollection { display_map: Entity, buffer: Entity, - pub next_selection_id: usize, + next_selection_id: usize, pub line_mode: bool, /// The non-pending, non-overlapping selections. /// The [SelectionsCollection::pending] selection could possibly overlap these - pub disjoint: Arc<[Selection]>, + disjoint: Arc<[Selection]>, /// A pending selection, such as when the mouse is being dragged - pub pending: Option, + pending: Option, } impl SelectionsCollection { @@ -84,20 +84,27 @@ impl SelectionsCollection { /// The non-pending, non-overlapping selections. There could be a pending selection that /// overlaps these if the mouse is being dragged, etc. This could also be empty if there is a /// pending selection. Returned as selections over Anchors. - pub fn disjoint_anchors(&self) -> Arc<[Selection]> { + pub fn disjoint_anchors_arc(&self) -> Arc<[Selection]> { self.disjoint.clone() } + /// The non-pending, non-overlapping selections. There could be a pending selection that + /// overlaps these if the mouse is being dragged, etc. This could also be empty if there is a + /// pending selection. Returned as selections over Anchors. + pub fn disjoint_anchors(&self) -> &[Selection] { + &self.disjoint + } + pub fn disjoint_anchor_ranges(&self) -> impl Iterator> { // Mapping the Arc slice would borrow it, whereas indexing captures it. - let disjoint = self.disjoint_anchors(); + let disjoint = self.disjoint_anchors_arc(); (0..disjoint.len()).map(move |ix| disjoint[ix].range()) } /// Non-overlapping selections using anchors, including the pending selection. pub fn all_anchors(&self, cx: &mut App) -> Arc<[Selection]> { if self.pending.is_none() { - self.disjoint_anchors() + self.disjoint_anchors_arc() } else { let all_offset_selections = self.all::(cx); let buffer = self.buffer(cx); @@ -108,10 +115,12 @@ impl SelectionsCollection { } } - pub fn pending_anchor(&self) -> Option> { - self.pending - .as_ref() - .map(|pending| pending.selection.clone()) + pub fn pending_anchor(&self) -> Option<&Selection> { + self.pending.as_ref().map(|pending| &pending.selection) + } + + pub fn pending_anchor_mut(&mut self) -> Option<&mut Selection> { + self.pending.as_mut().map(|pending| &mut pending.selection) } pub fn pending>( @@ -120,7 +129,7 @@ impl SelectionsCollection { ) -> Option> { let map = self.display_map(cx); - resolve_selections(self.pending_anchor().as_ref(), &map).next() + resolve_selections(self.pending_anchor(), &map).next() } pub(crate) fn pending_mode(&self) -> Option { @@ -234,8 +243,7 @@ impl SelectionsCollection { let map = self.display_map(cx); let disjoint_anchors = &self.disjoint; let mut disjoint = resolve_selections_display(disjoint_anchors.iter(), &map).peekable(); - let mut pending_opt = - resolve_selections_display(self.pending_anchor().as_ref(), &map).next(); + let mut pending_opt = resolve_selections_display(self.pending_anchor(), &map).next(); let selections = iter::from_fn(move || { if let Some(pending) = pending_opt.as_mut() { while let Some(next_selection) = disjoint.peek() { @@ -343,9 +351,9 @@ impl SelectionsCollection { #[cfg(any(test, feature = "test-support"))] pub fn display_ranges(&self, cx: &mut App) -> Vec> { let display_map = self.display_map(cx); - self.disjoint_anchors() + self.disjoint_anchors_arc() .iter() - .chain(self.pending_anchor().as_ref()) + .chain(self.pending_anchor()) .map(|s| { if s.reversed { s.end.to_display_point(&display_map)..s.start.to_display_point(&display_map) @@ -412,6 +420,10 @@ impl SelectionsCollection { ); (mutable_collection.selections_changed, result) } + + pub fn next_selection_id(&self) -> usize { + self.next_selection_id + } } pub struct MutableSelectionsCollection<'a> { diff --git a/crates/editor/src/test/editor_test_context.rs b/crates/editor/src/test/editor_test_context.rs index 8c54c265edf7a19af9d17e982a5f4cb6a0079cc3..fbf7a312fe56600ad78e13c278c85e29b8ca5aa5 100644 --- a/crates/editor/src/test/editor_test_context.rs +++ b/crates/editor/src/test/editor_test_context.rs @@ -396,7 +396,7 @@ impl EditorTestContext { let (multibuffer_snapshot, selections, excerpts) = self.update_editor(|editor, _, cx| { let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx); - let selections = editor.selections.disjoint_anchors(); + let selections = editor.selections.disjoint_anchors_arc(); let excerpts = multibuffer_snapshot .excerpts() .map(|(e_id, snapshot, range)| (e_id, snapshot.clone(), range)) diff --git a/crates/git_ui/src/text_diff_view.rs b/crates/git_ui/src/text_diff_view.rs index ebf32d1b994814fa277201176b555efed5e85e66..bd46a067dc8e6c3aeec4de878709024f66a819f2 100644 --- a/crates/git_ui/src/text_diff_view.rs +++ b/crates/git_ui/src/text_diff_view.rs @@ -416,7 +416,7 @@ impl Item for TextDiffView { pub fn selection_location_text(editor: &Editor, cx: &App) -> Option { let buffer = editor.buffer().read(cx); let buffer_snapshot = buffer.snapshot(cx); - let first_selection = editor.selections.disjoint.first()?; + let first_selection = editor.selections.disjoint_anchors().first()?; let selection_start = first_selection.start.to_point(&buffer_snapshot); let selection_end = first_selection.end.to_point(&buffer_snapshot); diff --git a/crates/vim/src/command.rs b/crates/vim/src/command.rs index 5fee0b95f11d94e8a448a8a11a43cc158786d190..53855c2c929ed44085b27bd22f80eba21e2e831d 100644 --- a/crates/vim/src/command.rs +++ b/crates/vim/src/command.rs @@ -463,7 +463,7 @@ pub fn register(editor: &mut Editor, cx: &mut Context) { .collect(); vim.switch_mode(Mode::Normal, true, window, cx); let initial_selections = - vim.update_editor(cx, |_, editor, _| editor.selections.disjoint_anchors()); + vim.update_editor(cx, |_, editor, _| editor.selections.disjoint_anchors_arc()); if let Some(range) = &action.range { let result = vim.update_editor(cx, |vim, editor, cx| { let range = range.buffer_range(vim, editor, window, cx)?; @@ -515,7 +515,7 @@ pub fn register(editor: &mut Editor, cx: &mut Context) { .buffer() .update(cx, |multi, cx| multi.last_transaction_id(cx)) { - let last_sel = editor.selections.disjoint_anchors(); + let last_sel = editor.selections.disjoint_anchors_arc(); editor.modify_transaction_selection_history(tx_id, |old| { old.0 = first_sel; old.1 = Some(last_sel); diff --git a/crates/vim/src/normal/mark.rs b/crates/vim/src/normal/mark.rs index 619769d41adc690014a2872eff9a18d6f0250ae6..acc4ef8d3c311892e864589fb998ffced7e47867 100644 --- a/crates/vim/src/normal/mark.rs +++ b/crates/vim/src/normal/mark.rs @@ -22,7 +22,7 @@ impl Vim { self.update_editor(cx, |vim, editor, cx| { let anchors = editor .selections - .disjoint_anchors() + .disjoint_anchors_arc() .iter() .map(|s| s.head()) .collect::>(); diff --git a/crates/vim/src/surrounds.rs b/crates/vim/src/surrounds.rs index 7c36ebe6747488376d2264e4984175fb536fed4f..8b3359c8f08046cf995db077a9a5ff0d36a97b95 100644 --- a/crates/vim/src/surrounds.rs +++ b/crates/vim/src/surrounds.rs @@ -326,7 +326,7 @@ impl Vim { let stable_anchors = editor .selections - .disjoint_anchors() + .disjoint_anchors_arc() .iter() .map(|selection| { let start = selection.start.bias_left(&display_map.buffer_snapshot); diff --git a/crates/vim/src/vim.rs b/crates/vim/src/vim.rs index 7faff54e73b179bdfa944798a9c87fafa245f732..5fb1f90a08e7a4346619c089cfe93c826bedf156 100644 --- a/crates/vim/src/vim.rs +++ b/crates/vim/src/vim.rs @@ -1075,16 +1075,16 @@ impl Vim { } let snapshot = s.display_map(); - if let Some(pending) = s.pending.as_mut() - && pending.selection.reversed + if let Some(pending) = s.pending_anchor_mut() + && pending.reversed && mode.is_visual() && !last_mode.is_visual() { - let mut end = pending.selection.end.to_point(&snapshot.buffer_snapshot); + let mut end = pending.end.to_point(&snapshot.buffer_snapshot); end = snapshot .buffer_snapshot .clip_point(end + Point::new(0, 1), Bias::Right); - pending.selection.end = snapshot.buffer_snapshot.anchor_before(end); + pending.end = snapshot.buffer_snapshot.anchor_before(end); } s.move_with(|map, selection| { @@ -1332,7 +1332,7 @@ impl Vim { self.update_editor(cx, |_, editor, _| { editor .selections - .disjoint_anchors() + .disjoint_anchors_arc() .iter() .map(|selection| selection.tail()..selection.head()) .collect() diff --git a/crates/vim/src/visual.rs b/crates/vim/src/visual.rs index 5fbc04fbee9570db95cc95a4ce023e8e82c3183c..35bc1eba2c900cd7c8f370629e0585584bc92d59 100644 --- a/crates/vim/src/visual.rs +++ b/crates/vim/src/visual.rs @@ -748,7 +748,7 @@ impl Vim { // after the change let stable_anchors = editor .selections - .disjoint_anchors() + .disjoint_anchors_arc() .iter() .map(|selection| { let start = selection.start.bias_left(&display_map.buffer_snapshot);