From 3028767d12a8eb1457cb3f469bfc8b6060ed61ca Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 8 Jun 2023 15:44:20 +0300 Subject: [PATCH] Improve on inlya locations --- crates/editor/src/display_map.rs | 15 +-- crates/editor/src/display_map/inlay_map.rs | 26 ++++-- crates/editor/src/editor.rs | 101 +++++++++++---------- 3 files changed, 75 insertions(+), 67 deletions(-) diff --git a/crates/editor/src/display_map.rs b/crates/editor/src/display_map.rs index ec768211079a4d2d11775307921b67186ff9ae0d..e8e199b233b7db4fdb61cfdfd21e7e94eb124723 100644 --- a/crates/editor/src/display_map.rs +++ b/crates/editor/src/display_map.rs @@ -5,7 +5,9 @@ mod suggestion_map; mod tab_map; mod wrap_map; -use crate::{Anchor, AnchorRangeExt, MultiBuffer, MultiBufferSnapshot, ToOffset, ToPoint}; +use crate::{ + Anchor, AnchorRangeExt, InlayHintLocation, MultiBuffer, MultiBufferSnapshot, ToOffset, ToPoint, +}; pub use block_map::{BlockMap, BlockPoint}; use collections::{HashMap, HashSet}; use fold_map::{FoldMap, FoldOffset}; @@ -284,19 +286,12 @@ impl DisplayMap { pub fn set_inlay_hints( &mut self, - new_hints: &[project::InlayHint], + new_hints: &HashMap>, cx: &mut ModelContext, ) { + // TODO kb map this to Anchor and set to the map let multi_buffer = self.buffer.read(cx); - // TODO kb carry both remote and local ids of the buffer? - // now, `.buffer` requires remote id, hence this map. - let buffers_to_local_id = multi_buffer - .all_buffers() - .into_iter() - .map(|buffer_handle| (buffer_handle.id(), buffer_handle)) - .collect::>(); - // multi_buffer.anchor_in_excerpt(excerpt_id, hint.position); // TODO kb !!! rework things from buffer_id to excerpt_id // let hint_anchor = multi_buffer diff --git a/crates/editor/src/display_map/inlay_map.rs b/crates/editor/src/display_map/inlay_map.rs index 61d67584fc7f21cde2c1fb0931b2e3914bec8fa6..a6b6d2f6bc3e5d35c629be7da397a5383980e0fd 100644 --- a/crates/editor/src/display_map/inlay_map.rs +++ b/crates/editor/src/display_map/inlay_map.rs @@ -7,7 +7,7 @@ use std::{ sync::atomic::{self, AtomicUsize}, }; -use crate::{Anchor, MultiBufferSnapshot, ToOffset, ToPoint}; +use crate::{Anchor, ExcerptId, InlayHintLocation, MultiBufferSnapshot, ToOffset, ToPoint}; use super::{ suggestion_map::{ @@ -31,7 +31,7 @@ pub struct InlayId(usize); pub struct InlayMap { snapshot: Mutex, next_inlay_id: usize, - inlays: HashMap, + inlays: HashMap, } #[derive(Clone)] @@ -224,18 +224,18 @@ impl InlayMap { pub fn splice( &mut self, to_remove: HashSet, - to_insert: Vec, + to_insert: Vec<(InlayHintLocation, InlayProperties)>, ) -> (InlaySnapshot, Vec, Vec) { let mut snapshot = self.snapshot.lock(); let mut inlays = BTreeMap::new(); let mut new_ids = Vec::new(); - for properties in to_insert { + for (location, properties) in to_insert { let inlay = Inlay { id: InlayId(post_inc(&mut self.next_inlay_id)), properties, }; - self.inlays.insert(inlay.id, inlay.clone()); + self.inlays.insert(inlay.id, (location, inlay.clone())); new_ids.push(inlay.id); let buffer_point = inlay @@ -253,7 +253,7 @@ impl InlayMap { } for inlay_id in to_remove { - if let Some(inlay) = self.inlays.remove(&inlay_id) { + if let Some((_, inlay)) = self.inlays.remove(&inlay_id) { let buffer_point = inlay .properties .position @@ -448,10 +448,16 @@ mod tests { let (inlay_snapshot, _, inlay_ids) = inlay_map.splice( HashSet::default(), - vec![InlayProperties { - position: buffer.read(cx).read(cx).anchor_before(3), - text: "|123|".into(), - }], + vec![( + InlayHintLocation { + buffer_id: 0, + excerpt_id: ExcerptId::default(), + }, + InlayProperties { + position: buffer.read(cx).read(cx).anchor_before(3), + text: "|123|".into(), + }, + )], ); assert_eq!(inlay_snapshot.text(), "abc|123|defghi"); diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index bb4f0e9c3d6d7c0f164218fed8e5bc90227ee8ba..b5d963efa4f2bd341947d4d243a30a45d2780c23 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -1153,24 +1153,30 @@ impl CopilotState { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct InlayHintLocation { + pub buffer_id: u64, + pub excerpt_id: ExcerptId, +} + // TODO kb #[derive(Debug, Default, Clone)] struct InlayHintVersions { - last_buffer_versions_with_hints: HashMap, + last_buffer_versions_with_hints: HashMap, } impl InlayHintVersions { - fn absent_or_newer(&self, buffer_id: usize, new_version: &Global) -> bool { + fn absent_or_newer(&self, location: &InlayHintLocation, new_version: &Global) -> bool { self.last_buffer_versions_with_hints - .get(&buffer_id) + .get(location) .map(|last_version_with_hints| new_version.changed_since(&last_version_with_hints)) .unwrap_or(true) } - fn insert(&mut self, buffer_id: usize, new_version: Global) -> bool { - if self.absent_or_newer(buffer_id, &new_version) { + fn insert(&mut self, location: InlayHintLocation, new_version: Global) -> bool { + if self.absent_or_newer(&location, &new_version) { self.last_buffer_versions_with_hints - .insert(buffer_id, new_version); + .insert(location, new_version); true } else { false @@ -2617,50 +2623,40 @@ impl Editor { return; } - let hint_fetch_tasks = self - .buffer() - .read(cx) - .all_buffers() - .into_iter() - .map(|buffer_handle| { - let buffer_id = buffer_handle.id(); + let multi_buffer = self.buffer().read(cx); + let buffer_snapshot = multi_buffer.snapshot(cx); + let hint_fetch_tasks = buffer_snapshot + .excerpts() + .map(|(excerpt_id, excerpt_buffer_snapshot, _)| { + (excerpt_id, excerpt_buffer_snapshot.clone()) + }) + .map(|(excerpt_id, excerpt_buffer_snapshot)| { cx.spawn(|editor, mut cx| async move { - let task_data = editor + let task = editor .update(&mut cx, |editor, cx| { editor.project.as_ref().and_then(|project| { project.update(cx, |project, cx| { - let buffer = buffer_handle.read(cx); - let end = buffer.len(); - let version = buffer.version(); - - if editor - .inlay_hint_versions - .absent_or_newer(buffer_id, &version) - { - Some(( - version, - project.inlay_hints_for_buffer( - buffer_handle, - 0..end, - cx, - ), - )) - } else { - None - } + Some( + project.inlay_hints_for_buffer( + editor + .buffer() + .read(cx) + .buffer(excerpt_buffer_snapshot.remote_id())?, + 0..excerpt_buffer_snapshot.len(), + cx, + ), + ) }) }) }) .context("inlay hints fecth task spawn")?; anyhow::Ok(( - buffer_id, - match task_data { - Some((buffer_version, task)) => Some(( - buffer_version, - task.await.context("inlay hints for buffer task")?, - )), - None => None, + excerpt_id, + excerpt_buffer_snapshot, + match task { + Some(task) => task.await.context("inlay hints for buffer task")?, + None => Vec::new(), }, )) }) @@ -2668,21 +2664,32 @@ impl Editor { .collect::>(); cx.spawn(|editor, mut cx| async move { - let mut new_hints = Vec::new(); + let mut new_hints: HashMap> = + HashMap::default(); for task_result in futures::future::join_all(hint_fetch_tasks).await { match task_result { - Ok((_buffer_id, None)) => {} - Ok((buffer_id, Some((buffer_with_hints_version, buffer_hints)))) => { + Ok((excerpt_id, excerpt_buffer_snapshot, excerpt_hints)) => { + let buffer_id = excerpt_buffer_snapshot.remote_id(); let should_update_hints = editor .update(&mut cx, |editor, _| { - editor - .inlay_hint_versions - .insert(buffer_id, buffer_with_hints_version) + editor.inlay_hint_versions.insert( + InlayHintLocation { + buffer_id, + excerpt_id, + }, + excerpt_buffer_snapshot.version().clone(), + ) }) .log_err() .unwrap_or(false); if should_update_hints { - new_hints.extend(buffer_hints); + new_hints + .entry(InlayHintLocation { + buffer_id, + excerpt_id, + }) + .or_default() + .extend(excerpt_hints); } } Err(e) => error!("Failed to update hints for buffer: {e:#}"),