Use excerpt visible range in query filtering

This commit is contained in:
Kirill Bulatov 2023-06-24 01:52:48 +03:00
parent 83b3a914bc
commit 2c7900e11b
3 changed files with 107 additions and 54 deletions

View file

@ -7888,7 +7888,10 @@ async fn test_mutual_editor_inlay_hint_cache_update(
let editor_a = cx_a.add_view(window_a, |cx| { let editor_a = cx_a.add_view(window_a, |cx| {
Editor::for_buffer(buffer_a, Some(project_a.clone()), 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(); cx_a.foreground().run_until_parked();
editor_a.update(cx_a, |editor, _| { editor_a.update(cx_a, |editor, _| {
assert!( assert!(
@ -7915,7 +7918,10 @@ async fn test_mutual_editor_inlay_hint_cache_update(
let editor_b = cx_b.add_view(window_b, |cx| { let editor_b = cx_b.add_view(window_b, |cx| {
Editor::for_buffer(buffer_b, Some(project_b.clone()), 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(); cx_b.foreground().run_until_parked();
editor_b.update(cx_b, |editor, _| { editor_b.update(cx_b, |editor, _| {
assert!( assert!(

View file

@ -2638,7 +2638,10 @@ impl Editor {
let excerpts_to_query = self let excerpts_to_query = self
.excerpt_visible_offsets(cx) .excerpt_visible_offsets(cx)
.into_iter() .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::<HashMap<_, _>>(); .collect::<HashMap<_, _>>();
self.inlay_hint_cache self.inlay_hint_cache
.spawn_hints_update(excerpts_to_query, invalidate_cache, cx) .spawn_hints_update(excerpts_to_query, invalidate_cache, cx)
@ -2661,7 +2664,6 @@ impl Editor {
Bias::Left, Bias::Left,
); );
let multi_buffer_visible_range = multi_buffer_visible_start..multi_buffer_visible_end; let multi_buffer_visible_range = multi_buffer_visible_start..multi_buffer_visible_end;
multi_buffer.range_to_buffer_ranges(multi_buffer_visible_range, cx) multi_buffer.range_to_buffer_ranges(multi_buffer_visible_range, cx)
} }

View file

@ -1,4 +1,4 @@
use std::{cmp, sync::Arc}; use std::{cmp, ops::Range, sync::Arc};
use crate::{ use crate::{
display_map::Inlay, editor_settings, Anchor, Editor, ExcerptId, InlayId, MultiBuffer, display_map::Inlay, editor_settings, Anchor, Editor, ExcerptId, InlayId, MultiBuffer,
@ -38,13 +38,35 @@ pub struct CachedExcerptHints {
struct ExcerptQuery { struct ExcerptQuery {
buffer_id: u64, buffer_id: u64,
excerpt_id: ExcerptId, excerpt_id: ExcerptId,
excerpt_range_start: language::Anchor, dimensions: ExcerptDimensions,
excerpt_range_end: language::Anchor,
cache_version: usize, cache_version: usize,
invalidate: InvalidationStrategy, invalidate: InvalidationStrategy,
} }
impl ExcerptQuery {
fn contains_position(&self, position: text::Anchor, buffer_snapshot: &BufferSnapshot) -> bool { #[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_le()
&& self
.excerpt_visible_range_end
.cmp(&position, buffer_snapshot)
.is_ge()
} else {
self.excerpt_range_start self.excerpt_range_start
.cmp(&position, buffer_snapshot) .cmp(&position, buffer_snapshot)
.is_le() .is_le()
@ -53,6 +75,7 @@ impl ExcerptQuery {
.cmp(&position, buffer_snapshot) .cmp(&position, buffer_snapshot)
.is_ge() .is_ge()
} }
}
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@ -127,7 +150,7 @@ impl InlayHintCache {
pub fn spawn_hints_update( pub fn spawn_hints_update(
&mut self, &mut self,
mut excerpts_to_query: HashMap<ExcerptId, ModelHandle<Buffer>>, mut excerpts_to_query: HashMap<ExcerptId, (ModelHandle<Buffer>, Range<usize>)>,
invalidate: InvalidationStrategy, invalidate: InvalidationStrategy,
cx: &mut ViewContext<Editor>, cx: &mut ViewContext<Editor>,
) { ) {
@ -172,34 +195,12 @@ impl InlayHintCache {
.update(&mut cx, |editor, cx| { .update(&mut cx, |editor, cx| {
let visible_hints = let visible_hints =
Arc::new(visible_inlay_hints(editor, cx).cloned().collect::<Vec<_>>()); Arc::new(visible_inlay_hints(editor, cx).cloned().collect::<Vec<_>>());
for (excerpt_id, buffer_handle) in excerpts_to_query { for (excerpt_id, (buffer_handle, excerpt_visible_range)) in excerpts_to_query {
let (multi_buffer_snapshot, excerpt_range) = if !excerpt_visible_range.is_empty() {
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 {
let buffer = buffer_handle.read(cx); let buffer = buffer_handle.read(cx);
let buffer_snapshot = buffer.snapshot(); 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 = let cached_excxerpt_hints =
editor.inlay_hint_cache.hints.get(&excerpt_id).cloned(); editor.inlay_hint_cache.hints.get(&excerpt_id).cloned();
if let Some(cached_excerpt_hints) = &cached_excxerpt_hints { if let Some(cached_excerpt_hints) = &cached_excxerpt_hints {
let new_task_buffer_version = buffer_snapshot.version(); let new_task_buffer_version = buffer_snapshot.version();
let cached_excerpt_hints = cached_excerpt_hints.read(); let cached_excerpt_hints = cached_excerpt_hints.read();
@ -214,6 +215,38 @@ impl InlayHintCache {
} }
} }
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( editor.inlay_hint_cache.update_tasks.insert(
excerpt_id, excerpt_id,
new_update_task( new_update_task(
@ -227,6 +260,7 @@ impl InlayHintCache {
); );
} }
} }
}
}) })
.ok(); .ok();
}) })
@ -461,7 +495,10 @@ fn new_excerpt_hints_update_result(
let mut excerpt_hints_to_persist = HashMap::default(); let mut excerpt_hints_to_persist = HashMap::default();
for new_hint in new_excerpt_hints { 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; continue;
} }
let missing_from_cache = match &cached_excerpt_hints { let missing_from_cache = match &cached_excerpt_hints {
@ -499,7 +536,13 @@ fn new_excerpt_hints_update_result(
visible_hints visible_hints
.iter() .iter()
.filter(|hint| hint.position.excerpt_id == query.excerpt_id) .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) .map(|inlay_hint| inlay_hint.id)
.filter(|hint_id| !excerpt_hints_to_persist.contains_key(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| { Some(project.update(cx, |project, cx| {
project.inlay_hints( project.inlay_hints(
buffer, 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, cx,
) )
})) }))