Store inlays per paths and query on editor open

This commit is contained in:
Kirill Bulatov 2023-06-13 17:14:38 +03:00
parent 8acc5cf8f4
commit ea837a183b
3 changed files with 34 additions and 27 deletions

View file

@ -84,6 +84,7 @@ use serde::{Deserialize, Serialize};
use settings::SettingsStore; use settings::SettingsStore;
use smallvec::SmallVec; use smallvec::SmallVec;
use snippet::Snippet; use snippet::Snippet;
use std::path::PathBuf;
use std::{ use std::{
any::TypeId, any::TypeId,
borrow::Cow, borrow::Cow,
@ -1297,7 +1298,6 @@ impl Editor {
project_subscriptions.push(cx.subscribe(project, |editor, _, event, cx| { project_subscriptions.push(cx.subscribe(project, |editor, _, event, cx| {
if let project::Event::RefreshInlays = event { if let project::Event::RefreshInlays = event {
editor.refresh_inlays(cx); editor.refresh_inlays(cx);
cx.notify()
}; };
})); }));
} }
@ -1352,6 +1352,7 @@ impl Editor {
hover_state: Default::default(), hover_state: Default::default(),
link_go_to_definition_state: Default::default(), link_go_to_definition_state: Default::default(),
copilot_state: Default::default(), copilot_state: Default::default(),
// TODO kb has to live between editors
inlay_cache: InlayCache::default(), inlay_cache: InlayCache::default(),
gutter_hovered: false, gutter_hovered: false,
_subscriptions: vec![ _subscriptions: vec![
@ -1377,6 +1378,7 @@ impl Editor {
} }
this.report_editor_event("open", None, cx); this.report_editor_event("open", None, cx);
this.refresh_inlays(cx);
this this
} }
@ -2594,7 +2596,7 @@ impl Editor {
} }
struct InlayRequestKey { struct InlayRequestKey {
buffer_id: u64, buffer_path: PathBuf,
buffer_version: Global, buffer_version: Global,
excerpt_id: ExcerptId, excerpt_id: ExcerptId,
} }
@ -2603,22 +2605,21 @@ impl Editor {
let multi_buffer_snapshot = multi_buffer.read(cx).snapshot(cx); let multi_buffer_snapshot = multi_buffer.read(cx).snapshot(cx);
let inlay_fetch_tasks = multi_buffer_snapshot let inlay_fetch_tasks = multi_buffer_snapshot
.excerpts() .excerpts()
.map(|(excerpt_id, buffer_snapshot, excerpt_range)| { .filter_map(|(excerpt_id, buffer_snapshot, excerpt_range)| {
// TODO kb every time I reopen the same buffer, it's different. let buffer_path = buffer_snapshot.resolve_file_path(cx, true)?;
// Find a way to understand it's the same buffer. Use paths?
let buffer_id = buffer_snapshot.remote_id(); let buffer_id = buffer_snapshot.remote_id();
let buffer_version = buffer_snapshot.version().clone(); let buffer_version = buffer_snapshot.version().clone();
let buffer_handle = multi_buffer.read(cx).buffer(buffer_id); let buffer_handle = multi_buffer.read(cx).buffer(buffer_id);
let inlays_up_to_date = let inlays_up_to_date =
self.inlay_cache self.inlay_cache
.inlays_up_to_date(buffer_id, &buffer_version, excerpt_id); .inlays_up_to_date(&buffer_path, &buffer_version, excerpt_id);
let key = InlayRequestKey { let key = InlayRequestKey {
buffer_id, buffer_path,
buffer_version, buffer_version,
excerpt_id, excerpt_id,
}; };
cx.spawn(|editor, mut cx| async move { let task = cx.spawn(|editor, mut cx| async move {
if inlays_up_to_date { if inlays_up_to_date {
anyhow::Ok((key, None)) anyhow::Ok((key, None))
} else { } else {
@ -2631,7 +2632,7 @@ impl Editor {
.update(&mut cx, |editor, cx| { .update(&mut cx, |editor, cx| {
editor.project.as_ref().map(|project| { editor.project.as_ref().map(|project| {
project.update(cx, |project, cx| { project.update(cx, |project, cx| {
project.inlay_hints_for_buffer( project.query_inlay_hints_for_buffer(
buffer_handle, buffer_handle,
query_start..query_end, query_start..query_end,
cx, cx,
@ -2658,13 +2659,15 @@ impl Editor {
None => Some(Vec::new()), None => Some(Vec::new()),
})) }))
} }
}) });
Some(task)
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
cx.spawn(|editor, mut cx| async move { cx.spawn(|editor, mut cx| async move {
let mut inlay_updates: HashMap< let mut inlay_updates: HashMap<
u64, PathBuf,
( (
Global, Global,
HashMap<ExcerptId, Option<OrderedByAnchorOffset<InlayHint>>>, HashMap<ExcerptId, Option<OrderedByAnchorOffset<InlayHint>>>,
@ -2692,7 +2695,7 @@ impl Editor {
) )
}), }),
)]); )]);
match inlay_updates.entry(request_key.buffer_id) { match inlay_updates.entry(request_key.buffer_path) {
hash_map::Entry::Occupied(mut o) => { hash_map::Entry::Occupied(mut o) => {
o.get_mut().1.extend(inlays_per_excerpt); o.get_mut().1.extend(inlays_per_excerpt);
} }
@ -7243,7 +7246,7 @@ impl Editor {
event: &multi_buffer::Event, event: &multi_buffer::Event,
cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
) { ) {
let update_inlay_hints = match event { let refresh_inlay_hints = match event {
multi_buffer::Event::Edited => { multi_buffer::Event::Edited => {
self.refresh_active_diagnostics(cx); self.refresh_active_diagnostics(cx);
self.refresh_code_actions(cx); self.refresh_code_actions(cx);
@ -7304,7 +7307,7 @@ impl Editor {
_ => false, _ => false,
}; };
if update_inlay_hints { if refresh_inlay_hints {
self.refresh_inlays(cx); self.refresh_inlays(cx);
} }
} }

View file

@ -1,4 +1,7 @@
use std::cmp; use std::{
cmp,
path::{Path, PathBuf},
};
use crate::{Anchor, ExcerptId}; use crate::{Anchor, ExcerptId};
use clock::{Global, Local}; use clock::{Global, Local};
@ -9,7 +12,7 @@ use collections::{BTreeMap, HashMap};
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
pub struct InlayCache { pub struct InlayCache {
inlays_per_buffer: HashMap<u64, BufferInlays>, inlays_per_buffer: HashMap<PathBuf, BufferInlays>,
next_inlay_id: usize, next_inlay_id: usize,
} }
@ -60,11 +63,11 @@ pub struct InlaysUpdate {
impl InlayCache { impl InlayCache {
pub fn inlays_up_to_date( pub fn inlays_up_to_date(
&self, &self,
buffer_id: u64, buffer_path: &Path,
buffer_version: &Global, buffer_version: &Global,
excerpt_id: ExcerptId, excerpt_id: ExcerptId,
) -> bool { ) -> bool {
let Some(buffer_inlays) = self.inlays_per_buffer.get(&buffer_id) else { return false }; let Some(buffer_inlays) = self.inlays_per_buffer.get(buffer_path) else { return false };
let buffer_up_to_date = buffer_version == &buffer_inlays.buffer_version let buffer_up_to_date = buffer_version == &buffer_inlays.buffer_version
|| buffer_inlays.buffer_version.changed_since(buffer_version); || buffer_inlays.buffer_version.changed_since(buffer_version);
buffer_up_to_date && buffer_inlays.inlays_per_excerpts.contains_key(&excerpt_id) buffer_up_to_date && buffer_inlays.inlays_per_excerpts.contains_key(&excerpt_id)
@ -73,7 +76,7 @@ impl InlayCache {
pub fn update_inlays( pub fn update_inlays(
&mut self, &mut self,
inlay_updates: HashMap< inlay_updates: HashMap<
u64, PathBuf,
( (
Global, Global,
HashMap<ExcerptId, Option<OrderedByAnchorOffset<InlayHint>>>, HashMap<ExcerptId, Option<OrderedByAnchorOffset<InlayHint>>>,
@ -84,17 +87,17 @@ impl InlayCache {
let mut to_remove = Vec::new(); let mut to_remove = Vec::new();
let mut to_insert = Vec::new(); let mut to_insert = Vec::new();
for (buffer_id, (buffer_version, new_buffer_inlays)) in inlay_updates { for (buffer_path, (buffer_version, new_buffer_inlays)) in inlay_updates {
match old_inlays.remove(&buffer_id) { match old_inlays.remove(&buffer_path) {
Some(mut old_buffer_inlays) => { Some(mut old_buffer_inlays) => {
for (excerpt_id, new_excerpt_inlays) in new_buffer_inlays { for (excerpt_id, new_excerpt_inlays) in new_buffer_inlays {
if self.inlays_up_to_date(buffer_id, &buffer_version, excerpt_id) { if self.inlays_up_to_date(&buffer_path, &buffer_version, excerpt_id) {
continue; continue;
} }
let self_inlays_per_buffer = self let self_inlays_per_buffer = self
.inlays_per_buffer .inlays_per_buffer
.get_mut(&buffer_id) .get_mut(&buffer_path)
.expect("element expected: `old_inlays.remove` returned `Some`"); .expect("element expected: `old_inlays.remove` returned `Some`");
let mut new_excerpt_inlays = match new_excerpt_inlays { let mut new_excerpt_inlays = match new_excerpt_inlays {
Some(new_inlays) => { Some(new_inlays) => {
@ -112,6 +115,7 @@ impl InlayCache {
.get_mut(&excerpt_id) .get_mut(&excerpt_id)
.expect("element expected: `old_excerpt_inlays` is `Some`"); .expect("element expected: `old_excerpt_inlays` is `Some`");
let mut hints_to_add = Vec::<(Anchor, (InlayId, InlayHint))>::new(); let mut hints_to_add = Vec::<(Anchor, (InlayId, InlayHint))>::new();
// TODO kb update inner buffer_id and version with the new data?
self_excerpt_inlays.0.retain( self_excerpt_inlays.0.retain(
|_, (old_anchor, (old_inlay_id, old_inlay))| { |_, (old_anchor, (old_inlay_id, old_inlay))| {
let mut retain = false; let mut retain = false;
@ -202,7 +206,7 @@ impl InlayCache {
} }
} }
self.inlays_per_buffer.insert( self.inlays_per_buffer.insert(
buffer_id, buffer_path,
BufferInlays { BufferInlays {
buffer_version, buffer_version,
inlays_per_excerpts, inlays_per_excerpts,

View file

@ -4928,7 +4928,7 @@ impl Project {
) )
} }
pub fn inlay_hints_for_buffer<T: ToOffset>( pub fn query_inlay_hints_for_buffer<T: ToOffset>(
&self, &self,
buffer_handle: ModelHandle<Buffer>, buffer_handle: ModelHandle<Buffer>,
range: Range<T>, range: Range<T>,
@ -4951,7 +4951,6 @@ impl Project {
}) })
.await .await
.context("waiting for inlay hint request range edits")?; .context("waiting for inlay hint request range edits")?;
match lsp_request_task.await { match lsp_request_task.await {
Ok(hints) => Ok(Some(hints)), Ok(hints) => Ok(Some(hints)),
Err(e) if is_content_modified_error(&e) => Ok(None), Err(e) if is_content_modified_error(&e) => Ok(None),
@ -6767,7 +6766,8 @@ impl Project {
let buffer_hints = this let buffer_hints = this
.update(&mut cx, |project, cx| { .update(&mut cx, |project, cx| {
let buffer_end = buffer.read(cx).len(); let buffer_end = buffer.read(cx).len();
project.inlay_hints_for_buffer( // TODO kb use cache before querying?
project.query_inlay_hints_for_buffer(
buffer, buffer,
envelope envelope
.payload .payload