Move away heavy inlay computations into background tasks

This commit is contained in:
Kirill Bulatov 2023-06-21 22:17:47 +03:00
parent 31f0f9f7b1
commit 7fddc223cd
4 changed files with 395 additions and 825 deletions

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::{InlayHintCache, InlayHintQuery};
use inlay_hint_cache::{get_update_state, InlayHintCache, InlaySplice};
pub use items::MAX_TAB_TITLE_LEN;
use itertools::Itertools;
pub use language::{char_kind, CharKind};
@ -1196,7 +1196,7 @@ enum GotoDefinitionKind {
#[derive(Debug, Copy, Clone)]
enum InlayRefreshReason {
SettingsChange(editor_settings::InlayHints),
Scroll(ScrollAnchor),
Scroll,
VisibleExcerptsChange,
}
@ -1367,10 +1367,7 @@ impl Editor {
hover_state: Default::default(),
link_go_to_definition_state: Default::default(),
copilot_state: Default::default(),
inlay_hint_cache: InlayHintCache::new(
settings::get::<EditorSettings>(cx).inlay_hints,
cx,
),
inlay_hint_cache: InlayHintCache::new(settings::get::<EditorSettings>(cx).inlay_hints),
gutter_hovered: false,
_subscriptions: vec![
cx.observe(&buffer, Self::on_buffer_changed),
@ -2612,67 +2609,23 @@ impl Editor {
{
return;
}
let multi_buffer_snapshot = self.buffer().read(cx).snapshot(cx);
let current_inlays = self
.display_map
.read(cx)
.current_inlays()
.cloned()
.filter(|inlay| Some(inlay.id) != self.copilot_state.suggestion.as_ref().map(|h| h.id))
.collect();
match reason {
InlayRefreshReason::SettingsChange(new_settings) => self
.inlay_hint_cache
.spawn_settings_update(multi_buffer_snapshot, new_settings, current_inlays),
InlayRefreshReason::Scroll(scrolled_to) => {
if let Some(new_query) = self.excerpt_visible_offsets(cx).into_iter().find_map(
|(buffer, _, excerpt_id)| {
let buffer_id = scrolled_to.anchor.buffer_id?;
if buffer_id == buffer.read(cx).remote_id()
&& scrolled_to.anchor.excerpt_id == excerpt_id
{
Some(InlayHintQuery {
buffer_id,
buffer_version: buffer.read(cx).version(),
cache_version: self.inlay_hint_cache.version(),
excerpt_id,
})
} else {
None
}
},
) {
self.inlay_hint_cache.spawn_hints_update(
multi_buffer_snapshot,
vec![new_query],
current_inlays,
false,
cx,
)
InlayRefreshReason::SettingsChange(new_settings) => {
let update_state = get_update_state(self, cx);
let new_splice = self
.inlay_hint_cache
.update_settings(new_settings, update_state);
if let Some(InlaySplice {
to_remove,
to_insert,
}) = new_splice
{
self.splice_inlay_hints(to_remove, to_insert, cx);
}
}
InlayRefreshReason::Scroll => self.inlay_hint_cache.spawn_hints_update(false, cx),
InlayRefreshReason::VisibleExcerptsChange => {
let replacement_queries = self
.excerpt_visible_offsets(cx)
.into_iter()
.map(|(buffer, _, excerpt_id)| {
let buffer = buffer.read(cx);
InlayHintQuery {
buffer_id: buffer.remote_id(),
buffer_version: buffer.version(),
cache_version: self.inlay_hint_cache.version(),
excerpt_id,
}
})
.collect::<Vec<_>>();
self.inlay_hint_cache.spawn_hints_update(
multi_buffer_snapshot,
replacement_queries,
current_inlays,
true,
cx,
)
self.inlay_hint_cache.spawn_hints_update(true, cx)
}
};
}
@ -2701,13 +2654,13 @@ impl Editor {
fn splice_inlay_hints(
&self,
to_remove: Vec<InlayId>,
to_insert: Vec<(InlayId, Anchor, project::InlayHint)>,
to_insert: Vec<(Anchor, InlayId, project::InlayHint)>,
cx: &mut ViewContext<Self>,
) {
let buffer = self.buffer.read(cx).read(cx);
let new_inlays = to_insert
.into_iter()
.map(|(id, position, hint)| {
.map(|(position, id, hint)| {
let mut text = hint.text();
// TODO kb styling instead?
if hint.padding_right {
@ -7298,7 +7251,7 @@ impl Editor {
}
multi_buffer::Event::ExcerptsRemoved { ids } => {
cx.emit(Event::ExcerptsRemoved { ids: ids.clone() });
true
false
}
multi_buffer::Event::Reparsed => {
cx.emit(Event::Reparsed);
@ -7336,7 +7289,11 @@ impl Editor {
};
if refresh_inlays {
self.refresh_inlays(InlayRefreshReason::VisibleExcerptsChange, cx);
if let Some(_project) = self.project.as_ref() {
// TODO kb non-rust buffer can be edited (e.g. settings) and trigger rust updates
// let zz = project.read(cx).language_servers_for_buffer(buffer, cx);
self.refresh_inlays(InlayRefreshReason::VisibleExcerptsChange, cx);
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -176,7 +176,7 @@ impl ScrollManager {
autoscroll: bool,
workspace_id: Option<i64>,
cx: &mut ViewContext<Editor>,
) -> ScrollAnchor {
) {
let (new_anchor, top_row) = if scroll_position.y() <= 0. {
(
ScrollAnchor {
@ -205,7 +205,6 @@ impl ScrollManager {
};
self.set_anchor(new_anchor, top_row, local, autoscroll, workspace_id, cx);
new_anchor
}
fn set_anchor(
@ -313,7 +312,7 @@ impl Editor {
hide_hover(self, cx);
let workspace_id = self.workspace.as_ref().map(|workspace| workspace.1);
let scroll_anchor = self.scroll_manager.set_scroll_position(
self.scroll_manager.set_scroll_position(
scroll_position,
&map,
local,
@ -323,7 +322,7 @@ impl Editor {
);
if !self.is_singleton(cx) {
self.refresh_inlays(crate::InlayRefreshReason::Scroll(scroll_anchor), cx);
self.refresh_inlays(crate::InlayRefreshReason::Scroll, cx);
}
}

View file

@ -4929,7 +4929,7 @@ impl Project {
)
}
pub fn query_inlay_hints_for_buffer<T: ToOffset>(
pub fn inlay_hints<T: ToOffset>(
&self,
buffer_handle: ModelHandle<Buffer>,
range: Range<T>,
@ -6768,7 +6768,7 @@ impl Project {
.update(&mut cx, |project, cx| {
let buffer_end = buffer.read(cx).len();
// TODO kb use cache before querying?
project.query_inlay_hints_for_buffer(
project.inlay_hints(
buffer,
envelope
.payload