From 49c00fd57117e3d0042f3ac2713e707152a49081 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 16 Jun 2023 17:56:44 +0300 Subject: [PATCH] Generate InlayIds in InlayMap, prepare InlayCache for refactoring --- crates/editor/src/display_map.rs | 9 +- crates/editor/src/display_map/fold_map.rs | 3 +- crates/editor/src/display_map/inlay_map.rs | 116 ++-- crates/editor/src/display_map/tab_map.rs | 2 +- crates/editor/src/display_map/wrap_map.rs | 4 +- crates/editor/src/editor.rs | 32 +- crates/editor/src/inlay_cache.rs | 690 ++++++++++----------- 7 files changed, 391 insertions(+), 465 deletions(-) diff --git a/crates/editor/src/display_map.rs b/crates/editor/src/display_map.rs index 73be4763199808e69508114535a9acb941efdd26..b0b97fd70d49fe64f3bf4b5f70c4de2d06614d15 100644 --- a/crates/editor/src/display_map.rs +++ b/crates/editor/src/display_map.rs @@ -246,11 +246,11 @@ impl DisplayMap { pub fn splice_inlays>( &mut self, to_remove: Vec, - to_insert: Vec<(InlayId, InlayProperties)>, + to_insert: Vec>, cx: &mut ModelContext, - ) { + ) -> Vec { if to_remove.is_empty() && to_insert.is_empty() { - return; + return Vec::new(); } let buffer_snapshot = self.buffer.read(cx).snapshot(cx); @@ -264,13 +264,14 @@ impl DisplayMap { .update(cx, |map, cx| map.sync(snapshot, edits, cx)); self.block_map.read(snapshot, edits); - let (snapshot, edits) = self.inlay_map.splice(to_remove, to_insert); + let (snapshot, edits, new_inlay_ids) = 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 fe3c0d86abd18661b1be39ec6b1a7bd36b5b5fb0..fb0892b82d92152c8732cdfb8fcd8ef1c651d654 100644 --- a/crates/editor/src/display_map/fold_map.rs +++ b/crates/editor/src/display_map/fold_map.rs @@ -1475,7 +1475,6 @@ 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(); @@ -1485,7 +1484,7 @@ mod tests { snapshot_edits.extend(map.randomly_mutate(&mut rng)); } 40..=59 => { - let (_, edits) = inlay_map.randomly_mutate(&mut next_inlay_id, &mut rng); + let (_, edits) = inlay_map.randomly_mutate(&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 d731e0dc4c4f297720607ee370d3cafd6454cf5c..3571a603a9c8f485626b0ae73bc8d75c521dcd98 100644 --- a/crates/editor/src/display_map/inlay_map.rs +++ b/crates/editor/src/display_map/inlay_map.rs @@ -13,11 +13,13 @@ 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)] @@ -297,8 +299,9 @@ impl InlayMap { ( Self { snapshot: Mutex::new(snapshot.clone()), - inlays_by_id: Default::default(), - inlays: Default::default(), + inlays_by_id: HashMap::default(), + inlays: Vec::new(), + next_inlay_id: 0, }, snapshot, ) @@ -443,8 +446,8 @@ impl InlayMap { pub fn splice>( &mut self, to_remove: Vec, - to_insert: Vec<(InlayId, InlayProperties)>, - ) -> (InlaySnapshot, Vec) { + to_insert: Vec>, + ) -> (InlaySnapshot, Vec, Vec) { let snapshot = self.snapshot.lock(); let mut edits = BTreeSet::new(); @@ -456,12 +459,14 @@ impl InlayMap { } } - for (id, properties) in to_insert { + let mut new_inlay_ids = Vec::with_capacity(to_insert.len()); + for properties in to_insert { let inlay = Inlay { - id, + id: InlayId(post_inc(&mut self.next_inlay_id)), position: properties.position, text: properties.text.into(), }; + new_inlay_ids.push(inlay.id); self.inlays_by_id.insert(inlay.id, inlay.clone()); match self .inlays @@ -485,17 +490,16 @@ impl InlayMap { .collect(); let buffer_snapshot = snapshot.buffer.clone(); drop(snapshot); - self.sync(buffer_snapshot, buffer_edits) + let (snapshot, edits) = self.sync(buffer_snapshot, buffer_edits); + (snapshot, edits, new_inlay_ids) } #[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(); @@ -515,13 +519,10 @@ impl InlayMap { bias, text ); - to_insert.push(( - InlayId(post_inc(next_inlay_id)), - InlayProperties { - position: snapshot.buffer.anchor_at(position, bias), - text, - }, - )); + to_insert.push(InlayProperties { + position: snapshot.buffer.anchor_at(position, bias), + text, + }); } else { to_remove.push(*self.inlays_by_id.keys().choose(rng).unwrap()); } @@ -529,7 +530,8 @@ impl InlayMap { log::info!("removing inlays: {:?}", to_remove); drop(snapshot); - self.splice(to_remove, to_insert) + let (snapshot, edits, _) = self.splice(to_remove, to_insert); + (snapshot, edits) } } @@ -840,7 +842,6 @@ mod tests { use settings::SettingsStore; use std::env; use text::Patch; - use util::post_inc; #[gpui::test] fn test_basic_inlays(cx: &mut AppContext) { @@ -848,17 +849,13 @@ 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![( - InlayId(post_inc(&mut next_inlay_id)), - InlayProperties { - position: buffer.read(cx).snapshot(cx).anchor_after(3), - text: "|123|", - }, - )], + vec![InlayProperties { + position: buffer.read(cx).snapshot(cx).anchor_after(3), + text: "|123|", + }], ); assert_eq!(inlay_snapshot.text(), "abc|123|defghi"); assert_eq!( @@ -928,23 +925,17 @@ mod tests { ); assert_eq!(inlay_snapshot.text(), "abxyDzefghi"); - let (inlay_snapshot, _) = inlay_map.splice( + let (inlay_snapshot, _, _) = inlay_map.splice( Vec::new(), vec![ - ( - InlayId(post_inc(&mut next_inlay_id)), - InlayProperties { - position: buffer.read(cx).snapshot(cx).anchor_before(3), - text: "|123|", - }, - ), - ( - InlayId(post_inc(&mut next_inlay_id)), - InlayProperties { - position: buffer.read(cx).snapshot(cx).anchor_after(3), - text: "|456|", - }, - ), + InlayProperties { + position: buffer.read(cx).snapshot(cx).anchor_before(3), + text: "|123|", + }, + InlayProperties { + position: buffer.read(cx).snapshot(cx).anchor_after(3), + text: "|456|", + }, ], ); assert_eq!(inlay_snapshot.text(), "abx|123||456|yDzefghi"); @@ -958,7 +949,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"); } @@ -969,30 +960,21 @@ mod tests { let (mut inlay_map, inlay_snapshot) = InlayMap::new(buffer.read(cx).snapshot(cx)); assert_eq!(inlay_snapshot.text(), "abc\ndef\nghi"); - let (inlay_snapshot, _) = inlay_map.splice( + let (inlay_snapshot, _, _) = inlay_map.splice( Vec::new(), vec![ - ( - InlayId(0), - InlayProperties { - position: buffer.read(cx).snapshot(cx).anchor_before(0), - text: "|123|\n", - }, - ), - ( - InlayId(1), - InlayProperties { - position: buffer.read(cx).snapshot(cx).anchor_before(4), - text: "|456|", - }, - ), - ( - InlayId(1), - InlayProperties { - position: buffer.read(cx).snapshot(cx).anchor_before(7), - text: "\n|567|\n", - }, - ), + InlayProperties { + position: buffer.read(cx).snapshot(cx).anchor_before(0), + text: "|123|\n", + }, + InlayProperties { + position: buffer.read(cx).snapshot(cx).anchor_before(4), + text: "|456|", + }, + InlayProperties { + position: buffer.read(cx).snapshot(cx).anchor_before(7), + text: "\n|567|\n", + }, ], ); assert_eq!(inlay_snapshot.text(), "|123|\nabc\n|456|def\n|567|\n\nghi"); @@ -1023,8 +1005,6 @@ mod tests { log::info!("buffer text: {:?}", buffer_snapshot.text()); let (mut inlay_map, mut inlay_snapshot) = InlayMap::new(buffer_snapshot.clone()); - let mut next_inlay_id = 0; - for _ in 0..operations { let mut inlay_edits = Patch::default(); @@ -1032,7 +1012,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 next_inlay_id, &mut rng); + let (snapshot, edits) = inlay_map.randomly_mutate(&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 9157caace496e72597e70ac039e7797672122dbc..021712cd4041fc620d68f0cd8ed332567f236ae3 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 0, &mut rng); + let (inlay_snapshot, _) = inlay_map.randomly_mutate(&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 5197a2e0de49150f38e37e39ca7e42ba4050c026..a1f60920cd2b2068ec4ae08eb295b0b7a5ff8eb7 100644 --- a/crates/editor/src/display_map/wrap_map.rs +++ b/crates/editor/src/display_map/wrap_map.rs @@ -1119,7 +1119,6 @@ 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); @@ -1147,8 +1146,7 @@ mod tests { } } 40..=59 => { - let (inlay_snapshot, inlay_edits) = - inlay_map.randomly_mutate(&mut next_inlay_id, &mut rng); + let (inlay_snapshot, inlay_edits) = inlay_map.randomly_mutate(&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 1e5370cce50be74960d53060633e93c057df57a5..4a40d6ef2f2885e980adfddb1d9ac9ee91046836 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -2709,13 +2709,13 @@ impl Editor { fn splice_inlay_hints( &self, to_remove: Vec, - to_insert: Vec<(InlayId, Anchor, project::InlayHint)>, + to_insert: Vec<(Anchor, project::InlayHint)>, cx: &mut ViewContext, ) { let buffer = self.buffer.read(cx).read(cx); - let new_inlays: Vec<(InlayId, InlayProperties)> = to_insert + let new_inlays = to_insert .into_iter() - .map(|(inlay_id, hint_anchor, hint)| { + .map(|(hint_anchor, hint)| { let mut text = hint.text(); // TODO kb styling instead? if hint.padding_right { @@ -2725,13 +2725,10 @@ impl Editor { text.insert(0, ' '); } - ( - inlay_id, - InlayProperties { - position: hint_anchor.bias_left(&buffer), - text, - }, - ) + InlayProperties { + position: hint_anchor.bias_left(&buffer), + text, + } }) .collect(); drop(buffer); @@ -3485,15 +3482,10 @@ impl Editor { to_remove.push(suggestion.id); } - let to_insert = vec![( - // TODO kb check how can I get the unique id for the suggestion - // Move the generation of the id inside the map - InlayId(usize::MAX), - InlayProperties { - position: cursor, - text: text.clone(), - }, - )]; + let to_insert = vec![InlayProperties { + position: cursor, + text: text.clone(), + }]; self.display_map.update(cx, move |map, cx| { map.splice_inlays(to_remove, to_insert, cx) }); @@ -7664,7 +7656,6 @@ fn inlay_hint_query( cx: &mut ViewContext<'_, '_, Editor>, ) -> Option { let buffer = buffer.read(cx); - let buffer_snapshot = buffer.snapshot(); let max_buffer_len = buffer.len(); let visible_offset_range_len = excerpt_visible_offset_range.len(); @@ -7677,7 +7668,6 @@ fn inlay_hint_query( .saturating_add(visible_offset_range_len), ); Some(InlayHintQuery { - buffer_path: buffer_snapshot.resolve_file_path(cx, true)?, buffer_id: buffer.remote_id(), buffer_version: buffer.version().clone(), excerpt_id, diff --git a/crates/editor/src/inlay_cache.rs b/crates/editor/src/inlay_cache.rs index b571a29cc14c6458ebf45f3bfec1c6455fbd1fff..7a362085147d514f7f71ea0a00e1308fec81b505 100644 --- a/crates/editor/src/inlay_cache.rs +++ b/crates/editor/src/inlay_cache.rs @@ -1,19 +1,13 @@ -use std::{ - cmp, - ops::Range, - path::{Path, PathBuf}, -}; +use std::ops::Range; use crate::{editor_settings, scroll::ScrollAnchor, Anchor, Editor, ExcerptId, MultiBuffer}; -use anyhow::Context; -use clock::{Global, Local}; +use clock::Global; use gpui::{ModelHandle, Task, ViewContext}; -use log::error; use project::{InlayHint, InlayHintKind}; -use util::post_inc; -use collections::{hash_map, BTreeMap, HashMap, HashSet}; +use collections::{HashMap, HashSet}; +// TODO kb move to inlay_map along with the next one? #[derive(Debug, Clone)] pub struct Inlay { pub id: InlayId, @@ -36,48 +30,14 @@ pub enum InlayRefreshReason { #[derive(Debug, Clone, Default)] pub struct InlayCache { - inlays_per_buffer: HashMap, + inlays_per_buffer: HashMap, allowed_hint_kinds: HashSet>, - next_inlay_id: usize, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct AnchorKey { - offset: usize, - version: Local, -} - -#[derive(Clone, Debug)] -pub struct OrderedByAnchorOffset(pub BTreeMap); - -impl OrderedByAnchorOffset { - pub fn add(&mut self, anchor: Anchor, t: T) { - let key = AnchorKey { - offset: anchor.text_anchor.offset, - version: anchor.text_anchor.timestamp, - }; - self.0.insert(key, (anchor, t)); - } - - fn into_ordered_elements(self) -> impl Iterator { - self.0.into_values() - } - - fn ordered_elements(&self) -> impl Iterator { - self.0.values() - } -} - -impl Default for OrderedByAnchorOffset { - fn default() -> Self { - Self(BTreeMap::default()) - } } #[derive(Clone, Debug, Default)] struct BufferInlays { buffer_version: Global, - inlays_per_excerpts: HashMap>, + ordered_by_anchor_inlays: Vec<(Anchor, InlayId, InlayHint)>, } #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -86,12 +46,11 @@ pub struct InlayId(pub usize); #[derive(Debug, Default)] pub struct InlaySplice { pub to_remove: Vec, - pub to_insert: Vec<(InlayId, Anchor, InlayHint)>, + pub to_insert: Vec<(Anchor, InlayHint)>, } pub struct InlayHintQuery { pub buffer_id: u64, - pub buffer_path: PathBuf, pub buffer_version: Global, pub excerpt_id: ExcerptId, pub excerpt_offset_query_range: Range, @@ -100,307 +59,8 @@ pub struct InlayHintQuery { impl InlayCache { pub fn new(inlay_hint_settings: editor_settings::InlayHints) -> Self { Self { - inlays_per_buffer: HashMap::default(), allowed_hint_kinds: allowed_inlay_hint_types(inlay_hint_settings), - next_inlay_id: 0, - } - } - - pub fn append_inlays( - &mut self, - multi_buffer: ModelHandle, - ranges_to_add: impl Iterator, - cx: &mut ViewContext, - ) -> Task> { - self.fetch_inlays(multi_buffer, ranges_to_add, false, cx) - } - - pub fn replace_inlays( - &mut self, - multi_buffer: ModelHandle, - new_ranges: impl Iterator, - cx: &mut ViewContext, - ) -> Task> { - self.fetch_inlays(multi_buffer, new_ranges, true, cx) - } - - fn fetch_inlays( - &mut self, - multi_buffer: ModelHandle, - inlay_fetch_ranges: impl Iterator, - replace_old: bool, - cx: &mut ViewContext, - ) -> Task> { - let mut inlay_fetch_tasks = Vec::new(); - for inlay_fetch_range in inlay_fetch_ranges { - let inlays_up_to_date = self.inlays_up_to_date( - &inlay_fetch_range.buffer_path, - &inlay_fetch_range.buffer_version, - inlay_fetch_range.excerpt_id, - ); - let task_multi_buffer = multi_buffer.clone(); - let task = cx.spawn(|editor, mut cx| async move { - if inlays_up_to_date { - anyhow::Ok((inlay_fetch_range, None)) - } else { - let Some(buffer_handle) = cx.read(|cx| task_multi_buffer.read(cx).buffer(inlay_fetch_range.buffer_id)) - else { return Ok((inlay_fetch_range, Some(Vec::new()))) }; - let task = editor - .update(&mut cx, |editor, cx| { - editor.project.as_ref().map(|project| { - project.update(cx, |project, cx| { - project.query_inlay_hints_for_buffer( - buffer_handle, - inlay_fetch_range.excerpt_offset_query_range.clone(), - cx, - ) - }) - }) - }) - .context("inlays fecth task spawn")?; - - Ok((inlay_fetch_range, match task { - Some(task) => task.await.context("inlays for buffer task")?, - None => Some(Vec::new()), - })) - } - }); - inlay_fetch_tasks.push(task); - } - - let final_task = cx.spawn(|editor, mut cx| async move { - let mut inlay_updates: HashMap< - PathBuf, - ( - Global, - HashMap, OrderedByAnchorOffset)>>, - ), - > = HashMap::default(); - let multi_buffer_snapshot = - editor.read_with(&cx, |editor, cx| editor.buffer().read(cx).snapshot(cx))?; - - for task_result in futures::future::join_all(inlay_fetch_tasks).await { - match task_result { - Ok((inlay_fetch_range, response_inlays)) => { - // TODO kb different caching now - let inlays_per_excerpt = HashMap::from_iter([( - inlay_fetch_range.excerpt_id, - response_inlays - .map(|excerpt_inlays| { - excerpt_inlays.into_iter().fold( - OrderedByAnchorOffset::default(), - |mut ordered_inlays, inlay| { - let anchor = multi_buffer_snapshot.anchor_in_excerpt( - inlay_fetch_range.excerpt_id, - inlay.position, - ); - ordered_inlays.add(anchor, inlay); - ordered_inlays - }, - ) - }) - .map(|inlays| { - (inlay_fetch_range.excerpt_offset_query_range, inlays) - }), - )]); - match inlay_updates.entry(inlay_fetch_range.buffer_path) { - hash_map::Entry::Occupied(mut o) => { - o.get_mut().1.extend(inlays_per_excerpt); - } - hash_map::Entry::Vacant(v) => { - v.insert((inlay_fetch_range.buffer_version, inlays_per_excerpt)); - } - } - } - Err(e) => error!("Failed to update inlays for buffer: {e:#}"), - } - } - - let updates = if !inlay_updates.is_empty() { - let inlays_update = editor.update(&mut cx, |editor, _| { - editor.inlay_cache.apply_fetch_inlays(inlay_updates) - })?; - inlays_update - } else { - InlaySplice::default() - }; - - anyhow::Ok(updates) - }); - - final_task - } - - fn inlays_up_to_date( - &self, - buffer_path: &Path, - buffer_version: &Global, - excerpt_id: ExcerptId, - ) -> bool { - 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) - } - - fn apply_fetch_inlays( - &mut self, - fetched_inlays: HashMap< - PathBuf, - ( - Global, - HashMap, OrderedByAnchorOffset)>>, - ), - >, - ) -> InlaySplice { - let mut old_inlays = self.inlays_per_buffer.clone(); - let mut to_remove = Vec::new(); - let mut to_insert = Vec::new(); - - for (buffer_path, (buffer_version, new_buffer_inlays)) in fetched_inlays { - match old_inlays.remove(&buffer_path) { - Some(mut old_buffer_inlays) => { - for (excerpt_id, new_excerpt_inlays) in new_buffer_inlays { - let (_, mut new_excerpt_inlays) = match new_excerpt_inlays { - Some((excerpt_offset_range, new_inlays)) => ( - excerpt_offset_range, - new_inlays.into_ordered_elements().fuse().peekable(), - ), - None => continue, - }; - 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_path) - .expect("element expected: `old_inlays.remove` returned `Some`"); - - if old_buffer_inlays - .inlays_per_excerpts - .remove(&excerpt_id) - .is_some() - { - let self_excerpt_inlays = self_inlays_per_buffer - .inlays_per_excerpts - .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; - - while let Some(new_offset) = new_excerpt_inlays - .peek() - .map(|(new_anchor, _)| new_anchor.text_anchor.offset) - { - let old_offset = old_anchor.text_anchor.offset; - match new_offset.cmp(&old_offset) { - cmp::Ordering::Less => { - let (new_anchor, new_inlay) = - new_excerpt_inlays.next().expect( - "element expected: `peek` returned `Some`", - ); - hints_to_add.push(( - new_anchor, - ( - InlayId(post_inc(&mut self.next_inlay_id)), - new_inlay, - ), - )); - } - cmp::Ordering::Equal => { - let (new_anchor, new_inlay) = - new_excerpt_inlays.next().expect( - "element expected: `peek` returned `Some`", - ); - if &new_inlay == old_inlay { - retain = true; - } else { - hints_to_add.push(( - new_anchor, - ( - InlayId(post_inc( - &mut self.next_inlay_id, - )), - new_inlay, - ), - )); - } - } - cmp::Ordering::Greater => break, - } - } - - if !retain { - to_remove.push(*old_inlay_id); - } - retain - }, - ); - - for (new_anchor, (id, new_inlay)) in hints_to_add { - self_excerpt_inlays.add(new_anchor, (id, new_inlay.clone())); - to_insert.push((id, new_anchor, new_inlay)); - } - } - - for (new_anchor, new_inlay) in new_excerpt_inlays { - let id = InlayId(post_inc(&mut self.next_inlay_id)); - self_inlays_per_buffer - .inlays_per_excerpts - .entry(excerpt_id) - .or_default() - .add(new_anchor, (id, new_inlay.clone())); - to_insert.push((id, new_anchor, new_inlay)); - } - } - } - None => { - let mut inlays_per_excerpts: HashMap< - ExcerptId, - OrderedByAnchorOffset<(InlayId, InlayHint)>, - > = HashMap::default(); - for (new_excerpt_id, new_ordered_inlays) in new_buffer_inlays { - if let Some((_, new_ordered_inlays)) = new_ordered_inlays { - for (new_anchor, new_inlay) in - new_ordered_inlays.into_ordered_elements() - { - let id = InlayId(post_inc(&mut self.next_inlay_id)); - inlays_per_excerpts - .entry(new_excerpt_id) - .or_default() - .add(new_anchor, (id, new_inlay.clone())); - to_insert.push((id, new_anchor, new_inlay)); - } - } - } - self.inlays_per_buffer.insert( - buffer_path, - BufferInlays { - buffer_version, - inlays_per_excerpts, - }, - ); - } - } - } - - for (_, old_buffer_inlays) in old_inlays { - for (_, old_excerpt_inlays) in old_buffer_inlays.inlays_per_excerpts { - for (_, (id_to_remove, _)) in old_excerpt_inlays.into_ordered_elements() { - to_remove.push(id_to_remove); - } - } - } - - to_insert.retain(|(_, _, new_hint)| self.allowed_hint_kinds.contains(&new_hint.kind)); - - InlaySplice { - to_remove, - to_insert, + inlays_per_buffer: HashMap::default(), } } @@ -420,22 +80,17 @@ impl InlayCache { .collect::>(); let mut to_remove = Vec::new(); let mut to_insert = Vec::new(); - for (anchor, (inlay_id, inlay_hint)) in self + for (_, inlay_id, inlay_hint) in self .inlays_per_buffer .iter() - .map(|(_, buffer_inlays)| { - buffer_inlays - .inlays_per_excerpts - .iter() - .map(|(_, excerpt_inlays)| excerpt_inlays.ordered_elements()) - .flatten() - }) + .map(|(_, buffer_inlays)| buffer_inlays.ordered_by_anchor_inlays.iter()) .flatten() { if removed_hint_kinds.contains(&inlay_hint.kind) { to_remove.push(*inlay_id); } else if new_allowed_hint_kinds.contains(&inlay_hint.kind) { - to_insert.push((*inlay_id, *anchor, inlay_hint.to_owned())); + todo!("TODO kb: agree with InlayMap how splice works") + // to_insert.push((*inlay_id, *anchor, inlay_hint.to_owned())); } } @@ -450,20 +105,323 @@ impl InlayCache { pub fn clear(&mut self) -> Vec { self.inlays_per_buffer .drain() - .map(|(_, buffer_inlays)| { + .flat_map(|(_, buffer_inlays)| { buffer_inlays - .inlays_per_excerpts + .ordered_by_anchor_inlays .into_iter() - .map(|(_, excerpt_inlays)| { - excerpt_inlays - .into_ordered_elements() - .map(|(_, (id, _))| id) - }) - .flatten() + .map(|(_, id, _)| id) }) - .flatten() .collect() } + + pub fn append_inlays( + &mut self, + multi_buffer: ModelHandle, + ranges_to_add: impl Iterator, + cx: &mut ViewContext, + ) -> Task> { + self.fetch_inlays(multi_buffer, ranges_to_add, false, cx) + } + + pub fn replace_inlays( + &mut self, + multi_buffer: ModelHandle, + new_ranges: impl Iterator, + cx: &mut ViewContext, + ) -> Task> { + self.fetch_inlays(multi_buffer, new_ranges, true, cx) + } + + fn fetch_inlays( + &mut self, + multi_buffer: ModelHandle, + inlay_fetch_ranges: impl Iterator, + replace_old: bool, + cx: &mut ViewContext, + ) -> Task> { + // TODO kb + todo!("TODO kb") + } + + // fn fetch_inlays( + // &mut self, + // multi_buffer: ModelHandle, + // inlay_fetch_ranges: impl Iterator, + // replace_old: bool, + // cx: &mut ViewContext, + // ) -> Task> { + // let mut inlay_fetch_tasks = Vec::new(); + // for inlay_fetch_range in inlay_fetch_ranges { + // let inlays_up_to_date = self.inlays_up_to_date( + // &inlay_fetch_range.buffer_path, + // &inlay_fetch_range.buffer_version, + // inlay_fetch_range.excerpt_id, + // ); + // let task_multi_buffer = multi_buffer.clone(); + // let task = cx.spawn(|editor, mut cx| async move { + // if inlays_up_to_date { + // anyhow::Ok((inlay_fetch_range, None)) + // } else { + // let Some(buffer_handle) = cx.read(|cx| task_multi_buffer.read(cx).buffer(inlay_fetch_range.buffer_id)) + // else { return Ok((inlay_fetch_range, Some(Vec::new()))) }; + // let task = editor + // .update(&mut cx, |editor, cx| { + // editor.project.as_ref().map(|project| { + // project.update(cx, |project, cx| { + // project.query_inlay_hints_for_buffer( + // buffer_handle, + // inlay_fetch_range.excerpt_offset_query_range.clone(), + // cx, + // ) + // }) + // }) + // }) + // .context("inlays fecth task spawn")?; + + // Ok((inlay_fetch_range, match task { + // Some(task) => task.await.context("inlays for buffer task")?, + // None => Some(Vec::new()), + // })) + // } + // }); + // inlay_fetch_tasks.push(task); + // } + + // let final_task = cx.spawn(|editor, mut cx| async move { + // let mut inlay_updates: HashMap< + // PathBuf, + // ( + // Global, + // HashMap, OrderedByAnchorOffset)>>, + // ), + // > = HashMap::default(); + // let multi_buffer_snapshot = + // editor.read_with(&cx, |editor, cx| editor.buffer().read(cx).snapshot(cx))?; + + // for task_result in futures::future::join_all(inlay_fetch_tasks).await { + // match task_result { + // Ok((inlay_fetch_range, response_inlays)) => { + // // TODO kb different caching now + // let inlays_per_excerpt = HashMap::from_iter([( + // inlay_fetch_range.excerpt_id, + // response_inlays + // .map(|excerpt_inlays| { + // excerpt_inlays.into_iter().fold( + // OrderedByAnchorOffset::default(), + // |mut ordered_inlays, inlay| { + // let anchor = multi_buffer_snapshot.anchor_in_excerpt( + // inlay_fetch_range.excerpt_id, + // inlay.position, + // ); + // ordered_inlays.add(anchor, inlay); + // ordered_inlays + // }, + // ) + // }) + // .map(|inlays| { + // (inlay_fetch_range.excerpt_offset_query_range, inlays) + // }), + // )]); + // match inlay_updates.entry(inlay_fetch_range.buffer_path) { + // hash_map::Entry::Occupied(mut o) => { + // o.get_mut().1.extend(inlays_per_excerpt); + // } + // hash_map::Entry::Vacant(v) => { + // v.insert((inlay_fetch_range.buffer_version, inlays_per_excerpt)); + // } + // } + // } + // Err(e) => error!("Failed to update inlays for buffer: {e:#}"), + // } + // } + + // let updates = if !inlay_updates.is_empty() { + // let inlays_update = editor.update(&mut cx, |editor, _| { + // editor.inlay_cache.apply_fetch_inlays(inlay_updates) + // })?; + // inlays_update + // } else { + // InlaySplice::default() + // }; + + // anyhow::Ok(updates) + // }); + + // final_task + // } + + // fn inlays_up_to_date( + // &self, + // buffer_path: &Path, + // buffer_version: &Global, + // excerpt_id: ExcerptId, + // ) -> bool { + // 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) + // } + + // fn apply_fetch_inlays( + // &mut self, + // fetched_inlays: HashMap< + // PathBuf, + // ( + // Global, + // HashMap, OrderedByAnchorOffset)>>, + // ), + // >, + // ) -> InlaySplice { + // let mut old_inlays = self.inlays_per_buffer.clone(); + // let mut to_remove = Vec::new(); + // let mut to_insert = Vec::new(); + + // for (buffer_path, (buffer_version, new_buffer_inlays)) in fetched_inlays { + // match old_inlays.remove(&buffer_path) { + // Some(mut old_buffer_inlays) => { + // for (excerpt_id, new_excerpt_inlays) in new_buffer_inlays { + // let (_, mut new_excerpt_inlays) = match new_excerpt_inlays { + // Some((excerpt_offset_range, new_inlays)) => ( + // excerpt_offset_range, + // new_inlays.into_ordered_elements().fuse().peekable(), + // ), + // None => continue, + // }; + // 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_path) + // .expect("element expected: `old_inlays.remove` returned `Some`"); + + // if old_buffer_inlays + // .inlays_per_excerpts + // .remove(&excerpt_id) + // .is_some() + // { + // let self_excerpt_inlays = self_inlays_per_buffer + // .inlays_per_excerpts + // .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; + + // while let Some(new_offset) = new_excerpt_inlays + // .peek() + // .map(|(new_anchor, _)| new_anchor.text_anchor.offset) + // { + // let old_offset = old_anchor.text_anchor.offset; + // match new_offset.cmp(&old_offset) { + // cmp::Ordering::Less => { + // let (new_anchor, new_inlay) = + // new_excerpt_inlays.next().expect( + // "element expected: `peek` returned `Some`", + // ); + // hints_to_add.push(( + // new_anchor, + // ( + // InlayId(post_inc(&mut self.next_inlay_id)), + // new_inlay, + // ), + // )); + // } + // cmp::Ordering::Equal => { + // let (new_anchor, new_inlay) = + // new_excerpt_inlays.next().expect( + // "element expected: `peek` returned `Some`", + // ); + // if &new_inlay == old_inlay { + // retain = true; + // } else { + // hints_to_add.push(( + // new_anchor, + // ( + // InlayId(post_inc( + // &mut self.next_inlay_id, + // )), + // new_inlay, + // ), + // )); + // } + // } + // cmp::Ordering::Greater => break, + // } + // } + + // if !retain { + // to_remove.push(*old_inlay_id); + // } + // retain + // }, + // ); + + // for (new_anchor, (id, new_inlay)) in hints_to_add { + // self_excerpt_inlays.add(new_anchor, (id, new_inlay.clone())); + // to_insert.push((id, new_anchor, new_inlay)); + // } + // } + + // for (new_anchor, new_inlay) in new_excerpt_inlays { + // let id = InlayId(post_inc(&mut self.next_inlay_id)); + // self_inlays_per_buffer + // .inlays_per_excerpts + // .entry(excerpt_id) + // .or_default() + // .add(new_anchor, (id, new_inlay.clone())); + // to_insert.push((id, new_anchor, new_inlay)); + // } + // } + // } + // None => { + // let mut inlays_per_excerpts: HashMap< + // ExcerptId, + // OrderedByAnchorOffset<(InlayId, InlayHint)>, + // > = HashMap::default(); + // for (new_excerpt_id, new_ordered_inlays) in new_buffer_inlays { + // if let Some((_, new_ordered_inlays)) = new_ordered_inlays { + // for (new_anchor, new_inlay) in + // new_ordered_inlays.into_ordered_elements() + // { + // let id = InlayId(post_inc(&mut self.next_inlay_id)); + // inlays_per_excerpts + // .entry(new_excerpt_id) + // .or_default() + // .add(new_anchor, (id, new_inlay.clone())); + // to_insert.push((id, new_anchor, new_inlay)); + // } + // } + // } + // self.inlays_per_buffer.insert( + // buffer_path, + // BufferInlays { + // buffer_version, + // inlays_per_excerpts, + // }, + // ); + // } + // } + // } + + // for (_, old_buffer_inlays) in old_inlays { + // for (_, old_excerpt_inlays) in old_buffer_inlays.inlays_per_excerpts { + // for (_, (id_to_remove, _)) in old_excerpt_inlays.into_ordered_elements() { + // to_remove.push(id_to_remove); + // } + // } + // } + + // to_insert.retain(|(_, _, new_hint)| self.allowed_hint_kinds.contains(&new_hint.kind)); + + // InlaySplice { + // to_remove, + // to_insert, + // } + // } } fn allowed_inlay_hint_types(