Finish modelling

Kirill Bulatov created

Change summary

crates/editor/src/editor.rs           |   2 
crates/editor/src/inlay_hint_cache.rs | 659 ++++++++++++++--------------
2 files changed, 333 insertions(+), 328 deletions(-)

Detailed changes

crates/editor/src/editor.rs 🔗

@@ -2647,6 +2647,7 @@ impl Editor {
                         vec![new_query],
                         current_inlays,
                         false,
+                        cx,
                     )
                 }
             }
@@ -2668,6 +2669,7 @@ impl Editor {
                     replacement_queries,
                     current_inlays,
                     true,
+                    cx,
                 )
             }
         };

crates/editor/src/inlay_hint_cache.rs 🔗

@@ -1,17 +1,17 @@
 use std::cmp;
 
 use crate::{
-    display_map::Inlay, editor_settings, Anchor, Editor, ExcerptId, InlayId, MultiBuffer,
-    MultiBufferSnapshot,
+    display_map::Inlay, editor_settings, Anchor, Editor, ExcerptId, InlayId, MultiBufferSnapshot,
 };
 use anyhow::Context;
 use clock::Global;
 use futures::{stream::FuturesUnordered, FutureExt, StreamExt};
-use gpui::{ModelHandle, Task, ViewContext};
+use gpui::{Task, ViewContext};
 use log::error;
 use project::{InlayHint, InlayHintKind};
 
-use collections::{hash_map, HashMap, HashSet};
+use collections::{HashMap, HashSet};
+use util::post_inc;
 
 #[derive(Debug)]
 pub struct InlayHintCache {
@@ -57,73 +57,136 @@ impl InlayHintCache {
     ) -> Self {
         let (hint_updates_tx, hint_updates_rx) = smol::channel::unbounded();
         let (update_results_tx, update_results_rx) = smol::channel::unbounded();
+
         spawn_hints_update_loop(hint_updates_rx, update_results_tx, cx);
         cx.spawn(|editor, mut cx| async move {
             while let Ok(update_result) = update_results_rx.recv().await {
                 let editor_absent = editor
                     .update(&mut cx, |editor, cx| {
                         let multi_buffer_snapshot = editor.buffer().read(cx).snapshot(cx);
-                        let inlay_hint_cache = &mut editor.inlay_hint_cache;
-                        if let Some(new_allowed_hint_kinds) = update_result.new_allowed_hint_kinds {
-                            inlay_hint_cache.allowed_hint_kinds = new_allowed_hint_kinds;
-                        }
-
-                        inlay_hint_cache.hints_in_buffers.retain(|_, buffer_hints| {
-                            buffer_hints.hints_per_excerpt.retain(|_, excerpt_hints| {
-                                excerpt_hints.retain(|(_, hint_id)| {
-                                    !update_result.remove_from_cache.contains(hint_id)
-                                });
-                                !excerpt_hints.is_empty()
-                            });
-                            !buffer_hints.hints_per_excerpt.is_empty()
-                        });
-                        inlay_hint_cache.inlay_hints.retain(|hint_id, _| {
-                            !update_result.remove_from_cache.contains(hint_id)
-                        });
-
-                        for (new_buffer_id, new_buffer_inlays) in update_result.add_to_cache {
-                            let cached_buffer_hints = inlay_hint_cache
-                                .hints_in_buffers
-                                .entry(new_buffer_id)
-                                .or_insert_with(|| {
-                                    BufferHints::new(new_buffer_inlays.buffer_version.clone())
-                                });
-                            if cached_buffer_hints
-                                .buffer_version
-                                .changed_since(&new_buffer_inlays.buffer_version)
-                            {
-                                continue;
-                            }
-                            for (excerpt_id, new_excerpt_inlays) in
-                                new_buffer_inlays.hints_per_excerpt
-                            {
-                                let cached_excerpt_hints = cached_buffer_hints
-                                    .hints_per_excerpt
-                                    .entry(excerpt_id)
-                                    .or_default();
-                                for (new_hint_position, new_hint, new_inlay_id) in
-                                    new_excerpt_inlays
-                                {
-                                    if let hash_map::Entry::Vacant(v) =
-                                        inlay_hint_cache.inlay_hints.entry(new_inlay_id)
+                        if let Some((splice, remove_from_cache)) = match update_result {
+                            UpdateResult::HintQuery {
+                                query,
+                                add_to_cache,
+                                remove_from_cache,
+                                remove_from_visible,
+                            } => editor.buffer().read(cx).buffer(query.buffer_id).and_then(
+                                |buffer| {
+                                    if !buffer.read(cx).version.changed_since(&query.buffer_version)
                                     {
-                                        v.insert(new_hint);
-                                        match cached_excerpt_hints.binary_search_by(|probe| {
-                                            new_hint_position.cmp(&probe.0, &multi_buffer_snapshot)
-                                        }) {
-                                            Ok(ix) | Err(ix) => cached_excerpt_hints
-                                                .insert(ix, (new_hint_position, new_inlay_id)),
+                                        let mut new_hints_splice = InlaySplice {
+                                            to_remove: remove_from_visible,
+                                            to_insert: Vec::new(),
+                                        };
+                                        for (new_buffer_id, new_buffer_inlays) in add_to_cache {
+                                            let cached_buffer_hints = editor
+                                                .inlay_hint_cache
+                                                .hints_in_buffers
+                                                .entry(new_buffer_id)
+                                                .or_insert_with(|| {
+                                                    BufferHints::new(
+                                                        new_buffer_inlays.buffer_version.clone(),
+                                                    )
+                                                });
+                                            if cached_buffer_hints
+                                                .buffer_version
+                                                .changed_since(&new_buffer_inlays.buffer_version)
+                                            {
+                                                continue;
+                                            }
+                                            for (excerpt_id, new_excerpt_inlays) in
+                                                new_buffer_inlays.hints_per_excerpt
+                                            {
+                                                let cached_excerpt_hints = cached_buffer_hints
+                                                    .hints_per_excerpt
+                                                    .entry(excerpt_id)
+                                                    .or_default();
+                                                for (shown_id, new_hint_position, new_hint) in
+                                                    new_excerpt_inlays
+                                                {
+                                                    let new_inlay_id = match shown_id {
+                                                        Some(id) => id,
+                                                        None => {
+                                                            let new_inlay_id = InlayId(post_inc(
+                                                                &mut editor.next_inlay_id,
+                                                            ));
+                                                            if editor
+                                                                .inlay_hint_cache
+                                                                .allowed_hint_kinds
+                                                                .contains(&new_hint.kind)
+                                                            {
+                                                                new_hints_splice.to_insert.push((
+                                                                    new_inlay_id,
+                                                                    new_hint_position,
+                                                                    new_hint.clone(),
+                                                                ));
+                                                            }
+                                                            new_inlay_id
+                                                        }
+                                                    };
+
+                                                    editor
+                                                        .inlay_hint_cache
+                                                        .inlay_hints
+                                                        .insert(new_inlay_id, new_hint);
+                                                    match cached_excerpt_hints.binary_search_by(
+                                                        |probe| {
+                                                            new_hint_position.cmp(
+                                                                &probe.0,
+                                                                &multi_buffer_snapshot,
+                                                            )
+                                                        },
+                                                    ) {
+                                                        Ok(ix) | Err(ix) => cached_excerpt_hints
+                                                            .insert(
+                                                                ix,
+                                                                (new_hint_position, new_inlay_id),
+                                                            ),
+                                                    }
+                                                }
+                                            }
                                         }
+                                        Some((new_hints_splice, remove_from_cache))
+                                    } else {
+                                        None
                                     }
+                                },
+                            ),
+                            UpdateResult::Other {
+                                new_allowed_hint_kinds,
+                                splice,
+                                remove_from_cache,
+                            } => {
+                                if let Some(new_allowed_hint_kinds) = new_allowed_hint_kinds {
+                                    editor.inlay_hint_cache.allowed_hint_kinds =
+                                        new_allowed_hint_kinds;
                                 }
+                                Some((splice, remove_from_cache))
                             }
+                        } {
+                            editor
+                                .inlay_hint_cache
+                                .hints_in_buffers
+                                .retain(|_, buffer_hints| {
+                                    buffer_hints.hints_per_excerpt.retain(|_, excerpt_hints| {
+                                        excerpt_hints.retain(|(_, hint_id)| {
+                                            !remove_from_cache.contains(hint_id)
+                                        });
+                                        !excerpt_hints.is_empty()
+                                    });
+                                    !buffer_hints.hints_per_excerpt.is_empty()
+                                });
+                            editor
+                                .inlay_hint_cache
+                                .inlay_hints
+                                .retain(|hint_id, _| !remove_from_cache.contains(hint_id));
+
+                            let InlaySplice {
+                                to_remove,
+                                to_insert,
+                            } = splice;
+                            editor.splice_inlay_hints(to_remove, to_insert, cx)
                         }
-
-                        let InlaySplice {
-                            to_remove,
-                            to_insert,
-                        } = update_result.splice;
-                        editor.splice_inlay_hints(to_remove, to_insert, cx)
                     })
                     .is_err();
                 if editor_absent {
@@ -186,6 +249,7 @@ impl InlayHintCache {
         queries: Vec<InlayHintQuery>,
         current_inlays: Vec<Inlay>,
         conflicts_invalidate_cache: bool,
+        cx: &mut ViewContext<Editor>,
     ) {
         let conflicts_with_cache = conflicts_invalidate_cache
             && queries.iter().any(|update_query| {
@@ -230,23 +294,36 @@ impl InlayHintCache {
                 }
             })
             .fold(
-                HashMap::<u64, (Global, Vec<ExcerptId>)>::default(),
+                HashMap::<
+                    u64,
+                    (
+                        Global,
+                        HashMap<
+                            ExcerptId,
+                            Task<anyhow::Result<(InlayHintQuery, Option<Vec<InlayHint>>)>>,
+                        >,
+                    ),
+                >::default(),
                 |mut queries_per_buffer, new_query| {
-                    let (current_verison, excerpts_to_query) =
+                    let (current_verison, excerpt_queries) =
                         queries_per_buffer.entry(new_query.buffer_id).or_default();
 
                     if new_query.buffer_version.changed_since(current_verison) {
-                        *current_verison = new_query.buffer_version;
-                        *excerpts_to_query = vec![new_query.excerpt_id];
+                        *current_verison = new_query.buffer_version.clone();
+                        *excerpt_queries = HashMap::from_iter([(
+                            new_query.excerpt_id,
+                            hints_fetch_task(new_query, cx),
+                        )]);
                     } else if !current_verison.changed_since(&new_query.buffer_version) {
-                        excerpts_to_query.push(new_query.excerpt_id);
+                        excerpt_queries
+                            .insert(new_query.excerpt_id, hints_fetch_task(new_query, cx));
                     }
 
                     queries_per_buffer
                 },
             );
 
-        for (queried_buffer, (buffer_version, excerpts)) in queries_per_buffer {
+        for (queried_buffer, (buffer_version, excerpt_queries)) in queries_per_buffer {
             self.hint_updates_tx
                 .send_blocking(HintsUpdate {
                     multi_buffer_snapshot: multi_buffer_snapshot.clone(),
@@ -256,7 +333,7 @@ impl InlayHintCache {
                         invalidate_cache: conflicts_with_cache,
                         buffer_id: queried_buffer,
                         buffer_version,
-                        excerpts,
+                        excerpt_queries,
                     },
                 })
                 .ok();
@@ -295,16 +372,24 @@ enum HintsUpdateKind {
     BufferUpdate {
         buffer_id: u64,
         buffer_version: Global,
-        excerpts: Vec<ExcerptId>,
+        excerpt_queries:
+            HashMap<ExcerptId, Task<anyhow::Result<(InlayHintQuery, Option<Vec<InlayHint>>)>>>,
         invalidate_cache: bool,
     },
 }
 
-struct UpdateResult {
-    splice: InlaySplice,
-    new_allowed_hint_kinds: Option<HashSet<Option<InlayHintKind>>>,
-    remove_from_cache: HashSet<InlayId>,
-    add_to_cache: HashMap<u64, BufferHints<(Anchor, InlayHint, InlayId)>>,
+enum UpdateResult {
+    HintQuery {
+        query: InlayHintQuery,
+        remove_from_visible: Vec<InlayId>,
+        remove_from_cache: HashSet<InlayId>,
+        add_to_cache: HashMap<u64, BufferHints<(Option<InlayId>, Anchor, InlayHint)>>,
+    },
+    Other {
+        splice: InlaySplice,
+        new_allowed_hint_kinds: Option<HashSet<Option<InlayHintKind>>>,
+        remove_from_cache: HashSet<InlayId>,
+    },
 }
 
 impl HintsUpdate {
@@ -322,13 +407,13 @@ impl HintsUpdate {
                 HintsUpdateKind::BufferUpdate {
                     buffer_id: old_buffer_id,
                     buffer_version: old_buffer_version,
-                    excerpts: old_excerpts,
+                    excerpt_queries: old_excerpt_queries,
                     ..
                 },
                 HintsUpdateKind::BufferUpdate {
                     buffer_id: new_buffer_id,
                     buffer_version: new_buffer_version,
-                    excerpts: new_excerpts,
+                    excerpt_queries: new_excerpt_queries,
                     invalidate_cache: new_invalidate_cache,
                 },
             ) => {
@@ -353,8 +438,7 @@ impl HintsUpdate {
                             .map(|inlay| inlay.id)
                             .collect::<Vec<_>>();
                         if old_inlays == new_inlays {
-                            old_excerpts.extend(new_excerpts.drain(..));
-                            old_excerpts.dedup();
+                            old_excerpt_queries.extend(new_excerpt_queries.drain());
                             return Ok(());
                         }
                     }
@@ -371,7 +455,7 @@ impl HintsUpdate {
             HintsUpdateKind::Clean => {
                 if !self.cache.inlay_hints.is_empty() || !self.visible_inlays.is_empty() {
                     result_sender
-                        .send(UpdateResult {
+                        .send(UpdateResult::Other {
                             splice: InlaySplice {
                                 to_remove: self
                                     .visible_inlays
@@ -382,7 +466,6 @@ impl HintsUpdate {
                             },
                             new_allowed_hint_kinds: None,
                             remove_from_cache: self.cache.inlay_hints.keys().copied().collect(),
-                            add_to_cache: HashMap::default(),
                         })
                         .await
                         .ok();
@@ -396,11 +479,10 @@ impl HintsUpdate {
                     &new,
                 ) {
                     result_sender
-                        .send(UpdateResult {
+                        .send(UpdateResult::Other {
                             splice,
                             new_allowed_hint_kinds: Some(new),
                             remove_from_cache: HashSet::default(),
-                            add_to_cache: HashMap::default(),
                         })
                         .await
                         .ok();
@@ -408,19 +490,39 @@ impl HintsUpdate {
             }
             HintsUpdateKind::BufferUpdate {
                 buffer_id,
-                buffer_version,
-                excerpts,
+                excerpt_queries,
                 invalidate_cache,
+                ..
             } => {
-                let mut tasks = excerpts
+                let mut task_query = excerpt_queries
                     .into_iter()
-                    .map(|excerpt_id| async move {
-                        //
-                        todo!("TODO kb")
+                    .map(|(excerpt_id, task)| async move {
+                        let task = task.await;
+                        (excerpt_id, task)
                     })
                     .collect::<FuturesUnordered<_>>();
-                while let Some(update) = tasks.next().await {
-                    todo!("TODO kb")
+                while let Some((excerpt_id, task_result)) = task_query.next().await {
+                    match task_result {
+                        Ok((query, Some(new_hints))) => {
+                            if !new_hints.is_empty() {
+                                if let Some(hint_update_result) = new_excerpt_hints_update_result(
+                                    &self.multi_buffer_snapshot,
+                                    &self.visible_inlays,
+                                    &self.cache,
+                                    query,
+                                    new_hints,
+                                    invalidate_cache,
+                                ) {
+                                    result_sender
+                                        .send(hint_update_result)
+                                        .await
+                                        .ok();
+                                }
+                            }
+                        },
+                        Ok((_, None)) => {},
+                        Err(e) => error!("Excerpt {excerpt_id:?} from buffer {buffer_id} failed to update its hints: {e:#}"),
+                    }
                 }
             }
         }
@@ -514,7 +616,7 @@ fn new_allowed_hint_kinds_splice(
 
     let mut to_remove = Vec::new();
     let mut to_insert = Vec::new();
-    let mut shown_hints_to_remove = group_inlays(current_inlays);
+    let mut shown_hints_to_remove = group_inlays(&current_inlays);
 
     for (buffer_id, cached_buffer_hints) in &hints_cache.hints_in_buffers {
         let shown_buffer_hints_to_remove = shown_hints_to_remove.entry(*buffer_id).or_default();
@@ -589,6 +691,117 @@ fn new_allowed_hint_kinds_splice(
     })
 }
 
+fn new_excerpt_hints_update_result(
+    multi_buffer_snapshot: &MultiBufferSnapshot,
+    current_inlays: &[Inlay],
+    inlay_hint_cache: &CacheSnapshot,
+    query: InlayHintQuery,
+    new_excerpt_hints: Vec<InlayHint>,
+    invalidate_cache: bool,
+) -> Option<UpdateResult> {
+    let mut remove_from_visible = Vec::new();
+    let mut remove_from_cache = HashSet::default();
+    let mut add_to_cache: HashMap<u64, BufferHints<(Option<InlayId>, Anchor, InlayHint)>> =
+        HashMap::default();
+    let mut cache_hints_to_persist: HashSet<InlayId> = HashSet::default();
+
+    let currently_shown_hints = group_inlays(&current_inlays);
+    let empty = Vec::new();
+    let cached_excerpt_hints = inlay_hint_cache
+        .hints_in_buffers
+        .get(&query.buffer_id)
+        .map(|buffer_hints| &buffer_hints.hints_per_excerpt)
+        .and_then(|excerpt_hints_hints| excerpt_hints_hints.get(&query.excerpt_id))
+        .unwrap_or(&empty);
+    let shown_excerpt_hints = currently_shown_hints
+        .get(&query.buffer_id)
+        .and_then(|hints| hints.get(&query.excerpt_id))
+        .unwrap_or(&empty);
+    for new_hint in new_excerpt_hints {
+        let new_hint_anchor =
+            multi_buffer_snapshot.anchor_in_excerpt(query.excerpt_id, new_hint.position);
+        let should_add_to_cache = match cached_excerpt_hints
+            .binary_search_by(|probe| new_hint_anchor.cmp(&probe.0, &multi_buffer_snapshot))
+        {
+            Ok(ix) => {
+                let (_, cached_inlay_id) = cached_excerpt_hints[ix];
+                let cache_hit = inlay_hint_cache
+                    .inlay_hints
+                    .get(&cached_inlay_id)
+                    .filter(|cached_hint| cached_hint == &&new_hint)
+                    .is_some();
+                if cache_hit {
+                    cache_hints_to_persist.insert(cached_inlay_id);
+                    false
+                } else {
+                    true
+                }
+            }
+            Err(_) => true,
+        };
+
+        let shown_inlay_id = match shown_excerpt_hints
+            .binary_search_by(|probe| probe.0.cmp(&new_hint_anchor, &multi_buffer_snapshot))
+        {
+            Ok(ix) => {
+                let (_, shown_inlay_id) = shown_excerpt_hints[ix];
+                let shown_hint_found = inlay_hint_cache
+                    .inlay_hints
+                    .get(&shown_inlay_id)
+                    .filter(|cached_hint| cached_hint == &&new_hint)
+                    .is_some();
+                if shown_hint_found {
+                    Some(shown_inlay_id)
+                } else {
+                    None
+                }
+            }
+            Err(_) => None,
+        };
+
+        if should_add_to_cache {
+            let id_to_add = match shown_inlay_id {
+                Some(shown_inlay_id) => {
+                    cache_hints_to_persist.insert(shown_inlay_id);
+                    Some(shown_inlay_id)
+                }
+                None => None,
+            };
+            add_to_cache
+                .entry(query.buffer_id)
+                .or_insert_with(|| BufferHints::new(query.buffer_version.clone()))
+                .hints_per_excerpt
+                .entry(query.excerpt_id)
+                .or_default()
+                .push((id_to_add, new_hint_anchor, new_hint.clone()));
+        }
+    }
+
+    if invalidate_cache {
+        remove_from_visible.extend(
+            shown_excerpt_hints
+                .iter()
+                .map(|(_, hint_id)| hint_id)
+                .filter(|hint_id| cache_hints_to_persist.contains(hint_id))
+                .copied(),
+        );
+        remove_from_cache.extend(
+            inlay_hint_cache
+                .inlay_hints
+                .keys()
+                .filter(|cached_inlay_id| cache_hints_to_persist.contains(cached_inlay_id))
+                .copied(),
+        );
+    }
+
+    Some(UpdateResult::HintQuery {
+        query,
+        remove_from_visible,
+        remove_from_cache,
+        add_to_cache,
+    })
+}
+
 fn allowed_hint_types(
     inlay_hint_settings: editor_settings::InlayHints,
 ) -> HashSet<Option<InlayHintKind>> {
@@ -605,86 +818,42 @@ fn allowed_hint_types(
     new_allowed_hint_types
 }
 
-// TODO kb wrong, query and update the editor separately
-fn fetch_queries(
-    multi_buffer: ModelHandle<MultiBuffer>,
-    queries: impl Iterator<Item = InlayHintQuery>,
+fn hints_fetch_task(
+    query: InlayHintQuery,
     cx: &mut ViewContext<'_, '_, Editor>,
-) -> Task<anyhow::Result<HashMap<u64, BufferHints<InlayHint>>>> {
-    let mut inlay_fetch_tasks = Vec::new();
-    for query in queries {
-        let task_multi_buffer = multi_buffer.clone();
-        let task = cx.spawn(|editor, mut cx| async move {
-            let Some(buffer_handle) = cx.read(|cx| task_multi_buffer.read(cx).buffer(query.buffer_id))
-                else { return anyhow::Ok((query, Some(Vec::new()))) };
-            let task = editor
-                .update(&mut cx, |editor, cx| {
-                    if let Some((_, excerpt_range)) = task_multi_buffer.read(cx)
+) -> Task<anyhow::Result<(InlayHintQuery, Option<Vec<InlayHint>>)>> {
+    cx.spawn(|editor, mut cx| async move {
+        let Ok(task) = editor
+            .update(&mut cx, |editor, cx| {
+                Some({
+                    let multi_buffer = editor.buffer().read(cx);
+                    let buffer_handle = multi_buffer.buffer(query.buffer_id)?;
+                    let (_, excerpt_range) = multi_buffer
                         .excerpts_for_buffer(&buffer_handle, cx)
                         .into_iter()
-                        .find(|(excerpt_id, _)| excerpt_id == &query.excerpt_id)
-                    {
-                        editor.project.as_ref().map(|project| {
-                            project.update(cx, |project, cx| {
-                                project.query_inlay_hints_for_buffer(
-                                    buffer_handle,
-                                    excerpt_range.context,
-                                    cx,
-                                )
-                            })
-                        })
-                    } else {
-                        None
-                    }
+                        .find(|(excerpt_id, _)| excerpt_id == &query.excerpt_id)?;
+                    editor.project.as_ref()?.update(cx, |project, cx| {
+                        project.query_inlay_hints_for_buffer(
+                            buffer_handle,
+                            excerpt_range.context,
+                            cx,
+                        )
+                    })
                 })
-                .context("inlays fetch task spawn")?;
-            Ok((
-                query,
-                match task {
-                    Some(task) => task.await.context("inlays for buffer task")?,
-                    None => Some(Vec::new()),
-                },
-            ))
-        });
-
-        inlay_fetch_tasks.push(task);
-    }
-
-    cx.spawn(|editor, cx| async move {
-        let mut inlay_updates: HashMap<u64, BufferHints<InlayHint>> = HashMap::default();
-        for task_result in futures::future::join_all(inlay_fetch_tasks).await {
-            match task_result {
-                Ok((query, Some(response_hints))) => {
-                    let Some(buffer_snapshot) = editor.read_with(&cx, |editor, cx| {
-                        editor.buffer().read(cx).buffer(query.buffer_id).map(|buffer| buffer.read(cx).snapshot())
-                    })? else { continue; };
-                    let buffer_hints = inlay_updates
-                        .entry(query.buffer_id)
-                        .or_insert_with(|| BufferHints::new(query.buffer_version.clone()));
-                    if buffer_snapshot.version().changed_since(&buffer_hints.buffer_version) {
-                        continue;
-                    }
-                    let cached_excerpt_hints = buffer_hints
-                        .hints_per_excerpt
-                        .entry(query.excerpt_id)
-                        .or_default();
-                    for inlay in response_hints {
-                        match cached_excerpt_hints.binary_search_by(|probe| {
-                            inlay.position.cmp(&probe.position, &buffer_snapshot)
-                        }) {
-                            Ok(ix) | Err(ix) => cached_excerpt_hints.insert(ix, inlay),
-                        }
-                    }
-                }
-                Ok((_, None)) => {}
-                Err(e) => error!("Failed to update inlays for buffer: {e:#}"),
-            }
-        }
-        Ok(inlay_updates)
+            }) else {
+                return Ok((query, None));
+            };
+        Ok((
+            query,
+            match task {
+                Some(task) => task.await.context("inlays for buffer task")?,
+                None => Some(Vec::new()),
+            },
+        ))
     })
 }
 
-fn group_inlays(inlays: Vec<Inlay>) -> HashMap<u64, HashMap<ExcerptId, Vec<(Anchor, InlayId)>>> {
+fn group_inlays(inlays: &[Inlay]) -> HashMap<u64, HashMap<ExcerptId, Vec<(Anchor, InlayId)>>> {
     inlays.into_iter().fold(
         HashMap::<u64, HashMap<ExcerptId, Vec<(Anchor, InlayId)>>>::default(),
         |mut current_hints, inlay| {
@@ -700,169 +869,3 @@ fn group_inlays(inlays: Vec<Inlay>) -> HashMap<u64, HashMap<ExcerptId, Vec<(Anch
         },
     )
 }
-
-// async fn update_hints(
-//     multi_buffer: ModelHandle<MultiBuffer>,
-//     queries: Vec<InlayHintQuery>,
-//     current_inlays: Vec<Inlay>,
-//     invalidate_cache: bool,
-//     cx: &mut ViewContext<'_, '_, Editor>,
-// ) -> Option<InlaySplice> {
-//     let fetch_queries_task = fetch_queries(multi_buffer, queries.into_iter(), cx);
-//     let new_hints = fetch_queries_task.await.context("inlay hints fetch")?;
-
-//     let mut to_remove = Vec::new();
-//     let mut to_insert = Vec::new();
-//     let mut cache_hints_to_persist: HashMap<u64, (Global, HashMap<ExcerptId, HashSet<InlayId>>)> =
-//         HashMap::default();
-
-//     editor.update(&mut cx, |editor, cx| {
-//         let multi_buffer_snapshot = task_multi_buffer.read(cx).snapshot(cx);
-//         for (new_buffer_id, new_hints_per_buffer) in new_hints {
-//             let cached_buffer_hints = editor
-//                 .inlay_hint_cache
-//                 .hints_in_buffers
-//                 .entry(new_buffer_id)
-//                 .or_insert_with(|| {
-//                     BufferHints::new(new_hints_per_buffer.buffer_version.clone())
-//                 });
-
-//             let buffer_cache_hints_to_persist =
-//                 cache_hints_to_persist.entry(new_buffer_id).or_insert_with(|| (new_hints_per_buffer.buffer_version.clone(), HashMap::default()));
-//             if cached_buffer_hints
-//                 .buffer_version
-//                 .changed_since(&new_hints_per_buffer.buffer_version)
-//             {
-//                 buffer_cache_hints_to_persist.0 = new_hints_per_buffer.buffer_version;
-//                 buffer_cache_hints_to_persist.1.extend(
-//                     cached_buffer_hints.hints_per_excerpt.iter().map(
-//                         |(excerpt_id, excerpt_hints)| {
-//                             (
-//                                 *excerpt_id,
-//                                 excerpt_hints.iter().map(|(_, id)| *id).collect(),
-//                             )
-//                         },
-//                     ),
-//                 );
-//                 continue;
-//             }
-
-//             let shown_buffer_hints = currently_shown_hints.get(&new_buffer_id);
-//             for (new_excerpt_id, new_hints_per_excerpt) in
-//                 new_hints_per_buffer.hints_per_excerpt
-//             {
-//                 let excerpt_cache_hints_to_persist = buffer_cache_hints_to_persist.1
-//                     .entry(new_excerpt_id)
-//                     .or_default();
-//                 let cached_excerpt_hints = cached_buffer_hints
-//                     .hints_per_excerpt
-//                     .entry(new_excerpt_id)
-//                     .or_default();
-//                 let empty_shown_excerpt_hints = Vec::new();
-//                 let shown_excerpt_hints = shown_buffer_hints.and_then(|hints| hints.get(&new_excerpt_id)).unwrap_or(&empty_shown_excerpt_hints);
-//                 for new_hint in new_hints_per_excerpt {
-//                     let new_hint_anchor = multi_buffer_snapshot
-//                         .anchor_in_excerpt(new_excerpt_id, new_hint.position);
-//                     let cache_insert_ix = match cached_excerpt_hints.binary_search_by(|probe| {
-//                         new_hint_anchor.cmp(&probe.0, &multi_buffer_snapshot)
-//                     }) {
-//                         Ok(ix) => {
-//                             let (_, cached_inlay_id) = cached_excerpt_hints[ix];
-//                             let cache_hit = editor
-//                                 .inlay_hint_cache
-//                                 .inlay_hints
-//                                 .get(&cached_inlay_id)
-//                                 .filter(|cached_hint| cached_hint == &&new_hint)
-//                                 .is_some();
-//                             if cache_hit {
-//                                 excerpt_cache_hints_to_persist
-//                                     .insert(cached_inlay_id);
-//                                 None
-//                             } else {
-//                                 Some(ix)
-//                             }
-//                         }
-//                         Err(ix) => Some(ix),
-//                     };
-
-//                     let shown_inlay_id = match shown_excerpt_hints.binary_search_by(|probe| {
-//                         probe.0.cmp(&new_hint_anchor, &multi_buffer_snapshot)
-//                     }) {
-//                         Ok(ix) => {{
-//                             let (_, shown_inlay_id) = shown_excerpt_hints[ix];
-//                             let shown_hint_found =  editor.inlay_hint_cache.inlay_hints.get(&shown_inlay_id)
-//                                 .filter(|cached_hint| cached_hint == &&new_hint).is_some();
-//                             if shown_hint_found {
-//                                 Some(shown_inlay_id)
-//                             } else {
-//                                 None
-//                             }
-//                         }},
-//                         Err(_) => None,
-//                     };
-
-//                     if let Some(insert_ix) = cache_insert_ix {
-//                         let hint_id = match shown_inlay_id {
-//                             Some(shown_inlay_id) => shown_inlay_id,
-//                             None => {
-//                                 let new_hint_id = InlayId(post_inc(&mut editor.next_inlay_id));
-//                                 if editor.inlay_hint_cache.allowed_hint_kinds.contains(&new_hint.kind)
-//                                 {
-//                                     to_insert.push((new_hint_id, new_hint_anchor, new_hint.clone()));
-//                                 }
-//                                 new_hint_id
-//                             }
-//                         };
-//                         excerpt_cache_hints_to_persist.insert(hint_id);
-//                         cached_excerpt_hints.insert(insert_ix, (new_hint_anchor, hint_id));
-//                         editor
-//                             .inlay_hint_cache
-//                             .inlay_hints
-//                             .insert(hint_id, new_hint);
-//                     }
-//                 }
-//             }
-//         }
-
-//         if conflicts_with_cache {
-//             for (shown_buffer_id, mut shown_hints_to_clean) in currently_shown_hints {
-//                 match cache_hints_to_persist.get(&shown_buffer_id) {
-//                     Some(cached_buffer_hints) => {
-//                         for (persisted_id, cached_hints) in &cached_buffer_hints.1 {
-//                             shown_hints_to_clean.entry(*persisted_id).or_default()
-//                                 .retain(|(_, shown_id)| !cached_hints.contains(shown_id));
-//                         }
-//                     },
-//                     None => {},
-//                 }
-//                 to_remove.extend(shown_hints_to_clean.into_iter()
-//                     .flat_map(|(_, excerpt_hints)| excerpt_hints.into_iter().map(|(_, hint_id)| hint_id)));
-//             }
-
-//             editor.inlay_hint_cache.hints_in_buffers.retain(|buffer_id, buffer_hints| {
-//                 let Some(mut buffer_hints_to_persist) = cache_hints_to_persist.remove(buffer_id) else { return false; };
-//                 buffer_hints.buffer_version = buffer_hints_to_persist.0;
-//                 buffer_hints.hints_per_excerpt.retain(|excerpt_id, excerpt_hints| {
-//                     let Some(excerpt_hints_to_persist) = buffer_hints_to_persist.1.remove(&excerpt_id) else { return false; };
-//                     excerpt_hints.retain(|(_, hint_id)| {
-//                         let retain = excerpt_hints_to_persist.contains(hint_id);
-//                         if !retain {
-//                             editor
-//                                 .inlay_hint_cache
-//                                 .inlay_hints
-//                                 .remove(hint_id);
-//                         }
-//                         retain
-//                     });
-//                     !excerpt_hints.is_empty()
-//                 });
-//                 !buffer_hints.hints_per_excerpt.is_empty()
-//             });
-//         }
-
-//         Some(InlaySplice {
-//             to_remove,
-//             to_insert,
-//         })
-//     })
-// }