React on multibuffer scrolls again

Kirill Bulatov created

Change summary

crates/editor/src/editor.rs           | 32 +++++++++++++++++++++++
crates/editor/src/inlay_hint_cache.rs | 39 ++++++++++++++--------------
crates/editor/src/scroll.rs           | 11 +++++--
3 files changed, 59 insertions(+), 23 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -1196,6 +1196,7 @@ enum GotoDefinitionKind {
 #[derive(Debug, Copy, Clone)]
 enum InlayRefreshReason {
     SettingsChange(editor_settings::InlayHints),
+    Scroll(ScrollAnchor),
     VisibleExcerptsChange,
 }
 
@@ -2624,6 +2625,34 @@ impl Editor {
             InlayRefreshReason::SettingsChange(new_settings) => self
                 .inlay_hint_cache
                 .spawn_settings_update(multi_buffer_handle, new_settings, current_inlays),
+            InlayRefreshReason::Scroll(scrolled_to) => {
+                if let Some(new_query) = self
+                    .excerpt_visible_offsets(&multi_buffer_handle, cx)
+                    .into_iter()
+                    .find_map(|(buffer, _, excerpt_id)| {
+                        let buffer_id = scrolled_to.anchor.buffer_id?;
+                        if buffer_id == buffer.read(cx).remote_id()
+                            && scrolled_to.anchor.excerpt_id == excerpt_id
+                        {
+                            Some(InlayHintQuery {
+                                buffer_id,
+                                buffer_version: buffer.read(cx).version(),
+                                excerpt_id,
+                            })
+                        } else {
+                            None
+                        }
+                    })
+                {
+                    self.inlay_hint_cache.spawn_hints_update(
+                        multi_buffer_handle,
+                        vec![new_query],
+                        current_inlays,
+                        false,
+                        cx,
+                    )
+                }
+            }
             InlayRefreshReason::VisibleExcerptsChange => {
                 let replacement_queries = self
                     .excerpt_visible_offsets(&multi_buffer_handle, cx)
@@ -2632,7 +2661,7 @@ impl Editor {
                         let buffer = buffer.read(cx);
                         InlayHintQuery {
                             buffer_id: buffer.remote_id(),
-                            buffer_version: buffer.version.clone(),
+                            buffer_version: buffer.version(),
                             excerpt_id,
                         }
                     })
@@ -2641,6 +2670,7 @@ impl Editor {
                     multi_buffer_handle,
                     replacement_queries,
                     current_inlays,
+                    true,
                     cx,
                 )
             }

crates/editor/src/inlay_hint_cache.rs 🔗

@@ -102,27 +102,29 @@ impl InlayHintCache {
         multi_buffer: ModelHandle<MultiBuffer>,
         queries: Vec<InlayHintQuery>,
         current_inlays: Vec<Inlay>,
+        conflicts_invalidate_cache: bool,
         cx: &mut ViewContext<Editor>,
     ) {
-        let conflicts_with_cache = queries.iter().any(|update_query| {
-            let Some(cached_buffer_hints) = self.hints_in_buffers.get(&update_query.buffer_id)
+        let conflicts_with_cache = conflicts_invalidate_cache
+            && queries.iter().any(|update_query| {
+                let Some(cached_buffer_hints) = self.hints_in_buffers.get(&update_query.buffer_id)
                 else { return false };
-            if cached_buffer_hints
-                .buffer_version
-                .changed_since(&update_query.buffer_version)
-            {
-                false
-            } else if update_query
-                .buffer_version
-                .changed_since(&cached_buffer_hints.buffer_version)
-            {
-                true
-            } else {
-                cached_buffer_hints
-                    .hints_per_excerpt
-                    .contains_key(&update_query.excerpt_id)
-            }
-        });
+                if cached_buffer_hints
+                    .buffer_version
+                    .changed_since(&update_query.buffer_version)
+                {
+                    false
+                } else if update_query
+                    .buffer_version
+                    .changed_since(&cached_buffer_hints.buffer_version)
+                {
+                    true
+                } else {
+                    cached_buffer_hints
+                        .hints_per_excerpt
+                        .contains_key(&update_query.excerpt_id)
+                }
+            });
 
         let queries_per_buffer = queries
             .into_iter()
@@ -569,7 +571,6 @@ fn allowed_hint_types(
 }
 
 // TODO kb wrong, query and update the editor separately
-// TODO kb need to react on react on scrolling too, for multibuffer excerpts
 fn fetch_queries(
     multi_buffer: ModelHandle<MultiBuffer>,
     queries: impl Iterator<Item = InlayHintQuery>,

crates/editor/src/scroll.rs 🔗

@@ -13,7 +13,7 @@ use gpui::{
 };
 use language::{Bias, Point};
 use util::ResultExt;
-use workspace::WorkspaceId;
+use workspace::{item::Item, WorkspaceId};
 
 use crate::{
     display_map::{DisplaySnapshot, ToDisplayPoint},
@@ -176,7 +176,7 @@ impl ScrollManager {
         autoscroll: bool,
         workspace_id: Option<i64>,
         cx: &mut ViewContext<Editor>,
-    ) {
+    ) -> ScrollAnchor {
         let (new_anchor, top_row) = if scroll_position.y() <= 0. {
             (
                 ScrollAnchor {
@@ -205,6 +205,7 @@ impl ScrollManager {
         };
 
         self.set_anchor(new_anchor, top_row, local, autoscroll, workspace_id, cx);
+        new_anchor
     }
 
     fn set_anchor(
@@ -312,7 +313,7 @@ impl Editor {
 
         hide_hover(self, cx);
         let workspace_id = self.workspace.as_ref().map(|workspace| workspace.1);
-        self.scroll_manager.set_scroll_position(
+        let scroll_anchor = self.scroll_manager.set_scroll_position(
             scroll_position,
             &map,
             local,
@@ -320,6 +321,10 @@ impl Editor {
             workspace_id,
             cx,
         );
+
+        if !self.is_singleton(cx) {
+            self.refresh_inlays(crate::InlayRefreshReason::Scroll(scroll_anchor), cx);
+        }
     }
 
     pub fn scroll_position(&self, cx: &mut ViewContext<Self>) -> Vector2F {