diff --git a/crates/editor/src/display_map.rs b/crates/editor/src/display_map.rs index 16d44fbacf..b117120e81 100644 --- a/crates/editor/src/display_map.rs +++ b/crates/editor/src/display_map.rs @@ -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); diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 9b944cb7b8..288ee516d1 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -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 diff --git a/crates/editor/src/inlay_hint_cache.rs b/crates/editor/src/inlay_hint_cache.rs index b3efbe9e87..019b6e5429 100644 --- a/crates/editor/src/inlay_hint_cache.rs +++ b/crates/editor/src/inlay_hint_cache.rs @@ -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>, - invalidate_cache: bool, + invalidate: InvalidationStrategy, cx: &mut ViewContext, ) { 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()