From 2c7900e11b2c3ec816f4113b7e9e95790bc3e3f5 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sat, 24 Jun 2023 01:52:48 +0300 Subject: [PATCH] Use excerpt visible range in query filtering --- crates/collab/src/tests/integration_tests.rs | 10 +- crates/editor/src/editor.rs | 6 +- crates/editor/src/inlay_hint_cache.rs | 145 ++++++++++++------- 3 files changed, 107 insertions(+), 54 deletions(-) diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs index 35b6f2c100..d6f9846ab5 100644 --- a/crates/collab/src/tests/integration_tests.rs +++ b/crates/collab/src/tests/integration_tests.rs @@ -7888,7 +7888,10 @@ async fn test_mutual_editor_inlay_hint_cache_update( let editor_a = cx_a.add_view(window_a, |cx| { Editor::for_buffer(buffer_a, Some(project_a.clone()), cx) }); - editor_a.update(cx_a, |_, cx| cx.focus(&editor_a)); + editor_a.update(cx_a, |editor, cx| { + editor.set_scroll_position(vec2f(0., 1.), cx); + cx.focus(&editor_a) + }); cx_a.foreground().run_until_parked(); editor_a.update(cx_a, |editor, _| { assert!( @@ -7915,7 +7918,10 @@ async fn test_mutual_editor_inlay_hint_cache_update( let editor_b = cx_b.add_view(window_b, |cx| { Editor::for_buffer(buffer_b, Some(project_b.clone()), cx) }); - editor_b.update(cx_b, |_, cx| cx.focus(&editor_b)); + editor_b.update(cx_b, |editor, cx| { + editor.set_scroll_position(vec2f(0., 1.), cx); + cx.focus(&editor_b) + }); cx_b.foreground().run_until_parked(); editor_b.update(cx_b, |editor, _| { assert!( diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 753adc16d6..dea3655953 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -2638,7 +2638,10 @@ impl Editor { let excerpts_to_query = self .excerpt_visible_offsets(cx) .into_iter() - .map(|(buffer, _, excerpt_id)| (excerpt_id, buffer)) + .filter(|(_, excerpt_visible_range, _)| !excerpt_visible_range.is_empty()) + .map(|(buffer, excerpt_visible_range, excerpt_id)| { + (excerpt_id, (buffer, excerpt_visible_range)) + }) .collect::>(); self.inlay_hint_cache .spawn_hints_update(excerpts_to_query, invalidate_cache, cx) @@ -2661,7 +2664,6 @@ impl Editor { Bias::Left, ); let multi_buffer_visible_range = multi_buffer_visible_start..multi_buffer_visible_end; - multi_buffer.range_to_buffer_ranges(multi_buffer_visible_range, cx) } diff --git a/crates/editor/src/inlay_hint_cache.rs b/crates/editor/src/inlay_hint_cache.rs index aa10807b04..d75ecbe888 100644 --- a/crates/editor/src/inlay_hint_cache.rs +++ b/crates/editor/src/inlay_hint_cache.rs @@ -1,4 +1,4 @@ -use std::{cmp, sync::Arc}; +use std::{cmp, ops::Range, sync::Arc}; use crate::{ display_map::Inlay, editor_settings, Anchor, Editor, ExcerptId, InlayId, MultiBuffer, @@ -38,20 +38,43 @@ pub struct CachedExcerptHints { struct ExcerptQuery { buffer_id: u64, excerpt_id: ExcerptId, - excerpt_range_start: language::Anchor, - excerpt_range_end: language::Anchor, + dimensions: ExcerptDimensions, cache_version: usize, invalidate: InvalidationStrategy, } -impl ExcerptQuery { - fn contains_position(&self, position: text::Anchor, buffer_snapshot: &BufferSnapshot) -> bool { - self.excerpt_range_start - .cmp(&position, buffer_snapshot) - .is_le() - && self - .excerpt_range_end + +#[derive(Debug, Clone, Copy)] +struct ExcerptDimensions { + excerpt_range_start: language::Anchor, + excerpt_range_end: language::Anchor, + excerpt_visible_range_start: language::Anchor, + excerpt_visible_range_end: language::Anchor, +} + +impl ExcerptDimensions { + fn contains_position( + &self, + position: language::Anchor, + buffer_snapshot: &BufferSnapshot, + visible_only: bool, + ) -> bool { + if visible_only { + self.excerpt_visible_range_start .cmp(&position, buffer_snapshot) - .is_ge() + .is_le() + && self + .excerpt_visible_range_end + .cmp(&position, buffer_snapshot) + .is_ge() + } else { + self.excerpt_range_start + .cmp(&position, buffer_snapshot) + .is_le() + && self + .excerpt_range_end + .cmp(&position, buffer_snapshot) + .is_ge() + } } } @@ -127,7 +150,7 @@ impl InlayHintCache { pub fn spawn_hints_update( &mut self, - mut excerpts_to_query: HashMap>, + mut excerpts_to_query: HashMap, Range)>, invalidate: InvalidationStrategy, cx: &mut ViewContext, ) { @@ -172,34 +195,12 @@ impl InlayHintCache { .update(&mut cx, |editor, cx| { let visible_hints = Arc::new(visible_inlay_hints(editor, cx).cloned().collect::>()); - for (excerpt_id, buffer_handle) in excerpts_to_query { - let (multi_buffer_snapshot, excerpt_range) = - editor.buffer.update(cx, |multi_buffer, cx| { - let multi_buffer_snapshot = multi_buffer.snapshot(cx); - ( - multi_buffer_snapshot, - multi_buffer - .excerpts_for_buffer(&buffer_handle, cx) - .into_iter() - .find(|(id, _)| id == &excerpt_id) - .map(|(_, range)| range.context), - ) - }); - - if let Some(excerpt_range) = excerpt_range { + for (excerpt_id, (buffer_handle, excerpt_visible_range)) in excerpts_to_query { + if !excerpt_visible_range.is_empty() { let buffer = buffer_handle.read(cx); let buffer_snapshot = buffer.snapshot(); - let query = ExcerptQuery { - buffer_id: buffer.remote_id(), - excerpt_id, - excerpt_range_start: excerpt_range.start, - excerpt_range_end: excerpt_range.end, - cache_version, - invalidate, - }; let cached_excxerpt_hints = editor.inlay_hint_cache.hints.get(&excerpt_id).cloned(); - if let Some(cached_excerpt_hints) = &cached_excxerpt_hints { let new_task_buffer_version = buffer_snapshot.version(); let cached_excerpt_hints = cached_excerpt_hints.read(); @@ -214,17 +215,50 @@ impl InlayHintCache { } } - editor.inlay_hint_cache.update_tasks.insert( - excerpt_id, - new_update_task( - query, - multi_buffer_snapshot, - buffer_snapshot, - Arc::clone(&visible_hints), - cached_excxerpt_hints, - cx, - ), - ); + let buffer_id = buffer.remote_id(); + let excerpt_range_start = + buffer.anchor_before(excerpt_visible_range.start); + let excerpt_range_end = buffer.anchor_after(excerpt_visible_range.end); + + let (multi_buffer_snapshot, full_excerpt_range) = + editor.buffer.update(cx, |multi_buffer, cx| { + let multi_buffer_snapshot = multi_buffer.snapshot(cx); + ( + multi_buffer_snapshot, + multi_buffer + .excerpts_for_buffer(&buffer_handle, cx) + .into_iter() + .find(|(id, _)| id == &excerpt_id) + .map(|(_, range)| range.context), + ) + }); + + if let Some(full_excerpt_range) = full_excerpt_range { + let query = ExcerptQuery { + buffer_id, + excerpt_id, + dimensions: ExcerptDimensions { + excerpt_range_start, + excerpt_range_end, + excerpt_visible_range_start: full_excerpt_range.start, + excerpt_visible_range_end: full_excerpt_range.end, + }, + cache_version, + invalidate, + }; + + editor.inlay_hint_cache.update_tasks.insert( + excerpt_id, + new_update_task( + query, + multi_buffer_snapshot, + buffer_snapshot, + Arc::clone(&visible_hints), + cached_excxerpt_hints, + cx, + ), + ); + } } } }) @@ -461,7 +495,10 @@ fn new_excerpt_hints_update_result( let mut excerpt_hints_to_persist = HashMap::default(); for new_hint in new_excerpt_hints { - if !query.contains_position(new_hint.position, buffer_snapshot) { + if !query + .dimensions + .contains_position(new_hint.position, buffer_snapshot, false) + { continue; } let missing_from_cache = match &cached_excerpt_hints { @@ -499,7 +536,13 @@ fn new_excerpt_hints_update_result( visible_hints .iter() .filter(|hint| hint.position.excerpt_id == query.excerpt_id) - .filter(|hint| query.contains_position(hint.position.text_anchor, buffer_snapshot)) + .filter(|hint| { + query.dimensions.contains_position( + hint.position.text_anchor, + buffer_snapshot, + false, + ) + }) .map(|inlay_hint| inlay_hint.id) .filter(|hint_id| !excerpt_hints_to_persist.contains_key(hint_id)), ); @@ -563,7 +606,9 @@ fn hints_fetch_task( Some(project.update(cx, |project, cx| { project.inlay_hints( buffer, - query.excerpt_range_start..query.excerpt_range_end, + // TODO kb split into 3 queries + query.dimensions.excerpt_range_start + ..query.dimensions.excerpt_range_end, cx, ) }))