From ea837a183bc9f063060df64178c96005a26b421e Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Tue, 13 Jun 2023 17:14:38 +0300 Subject: [PATCH] Store inlays per paths and query on editor open --- crates/editor/src/editor.rs | 31 +++++++++++++++++-------------- crates/editor/src/inlay_cache.rs | 24 ++++++++++++++---------- crates/project/src/project.rs | 6 +++--- 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index da2d0950a2a6b00a53e86dfac124b76676c5f4d5..93535c94804d38d5121bafd03b6b2dba6e982cbb 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -84,6 +84,7 @@ use serde::{Deserialize, Serialize}; use settings::SettingsStore; use smallvec::SmallVec; use snippet::Snippet; +use std::path::PathBuf; use std::{ any::TypeId, borrow::Cow, @@ -1297,7 +1298,6 @@ impl Editor { project_subscriptions.push(cx.subscribe(project, |editor, _, event, cx| { if let project::Event::RefreshInlays = event { editor.refresh_inlays(cx); - cx.notify() }; })); } @@ -1352,6 +1352,7 @@ impl Editor { hover_state: Default::default(), link_go_to_definition_state: Default::default(), copilot_state: Default::default(), + // TODO kb has to live between editors inlay_cache: InlayCache::default(), gutter_hovered: false, _subscriptions: vec![ @@ -1377,6 +1378,7 @@ impl Editor { } this.report_editor_event("open", None, cx); + this.refresh_inlays(cx); this } @@ -2594,7 +2596,7 @@ impl Editor { } struct InlayRequestKey { - buffer_id: u64, + buffer_path: PathBuf, buffer_version: Global, excerpt_id: ExcerptId, } @@ -2603,22 +2605,21 @@ impl Editor { let multi_buffer_snapshot = multi_buffer.read(cx).snapshot(cx); let inlay_fetch_tasks = multi_buffer_snapshot .excerpts() - .map(|(excerpt_id, buffer_snapshot, excerpt_range)| { - // TODO kb every time I reopen the same buffer, it's different. - // Find a way to understand it's the same buffer. Use paths? + .filter_map(|(excerpt_id, buffer_snapshot, excerpt_range)| { + let buffer_path = buffer_snapshot.resolve_file_path(cx, true)?; let buffer_id = buffer_snapshot.remote_id(); let buffer_version = buffer_snapshot.version().clone(); let buffer_handle = multi_buffer.read(cx).buffer(buffer_id); let inlays_up_to_date = 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 { - buffer_id, + buffer_path, buffer_version, excerpt_id, }; - cx.spawn(|editor, mut cx| async move { + let task = cx.spawn(|editor, mut cx| async move { if inlays_up_to_date { anyhow::Ok((key, None)) } else { @@ -2631,7 +2632,7 @@ impl Editor { .update(&mut cx, |editor, cx| { editor.project.as_ref().map(|project| { project.update(cx, |project, cx| { - project.inlay_hints_for_buffer( + project.query_inlay_hints_for_buffer( buffer_handle, query_start..query_end, cx, @@ -2658,13 +2659,15 @@ impl Editor { None => Some(Vec::new()), })) } - }) + }); + + Some(task) }) .collect::>(); cx.spawn(|editor, mut cx| async move { let mut inlay_updates: HashMap< - u64, + PathBuf, ( Global, HashMap>>, @@ -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) => { o.get_mut().1.extend(inlays_per_excerpt); } @@ -7243,7 +7246,7 @@ impl Editor { event: &multi_buffer::Event, cx: &mut ViewContext, ) { - let update_inlay_hints = match event { + let refresh_inlay_hints = match event { multi_buffer::Event::Edited => { self.refresh_active_diagnostics(cx); self.refresh_code_actions(cx); @@ -7304,7 +7307,7 @@ impl Editor { _ => false, }; - if update_inlay_hints { + if refresh_inlay_hints { self.refresh_inlays(cx); } } diff --git a/crates/editor/src/inlay_cache.rs b/crates/editor/src/inlay_cache.rs index d1b14f33428378b617151a7381512ac366d79987..2f5f4204b9d3cd1148b7135187fc5c4c23e3b465 100644 --- a/crates/editor/src/inlay_cache.rs +++ b/crates/editor/src/inlay_cache.rs @@ -1,4 +1,7 @@ -use std::cmp; +use std::{ + cmp, + path::{Path, PathBuf}, +}; use crate::{Anchor, ExcerptId}; use clock::{Global, Local}; @@ -9,7 +12,7 @@ use collections::{BTreeMap, HashMap}; #[derive(Clone, Debug, Default)] pub struct InlayCache { - inlays_per_buffer: HashMap, + inlays_per_buffer: HashMap, next_inlay_id: usize, } @@ -60,11 +63,11 @@ pub struct InlaysUpdate { impl InlayCache { pub fn inlays_up_to_date( &self, - buffer_id: u64, + buffer_path: &Path, buffer_version: &Global, excerpt_id: ExcerptId, ) -> 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 || buffer_inlays.buffer_version.changed_since(buffer_version); buffer_up_to_date && buffer_inlays.inlays_per_excerpts.contains_key(&excerpt_id) @@ -73,7 +76,7 @@ impl InlayCache { pub fn update_inlays( &mut self, inlay_updates: HashMap< - u64, + PathBuf, ( Global, HashMap>>, @@ -84,17 +87,17 @@ impl InlayCache { let mut to_remove = Vec::new(); let mut to_insert = Vec::new(); - for (buffer_id, (buffer_version, new_buffer_inlays)) in inlay_updates { - match old_inlays.remove(&buffer_id) { + for (buffer_path, (buffer_version, new_buffer_inlays)) in inlay_updates { + match old_inlays.remove(&buffer_path) { Some(mut old_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; } let self_inlays_per_buffer = self .inlays_per_buffer - .get_mut(&buffer_id) + .get_mut(&buffer_path) .expect("element expected: `old_inlays.remove` returned `Some`"); let mut new_excerpt_inlays = match new_excerpt_inlays { Some(new_inlays) => { @@ -112,6 +115,7 @@ impl InlayCache { .get_mut(&excerpt_id) .expect("element expected: `old_excerpt_inlays` is `Some`"); 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( |_, (old_anchor, (old_inlay_id, old_inlay))| { let mut retain = false; @@ -202,7 +206,7 @@ impl InlayCache { } } self.inlays_per_buffer.insert( - buffer_id, + buffer_path, BufferInlays { buffer_version, inlays_per_excerpts, diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 2f22201ea42a80c1c6e27b57990e31798693a0ef..5c08ff6b8249c813050762e87d7dfdc052028cf2 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -4928,7 +4928,7 @@ impl Project { ) } - pub fn inlay_hints_for_buffer( + pub fn query_inlay_hints_for_buffer( &self, buffer_handle: ModelHandle, range: Range, @@ -4951,7 +4951,6 @@ impl Project { }) .await .context("waiting for inlay hint request range edits")?; - match lsp_request_task.await { Ok(hints) => Ok(Some(hints)), Err(e) if is_content_modified_error(&e) => Ok(None), @@ -6767,7 +6766,8 @@ impl Project { let buffer_hints = this .update(&mut cx, |project, cx| { 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, envelope .payload