Deduplicate inlay hints queries with buffer versions

This commit is contained in:
Kirill Bulatov 2023-06-23 01:27:58 +03:00
parent f25a09bfd8
commit ba3d1e4dba
3 changed files with 43 additions and 10 deletions

View file

@ -255,7 +255,6 @@ impl DisplayMap {
if to_remove.is_empty() && to_insert.is_empty() {
return;
}
let buffer_snapshot = self.buffer.read(cx).snapshot(cx);
let edits = self.buffer_subscription.consume().into_inner();
let (snapshot, edits) = self.inlay_map.sync(buffer_snapshot, edits);

View file

@ -54,7 +54,7 @@ use gpui::{
};
use highlight_matching_bracket::refresh_matching_bracket_highlights;
use hover_popover::{hide_hover, HoverState};
use inlay_hint_cache::{visible_inlay_hints, InlayHintCache, InlaySplice};
use inlay_hint_cache::{visible_inlay_hints, InlayHintCache, InlaySplice, InvalidationStrategy};
pub use items::MAX_TAB_TITLE_LEN;
use itertools::Itertools;
pub use language::{char_kind, CharKind};
@ -1198,6 +1198,7 @@ enum InlayRefreshReason {
SettingsChange(editor_settings::InlayHints),
NewLinesShown,
ExcerptEdited,
RefreshRequested,
}
impl Editor {
@ -1311,7 +1312,7 @@ impl Editor {
}
project_subscriptions.push(cx.subscribe(project, |editor, _, event, cx| {
if let project::Event::RefreshInlays = event {
editor.refresh_inlays(InlayRefreshReason::ExcerptEdited, cx);
editor.refresh_inlays(InlayRefreshReason::RefreshRequested, cx);
};
}));
}
@ -2629,8 +2630,9 @@ impl Editor {
}
return;
}
InlayRefreshReason::NewLinesShown => false,
InlayRefreshReason::ExcerptEdited => true,
InlayRefreshReason::NewLinesShown => InvalidationStrategy::None,
InlayRefreshReason::ExcerptEdited => InvalidationStrategy::OnConflict,
InlayRefreshReason::RefreshRequested => InvalidationStrategy::All,
};
let excerpts_to_query = self

View file

@ -5,6 +5,7 @@ use crate::{
MultiBufferSnapshot,
};
use anyhow::Context;
use clock::Global;
use gpui::{ModelHandle, Task, ViewContext};
use language::{Buffer, BufferSnapshot};
use log::error;
@ -31,6 +32,7 @@ struct CacheSnapshot {
struct CachedExcerptHints {
version: usize,
buffer_version: Global,
hints: Vec<(InlayId, InlayHint)>,
}
@ -41,7 +43,14 @@ struct ExcerptQuery {
excerpt_range_start: language::Anchor,
excerpt_range_end: language::Anchor,
cache_version: usize,
invalidate_cache: bool,
invalidate: InvalidationStrategy,
}
#[derive(Debug, Clone, Copy)]
pub enum InvalidationStrategy {
All,
OnConflict,
None,
}
#[derive(Debug, Default)]
@ -116,10 +125,14 @@ impl InlayHintCache {
pub fn spawn_hints_update(
&mut self,
mut excerpts_to_query: HashMap<ExcerptId, ModelHandle<Buffer>>,
invalidate_cache: bool,
invalidate: InvalidationStrategy,
cx: &mut ViewContext<Editor>,
) {
let update_tasks = &mut self.update_tasks;
let invalidate_cache = matches!(
invalidate,
InvalidationStrategy::All | InvalidationStrategy::OnConflict
);
if invalidate_cache {
update_tasks
.retain(|task_excerpt_id, _| excerpts_to_query.contains_key(task_excerpt_id));
@ -179,7 +192,7 @@ impl InlayHintCache {
excerpt_range_start: excerpt_range.start,
excerpt_range_end: excerpt_range.end,
cache_version,
invalidate_cache,
invalidate,
};
let cached_excxerpt_hints = editor
.inlay_hint_cache
@ -187,6 +200,20 @@ impl InlayHintCache {
.hints
.get(&excerpt_id)
.cloned();
if let Some(cached_excerpt_hints) = &cached_excxerpt_hints {
let new_task_buffer_version = buffer_snapshot.version();
let cached_buffer_version = &cached_excerpt_hints.buffer_version;
if cached_buffer_version.changed_since(new_task_buffer_version) {
return;
}
if !new_task_buffer_version.changed_since(&cached_buffer_version)
&& !matches!(invalidate, InvalidationStrategy::All)
{
return;
}
}
editor.inlay_hint_cache.update_tasks.insert(
excerpt_id,
new_update_task(
@ -252,6 +279,7 @@ fn new_update_task(
.or_insert_with(|| {
Arc::new(CachedExcerptHints {
version: new_update.cache_version,
buffer_version: buffer_snapshot.version().clone(),
hints: Vec::new(),
})
});
@ -267,7 +295,8 @@ fn new_update_task(
cached_excerpt_hints.hints.retain(|(hint_id, _)| {
!new_update.remove_from_cache.contains(hint_id)
});
cached_excerpt_hints.buffer_version =
buffer_snapshot.version().clone();
editor.inlay_hint_cache.snapshot.version += 1;
let mut splice = InlaySplice {
@ -457,7 +486,10 @@ fn new_excerpt_hints_update_result(
let mut remove_from_visible = Vec::new();
let mut remove_from_cache = HashSet::default();
if query.invalidate_cache {
if matches!(
query.invalidate,
InvalidationStrategy::All | InvalidationStrategy::OnConflict
) {
remove_from_visible.extend(
visible_hints
.iter()