Store inlays per paths and query on editor open

Kirill Bulatov created

Change summary

crates/editor/src/editor.rs      | 31 +++++++++++++++++--------------
crates/editor/src/inlay_cache.rs | 24 ++++++++++++++----------
crates/project/src/project.rs    |  6 +++---
3 files changed, 34 insertions(+), 27 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -84,6 +84,7 @@ use serde::{Deserialize, Serialize};
 use settings::SettingsStore;
 use smallvec::SmallVec;
 use snippet::Snippet;
+use std::path::PathBuf;
 use std::{
     any::TypeId,
     borrow::Cow,
@@ -1297,7 +1298,6 @@ impl Editor {
                 project_subscriptions.push(cx.subscribe(project, |editor, _, event, cx| {
                     if let project::Event::RefreshInlays = event {
                         editor.refresh_inlays(cx);
-                        cx.notify()
                     };
                 }));
             }
@@ -1352,6 +1352,7 @@ impl Editor {
             hover_state: Default::default(),
             link_go_to_definition_state: Default::default(),
             copilot_state: Default::default(),
+            // TODO kb has to live between editors
             inlay_cache: InlayCache::default(),
             gutter_hovered: false,
             _subscriptions: vec![
@@ -1377,6 +1378,7 @@ impl Editor {
         }
 
         this.report_editor_event("open", None, cx);
+        this.refresh_inlays(cx);
         this
     }
 
@@ -2594,7 +2596,7 @@ impl Editor {
         }
 
         struct InlayRequestKey {
-            buffer_id: u64,
+            buffer_path: PathBuf,
             buffer_version: Global,
             excerpt_id: ExcerptId,
         }
@@ -2603,22 +2605,21 @@ impl Editor {
         let multi_buffer_snapshot = multi_buffer.read(cx).snapshot(cx);
         let inlay_fetch_tasks = multi_buffer_snapshot
             .excerpts()
-            .map(|(excerpt_id, buffer_snapshot, excerpt_range)| {
-                // TODO kb every time I reopen the same buffer, it's different.
-                // Find a way to understand it's the same buffer. Use paths?
+            .filter_map(|(excerpt_id, buffer_snapshot, excerpt_range)| {
+                let buffer_path = buffer_snapshot.resolve_file_path(cx, true)?;
                 let buffer_id = buffer_snapshot.remote_id();
                 let buffer_version = buffer_snapshot.version().clone();
                 let buffer_handle = multi_buffer.read(cx).buffer(buffer_id);
                 let inlays_up_to_date =
                     self.inlay_cache
-                        .inlays_up_to_date(buffer_id, &buffer_version, excerpt_id);
+                        .inlays_up_to_date(&buffer_path, &buffer_version, excerpt_id);
                 let key = InlayRequestKey {
-                    buffer_id,
+                    buffer_path,
                     buffer_version,
                     excerpt_id,
                 };
 
-                cx.spawn(|editor, mut cx| async move {
+                let task = cx.spawn(|editor, mut cx| async move {
                     if inlays_up_to_date {
                         anyhow::Ok((key, None))
                     } else {
@@ -2631,7 +2632,7 @@ impl Editor {
                             .update(&mut cx, |editor, cx| {
                                 editor.project.as_ref().map(|project| {
                                     project.update(cx, |project, cx| {
-                                        project.inlay_hints_for_buffer(
+                                        project.query_inlay_hints_for_buffer(
                                             buffer_handle,
                                             query_start..query_end,
                                             cx,
@@ -2658,13 +2659,15 @@ impl Editor {
                             None => Some(Vec::new()),
                         }))
                     }
-                })
+                });
+
+                Some(task)
             })
             .collect::<Vec<_>>();
 
         cx.spawn(|editor, mut cx| async move {
             let mut inlay_updates: HashMap<
-                u64,
+                PathBuf,
                 (
                     Global,
                     HashMap<ExcerptId, Option<OrderedByAnchorOffset<InlayHint>>>,
@@ -2692,7 +2695,7 @@ impl Editor {
                                 )
                             }),
                         )]);
-                        match inlay_updates.entry(request_key.buffer_id) {
+                        match inlay_updates.entry(request_key.buffer_path) {
                             hash_map::Entry::Occupied(mut o) => {
                                 o.get_mut().1.extend(inlays_per_excerpt);
                             }
@@ -7243,7 +7246,7 @@ impl Editor {
         event: &multi_buffer::Event,
         cx: &mut ViewContext<Self>,
     ) {
-        let update_inlay_hints = match event {
+        let refresh_inlay_hints = match event {
             multi_buffer::Event::Edited => {
                 self.refresh_active_diagnostics(cx);
                 self.refresh_code_actions(cx);
@@ -7304,7 +7307,7 @@ impl Editor {
             _ => false,
         };
 
-        if update_inlay_hints {
+        if refresh_inlay_hints {
             self.refresh_inlays(cx);
         }
     }

crates/editor/src/inlay_cache.rs 🔗

@@ -1,4 +1,7 @@
-use std::cmp;
+use std::{
+    cmp,
+    path::{Path, PathBuf},
+};
 
 use crate::{Anchor, ExcerptId};
 use clock::{Global, Local};
@@ -9,7 +12,7 @@ use collections::{BTreeMap, HashMap};
 
 #[derive(Clone, Debug, Default)]
 pub struct InlayCache {
-    inlays_per_buffer: HashMap<u64, BufferInlays>,
+    inlays_per_buffer: HashMap<PathBuf, BufferInlays>,
     next_inlay_id: usize,
 }
 
@@ -60,11 +63,11 @@ pub struct InlaysUpdate {
 impl InlayCache {
     pub fn inlays_up_to_date(
         &self,
-        buffer_id: u64,
+        buffer_path: &Path,
         buffer_version: &Global,
         excerpt_id: ExcerptId,
     ) -> bool {
-        let Some(buffer_inlays) = self.inlays_per_buffer.get(&buffer_id) else { return false };
+        let Some(buffer_inlays) = self.inlays_per_buffer.get(buffer_path) else { return false };
         let buffer_up_to_date = buffer_version == &buffer_inlays.buffer_version
             || buffer_inlays.buffer_version.changed_since(buffer_version);
         buffer_up_to_date && buffer_inlays.inlays_per_excerpts.contains_key(&excerpt_id)
@@ -73,7 +76,7 @@ impl InlayCache {
     pub fn update_inlays(
         &mut self,
         inlay_updates: HashMap<
-            u64,
+            PathBuf,
             (
                 Global,
                 HashMap<ExcerptId, Option<OrderedByAnchorOffset<InlayHint>>>,
@@ -84,17 +87,17 @@ impl InlayCache {
         let mut to_remove = Vec::new();
         let mut to_insert = Vec::new();
 
-        for (buffer_id, (buffer_version, new_buffer_inlays)) in inlay_updates {
-            match old_inlays.remove(&buffer_id) {
+        for (buffer_path, (buffer_version, new_buffer_inlays)) in inlay_updates {
+            match old_inlays.remove(&buffer_path) {
                 Some(mut old_buffer_inlays) => {
                     for (excerpt_id, new_excerpt_inlays) in new_buffer_inlays {
-                        if self.inlays_up_to_date(buffer_id, &buffer_version, excerpt_id) {
+                        if self.inlays_up_to_date(&buffer_path, &buffer_version, excerpt_id) {
                             continue;
                         }
 
                         let self_inlays_per_buffer = self
                             .inlays_per_buffer
-                            .get_mut(&buffer_id)
+                            .get_mut(&buffer_path)
                             .expect("element expected: `old_inlays.remove` returned `Some`");
                         let mut new_excerpt_inlays = match new_excerpt_inlays {
                             Some(new_inlays) => {
@@ -112,6 +115,7 @@ impl InlayCache {
                                 .get_mut(&excerpt_id)
                                 .expect("element expected: `old_excerpt_inlays` is `Some`");
                             let mut hints_to_add = Vec::<(Anchor, (InlayId, InlayHint))>::new();
+                            // TODO kb update inner buffer_id and version with the new data?
                             self_excerpt_inlays.0.retain(
                                 |_, (old_anchor, (old_inlay_id, old_inlay))| {
                                     let mut retain = false;
@@ -202,7 +206,7 @@ impl InlayCache {
                         }
                     }
                     self.inlays_per_buffer.insert(
-                        buffer_id,
+                        buffer_path,
                         BufferInlays {
                             buffer_version,
                             inlays_per_excerpts,

crates/project/src/project.rs 🔗

@@ -4928,7 +4928,7 @@ impl Project {
         )
     }
 
-    pub fn inlay_hints_for_buffer<T: ToOffset>(
+    pub fn query_inlay_hints_for_buffer<T: ToOffset>(
         &self,
         buffer_handle: ModelHandle<Buffer>,
         range: Range<T>,
@@ -4951,7 +4951,6 @@ impl Project {
                     })
                     .await
                     .context("waiting for inlay hint request range edits")?;
-
                 match lsp_request_task.await {
                     Ok(hints) => Ok(Some(hints)),
                     Err(e) if is_content_modified_error(&e) => Ok(None),
@@ -6767,7 +6766,8 @@ impl Project {
         let buffer_hints = this
             .update(&mut cx, |project, cx| {
                 let buffer_end = buffer.read(cx).len();
-                project.inlay_hints_for_buffer(
+                // TODO kb use cache before querying?
+                project.query_inlay_hints_for_buffer(
                     buffer,
                     envelope
                         .payload