Do not add duplicate hints to the cache
This commit is contained in:
parent
0e2a1fc149
commit
56f89739f8
2 changed files with 53 additions and 54 deletions
|
@ -193,29 +193,21 @@ impl InlayHintCache {
|
||||||
|
|
||||||
let mut invalidated_hints = Vec::new();
|
let mut invalidated_hints = Vec::new();
|
||||||
if invalidate.should_invalidate() {
|
if invalidate.should_invalidate() {
|
||||||
let mut changed = false;
|
self.update_tasks
|
||||||
self.update_tasks.retain(|task_excerpt_id, _| {
|
.retain(|task_excerpt_id, _| excerpts_to_query.contains_key(task_excerpt_id));
|
||||||
let retain = excerpts_to_query.contains_key(task_excerpt_id);
|
|
||||||
changed |= !retain;
|
|
||||||
retain
|
|
||||||
});
|
|
||||||
self.hints.retain(|cached_excerpt, cached_hints| {
|
self.hints.retain(|cached_excerpt, cached_hints| {
|
||||||
let retain = excerpts_to_query.contains_key(cached_excerpt);
|
let retain = excerpts_to_query.contains_key(cached_excerpt);
|
||||||
changed |= !retain;
|
|
||||||
if !retain {
|
if !retain {
|
||||||
invalidated_hints.extend(cached_hints.read().hints.iter().map(|&(id, _)| id));
|
invalidated_hints.extend(cached_hints.read().hints.iter().map(|&(id, _)| id));
|
||||||
}
|
}
|
||||||
retain
|
retain
|
||||||
});
|
});
|
||||||
if changed {
|
|
||||||
self.version += 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if excerpts_to_query.is_empty() && invalidated_hints.is_empty() {
|
if excerpts_to_query.is_empty() && invalidated_hints.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let cache_version = self.version;
|
let cache_version = self.version + 1;
|
||||||
cx.spawn(|editor, mut cx| async move {
|
cx.spawn(|editor, mut cx| async move {
|
||||||
editor
|
editor
|
||||||
.update(&mut cx, |editor, cx| {
|
.update(&mut cx, |editor, cx| {
|
||||||
|
@ -475,7 +467,7 @@ fn determine_query_range(
|
||||||
|
|
||||||
fn new_update_task(
|
fn new_update_task(
|
||||||
query: ExcerptQuery,
|
query: ExcerptQuery,
|
||||||
hints_fetch_ranges: Vec<Range<language::Anchor>>,
|
hint_fetch_ranges: Vec<Range<language::Anchor>>,
|
||||||
multi_buffer_snapshot: MultiBufferSnapshot,
|
multi_buffer_snapshot: MultiBufferSnapshot,
|
||||||
buffer_snapshot: BufferSnapshot,
|
buffer_snapshot: BufferSnapshot,
|
||||||
visible_hints: Arc<Vec<Inlay>>,
|
visible_hints: Arc<Vec<Inlay>>,
|
||||||
|
@ -484,7 +476,7 @@ fn new_update_task(
|
||||||
) -> Task<()> {
|
) -> Task<()> {
|
||||||
cx.spawn(|editor, cx| async move {
|
cx.spawn(|editor, cx| async move {
|
||||||
let task_update_results =
|
let task_update_results =
|
||||||
futures::future::join_all(hints_fetch_ranges.into_iter().map(|range| {
|
futures::future::join_all(hint_fetch_ranges.into_iter().map(|range| {
|
||||||
fetch_and_update_hints(
|
fetch_and_update_hints(
|
||||||
editor.clone(),
|
editor.clone(),
|
||||||
multi_buffer_snapshot.clone(),
|
multi_buffer_snapshot.clone(),
|
||||||
|
@ -515,7 +507,7 @@ async fn fetch_and_update_hints(
|
||||||
query: ExcerptQuery,
|
query: ExcerptQuery,
|
||||||
fetch_range: Range<language::Anchor>,
|
fetch_range: Range<language::Anchor>,
|
||||||
mut cx: gpui::AsyncAppContext,
|
mut cx: gpui::AsyncAppContext,
|
||||||
) -> anyhow::Result<bool> {
|
) -> anyhow::Result<()> {
|
||||||
let inlay_hints_fetch_task = editor
|
let inlay_hints_fetch_task = editor
|
||||||
.update(&mut cx, |editor, cx| {
|
.update(&mut cx, |editor, cx| {
|
||||||
editor
|
editor
|
||||||
|
@ -531,8 +523,7 @@ async fn fetch_and_update_hints(
|
||||||
})
|
})
|
||||||
.ok()
|
.ok()
|
||||||
.flatten();
|
.flatten();
|
||||||
let mut update_happened = false;
|
let Some(inlay_hints_fetch_task) = inlay_hints_fetch_task else { return Ok(()) };
|
||||||
let Some(inlay_hints_fetch_task) = inlay_hints_fetch_task else { return Ok(update_happened) };
|
|
||||||
let new_hints = inlay_hints_fetch_task
|
let new_hints = inlay_hints_fetch_task
|
||||||
.await
|
.await
|
||||||
.context("inlay hint fetch task")?;
|
.context("inlay hint fetch task")?;
|
||||||
|
@ -555,10 +546,6 @@ async fn fetch_and_update_hints(
|
||||||
editor
|
editor
|
||||||
.update(&mut cx, |editor, cx| {
|
.update(&mut cx, |editor, cx| {
|
||||||
if let Some(new_update) = new_update {
|
if let Some(new_update) = new_update {
|
||||||
update_happened = !new_update.add_to_cache.is_empty()
|
|
||||||
|| !new_update.remove_from_cache.is_empty()
|
|
||||||
|| !new_update.remove_from_visible.is_empty();
|
|
||||||
|
|
||||||
let cached_excerpt_hints = editor
|
let cached_excerpt_hints = editor
|
||||||
.inlay_hint_cache
|
.inlay_hint_cache
|
||||||
.hints
|
.hints
|
||||||
|
@ -578,43 +565,51 @@ async fn fetch_and_update_hints(
|
||||||
cached_excerpt_hints.version = query.cache_version;
|
cached_excerpt_hints.version = query.cache_version;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut cached_inlays_changed = !new_update.remove_from_cache.is_empty();
|
||||||
cached_excerpt_hints
|
cached_excerpt_hints
|
||||||
.hints
|
.hints
|
||||||
.retain(|(hint_id, _)| !new_update.remove_from_cache.contains(hint_id));
|
.retain(|(hint_id, _)| !new_update.remove_from_cache.contains(hint_id));
|
||||||
cached_excerpt_hints.buffer_version = buffer_snapshot.version().clone();
|
|
||||||
editor.inlay_hint_cache.version += 1;
|
|
||||||
|
|
||||||
let mut splice = InlaySplice {
|
let mut splice = InlaySplice {
|
||||||
to_remove: new_update.remove_from_visible,
|
to_remove: new_update.remove_from_visible,
|
||||||
to_insert: Vec::new(),
|
to_insert: Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
for new_hint in new_update.add_to_cache {
|
for new_hint in new_update.add_to_cache {
|
||||||
let new_hint_position = multi_buffer_snapshot
|
let cached_hints = &mut cached_excerpt_hints.hints;
|
||||||
.anchor_in_excerpt(query.excerpt_id, new_hint.position);
|
let insert_position = match cached_hints.binary_search_by(|probe| {
|
||||||
let new_inlay_id = post_inc(&mut editor.next_inlay_id);
|
probe.1.position.cmp(&new_hint.position, &buffer_snapshot)
|
||||||
if editor
|
}) {
|
||||||
.inlay_hint_cache
|
Ok(i) => {
|
||||||
.allowed_hint_kinds
|
if cached_hints[i].1.text() == new_hint.text() {
|
||||||
.contains(&new_hint.kind)
|
None
|
||||||
{
|
} else {
|
||||||
splice.to_insert.push(Inlay::hint(
|
Some(i)
|
||||||
new_inlay_id,
|
}
|
||||||
new_hint_position,
|
}
|
||||||
&new_hint,
|
Err(i) => Some(i),
|
||||||
));
|
};
|
||||||
|
|
||||||
|
if let Some(insert_position) = insert_position {
|
||||||
|
let new_inlay_id = post_inc(&mut editor.next_inlay_id);
|
||||||
|
if editor
|
||||||
|
.inlay_hint_cache
|
||||||
|
.allowed_hint_kinds
|
||||||
|
.contains(&new_hint.kind)
|
||||||
|
{
|
||||||
|
let new_hint_position = multi_buffer_snapshot
|
||||||
|
.anchor_in_excerpt(query.excerpt_id, new_hint.position);
|
||||||
|
splice.to_insert.push(Inlay::hint(
|
||||||
|
new_inlay_id,
|
||||||
|
new_hint_position,
|
||||||
|
&new_hint,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
cached_hints
|
||||||
|
.insert(insert_position, (InlayId::Hint(new_inlay_id), new_hint));
|
||||||
|
cached_inlays_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
cached_excerpt_hints
|
|
||||||
.hints
|
|
||||||
.push((InlayId::Hint(new_inlay_id), new_hint));
|
|
||||||
}
|
}
|
||||||
|
cached_excerpt_hints.buffer_version = buffer_snapshot.version().clone();
|
||||||
cached_excerpt_hints
|
|
||||||
.hints
|
|
||||||
.sort_by(|(_, hint_a), (_, hint_b)| {
|
|
||||||
hint_a.position.cmp(&hint_b.position, &buffer_snapshot)
|
|
||||||
});
|
|
||||||
drop(cached_excerpt_hints);
|
drop(cached_excerpt_hints);
|
||||||
|
|
||||||
if query.invalidate.should_invalidate() {
|
if query.invalidate.should_invalidate() {
|
||||||
|
@ -633,6 +628,7 @@ async fn fetch_and_update_hints(
|
||||||
.extend(excerpt_hints.hints.iter().map(|(id, _)| id));
|
.extend(excerpt_hints.hints.iter().map(|(id, _)| id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
cached_inlays_changed |= !outdated_excerpt_caches.is_empty();
|
||||||
editor
|
editor
|
||||||
.inlay_hint_cache
|
.inlay_hint_cache
|
||||||
.hints
|
.hints
|
||||||
|
@ -643,14 +639,18 @@ async fn fetch_and_update_hints(
|
||||||
to_remove,
|
to_remove,
|
||||||
to_insert,
|
to_insert,
|
||||||
} = splice;
|
} = splice;
|
||||||
if !to_remove.is_empty() || !to_insert.is_empty() {
|
let displayed_inlays_changed = !to_remove.is_empty() || !to_insert.is_empty();
|
||||||
|
if cached_inlays_changed || displayed_inlays_changed {
|
||||||
|
editor.inlay_hint_cache.version += 1;
|
||||||
|
}
|
||||||
|
if displayed_inlays_changed {
|
||||||
editor.splice_inlay_hints(to_remove, to_insert, cx)
|
editor.splice_inlay_hints(to_remove, to_insert, cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
Ok(update_happened)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_hint_updates(
|
fn calculate_hint_updates(
|
||||||
|
@ -2093,7 +2093,7 @@ mod tests {
|
||||||
"main hint #1".to_string(),
|
"main hint #1".to_string(),
|
||||||
"main hint #2".to_string(),
|
"main hint #2".to_string(),
|
||||||
"main hint #3".to_string(),
|
"main hint #3".to_string(),
|
||||||
// TODO kb find the range needed
|
// TODO kb find the range needed. Is it due to the hint not fitting any excerpt subranges?
|
||||||
// "main hint #4".to_string(),
|
// "main hint #4".to_string(),
|
||||||
"main hint #5".to_string(),
|
"main hint #5".to_string(),
|
||||||
"other hint #0".to_string(),
|
"other hint #0".to_string(),
|
||||||
|
@ -2176,8 +2176,6 @@ mod tests {
|
||||||
"main hint(edited) #1".to_string(),
|
"main hint(edited) #1".to_string(),
|
||||||
"main hint(edited) #2".to_string(),
|
"main hint(edited) #2".to_string(),
|
||||||
"main hint(edited) #3".to_string(),
|
"main hint(edited) #3".to_string(),
|
||||||
// TODO kb why?
|
|
||||||
"main hint(edited) #3".to_string(),
|
|
||||||
"main hint(edited) #4".to_string(),
|
"main hint(edited) #4".to_string(),
|
||||||
"main hint(edited) #5".to_string(),
|
"main hint(edited) #5".to_string(),
|
||||||
"other hint(edited) #0".to_string(),
|
"other hint(edited) #0".to_string(),
|
||||||
|
@ -2192,8 +2190,8 @@ all hints should be invalidated and requeried for all of its visible excerpts"
|
||||||
assert_eq!(expected_layers, visible_hint_labels(editor, cx));
|
assert_eq!(expected_layers, visible_hint_labels(editor, cx));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
editor.inlay_hint_cache().version,
|
editor.inlay_hint_cache().version,
|
||||||
last_scroll_update_version + expected_layers.len() + 1,
|
last_scroll_update_version + expected_layers.len(),
|
||||||
"Due to every excerpt having one hint, cache should update per new excerpt received + 1 for outdated hints removal"
|
"Due to every excerpt having one hint, cache should update per new excerpt received"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -333,6 +333,7 @@ impl Editor {
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// TODO kb too many events + too many LSP requests even due to deduplication, why?
|
||||||
self.refresh_inlays(InlayRefreshReason::NewLinesShown, cx);
|
self.refresh_inlays(InlayRefreshReason::NewLinesShown, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue