Merge pull request #1980 from zed-industries/following-panics

Max Brunsfeld created

Fix panics when following

Change summary

crates/editor/src/editor.rs |  6 ++++++
crates/editor/src/items.rs  | 27 ++++++++++++++++++++++-----
crates/rpc/proto/zed.proto  | 14 ++++++++------
crates/rpc/src/rpc.rs       |  2 +-
4 files changed, 37 insertions(+), 12 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -5453,11 +5453,17 @@ impl Editor {
     pub fn set_selections_from_remote(
         &mut self,
         selections: Vec<Selection<Anchor>>,
+        pending_selection: Option<Selection<Anchor>>,
         cx: &mut ViewContext<Self>,
     ) {
         let old_cursor_position = self.selections.newest_anchor().head();
         self.selections.change_with(cx, |s| {
             s.select_anchors(selections);
+            if let Some(pending_selection) = pending_selection {
+                s.set_pending(pending_selection, SelectMode::Character);
+            } else {
+                s.clear_pending();
+            }
         });
         self.selections_did_change(false, &old_cursor_position, cx);
     }

crates/editor/src/items.rs 🔗

@@ -130,13 +130,17 @@ impl FollowableItem for Editor {
                             .ok_or_else(|| anyhow!("invalid selection"))
                     })
                     .collect::<Result<Vec<_>>>()?;
+                let pending_selection = state
+                    .pending_selection
+                    .map(|selection| deserialize_selection(&buffer, selection))
+                    .flatten();
                 let scroll_top_anchor = state
                     .scroll_top_anchor
                     .and_then(|anchor| deserialize_anchor(&buffer, anchor));
                 drop(buffer);
 
-                if !selections.is_empty() {
-                    editor.set_selections_from_remote(selections, cx);
+                if !selections.is_empty() || pending_selection.is_some() {
+                    editor.set_selections_from_remote(selections, pending_selection, cx);
                 }
 
                 if let Some(scroll_top_anchor) = scroll_top_anchor {
@@ -216,6 +220,11 @@ impl FollowableItem for Editor {
                 .iter()
                 .map(serialize_selection)
                 .collect(),
+            pending_selection: self
+                .selections
+                .pending_anchor()
+                .as_ref()
+                .map(serialize_selection),
         }))
     }
 
@@ -269,9 +278,13 @@ impl FollowableItem for Editor {
                         .selections
                         .disjoint_anchors()
                         .iter()
-                        .chain(self.selections.pending_anchor().as_ref())
                         .map(serialize_selection)
                         .collect();
+                    update.pending_selection = self
+                        .selections
+                        .pending_anchor()
+                        .as_ref()
+                        .map(serialize_selection);
                     true
                 }
                 _ => false,
@@ -307,6 +320,10 @@ impl FollowableItem for Editor {
             .into_iter()
             .filter_map(|selection| deserialize_selection(&multibuffer, selection))
             .collect::<Vec<_>>();
+        let pending_selection = message
+            .pending_selection
+            .and_then(|selection| deserialize_selection(&multibuffer, selection));
+
         let scroll_top_anchor = message
             .scroll_top_anchor
             .and_then(|anchor| deserialize_anchor(&multibuffer, anchor));
@@ -361,8 +378,8 @@ impl FollowableItem for Editor {
                     multibuffer.remove_excerpts(removals, cx);
                 });
 
-                if !selections.is_empty() {
-                    this.set_selections_from_remote(selections, cx);
+                if !selections.is_empty() || pending_selection.is_some() {
+                    this.set_selections_from_remote(selections, pending_selection, cx);
                     this.request_autoscroll_remotely(Autoscroll::newest(), cx);
                 } else if let Some(anchor) = scroll_top_anchor {
                     this.set_scroll_anchor_remote(ScrollAnchor {

crates/rpc/proto/zed.proto 🔗

@@ -853,9 +853,10 @@ message UpdateView {
         repeated ExcerptInsertion inserted_excerpts = 1;
         repeated uint64 deleted_excerpts = 2;
         repeated Selection selections = 3;
-        EditorAnchor scroll_top_anchor = 4;
-        float scroll_x = 5;
-        float scroll_y = 6;
+        optional Selection pending_selection = 4;
+        EditorAnchor scroll_top_anchor = 5;
+        float scroll_x = 6;
+        float scroll_y = 7;
     }
 }
 
@@ -872,9 +873,10 @@ message View {
         optional string title = 2;
         repeated Excerpt excerpts = 3;
         repeated Selection selections = 4;
-        EditorAnchor scroll_top_anchor = 5;
-        float scroll_x = 6;
-        float scroll_y = 7;
+        optional Selection pending_selection = 5;
+        EditorAnchor scroll_top_anchor = 6;
+        float scroll_x = 7;
+        float scroll_y = 8;
     }
 }
 

crates/rpc/src/rpc.rs 🔗

@@ -6,4 +6,4 @@ pub use conn::Connection;
 pub use peer::*;
 mod macros;
 
-pub const PROTOCOL_VERSION: u32 = 43;
+pub const PROTOCOL_VERSION: u32 = 44;