Improve on inlya locations

Kirill Bulatov created

Change summary

crates/editor/src/display_map.rs           |  15 +--
crates/editor/src/display_map/inlay_map.rs |  26 +++--
crates/editor/src/editor.rs                | 101 ++++++++++++-----------
3 files changed, 75 insertions(+), 67 deletions(-)

Detailed changes

crates/editor/src/display_map.rs 🔗

@@ -5,7 +5,9 @@ mod suggestion_map;
 mod tab_map;
 mod wrap_map;
 
-use crate::{Anchor, AnchorRangeExt, MultiBuffer, MultiBufferSnapshot, ToOffset, ToPoint};
+use crate::{
+    Anchor, AnchorRangeExt, InlayHintLocation, MultiBuffer, MultiBufferSnapshot, ToOffset, ToPoint,
+};
 pub use block_map::{BlockMap, BlockPoint};
 use collections::{HashMap, HashSet};
 use fold_map::{FoldMap, FoldOffset};
@@ -284,19 +286,12 @@ impl DisplayMap {
 
     pub fn set_inlay_hints(
         &mut self,
-        new_hints: &[project::InlayHint],
+        new_hints: &HashMap<InlayHintLocation, Vec<project::InlayHint>>,
         cx: &mut ModelContext<Self>,
     ) {
+        // TODO kb map this to Anchor and set to the map
         let multi_buffer = self.buffer.read(cx);
 
-        // TODO kb carry both remote and local ids of the buffer?
-        // now, `.buffer` requires remote id, hence this map.
-        let buffers_to_local_id = multi_buffer
-            .all_buffers()
-            .into_iter()
-            .map(|buffer_handle| (buffer_handle.id(), buffer_handle))
-            .collect::<HashMap<_, _>>();
-
         // multi_buffer.anchor_in_excerpt(excerpt_id, hint.position);
         // TODO kb !!! rework things from buffer_id to excerpt_id
         // let hint_anchor = multi_buffer

crates/editor/src/display_map/inlay_map.rs 🔗

@@ -7,7 +7,7 @@ use std::{
     sync::atomic::{self, AtomicUsize},
 };
 
-use crate::{Anchor, MultiBufferSnapshot, ToOffset, ToPoint};
+use crate::{Anchor, ExcerptId, InlayHintLocation, MultiBufferSnapshot, ToOffset, ToPoint};
 
 use super::{
     suggestion_map::{
@@ -31,7 +31,7 @@ pub struct InlayId(usize);
 pub struct InlayMap {
     snapshot: Mutex<InlaySnapshot>,
     next_inlay_id: usize,
-    inlays: HashMap<InlayId, Inlay>,
+    inlays: HashMap<InlayId, (InlayHintLocation, Inlay)>,
 }
 
 #[derive(Clone)]
@@ -224,18 +224,18 @@ impl InlayMap {
     pub fn splice(
         &mut self,
         to_remove: HashSet<InlayId>,
-        to_insert: Vec<InlayProperties>,
+        to_insert: Vec<(InlayHintLocation, InlayProperties)>,
     ) -> (InlaySnapshot, Vec<InlayEdit>, Vec<InlayId>) {
         let mut snapshot = self.snapshot.lock();
 
         let mut inlays = BTreeMap::new();
         let mut new_ids = Vec::new();
-        for properties in to_insert {
+        for (location, properties) in to_insert {
             let inlay = Inlay {
                 id: InlayId(post_inc(&mut self.next_inlay_id)),
                 properties,
             };
-            self.inlays.insert(inlay.id, inlay.clone());
+            self.inlays.insert(inlay.id, (location, inlay.clone()));
             new_ids.push(inlay.id);
 
             let buffer_point = inlay
@@ -253,7 +253,7 @@ impl InlayMap {
         }
 
         for inlay_id in to_remove {
-            if let Some(inlay) = self.inlays.remove(&inlay_id) {
+            if let Some((_, inlay)) = self.inlays.remove(&inlay_id) {
                 let buffer_point = inlay
                     .properties
                     .position
@@ -448,10 +448,16 @@ mod tests {
 
         let (inlay_snapshot, _, inlay_ids) = inlay_map.splice(
             HashSet::default(),
-            vec![InlayProperties {
-                position: buffer.read(cx).read(cx).anchor_before(3),
-                text: "|123|".into(),
-            }],
+            vec![(
+                InlayHintLocation {
+                    buffer_id: 0,
+                    excerpt_id: ExcerptId::default(),
+                },
+                InlayProperties {
+                    position: buffer.read(cx).read(cx).anchor_before(3),
+                    text: "|123|".into(),
+                },
+            )],
         );
         assert_eq!(inlay_snapshot.text(), "abc|123|defghi");
 

crates/editor/src/editor.rs 🔗

@@ -1153,24 +1153,30 @@ impl CopilotState {
     }
 }
 
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct InlayHintLocation {
+    pub buffer_id: u64,
+    pub excerpt_id: ExcerptId,
+}
+
 // TODO kb
 #[derive(Debug, Default, Clone)]
 struct InlayHintVersions {
-    last_buffer_versions_with_hints: HashMap<usize, Global>,
+    last_buffer_versions_with_hints: HashMap<InlayHintLocation, Global>,
 }
 
 impl InlayHintVersions {
-    fn absent_or_newer(&self, buffer_id: usize, new_version: &Global) -> bool {
+    fn absent_or_newer(&self, location: &InlayHintLocation, new_version: &Global) -> bool {
         self.last_buffer_versions_with_hints
-            .get(&buffer_id)
+            .get(location)
             .map(|last_version_with_hints| new_version.changed_since(&last_version_with_hints))
             .unwrap_or(true)
     }
 
-    fn insert(&mut self, buffer_id: usize, new_version: Global) -> bool {
-        if self.absent_or_newer(buffer_id, &new_version) {
+    fn insert(&mut self, location: InlayHintLocation, new_version: Global) -> bool {
+        if self.absent_or_newer(&location, &new_version) {
             self.last_buffer_versions_with_hints
-                .insert(buffer_id, new_version);
+                .insert(location, new_version);
             true
         } else {
             false
@@ -2617,50 +2623,40 @@ impl Editor {
             return;
         }
 
-        let hint_fetch_tasks = self
-            .buffer()
-            .read(cx)
-            .all_buffers()
-            .into_iter()
-            .map(|buffer_handle| {
-                let buffer_id = buffer_handle.id();
+        let multi_buffer = self.buffer().read(cx);
+        let buffer_snapshot = multi_buffer.snapshot(cx);
+        let hint_fetch_tasks = buffer_snapshot
+            .excerpts()
+            .map(|(excerpt_id, excerpt_buffer_snapshot, _)| {
+                (excerpt_id, excerpt_buffer_snapshot.clone())
+            })
+            .map(|(excerpt_id, excerpt_buffer_snapshot)| {
                 cx.spawn(|editor, mut cx| async move {
-                    let task_data = editor
+                    let task = editor
                         .update(&mut cx, |editor, cx| {
                             editor.project.as_ref().and_then(|project| {
                                 project.update(cx, |project, cx| {
-                                    let buffer = buffer_handle.read(cx);
-                                    let end = buffer.len();
-                                    let version = buffer.version();
-
-                                    if editor
-                                        .inlay_hint_versions
-                                        .absent_or_newer(buffer_id, &version)
-                                    {
-                                        Some((
-                                            version,
-                                            project.inlay_hints_for_buffer(
-                                                buffer_handle,
-                                                0..end,
-                                                cx,
-                                            ),
-                                        ))
-                                    } else {
-                                        None
-                                    }
+                                    Some(
+                                        project.inlay_hints_for_buffer(
+                                            editor
+                                                .buffer()
+                                                .read(cx)
+                                                .buffer(excerpt_buffer_snapshot.remote_id())?,
+                                            0..excerpt_buffer_snapshot.len(),
+                                            cx,
+                                        ),
+                                    )
                                 })
                             })
                         })
                         .context("inlay hints fecth task spawn")?;
 
                     anyhow::Ok((
-                        buffer_id,
-                        match task_data {
-                            Some((buffer_version, task)) => Some((
-                                buffer_version,
-                                task.await.context("inlay hints for buffer task")?,
-                            )),
-                            None => None,
+                        excerpt_id,
+                        excerpt_buffer_snapshot,
+                        match task {
+                            Some(task) => task.await.context("inlay hints for buffer task")?,
+                            None => Vec::new(),
                         },
                     ))
                 })
@@ -2668,21 +2664,32 @@ impl Editor {
             .collect::<Vec<_>>();
 
         cx.spawn(|editor, mut cx| async move {
-            let mut new_hints = Vec::new();
+            let mut new_hints: HashMap<InlayHintLocation, Vec<project::InlayHint>> =
+                HashMap::default();
             for task_result in futures::future::join_all(hint_fetch_tasks).await {
                 match task_result {
-                    Ok((_buffer_id, None)) => {}
-                    Ok((buffer_id, Some((buffer_with_hints_version, buffer_hints)))) => {
+                    Ok((excerpt_id, excerpt_buffer_snapshot, excerpt_hints)) => {
+                        let buffer_id = excerpt_buffer_snapshot.remote_id();
                         let should_update_hints = editor
                             .update(&mut cx, |editor, _| {
-                                editor
-                                    .inlay_hint_versions
-                                    .insert(buffer_id, buffer_with_hints_version)
+                                editor.inlay_hint_versions.insert(
+                                    InlayHintLocation {
+                                        buffer_id,
+                                        excerpt_id,
+                                    },
+                                    excerpt_buffer_snapshot.version().clone(),
+                                )
                             })
                             .log_err()
                             .unwrap_or(false);
                         if should_update_hints {
-                            new_hints.extend(buffer_hints);
+                            new_hints
+                                .entry(InlayHintLocation {
+                                    buffer_id,
+                                    excerpt_id,
+                                })
+                                .or_default()
+                                .extend(excerpt_hints);
                         }
                     }
                     Err(e) => error!("Failed to update hints for buffer: {e:#}"),