@@ -2596,81 +2596,106 @@ impl Editor {
return;
}
+ struct HintRequestKey {
+ buffer_id: u64,
+ buffer_version: Global,
+ excerpt_id: ExcerptId,
+ }
+
let multi_buffer = self.buffer();
let multi_buffer_snapshot = multi_buffer.read(cx).snapshot(cx);
let hint_fetch_tasks = multi_buffer_snapshot
.excerpts()
- .filter_map(|(excerpt_id, buffer_snapshot, excerpt_range)| {
+ .map(|(excerpt_id, buffer_snapshot, excerpt_range)| {
// TODO kb every time I reopen the same buffer, it's different.
// Find a way to understand it's the same buffer. Use paths?
let buffer_id = buffer_snapshot.remote_id();
let buffer_version = buffer_snapshot.version().clone();
- let buffer_handle = multi_buffer.read(cx).buffer(buffer_id)?;
- if self
- .inlay_hint_cache
- .inlays_up_to_date(buffer_id, &buffer_version, excerpt_id)
- {
- return None;
- }
+ let buffer_handle = multi_buffer.read(cx).buffer(buffer_id);
+ let hints_up_to_date =
+ self.inlay_hint_cache
+ .inlays_up_to_date(buffer_id, &buffer_version, excerpt_id);
+ let key = HintRequestKey {
+ buffer_id,
+ buffer_version,
+ excerpt_id,
+ };
- let task = cx.spawn(|editor, mut cx| async move {
- let task = editor
- .update(&mut cx, |editor, cx| {
- editor.project.as_ref().map(|project| {
- project.update(cx, |project, cx| {
- project.inlay_hints_for_buffer(
- buffer_handle,
- excerpt_range.context,
- cx,
- )
+ cx.spawn(|editor, mut cx| async move {
+ if hints_up_to_date {
+ anyhow::Ok((key, None))
+ } else {
+ let Some(buffer_handle) = buffer_handle else { return Ok((key, Some(Vec::new()))) };
+ let max_buffer_offset = cx.read(|cx| buffer_handle.read(cx).len());
+ let excerpt_range = excerpt_range.context;
+ let query_start = excerpt_range.start.offset;
+ let query_end = excerpt_range.end.offset.min(max_buffer_offset);
+ let task = editor
+ .update(&mut cx, |editor, cx| {
+ editor.project.as_ref().map(|project| {
+ project.update(cx, |project, cx| {
+ project.inlay_hints_for_buffer(
+ buffer_handle,
+ query_start..query_end,
+ cx,
+ )
+ })
})
})
- })
- .context("inlay hints fecth task spawn")?;
-
- anyhow::Ok((
- buffer_id,
- buffer_version,
- excerpt_id,
- match task {
- Some(task) => task.await.context("inlay hints for buffer task")?,
+ .context("inlay hints fecth task spawn")?;
+
+ Ok((key, Some(match task {
+ Some(task) => {
+ let mut new_hints = task.await.context("inlay hints for buffer task")?;
+ new_hints.retain(|hint| {
+ let hint_offset = hint.position.offset;
+ query_start <= hint_offset && hint_offset <= query_end
+ });
+ new_hints
+ },
None => Vec::new(),
- },
- ))
- });
- Some(task)
+ })))
+ }
+ })
})
.collect::<Vec<_>>();
cx.spawn(|editor, mut cx| async move {
- let mut hints_response: HashMap<
+ let mut inlay_updates: HashMap<
u64,
- (Global, HashMap<ExcerptId, OrderedByAnchorOffset<InlayHint>>),
+ (
+ Global,
+ HashMap<ExcerptId, Option<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(hint_fetch_tasks).await {
match task_result {
- Ok((buffer_id, buffer_version, excerpt_id, excerpt_hints)) => {
+ Ok((request_key, response_inlays)) => {
let excerpt_hints_response = HashMap::from_iter([(
- excerpt_id,
- excerpt_hints.into_iter().fold(
- OrderedByAnchorOffset::default(),
- |mut ordered_hints, hint| {
- let anchor = multi_buffer_snapshot
- .anchor_in_excerpt(excerpt_id, hint.position);
- ordered_hints.add(anchor, hint);
- ordered_hints
- },
- ),
+ request_key.excerpt_id,
+ response_inlays.map(|excerpt_hints| {
+ excerpt_hints.into_iter().fold(
+ OrderedByAnchorOffset::default(),
+ |mut ordered_hints, hint| {
+ let anchor = multi_buffer_snapshot.anchor_in_excerpt(
+ request_key.excerpt_id,
+ hint.position,
+ );
+ ordered_hints.add(anchor, hint);
+ ordered_hints
+ },
+ )
+ }),
)]);
- match hints_response.entry(buffer_id) {
+ match inlay_updates.entry(request_key.buffer_id) {
hash_map::Entry::Occupied(mut o) => {
o.get_mut().1.extend(excerpt_hints_response);
}
hash_map::Entry::Vacant(v) => {
- v.insert((buffer_version, excerpt_hints_response));
+ v.insert((request_key.buffer_version, excerpt_hints_response));
}
}
}
@@ -2678,12 +2703,12 @@ impl Editor {
}
}
- if !hints_response.is_empty() {
+ if !inlay_updates.is_empty() {
let InlaysUpdate {
to_remove,
to_insert,
} = editor.update(&mut cx, |editor, _| {
- editor.inlay_hint_cache.update_inlays(hints_response)
+ editor.inlay_hint_cache.update_inlays(inlay_updates)
})?;
editor.update(&mut cx, |editor, cx| {
@@ -7244,7 +7269,7 @@ impl Editor {
}
multi_buffer::Event::Reparsed => {
cx.emit(Event::Reparsed);
- true
+ false
}
multi_buffer::Event::DirtyChanged => {
cx.emit(Event::DirtyChanged);
@@ -1,7 +1,7 @@
use std::cmp;
use crate::{Anchor, ExcerptId};
-use clock::Global;
+use clock::{Global, Local};
use project::InlayHint;
use util::post_inc;
@@ -13,12 +13,22 @@ pub struct InlayCache {
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<usize, (Anchor, T)>);
+pub struct OrderedByAnchorOffset<T>(pub BTreeMap<AnchorKey, (Anchor, T)>);
impl<T> OrderedByAnchorOffset<T> {
pub fn add(&mut self, anchor: Anchor, t: T) {
- self.0.insert(anchor.text_anchor.offset, (anchor, 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)> {
@@ -62,13 +72,19 @@ impl InlayCache {
pub fn update_inlays(
&mut self,
- new_inlays: HashMap<u64, (Global, HashMap<ExcerptId, OrderedByAnchorOffset<InlayHint>>)>,
+ inlay_updates: HashMap<
+ u64,
+ (
+ Global,
+ HashMap<ExcerptId, Option<OrderedByAnchorOffset<InlayHint>>>,
+ ),
+ >,
) -> InlaysUpdate {
let mut old_inlays = self.inlays_per_buffer.clone();
let mut to_remove = Vec::new();
let mut to_insert = Vec::new();
- for (buffer_id, (buffer_version, new_buffer_inlays)) in new_inlays {
+ for (buffer_id, (buffer_version, new_buffer_inlays)) in inlay_updates {
match old_inlays.remove(&buffer_id) {
Some(mut old_buffer_inlays) => {
for (excerpt_id, new_excerpt_inlays) in new_buffer_inlays {
@@ -80,8 +96,12 @@ impl InlayCache {
.inlays_per_buffer
.get_mut(&buffer_id)
.expect("element expected: `old_inlays.remove` returned `Some`");
- let mut new_excerpt_inlays =
- new_excerpt_inlays.into_ordered_elements().fuse().peekable();
+ let mut new_excerpt_inlays = match new_excerpt_inlays {
+ Some(new_inlays) => {
+ new_inlays.into_ordered_elements().fuse().peekable()
+ }
+ None => continue,
+ };
if old_buffer_inlays
.inlays_per_excerpts
.remove(&excerpt_id)
@@ -168,13 +188,17 @@ impl InlayCache {
OrderedByAnchorOffset<(InlayId, InlayHint)>,
> = HashMap::default();
for (new_excerpt_id, new_ordered_inlays) in new_buffer_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));
+ 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(