Properly react on excerpts drop

Kirill Bulatov created

Change summary

crates/editor/src/editor.rs           | 21 ++++++++++++++++-----
crates/editor/src/inlay_hint_cache.rs | 22 ++++++++++++++++++++--
2 files changed, 36 insertions(+), 7 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -1251,15 +1251,17 @@ enum InlayHintRefreshReason {
     NewLinesShown,
     BufferEdited(HashSet<Arc<Language>>),
     RefreshRequested,
+    ExcerptsRemoved(Vec<ExcerptId>),
 }
 impl InlayHintRefreshReason {
     fn description(&self) -> &'static str {
         match self {
-            InlayHintRefreshReason::Toggle(_) => "toggle",
-            InlayHintRefreshReason::SettingsChange(_) => "settings change",
-            InlayHintRefreshReason::NewLinesShown => "new lines shown",
-            InlayHintRefreshReason::BufferEdited(_) => "buffer edited",
-            InlayHintRefreshReason::RefreshRequested => "refresh requested",
+            Self::Toggle(_) => "toggle",
+            Self::SettingsChange(_) => "settings change",
+            Self::NewLinesShown => "new lines shown",
+            Self::BufferEdited(_) => "buffer edited",
+            Self::RefreshRequested => "refresh requested",
+            Self::ExcerptsRemoved(_) => "excerpts removed",
         }
     }
 }
@@ -2789,6 +2791,14 @@ impl Editor {
                     ControlFlow::Continue(()) => (InvalidationStrategy::RefreshRequested, None),
                 }
             }
+            InlayHintRefreshReason::ExcerptsRemoved(excerpts_removed) => {
+                let InlaySplice {
+                    to_remove,
+                    to_insert,
+                } = self.inlay_hint_cache.remove_excerpts(excerpts_removed);
+                self.splice_inlay_hints(to_remove, to_insert, cx);
+                return;
+            }
             InlayHintRefreshReason::NewLinesShown => (InvalidationStrategy::None, None),
             InlayHintRefreshReason::BufferEdited(buffer_languages) => {
                 (InvalidationStrategy::BufferEdited, Some(buffer_languages))
@@ -7948,6 +7958,7 @@ impl Editor {
                 self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
             }
             multi_buffer::Event::ExcerptsRemoved { ids } => {
+                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
                 cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
             }
             multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),

crates/editor/src/inlay_hint_cache.rs 🔗

@@ -474,6 +474,24 @@ impl InlayHintCache {
         }
     }
 
+    pub fn remove_excerpts(&mut self, excerpts_removed: Vec<ExcerptId>) -> InlaySplice {
+        let mut to_remove = Vec::new();
+        for excerpt_to_remove in excerpts_removed {
+            self.update_tasks.remove(&excerpt_to_remove);
+            if let Some(cached_hints) = self.hints.remove(&excerpt_to_remove) {
+                let cached_hints = cached_hints.read();
+                to_remove.extend(cached_hints.hints.iter().map(|(id, _)| *id));
+            }
+        }
+        if !to_remove.is_empty() {
+            self.version += 1;
+        }
+        InlaySplice {
+            to_remove,
+            to_insert: Vec::new(),
+        }
+    }
+
     pub fn clear(&mut self) {
         self.version += 1;
         self.update_tasks.clear();
@@ -2956,7 +2974,7 @@ all hints should be invalidated and requeried for all of its visible excerpts"
             );
             assert_eq!(
                 editor.inlay_hint_cache().version,
-                2,
+                3,
                 "Excerpt removal should trigger a cache update"
             );
         });
@@ -2984,7 +3002,7 @@ all hints should be invalidated and requeried for all of its visible excerpts"
             );
             assert_eq!(
                 editor.inlay_hint_cache().version,
-                3,
+                4,
                 "Settings change should trigger a cache update"
             );
         });