Generate InlayIds in InlayMap, prepare InlayCache for refactoring

This commit is contained in:
Kirill Bulatov 2023-06-16 17:56:44 +03:00
parent e217a95fcc
commit 49c00fd571
7 changed files with 390 additions and 464 deletions

View file

@ -246,11 +246,11 @@ impl DisplayMap {
pub fn splice_inlays<T: Into<Rope>>( pub fn splice_inlays<T: Into<Rope>>(
&mut self, &mut self,
to_remove: Vec<InlayId>, to_remove: Vec<InlayId>,
to_insert: Vec<(InlayId, InlayProperties<T>)>, to_insert: Vec<InlayProperties<T>>,
cx: &mut ModelContext<Self>, cx: &mut ModelContext<Self>,
) { ) -> Vec<InlayId> {
if to_remove.is_empty() && to_insert.is_empty() { if to_remove.is_empty() && to_insert.is_empty() {
return; return Vec::new();
} }
let buffer_snapshot = self.buffer.read(cx).snapshot(cx); let buffer_snapshot = self.buffer.read(cx).snapshot(cx);
@ -264,13 +264,14 @@ impl DisplayMap {
.update(cx, |map, cx| map.sync(snapshot, edits, cx)); .update(cx, |map, cx| map.sync(snapshot, edits, cx));
self.block_map.read(snapshot, edits); 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.fold_map.read(snapshot, edits);
let (snapshot, edits) = self.tab_map.sync(snapshot, edits, tab_size); let (snapshot, edits) = self.tab_map.sync(snapshot, edits, tab_size);
let (snapshot, edits) = self let (snapshot, edits) = self
.wrap_map .wrap_map
.update(cx, |map, cx| map.sync(snapshot, edits, cx)); .update(cx, |map, cx| map.sync(snapshot, edits, cx));
self.block_map.read(snapshot, edits); self.block_map.read(snapshot, edits);
new_inlay_ids
} }
fn tab_size(buffer: &ModelHandle<MultiBuffer>, cx: &mut ModelContext<Self>) -> NonZeroU32 { fn tab_size(buffer: &ModelHandle<MultiBuffer>, cx: &mut ModelContext<Self>) -> NonZeroU32 {

View file

@ -1475,7 +1475,6 @@ mod tests {
Arc::new((HighlightStyle::default(), highlight_ranges)), Arc::new((HighlightStyle::default(), highlight_ranges)),
); );
let mut next_inlay_id = 0;
for _ in 0..operations { for _ in 0..operations {
log::info!("text: {:?}", buffer_snapshot.text()); log::info!("text: {:?}", buffer_snapshot.text());
let mut buffer_edits = Vec::new(); let mut buffer_edits = Vec::new();
@ -1485,7 +1484,7 @@ mod tests {
snapshot_edits.extend(map.randomly_mutate(&mut rng)); snapshot_edits.extend(map.randomly_mutate(&mut rng));
} }
40..=59 => { 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; inlay_edits = edits;
} }
_ => buffer.update(cx, |buffer, cx| { _ => buffer.update(cx, |buffer, cx| {

View file

@ -13,11 +13,13 @@ use std::{
}; };
use sum_tree::{Bias, Cursor, SumTree}; use sum_tree::{Bias, Cursor, SumTree};
use text::Patch; use text::Patch;
use util::post_inc;
pub struct InlayMap { pub struct InlayMap {
snapshot: Mutex<InlaySnapshot>, snapshot: Mutex<InlaySnapshot>,
inlays_by_id: HashMap<InlayId, Inlay>, inlays_by_id: HashMap<InlayId, Inlay>,
inlays: Vec<Inlay>, inlays: Vec<Inlay>,
next_inlay_id: usize,
} }
#[derive(Clone)] #[derive(Clone)]
@ -297,8 +299,9 @@ impl InlayMap {
( (
Self { Self {
snapshot: Mutex::new(snapshot.clone()), snapshot: Mutex::new(snapshot.clone()),
inlays_by_id: Default::default(), inlays_by_id: HashMap::default(),
inlays: Default::default(), inlays: Vec::new(),
next_inlay_id: 0,
}, },
snapshot, snapshot,
) )
@ -443,8 +446,8 @@ impl InlayMap {
pub fn splice<T: Into<Rope>>( pub fn splice<T: Into<Rope>>(
&mut self, &mut self,
to_remove: Vec<InlayId>, to_remove: Vec<InlayId>,
to_insert: Vec<(InlayId, InlayProperties<T>)>, to_insert: Vec<InlayProperties<T>>,
) -> (InlaySnapshot, Vec<InlayEdit>) { ) -> (InlaySnapshot, Vec<InlayEdit>, Vec<InlayId>) {
let snapshot = self.snapshot.lock(); let snapshot = self.snapshot.lock();
let mut edits = BTreeSet::new(); 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 { let inlay = Inlay {
id, id: InlayId(post_inc(&mut self.next_inlay_id)),
position: properties.position, position: properties.position,
text: properties.text.into(), text: properties.text.into(),
}; };
new_inlay_ids.push(inlay.id);
self.inlays_by_id.insert(inlay.id, inlay.clone()); self.inlays_by_id.insert(inlay.id, inlay.clone());
match self match self
.inlays .inlays
@ -485,17 +490,16 @@ impl InlayMap {
.collect(); .collect();
let buffer_snapshot = snapshot.buffer.clone(); let buffer_snapshot = snapshot.buffer.clone();
drop(snapshot); drop(snapshot);
self.sync(buffer_snapshot, buffer_edits) let (snapshot, edits) = self.sync(buffer_snapshot, buffer_edits);
(snapshot, edits, new_inlay_ids)
} }
#[cfg(test)] #[cfg(test)]
pub(crate) fn randomly_mutate( pub(crate) fn randomly_mutate(
&mut self, &mut self,
next_inlay_id: &mut usize,
rng: &mut rand::rngs::StdRng, rng: &mut rand::rngs::StdRng,
) -> (InlaySnapshot, Vec<InlayEdit>) { ) -> (InlaySnapshot, Vec<InlayEdit>) {
use rand::prelude::*; use rand::prelude::*;
use util::post_inc;
let mut to_remove = Vec::new(); let mut to_remove = Vec::new();
let mut to_insert = Vec::new(); let mut to_insert = Vec::new();
@ -515,13 +519,10 @@ impl InlayMap {
bias, bias,
text text
); );
to_insert.push(( to_insert.push(InlayProperties {
InlayId(post_inc(next_inlay_id)), position: snapshot.buffer.anchor_at(position, bias),
InlayProperties { text,
position: snapshot.buffer.anchor_at(position, bias), });
text,
},
));
} else { } else {
to_remove.push(*self.inlays_by_id.keys().choose(rng).unwrap()); to_remove.push(*self.inlays_by_id.keys().choose(rng).unwrap());
} }
@ -529,7 +530,8 @@ impl InlayMap {
log::info!("removing inlays: {:?}", to_remove); log::info!("removing inlays: {:?}", to_remove);
drop(snapshot); 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 settings::SettingsStore;
use std::env; use std::env;
use text::Patch; use text::Patch;
use util::post_inc;
#[gpui::test] #[gpui::test]
fn test_basic_inlays(cx: &mut AppContext) { fn test_basic_inlays(cx: &mut AppContext) {
@ -848,17 +849,13 @@ mod tests {
let buffer_edits = buffer.update(cx, |buffer, _| buffer.subscribe()); let buffer_edits = buffer.update(cx, |buffer, _| buffer.subscribe());
let (mut inlay_map, inlay_snapshot) = InlayMap::new(buffer.read(cx).snapshot(cx)); let (mut inlay_map, inlay_snapshot) = InlayMap::new(buffer.read(cx).snapshot(cx));
assert_eq!(inlay_snapshot.text(), "abcdefghi"); 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::new(),
vec![( vec![InlayProperties {
InlayId(post_inc(&mut next_inlay_id)), position: buffer.read(cx).snapshot(cx).anchor_after(3),
InlayProperties { text: "|123|",
position: buffer.read(cx).snapshot(cx).anchor_after(3), }],
text: "|123|",
},
)],
); );
assert_eq!(inlay_snapshot.text(), "abc|123|defghi"); assert_eq!(inlay_snapshot.text(), "abc|123|defghi");
assert_eq!( assert_eq!(
@ -928,23 +925,17 @@ mod tests {
); );
assert_eq!(inlay_snapshot.text(), "abxyDzefghi"); assert_eq!(inlay_snapshot.text(), "abxyDzefghi");
let (inlay_snapshot, _) = inlay_map.splice( let (inlay_snapshot, _, _) = inlay_map.splice(
Vec::new(), Vec::new(),
vec![ vec![
( InlayProperties {
InlayId(post_inc(&mut next_inlay_id)), position: buffer.read(cx).snapshot(cx).anchor_before(3),
InlayProperties { text: "|123|",
position: buffer.read(cx).snapshot(cx).anchor_before(3), },
text: "|123|", InlayProperties {
}, position: buffer.read(cx).snapshot(cx).anchor_after(3),
), text: "|456|",
( },
InlayId(post_inc(&mut next_inlay_id)),
InlayProperties {
position: buffer.read(cx).snapshot(cx).anchor_after(3),
text: "|456|",
},
),
], ],
); );
assert_eq!(inlay_snapshot.text(), "abx|123||456|yDzefghi"); 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"); assert_eq!(inlay_snapshot.text(), "abx|123|JKL|456|yDzefghi");
// The inlays can be manually removed. // The inlays can be manually removed.
let (inlay_snapshot, _) = inlay_map let (inlay_snapshot, _, _) = inlay_map
.splice::<String>(inlay_map.inlays_by_id.keys().copied().collect(), Vec::new()); .splice::<String>(inlay_map.inlays_by_id.keys().copied().collect(), Vec::new());
assert_eq!(inlay_snapshot.text(), "abxJKLyDzefghi"); 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)); let (mut inlay_map, inlay_snapshot) = InlayMap::new(buffer.read(cx).snapshot(cx));
assert_eq!(inlay_snapshot.text(), "abc\ndef\nghi"); assert_eq!(inlay_snapshot.text(), "abc\ndef\nghi");
let (inlay_snapshot, _) = inlay_map.splice( let (inlay_snapshot, _, _) = inlay_map.splice(
Vec::new(), Vec::new(),
vec![ vec![
( InlayProperties {
InlayId(0), position: buffer.read(cx).snapshot(cx).anchor_before(0),
InlayProperties { text: "|123|\n",
position: buffer.read(cx).snapshot(cx).anchor_before(0), },
text: "|123|\n", InlayProperties {
}, position: buffer.read(cx).snapshot(cx).anchor_before(4),
), text: "|456|",
( },
InlayId(1), InlayProperties {
InlayProperties { position: buffer.read(cx).snapshot(cx).anchor_before(7),
position: buffer.read(cx).snapshot(cx).anchor_before(4), text: "\n|567|\n",
text: "|456|", },
},
),
(
InlayId(1),
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"); 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()); log::info!("buffer text: {:?}", buffer_snapshot.text());
let (mut inlay_map, mut inlay_snapshot) = InlayMap::new(buffer_snapshot.clone()); let (mut inlay_map, mut inlay_snapshot) = InlayMap::new(buffer_snapshot.clone());
let mut next_inlay_id = 0;
for _ in 0..operations { for _ in 0..operations {
let mut inlay_edits = Patch::default(); let mut inlay_edits = Patch::default();
@ -1032,7 +1012,7 @@ mod tests {
let mut buffer_edits = Vec::new(); let mut buffer_edits = Vec::new();
match rng.gen_range(0..=100) { match rng.gen_range(0..=100) {
0..=50 => { 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()); log::info!("mutated text: {:?}", snapshot.text());
inlay_edits = Patch::new(edits); inlay_edits = Patch::new(edits);
} }

View file

@ -708,7 +708,7 @@ mod tests {
fold_map.randomly_mutate(&mut rng); fold_map.randomly_mutate(&mut rng);
let (fold_snapshot, _) = fold_map.read(inlay_snapshot, vec![]); let (fold_snapshot, _) = fold_map.read(inlay_snapshot, vec![]);
log::info!("FoldMap text: {:?}", fold_snapshot.text()); 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()); log::info!("InlayMap text: {:?}", inlay_snapshot.text());
let (tab_map, _) = TabMap::new(fold_snapshot.clone(), tab_size); let (tab_map, _) = TabMap::new(fold_snapshot.clone(), tab_size);

View file

@ -1119,7 +1119,6 @@ mod tests {
); );
log::info!("Wrapped text: {:?}", actual_text); log::info!("Wrapped text: {:?}", actual_text);
let mut next_inlay_id = 0;
let mut edits = Vec::new(); let mut edits = Vec::new();
for _i in 0..operations { for _i in 0..operations {
log::info!("{} ==============================================", _i); log::info!("{} ==============================================", _i);
@ -1147,8 +1146,7 @@ mod tests {
} }
} }
40..=59 => { 40..=59 => {
let (inlay_snapshot, inlay_edits) = let (inlay_snapshot, inlay_edits) = inlay_map.randomly_mutate(&mut rng);
inlay_map.randomly_mutate(&mut next_inlay_id, &mut rng);
let (fold_snapshot, fold_edits) = fold_map.read(inlay_snapshot, inlay_edits); let (fold_snapshot, fold_edits) = fold_map.read(inlay_snapshot, inlay_edits);
let (tabs_snapshot, tab_edits) = let (tabs_snapshot, tab_edits) =
tab_map.sync(fold_snapshot, fold_edits, tab_size); tab_map.sync(fold_snapshot, fold_edits, tab_size);

View file

@ -2709,13 +2709,13 @@ impl Editor {
fn splice_inlay_hints( fn splice_inlay_hints(
&self, &self,
to_remove: Vec<InlayId>, to_remove: Vec<InlayId>,
to_insert: Vec<(InlayId, Anchor, project::InlayHint)>, to_insert: Vec<(Anchor, project::InlayHint)>,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) { ) {
let buffer = self.buffer.read(cx).read(cx); let buffer = self.buffer.read(cx).read(cx);
let new_inlays: Vec<(InlayId, InlayProperties<String>)> = to_insert let new_inlays = to_insert
.into_iter() .into_iter()
.map(|(inlay_id, hint_anchor, hint)| { .map(|(hint_anchor, hint)| {
let mut text = hint.text(); let mut text = hint.text();
// TODO kb styling instead? // TODO kb styling instead?
if hint.padding_right { if hint.padding_right {
@ -2725,13 +2725,10 @@ impl Editor {
text.insert(0, ' '); text.insert(0, ' ');
} }
( InlayProperties {
inlay_id, position: hint_anchor.bias_left(&buffer),
InlayProperties { text,
position: hint_anchor.bias_left(&buffer), }
text,
},
)
}) })
.collect(); .collect();
drop(buffer); drop(buffer);
@ -3485,15 +3482,10 @@ impl Editor {
to_remove.push(suggestion.id); to_remove.push(suggestion.id);
} }
let to_insert = vec![( let to_insert = vec![InlayProperties {
// TODO kb check how can I get the unique id for the suggestion position: cursor,
// Move the generation of the id inside the map text: text.clone(),
InlayId(usize::MAX), }];
InlayProperties {
position: cursor,
text: text.clone(),
},
)];
self.display_map.update(cx, move |map, cx| { self.display_map.update(cx, move |map, cx| {
map.splice_inlays(to_remove, to_insert, cx) map.splice_inlays(to_remove, to_insert, cx)
}); });
@ -7664,7 +7656,6 @@ fn inlay_hint_query(
cx: &mut ViewContext<'_, '_, Editor>, cx: &mut ViewContext<'_, '_, Editor>,
) -> Option<InlayHintQuery> { ) -> Option<InlayHintQuery> {
let buffer = buffer.read(cx); let buffer = buffer.read(cx);
let buffer_snapshot = buffer.snapshot();
let max_buffer_len = buffer.len(); let max_buffer_len = buffer.len();
let visible_offset_range_len = excerpt_visible_offset_range.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), .saturating_add(visible_offset_range_len),
); );
Some(InlayHintQuery { Some(InlayHintQuery {
buffer_path: buffer_snapshot.resolve_file_path(cx, true)?,
buffer_id: buffer.remote_id(), buffer_id: buffer.remote_id(),
buffer_version: buffer.version().clone(), buffer_version: buffer.version().clone(),
excerpt_id, excerpt_id,

View file

@ -1,19 +1,13 @@
use std::{ use std::ops::Range;
cmp,
ops::Range,
path::{Path, PathBuf},
};
use crate::{editor_settings, scroll::ScrollAnchor, Anchor, Editor, ExcerptId, MultiBuffer}; use crate::{editor_settings, scroll::ScrollAnchor, Anchor, Editor, ExcerptId, MultiBuffer};
use anyhow::Context; use clock::Global;
use clock::{Global, Local};
use gpui::{ModelHandle, Task, ViewContext}; use gpui::{ModelHandle, Task, ViewContext};
use log::error;
use project::{InlayHint, InlayHintKind}; 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)] #[derive(Debug, Clone)]
pub struct Inlay { pub struct Inlay {
pub id: InlayId, pub id: InlayId,
@ -36,48 +30,14 @@ pub enum InlayRefreshReason {
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct InlayCache { pub struct InlayCache {
inlays_per_buffer: HashMap<PathBuf, BufferInlays>, inlays_per_buffer: HashMap<u64, BufferInlays>,
allowed_hint_kinds: HashSet<Option<InlayHintKind>>, allowed_hint_kinds: HashSet<Option<InlayHintKind>>,
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<T>(pub BTreeMap<AnchorKey, (Anchor, T)>);
impl<T> OrderedByAnchorOffset<T> {
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<Item = (Anchor, T)> {
self.0.into_values()
}
fn ordered_elements(&self) -> impl Iterator<Item = &(Anchor, T)> {
self.0.values()
}
}
impl<T> Default for OrderedByAnchorOffset<T> {
fn default() -> Self {
Self(BTreeMap::default())
}
} }
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
struct BufferInlays { struct BufferInlays {
buffer_version: Global, buffer_version: Global,
inlays_per_excerpts: HashMap<ExcerptId, OrderedByAnchorOffset<(InlayId, InlayHint)>>, ordered_by_anchor_inlays: Vec<(Anchor, InlayId, InlayHint)>,
} }
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
@ -86,12 +46,11 @@ pub struct InlayId(pub usize);
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct InlaySplice { pub struct InlaySplice {
pub to_remove: Vec<InlayId>, pub to_remove: Vec<InlayId>,
pub to_insert: Vec<(InlayId, Anchor, InlayHint)>, pub to_insert: Vec<(Anchor, InlayHint)>,
} }
pub struct InlayHintQuery { pub struct InlayHintQuery {
pub buffer_id: u64, pub buffer_id: u64,
pub buffer_path: PathBuf,
pub buffer_version: Global, pub buffer_version: Global,
pub excerpt_id: ExcerptId, pub excerpt_id: ExcerptId,
pub excerpt_offset_query_range: Range<usize>, pub excerpt_offset_query_range: Range<usize>,
@ -100,12 +59,61 @@ pub struct InlayHintQuery {
impl InlayCache { impl InlayCache {
pub fn new(inlay_hint_settings: editor_settings::InlayHints) -> Self { pub fn new(inlay_hint_settings: editor_settings::InlayHints) -> Self {
Self { Self {
inlays_per_buffer: HashMap::default(),
allowed_hint_kinds: allowed_inlay_hint_types(inlay_hint_settings), allowed_hint_kinds: allowed_inlay_hint_types(inlay_hint_settings),
next_inlay_id: 0, inlays_per_buffer: HashMap::default(),
} }
} }
pub fn apply_settings(
&mut self,
inlay_hint_settings: editor_settings::InlayHints,
) -> InlaySplice {
let new_allowed_inlay_hint_types = allowed_inlay_hint_types(inlay_hint_settings);
let new_allowed_hint_kinds = new_allowed_inlay_hint_types
.difference(&self.allowed_hint_kinds)
.copied()
.collect::<HashSet<_>>();
let removed_hint_kinds = self
.allowed_hint_kinds
.difference(&new_allowed_inlay_hint_types)
.collect::<HashSet<_>>();
let mut to_remove = Vec::new();
let mut to_insert = Vec::new();
for (_, inlay_id, inlay_hint) in self
.inlays_per_buffer
.iter()
.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) {
todo!("TODO kb: agree with InlayMap how splice works")
// to_insert.push((*inlay_id, *anchor, inlay_hint.to_owned()));
}
}
self.allowed_hint_kinds = new_allowed_hint_kinds;
InlaySplice {
to_remove,
to_insert,
}
}
pub fn clear(&mut self) -> Vec<InlayId> {
self.inlays_per_buffer
.drain()
.flat_map(|(_, buffer_inlays)| {
buffer_inlays
.ordered_by_anchor_inlays
.into_iter()
.map(|(_, id, _)| id)
})
.collect()
}
pub fn append_inlays( pub fn append_inlays(
&mut self, &mut self,
multi_buffer: ModelHandle<MultiBuffer>, multi_buffer: ModelHandle<MultiBuffer>,
@ -131,339 +139,289 @@ impl InlayCache {
replace_old: bool, replace_old: bool,
cx: &mut ViewContext<Editor>, cx: &mut ViewContext<Editor>,
) -> Task<anyhow::Result<InlaySplice>> { ) -> Task<anyhow::Result<InlaySplice>> {
let mut inlay_fetch_tasks = Vec::new(); // TODO kb
for inlay_fetch_range in inlay_fetch_ranges { todo!("TODO kb")
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<ExcerptId, Option<(Range<usize>, OrderedByAnchorOffset<InlayHint>)>>,
),
> = 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( // fn fetch_inlays(
&self, // &mut self,
buffer_path: &Path, // multi_buffer: ModelHandle<MultiBuffer>,
buffer_version: &Global, // inlay_fetch_ranges: impl Iterator<Item = InlayHintQuery>,
excerpt_id: ExcerptId, // replace_old: bool,
) -> bool { // cx: &mut ViewContext<Editor>,
let Some(buffer_inlays) = self.inlays_per_buffer.get(buffer_path) else { return false }; // ) -> Task<anyhow::Result<InlaySplice>> {
let buffer_up_to_date = buffer_version == &buffer_inlays.buffer_version // let mut inlay_fetch_tasks = Vec::new();
|| buffer_inlays.buffer_version.changed_since(&buffer_version); // for inlay_fetch_range in inlay_fetch_ranges {
buffer_up_to_date && buffer_inlays.inlays_per_excerpts.contains_key(&excerpt_id) // 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")?;
fn apply_fetch_inlays( // Ok((inlay_fetch_range, match task {
&mut self, // Some(task) => task.await.context("inlays for buffer task")?,
fetched_inlays: HashMap< // None => Some(Vec::new()),
PathBuf, // }))
( // }
Global, // });
HashMap<ExcerptId, Option<(Range<usize>, OrderedByAnchorOffset<InlayHint>)>>, // inlay_fetch_tasks.push(task);
), // }
>,
) -> 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 { // let final_task = cx.spawn(|editor, mut cx| async move {
match old_inlays.remove(&buffer_path) { // let mut inlay_updates: HashMap<
Some(mut old_buffer_inlays) => { // PathBuf,
for (excerpt_id, new_excerpt_inlays) in new_buffer_inlays { // (
let (_, mut new_excerpt_inlays) = match new_excerpt_inlays { // Global,
Some((excerpt_offset_range, new_inlays)) => ( // HashMap<ExcerptId, Option<(Range<usize>, OrderedByAnchorOffset<InlayHint>)>>,
excerpt_offset_range, // ),
new_inlays.into_ordered_elements().fuse().peekable(), // > = HashMap::default();
), // let multi_buffer_snapshot =
None => continue, // editor.read_with(&cx, |editor, cx| editor.buffer().read(cx).snapshot(cx))?;
};
if self.inlays_up_to_date(&buffer_path, &buffer_version, excerpt_id) {
continue;
}
let self_inlays_per_buffer = self // for task_result in futures::future::join_all(inlay_fetch_tasks).await {
.inlays_per_buffer // match task_result {
.get_mut(&buffer_path) // Ok((inlay_fetch_range, response_inlays)) => {
.expect("element expected: `old_inlays.remove` returned `Some`"); // // 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:#}"),
// }
// }
if old_buffer_inlays // let updates = if !inlay_updates.is_empty() {
.inlays_per_excerpts // let inlays_update = editor.update(&mut cx, |editor, _| {
.remove(&excerpt_id) // editor.inlay_cache.apply_fetch_inlays(inlay_updates)
.is_some() // })?;
{ // inlays_update
let self_excerpt_inlays = self_inlays_per_buffer // } else {
.inlays_per_excerpts // InlaySplice::default()
.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 // anyhow::Ok(updates)
.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 { // final_task
to_remove.push(*old_inlay_id); // }
}
retain
},
);
for (new_anchor, (id, new_inlay)) in hints_to_add { // fn inlays_up_to_date(
self_excerpt_inlays.add(new_anchor, (id, new_inlay.clone())); // &self,
to_insert.push((id, new_anchor, new_inlay)); // 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)
// }
for (new_anchor, new_inlay) in new_excerpt_inlays { // fn apply_fetch_inlays(
let id = InlayId(post_inc(&mut self.next_inlay_id)); // &mut self,
self_inlays_per_buffer // fetched_inlays: HashMap<
.inlays_per_excerpts // PathBuf,
.entry(excerpt_id) // (
.or_default() // Global,
.add(new_anchor, (id, new_inlay.clone())); // HashMap<ExcerptId, Option<(Range<usize>, OrderedByAnchorOffset<InlayHint>)>>,
to_insert.push((id, new_anchor, new_inlay)); // ),
} // >,
} // ) -> InlaySplice {
} // let mut old_inlays = self.inlays_per_buffer.clone();
None => { // let mut to_remove = Vec::new();
let mut inlays_per_excerpts: HashMap< // let mut to_insert = Vec::new();
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 (buffer_path, (buffer_version, new_buffer_inlays)) in fetched_inlays {
for (_, old_excerpt_inlays) in old_buffer_inlays.inlays_per_excerpts { // match old_inlays.remove(&buffer_path) {
for (_, (id_to_remove, _)) in old_excerpt_inlays.into_ordered_elements() { // Some(mut old_buffer_inlays) => {
to_remove.push(id_to_remove); // 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;
// }
to_insert.retain(|(_, _, new_hint)| self.allowed_hint_kinds.contains(&new_hint.kind)); // let self_inlays_per_buffer = self
// .inlays_per_buffer
// .get_mut(&buffer_path)
// .expect("element expected: `old_inlays.remove` returned `Some`");
InlaySplice { // if old_buffer_inlays
to_remove, // .inlays_per_excerpts
to_insert, // .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;
pub fn apply_settings( // while let Some(new_offset) = new_excerpt_inlays
&mut self, // .peek()
inlay_hint_settings: editor_settings::InlayHints, // .map(|(new_anchor, _)| new_anchor.text_anchor.offset)
) -> InlaySplice { // {
let new_allowed_inlay_hint_types = allowed_inlay_hint_types(inlay_hint_settings); // 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,
// }
// }
let new_allowed_hint_kinds = new_allowed_inlay_hint_types // if !retain {
.difference(&self.allowed_hint_kinds) // to_remove.push(*old_inlay_id);
.copied() // }
.collect::<HashSet<_>>(); // retain
let removed_hint_kinds = self // },
.allowed_hint_kinds // );
.difference(&new_allowed_inlay_hint_types)
.collect::<HashSet<_>>();
let mut to_remove = Vec::new();
let mut to_insert = Vec::new();
for (anchor, (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()
})
.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()));
}
}
self.allowed_hint_kinds = new_allowed_hint_kinds; // 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));
// }
// }
InlaySplice { // for (new_anchor, new_inlay) in new_excerpt_inlays {
to_remove, // let id = InlayId(post_inc(&mut self.next_inlay_id));
to_insert, // 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,
// },
// );
// }
// }
// }
pub fn clear(&mut self) -> Vec<InlayId> { // for (_, old_buffer_inlays) in old_inlays {
self.inlays_per_buffer // for (_, old_excerpt_inlays) in old_buffer_inlays.inlays_per_excerpts {
.drain() // for (_, (id_to_remove, _)) in old_excerpt_inlays.into_ordered_elements() {
.map(|(_, buffer_inlays)| { // to_remove.push(id_to_remove);
buffer_inlays // }
.inlays_per_excerpts // }
.into_iter() // }
.map(|(_, excerpt_inlays)| {
excerpt_inlays // to_insert.retain(|(_, _, new_hint)| self.allowed_hint_kinds.contains(&new_hint.kind));
.into_ordered_elements()
.map(|(_, (id, _))| id) // InlaySplice {
}) // to_remove,
.flatten() // to_insert,
}) // }
.flatten() // }
.collect()
}
} }
fn allowed_inlay_hint_types( fn allowed_inlay_hint_types(