From 8c03e9e1229c7fcd36bfa3b207c05996713cc8f8 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sat, 17 Jun 2023 23:10:48 +0300 Subject: [PATCH] Move InlayId generation back to InlayCache --- crates/editor/src/display_map.rs | 13 +- crates/editor/src/display_map/fold_map.rs | 3 +- crates/editor/src/display_map/inlay_map.rs | 54 +++---- crates/editor/src/display_map/tab_map.rs | 2 +- crates/editor/src/display_map/wrap_map.rs | 4 +- crates/editor/src/editor.rs | 27 ++-- crates/editor/src/inlay_hint_cache.rs | 177 +++++++++++---------- 7 files changed, 147 insertions(+), 133 deletions(-) diff --git a/crates/editor/src/display_map.rs b/crates/editor/src/display_map.rs index 791665bf78374f1d4d5c874e49c123836bfde424..16d44fbacfb9aaa806ed018ed48f7dbc3623f075 100644 --- a/crates/editor/src/display_map.rs +++ b/crates/editor/src/display_map.rs @@ -4,7 +4,7 @@ mod inlay_map; mod tab_map; mod wrap_map; -use crate::{Anchor, AnchorRangeExt, MultiBuffer, MultiBufferSnapshot, ToOffset, ToPoint}; +use crate::{Anchor, AnchorRangeExt, InlayId, MultiBuffer, MultiBufferSnapshot, ToOffset, ToPoint}; pub use block_map::{BlockMap, BlockPoint}; use collections::{HashMap, HashSet}; use fold_map::FoldMap; @@ -28,7 +28,7 @@ pub use block_map::{ BlockDisposition, BlockId, BlockProperties, BlockStyle, RenderBlock, TransformBlock, }; -pub use self::inlay_map::{Inlay, InlayId, InlayProperties}; +pub use self::inlay_map::{Inlay, InlayProperties}; #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum FoldStatus { @@ -249,11 +249,11 @@ impl DisplayMap { pub fn splice_inlays>( &mut self, to_remove: Vec, - to_insert: Vec<(Option, InlayProperties)>, + to_insert: Vec<(InlayId, InlayProperties)>, cx: &mut ModelContext, - ) -> Vec { + ) { if to_remove.is_empty() && to_insert.is_empty() { - return Vec::new(); + return; } let buffer_snapshot = self.buffer.read(cx).snapshot(cx); @@ -267,14 +267,13 @@ impl DisplayMap { .update(cx, |map, cx| map.sync(snapshot, edits, cx)); self.block_map.read(snapshot, edits); - let (snapshot, edits, new_inlay_ids) = self.inlay_map.splice(to_remove, to_insert); + let (snapshot, edits) = self.inlay_map.splice(to_remove, to_insert); let (snapshot, edits) = self.fold_map.read(snapshot, edits); let (snapshot, edits) = self.tab_map.sync(snapshot, edits, tab_size); let (snapshot, edits) = self .wrap_map .update(cx, |map, cx| map.sync(snapshot, edits, cx)); self.block_map.read(snapshot, edits); - new_inlay_ids } fn tab_size(buffer: &ModelHandle, cx: &mut ModelContext) -> NonZeroU32 { diff --git a/crates/editor/src/display_map/fold_map.rs b/crates/editor/src/display_map/fold_map.rs index fb0892b82d92152c8732cdfb8fcd8ef1c651d654..fe3c0d86abd18661b1be39ec6b1a7bd36b5b5fb0 100644 --- a/crates/editor/src/display_map/fold_map.rs +++ b/crates/editor/src/display_map/fold_map.rs @@ -1475,6 +1475,7 @@ mod tests { Arc::new((HighlightStyle::default(), highlight_ranges)), ); + let mut next_inlay_id = 0; for _ in 0..operations { log::info!("text: {:?}", buffer_snapshot.text()); let mut buffer_edits = Vec::new(); @@ -1484,7 +1485,7 @@ mod tests { snapshot_edits.extend(map.randomly_mutate(&mut rng)); } 40..=59 => { - let (_, edits) = inlay_map.randomly_mutate(&mut rng); + let (_, edits) = inlay_map.randomly_mutate(&mut next_inlay_id, &mut rng); inlay_edits = edits; } _ => buffer.update(cx, |buffer, cx| { diff --git a/crates/editor/src/display_map/inlay_map.rs b/crates/editor/src/display_map/inlay_map.rs index 0c7d1bd60396fb95a6e2989bb7fbd23c2d7c080f..43f86287d8080c519cf377c304d3d96478066d70 100644 --- a/crates/editor/src/display_map/inlay_map.rs +++ b/crates/editor/src/display_map/inlay_map.rs @@ -1,6 +1,6 @@ use crate::{ multi_buffer::{MultiBufferChunks, MultiBufferRows}, - Anchor, MultiBufferSnapshot, ToOffset, + Anchor, InlayId, MultiBufferSnapshot, ToOffset, }; use collections::{BTreeSet, HashMap}; use gpui::fonts::HighlightStyle; @@ -12,13 +12,11 @@ use std::{ }; use sum_tree::{Bias, Cursor, SumTree}; use text::Patch; -use util::post_inc; pub struct InlayMap { snapshot: Mutex, inlays_by_id: HashMap, inlays: Vec, - next_inlay_id: usize, } #[derive(Clone)] @@ -34,9 +32,6 @@ enum Transform { Inlay(Inlay), } -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct InlayId(usize); - #[derive(Debug, Clone)] pub struct Inlay { pub id: InlayId, @@ -316,7 +311,6 @@ impl InlayMap { snapshot: Mutex::new(snapshot.clone()), inlays_by_id: HashMap::default(), inlays: Vec::new(), - next_inlay_id: 0, }, snapshot, ) @@ -461,8 +455,8 @@ impl InlayMap { pub fn splice>( &mut self, to_remove: Vec, - to_insert: Vec<(Option, InlayProperties)>, - ) -> (InlaySnapshot, Vec, Vec) { + to_insert: Vec<(InlayId, InlayProperties)>, + ) -> (InlaySnapshot, Vec) { let snapshot = self.snapshot.lock(); let mut edits = BTreeSet::new(); @@ -474,16 +468,12 @@ impl InlayMap { } } - let mut new_inlay_ids = Vec::with_capacity(to_insert.len()); for (existing_id, properties) in to_insert { let inlay = Inlay { - id: existing_id.unwrap_or_else(|| InlayId(post_inc(&mut self.next_inlay_id))), + id: existing_id, position: properties.position, text: properties.text.into(), }; - if existing_id.is_none() { - new_inlay_ids.push(inlay.id); - } self.inlays_by_id.insert(inlay.id, inlay.clone()); match self .inlays @@ -508,7 +498,7 @@ impl InlayMap { let buffer_snapshot = snapshot.buffer.clone(); drop(snapshot); let (snapshot, edits) = self.sync(buffer_snapshot, buffer_edits); - (snapshot, edits, new_inlay_ids) + (snapshot, edits) } pub fn current_inlays(&self) -> impl Iterator { @@ -518,9 +508,11 @@ impl InlayMap { #[cfg(test)] pub(crate) fn randomly_mutate( &mut self, + next_inlay_id: &mut usize, rng: &mut rand::rngs::StdRng, ) -> (InlaySnapshot, Vec) { use rand::prelude::*; + use util::post_inc; let mut to_remove = Vec::new(); let mut to_insert = Vec::new(); @@ -541,7 +533,7 @@ impl InlayMap { text ); to_insert.push(( - None, + InlayId(post_inc(next_inlay_id)), InlayProperties { position: snapshot.buffer.anchor_at(position, bias), text, @@ -554,7 +546,7 @@ impl InlayMap { log::info!("removing inlays: {:?}", to_remove); drop(snapshot); - let (snapshot, edits, _) = self.splice(to_remove, to_insert); + let (snapshot, edits) = self.splice(to_remove, to_insert); (snapshot, edits) } } @@ -860,12 +852,13 @@ fn push_isomorphic(sum_tree: &mut SumTree, summary: TextSummary) { #[cfg(test)] mod tests { use super::*; - use crate::MultiBuffer; + use crate::{InlayId, MultiBuffer}; use gpui::AppContext; use rand::prelude::*; use settings::SettingsStore; use std::env; use text::Patch; + use util::post_inc; #[gpui::test] fn test_basic_inlays(cx: &mut AppContext) { @@ -873,11 +866,12 @@ mod tests { let buffer_edits = buffer.update(cx, |buffer, _| buffer.subscribe()); let (mut inlay_map, inlay_snapshot) = InlayMap::new(buffer.read(cx).snapshot(cx)); assert_eq!(inlay_snapshot.text(), "abcdefghi"); + let mut next_inlay_id = 0; - let (inlay_snapshot, _, _) = inlay_map.splice( + let (inlay_snapshot, _) = inlay_map.splice( Vec::new(), vec![( - None, + InlayId(post_inc(&mut next_inlay_id)), InlayProperties { position: buffer.read(cx).snapshot(cx).anchor_after(3), text: "|123|", @@ -952,18 +946,18 @@ mod tests { ); assert_eq!(inlay_snapshot.text(), "abxyDzefghi"); - let (inlay_snapshot, _, _) = inlay_map.splice( + let (inlay_snapshot, _) = inlay_map.splice( Vec::new(), vec![ ( - None, + InlayId(post_inc(&mut next_inlay_id)), InlayProperties { position: buffer.read(cx).snapshot(cx).anchor_before(3), text: "|123|", }, ), ( - None, + InlayId(post_inc(&mut next_inlay_id)), InlayProperties { position: buffer.read(cx).snapshot(cx).anchor_after(3), text: "|456|", @@ -982,7 +976,7 @@ mod tests { assert_eq!(inlay_snapshot.text(), "abx|123|JKL|456|yDzefghi"); // The inlays can be manually removed. - let (inlay_snapshot, _, _) = inlay_map + let (inlay_snapshot, _) = inlay_map .splice::(inlay_map.inlays_by_id.keys().copied().collect(), Vec::new()); assert_eq!(inlay_snapshot.text(), "abxJKLyDzefghi"); } @@ -992,26 +986,27 @@ mod tests { let buffer = MultiBuffer::build_simple("abc\ndef\nghi", cx); let (mut inlay_map, inlay_snapshot) = InlayMap::new(buffer.read(cx).snapshot(cx)); assert_eq!(inlay_snapshot.text(), "abc\ndef\nghi"); + let mut next_inlay_id = 0; - let (inlay_snapshot, _, _) = inlay_map.splice( + let (inlay_snapshot, _) = inlay_map.splice( Vec::new(), vec![ ( - None, + InlayId(post_inc(&mut next_inlay_id)), InlayProperties { position: buffer.read(cx).snapshot(cx).anchor_before(0), text: "|123|\n", }, ), ( - None, + InlayId(post_inc(&mut next_inlay_id)), InlayProperties { position: buffer.read(cx).snapshot(cx).anchor_before(4), text: "|456|", }, ), ( - None, + InlayId(post_inc(&mut next_inlay_id)), InlayProperties { position: buffer.read(cx).snapshot(cx).anchor_before(7), text: "\n|567|\n", @@ -1044,6 +1039,7 @@ mod tests { MultiBuffer::build_random(&mut rng, cx) }; let mut buffer_snapshot = buffer.read(cx).snapshot(cx); + let mut next_inlay_id = 0; log::info!("buffer text: {:?}", buffer_snapshot.text()); let (mut inlay_map, mut inlay_snapshot) = InlayMap::new(buffer_snapshot.clone()); @@ -1054,7 +1050,7 @@ mod tests { let mut buffer_edits = Vec::new(); match rng.gen_range(0..=100) { 0..=50 => { - let (snapshot, edits) = inlay_map.randomly_mutate(&mut rng); + let (snapshot, edits) = inlay_map.randomly_mutate(&mut next_inlay_id, &mut rng); log::info!("mutated text: {:?}", snapshot.text()); inlay_edits = Patch::new(edits); } diff --git a/crates/editor/src/display_map/tab_map.rs b/crates/editor/src/display_map/tab_map.rs index 021712cd4041fc620d68f0cd8ed332567f236ae3..9157caace496e72597e70ac039e7797672122dbc 100644 --- a/crates/editor/src/display_map/tab_map.rs +++ b/crates/editor/src/display_map/tab_map.rs @@ -708,7 +708,7 @@ mod tests { fold_map.randomly_mutate(&mut rng); let (fold_snapshot, _) = fold_map.read(inlay_snapshot, vec![]); log::info!("FoldMap text: {:?}", fold_snapshot.text()); - let (inlay_snapshot, _) = inlay_map.randomly_mutate(&mut rng); + let (inlay_snapshot, _) = inlay_map.randomly_mutate(&mut 0, &mut rng); log::info!("InlayMap text: {:?}", inlay_snapshot.text()); let (tab_map, _) = TabMap::new(fold_snapshot.clone(), tab_size); diff --git a/crates/editor/src/display_map/wrap_map.rs b/crates/editor/src/display_map/wrap_map.rs index a1f60920cd2b2068ec4ae08eb295b0b7a5ff8eb7..5197a2e0de49150f38e37e39ca7e42ba4050c026 100644 --- a/crates/editor/src/display_map/wrap_map.rs +++ b/crates/editor/src/display_map/wrap_map.rs @@ -1119,6 +1119,7 @@ mod tests { ); log::info!("Wrapped text: {:?}", actual_text); + let mut next_inlay_id = 0; let mut edits = Vec::new(); for _i in 0..operations { log::info!("{} ==============================================", _i); @@ -1146,7 +1147,8 @@ mod tests { } } 40..=59 => { - let (inlay_snapshot, inlay_edits) = inlay_map.randomly_mutate(&mut rng); + let (inlay_snapshot, inlay_edits) = + inlay_map.randomly_mutate(&mut next_inlay_id, &mut rng); let (fold_snapshot, fold_edits) = fold_map.read(inlay_snapshot, inlay_edits); let (tabs_snapshot, tab_edits) = tab_map.sync(fold_snapshot, fold_edits, tab_size); diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 03e98407db7b457424424e31f437651aeedeb0c8..ed76ee3b297162492bc808cc230f8c3224cba940 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -185,6 +185,9 @@ pub struct GutterHover { pub hovered: bool, } +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct InlayId(usize); + actions!( editor, [ @@ -541,6 +544,7 @@ pub struct Editor { link_go_to_definition_state: LinkGoToDefinitionState, copilot_state: CopilotState, inlay_hint_cache: InlayHintCache, + next_inlay_id: usize, _subscriptions: Vec, } @@ -1339,6 +1343,7 @@ impl Editor { .add_view(|cx| context_menu::ContextMenu::new(editor_view_id, cx)), completion_tasks: Default::default(), next_completion_id: 0, + next_inlay_id: 0, available_code_actions: Default::default(), code_actions_task: Default::default(), document_highlights_task: Default::default(), @@ -2664,7 +2669,7 @@ impl Editor { to_insert, } = editor .update(&mut cx, |editor, cx| { - editor.inlay_hint_cache.append_inlays( + editor.inlay_hint_cache.append_hints( multi_buffer_handle, std::iter::once(updated_range_query), cx, @@ -2693,7 +2698,7 @@ impl Editor { to_insert, } = editor .update(&mut cx, |editor, cx| { - editor.inlay_hint_cache.replace_inlays( + editor.inlay_hint_cache.replace_hints( multi_buffer_handle, replacement_queries.into_iter(), currently_shown_inlay_hints, @@ -2738,7 +2743,7 @@ impl Editor { fn splice_inlay_hints( &self, to_remove: Vec, - to_insert: Vec<(Option, Anchor, project::InlayHint)>, + to_insert: Vec<(InlayId, Anchor, project::InlayHint)>, cx: &mut ViewContext, ) { let buffer = self.buffer.read(cx).read(cx); @@ -3514,23 +3519,19 @@ impl Editor { to_remove.push(suggestion.id); } + let suggestion_inlay_id = self.next_inlay_id(); let to_insert = vec![( - None, + suggestion_inlay_id, InlayProperties { position: cursor, text: text.clone(), }, )]; - let new_inlay_ids = self.display_map.update(cx, move |map, cx| { + self.display_map.update(cx, move |map, cx| { map.splice_inlays(to_remove, to_insert, cx) }); - assert_eq!( - new_inlay_ids.len(), - 1, - "Expecting only copilot suggestion id generated" - ); self.copilot_state.suggestion = Some(Inlay { - id: new_inlay_ids.into_iter().next().unwrap(), + id: suggestion_inlay_id, position: cursor, text, }); @@ -7687,6 +7688,10 @@ impl Editor { let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else { return; }; cx.write_to_clipboard(ClipboardItem::new(lines)); } + + pub fn next_inlay_id(&mut self) -> InlayId { + InlayId(post_inc(&mut self.next_inlay_id)) + } } fn inlay_hint_query( diff --git a/crates/editor/src/inlay_hint_cache.rs b/crates/editor/src/inlay_hint_cache.rs index 7f3124b5e83ab3d5c23a7c6a9caec1a9a626178b..b37545bcdf1df657f44d3537bb41f7014da157de 100644 --- a/crates/editor/src/inlay_hint_cache.rs +++ b/crates/editor/src/inlay_hint_cache.rs @@ -1,8 +1,7 @@ use std::ops::Range; use crate::{ - display_map::InlayId, editor_settings, scroll::ScrollAnchor, Anchor, Editor, ExcerptId, - MultiBuffer, + editor_settings, scroll::ScrollAnchor, Anchor, Editor, ExcerptId, InlayId, MultiBuffer, }; use anyhow::Context; use clock::Global; @@ -12,6 +11,7 @@ use log::error; use project::{InlayHint, InlayHintKind}; use collections::{hash_map, HashMap, HashSet}; +use util::post_inc; #[derive(Debug, Copy, Clone)] pub enum InlayRefreshReason { @@ -20,26 +20,39 @@ pub enum InlayRefreshReason { VisibleExcerptsChange, } -#[derive(Debug, Clone, Default)] +#[derive(Debug, Default)] pub struct InlayHintCache { inlay_hints: HashMap, - inlays_in_buffers: HashMap>, + hints_in_buffers: HashMap>, allowed_hint_kinds: HashSet>, } -#[derive(Clone, Debug, Default)] -struct BufferInlays { +#[derive(Clone, Debug)] +struct BufferHints { buffer_version: Global, - cached_ranges: HashMap>>, - excerpt_inlays: HashMap>, + hints_per_excerpt: HashMap>, +} + +#[derive(Clone, Debug)] +struct ExcerptHints { + cached_excerpt_offsets: Vec>, + hints: Vec, +} + +impl Default for ExcerptHints { + fn default() -> Self { + Self { + cached_excerpt_offsets: Vec::new(), + hints: Vec::new(), + } + } } -impl BufferInlays { +impl BufferHints { fn new(buffer_version: Global) -> Self { Self { buffer_version, - excerpt_inlays: HashMap::default(), - cached_ranges: HashMap::default(), + hints_per_excerpt: HashMap::default(), } } } @@ -47,7 +60,7 @@ impl BufferInlays { #[derive(Debug, Default)] pub struct InlaySplice { pub to_remove: Vec, - pub to_insert: Vec<(Option, Anchor, InlayHint)>, + pub to_insert: Vec<(InlayId, Anchor, InlayHint)>, } pub struct InlayHintQuery { @@ -61,7 +74,7 @@ impl InlayHintCache { pub fn new(inlay_hint_settings: editor_settings::InlayHints) -> Self { Self { allowed_hint_kinds: allowed_inlay_hint_types(inlay_hint_settings), - inlays_in_buffers: HashMap::default(), + hints_in_buffers: HashMap::default(), inlay_hints: HashMap::default(), } } @@ -117,26 +130,27 @@ impl InlayHintCache { } let reenabled_hints = self - .inlays_in_buffers + .hints_in_buffers .iter() .filter_map(|(cached_buffer_id, cached_hints_per_excerpt)| { let considered_hints_in_excerpts = considered_hints.get(cached_buffer_id)?; - let not_considered_cached_inlays = cached_hints_per_excerpt - .excerpt_inlays + let not_considered_cached_hints = cached_hints_per_excerpt + .hints_per_excerpt .iter() - .filter_map(|(cached_excerpt_id, cached_hints)| { + .filter_map(|(cached_excerpt_id, cached_excerpt_hints)| { let considered_excerpt_hints = considered_hints_in_excerpts.get(&cached_excerpt_id)?; - let not_considered_cached_inlays = cached_hints + let not_considered_cached_hints = cached_excerpt_hints + .hints .iter() .filter(|(_, cached_hint_id)| { !considered_excerpt_hints.contains(cached_hint_id) }) .copied(); - Some(not_considered_cached_inlays) + Some(not_considered_cached_hints) }) .flatten(); - Some(not_considered_cached_inlays) + Some(not_considered_cached_hints) }) .flatten() .filter_map(|(cached_anchor, cached_inlay_id)| { @@ -148,11 +162,7 @@ impl InlayHintCache { }) .filter(|(_, _, cached_inlay)| self.allowed_hint_kinds.contains(&cached_inlay.kind)) .map(|(cached_anchor, cached_inlay_id, reenabled_inlay)| { - ( - Some(cached_inlay_id), - cached_anchor, - reenabled_inlay.clone(), - ) + (cached_inlay_id, cached_anchor, reenabled_inlay.clone()) }); to_insert.extend(reenabled_hints); @@ -173,25 +183,25 @@ impl InlayHintCache { pub fn clear(&mut self) -> Vec { let ids_to_remove = self.inlay_hints.drain().map(|(id, _)| id).collect(); - self.inlays_in_buffers.clear(); + self.hints_in_buffers.clear(); ids_to_remove } - pub fn append_inlays( + pub fn append_hints( &mut self, multi_buffer: ModelHandle, ranges_to_add: impl Iterator, cx: &mut ViewContext, ) -> Task> { let queries = ranges_to_add.filter_map(|additive_query| { - let Some(cached_buffer_inlays) = self.inlays_in_buffers.get(&additive_query.buffer_id) + let Some(cached_buffer_hints) = self.hints_in_buffers.get(&additive_query.buffer_id) else { return Some(vec![additive_query]) }; - if cached_buffer_inlays.buffer_version.changed_since(&additive_query.buffer_version) { + if cached_buffer_hints.buffer_version.changed_since(&additive_query.buffer_version) { return None } - let Some(excerpt_cached_ranges) = cached_buffer_inlays.cached_ranges.get(&additive_query.excerpt_id) + let Some(excerpt_hints) = cached_buffer_hints.hints_per_excerpt.get(&additive_query.excerpt_id) else { return Some(vec![additive_query]) }; - let non_cached_ranges = missing_subranges(&excerpt_cached_ranges, &additive_query.excerpt_offset_query_range); + let non_cached_ranges = missing_subranges(&excerpt_hints.cached_excerpt_offsets, &additive_query.excerpt_offset_query_range); if non_cached_ranges.is_empty() { None } else { @@ -210,55 +220,59 @@ impl InlayHintCache { let new_hints = fetch_queries_task.await?; editor.update(&mut cx, |editor, cx| { let multi_buffer_snapshot = task_multi_buffer.read(cx).snapshot(cx); - let inlay_hint_cache = &mut editor.inlay_hint_cache; let mut to_insert = Vec::new(); for (new_buffer_id, new_hints_per_buffer) in new_hints { - let cached_buffer_inlays = inlay_hint_cache - .inlays_in_buffers + let cached_buffer_hints = editor + .inlay_hint_cache + .hints_in_buffers .entry(new_buffer_id) .or_insert_with(|| { - BufferInlays::new(new_hints_per_buffer.buffer_version.clone()) + BufferHints::new(new_hints_per_buffer.buffer_version.clone()) }); - if cached_buffer_inlays + if cached_buffer_hints .buffer_version .changed_since(&new_hints_per_buffer.buffer_version) { continue; } - for (new_excerpt_id, new_ranges) in new_hints_per_buffer.cached_ranges { - let cached_ranges = cached_buffer_inlays - .cached_ranges + for (new_excerpt_id, new_excerpt_hints) in + new_hints_per_buffer.hints_per_excerpt + { + let cached_excerpt_hints = cached_buffer_hints + .hints_per_excerpt .entry(new_excerpt_id) - .or_default(); - for new_range in new_ranges { - insert_and_merge_ranges(cached_ranges, &new_range) + .or_insert_with(|| ExcerptHints::default()); + for new_range in new_excerpt_hints.cached_excerpt_offsets { + insert_and_merge_ranges( + &mut cached_excerpt_hints.cached_excerpt_offsets, + &new_range, + ) } - } - for (new_excerpt_id, new_hints) in new_hints_per_buffer.excerpt_inlays { - let cached_inlays = cached_buffer_inlays - .excerpt_inlays - .entry(new_excerpt_id) - .or_default(); - for new_inlay_hint in new_hints { - let new_inlay_id = todo!("TODO kb"); + for new_inlay_hint in new_excerpt_hints.hints { let hint_anchor = multi_buffer_snapshot .anchor_in_excerpt(new_excerpt_id, new_inlay_hint.position); - match cached_inlays.binary_search_by(|probe| { - hint_anchor.cmp(&probe.0, &multi_buffer_snapshot) - }) { - Ok(ix) | Err(ix) => { - cached_inlays.insert(ix, (hint_anchor, new_inlay_id)) - } - } - inlay_hint_cache + let insert_ix = + match cached_excerpt_hints.hints.binary_search_by(|probe| { + hint_anchor.cmp(&probe.0, &multi_buffer_snapshot) + }) { + Ok(ix) | Err(ix) => ix, + }; + + let new_inlay_id = InlayId(post_inc(&mut editor.next_inlay_id)); + cached_excerpt_hints + .hints + .insert(insert_ix, (hint_anchor, new_inlay_id)); + editor + .inlay_hint_cache .inlay_hints .insert(new_inlay_id, new_inlay_hint.clone()); - if inlay_hint_cache + if editor + .inlay_hint_cache .allowed_hint_kinds .contains(&new_inlay_hint.kind) { - to_insert.push((Some(new_inlay_id), hint_anchor, new_inlay_hint)); + to_insert.push((new_inlay_id, hint_anchor, new_inlay_hint)); } } } @@ -272,7 +286,7 @@ impl InlayHintCache { }) } - pub fn replace_inlays( + pub fn replace_hints( &mut self, multi_buffer: ModelHandle, new_ranges: impl Iterator, @@ -401,7 +415,7 @@ fn fetch_queries<'a, 'b>( multi_buffer: ModelHandle, queries: impl Iterator, cx: &mut ViewContext<'a, 'b, Editor>, -) -> Task>>> { +) -> Task>>> { let mut inlay_fetch_tasks = Vec::new(); for query in queries { let task_multi_buffer = multi_buffer.clone(); @@ -434,33 +448,30 @@ fn fetch_queries<'a, 'b>( } cx.spawn(|editor, cx| async move { - let mut inlay_updates: HashMap> = HashMap::default(); + let mut inlay_updates: HashMap> = HashMap::default(); for task_result in futures::future::join_all(inlay_fetch_tasks).await { match task_result { - Ok((query, Some(response_inlays))) => { + 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_inlays = inlay_updates + let buffer_hints = inlay_updates .entry(query.buffer_id) - .or_insert_with(|| BufferInlays::new(query.buffer_version.clone())); - assert_eq!(buffer_inlays.buffer_version, query.buffer_version); - { - let cached_ranges = buffer_inlays - .cached_ranges - .entry(query.excerpt_id) - .or_default(); - insert_and_merge_ranges(cached_ranges, &query.excerpt_offset_query_range); - let excerpt_inlays = buffer_inlays - .excerpt_inlays - .entry(query.excerpt_id) - .or_default(); - for inlay in response_inlays { - match excerpt_inlays.binary_search_by(|probe| { - inlay.position.cmp(&probe.position, &buffer_snapshot) - }) { - Ok(ix) | Err(ix) => excerpt_inlays.insert(ix, inlay), - } + .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(); + insert_and_merge_ranges(&mut cached_excerpt_hints.cached_excerpt_offsets, &query.excerpt_offset_query_range); + let excerpt_hints = &mut cached_excerpt_hints.hints; + for inlay in response_hints { + match excerpt_hints.binary_search_by(|probe| { + inlay.position.cmp(&probe.position, &buffer_snapshot) + }) { + Ok(ix) | Err(ix) => excerpt_hints.insert(ix, inlay), } } }