Properly handle settings toggle
This commit is contained in:
+28
-14
@@ -3,7 +3,7 @@ mod blink_manager;
|
||||
pub mod display_map;
|
||||
mod editor_settings;
|
||||
mod element;
|
||||
mod inlay_cache;
|
||||
mod inlay_hint_cache;
|
||||
|
||||
mod git;
|
||||
mod highlight_matching_bracket;
|
||||
@@ -54,7 +54,7 @@ use gpui::{
|
||||
};
|
||||
use highlight_matching_bracket::refresh_matching_bracket_highlights;
|
||||
use hover_popover::{hide_hover, HoverState};
|
||||
use inlay_cache::{InlayCache, InlayHintQuery, InlayRefreshReason, InlaySplice};
|
||||
use inlay_hint_cache::{InlayHintCache, InlayHintQuery, InlayRefreshReason, InlaySplice};
|
||||
pub use items::MAX_TAB_TITLE_LEN;
|
||||
use itertools::Itertools;
|
||||
pub use language::{char_kind, CharKind};
|
||||
@@ -540,7 +540,7 @@ pub struct Editor {
|
||||
gutter_hovered: bool,
|
||||
link_go_to_definition_state: LinkGoToDefinitionState,
|
||||
copilot_state: CopilotState,
|
||||
inlay_cache: InlayCache,
|
||||
inlay_cache: InlayHintCache,
|
||||
_subscriptions: Vec<Subscription>,
|
||||
}
|
||||
|
||||
@@ -1355,7 +1355,7 @@ impl Editor {
|
||||
hover_state: Default::default(),
|
||||
link_go_to_definition_state: Default::default(),
|
||||
copilot_state: Default::default(),
|
||||
inlay_cache: InlayCache::new(settings::get::<EditorSettings>(cx).inlay_hints),
|
||||
inlay_cache: InlayHintCache::new(settings::get::<EditorSettings>(cx).inlay_hints),
|
||||
gutter_hovered: false,
|
||||
_subscriptions: vec![
|
||||
cx.observe(&buffer, Self::on_buffer_changed),
|
||||
@@ -2604,23 +2604,37 @@ impl Editor {
|
||||
}
|
||||
|
||||
let multi_buffer_handle = self.buffer().clone();
|
||||
let multi_buffer_snapshot = multi_buffer_handle.read(cx).snapshot(cx);
|
||||
let currently_visible_ranges = self.excerpt_visible_offsets(&multi_buffer_handle, cx);
|
||||
let currently_shown_inlays = self
|
||||
.display_map
|
||||
.read(cx)
|
||||
.current_inlays()
|
||||
.map(|inlay| (inlay.position, inlay.id))
|
||||
.collect::<Vec<_>>();
|
||||
let currently_shown_inlay_hints = self.display_map.read(cx).current_inlays().fold(
|
||||
HashMap::<u64, HashMap<ExcerptId, Vec<(Anchor, InlayId)>>>::default(),
|
||||
|mut current_hints, inlay| {
|
||||
if let Some(buffer_id) = inlay.position.buffer_id {
|
||||
let excerpt_hints = current_hints
|
||||
.entry(buffer_id)
|
||||
.or_default()
|
||||
.entry(inlay.position.excerpt_id)
|
||||
.or_default();
|
||||
match excerpt_hints.binary_search_by(|probe| {
|
||||
inlay.position.cmp(&probe.0, &multi_buffer_snapshot)
|
||||
}) {
|
||||
Ok(ix) | Err(ix) => {
|
||||
excerpt_hints.insert(ix, (inlay.position, inlay.id));
|
||||
}
|
||||
}
|
||||
}
|
||||
current_hints
|
||||
},
|
||||
);
|
||||
match reason {
|
||||
InlayRefreshReason::SettingsChange(new_settings) => {
|
||||
if let Some(InlaySplice {
|
||||
to_remove,
|
||||
to_insert,
|
||||
}) = self.inlay_cache.apply_settings(
|
||||
multi_buffer_handle,
|
||||
new_settings,
|
||||
currently_visible_ranges,
|
||||
currently_shown_inlays,
|
||||
currently_shown_inlay_hints,
|
||||
cx,
|
||||
) {
|
||||
self.splice_inlay_hints(to_remove, to_insert, cx);
|
||||
@@ -2653,7 +2667,7 @@ impl Editor {
|
||||
editor.inlay_cache.append_inlays(
|
||||
multi_buffer_handle,
|
||||
std::iter::once(updated_range_query),
|
||||
currently_shown_inlays,
|
||||
currently_shown_inlay_hints,
|
||||
cx,
|
||||
)
|
||||
})?
|
||||
@@ -2683,7 +2697,7 @@ impl Editor {
|
||||
editor.inlay_cache.replace_inlays(
|
||||
multi_buffer_handle,
|
||||
replacement_queries.into_iter(),
|
||||
currently_shown_inlays,
|
||||
currently_shown_inlay_hints,
|
||||
cx,
|
||||
)
|
||||
})?
|
||||
|
||||
@@ -9,7 +9,7 @@ use gpui::{ModelHandle, Task, ViewContext};
|
||||
use language::Buffer;
|
||||
use project::{InlayHint, InlayHintKind};
|
||||
|
||||
use collections::{HashMap, HashSet};
|
||||
use collections::{hash_map, HashMap, HashSet};
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum InlayRefreshReason {
|
||||
@@ -19,16 +19,25 @@ pub enum InlayRefreshReason {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct InlayCache {
|
||||
pub struct InlayHintCache {
|
||||
inlay_hints: HashMap<InlayId, InlayHint>,
|
||||
inlays_in_buffers: HashMap<u64, BufferInlays>,
|
||||
inlays_in_buffers: HashMap<u64, BufferInlays<(Anchor, InlayId)>>,
|
||||
allowed_hint_kinds: HashSet<Option<InlayHintKind>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct BufferInlays {
|
||||
struct BufferInlays<I> {
|
||||
buffer_version: Global,
|
||||
ordered_by_anchor_inlays: Vec<(Anchor, InlayId)>,
|
||||
excerpt_inlays: HashMap<ExcerptId, Vec<I>>,
|
||||
}
|
||||
|
||||
impl<I> BufferInlays<I> {
|
||||
fn new(buffer_version: Global) -> Self {
|
||||
Self {
|
||||
buffer_version,
|
||||
excerpt_inlays: HashMap::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
@@ -44,7 +53,7 @@ pub struct InlayHintQuery {
|
||||
pub excerpt_offset_query_range: Range<usize>,
|
||||
}
|
||||
|
||||
impl InlayCache {
|
||||
impl InlayHintCache {
|
||||
pub fn new(inlay_hint_settings: editor_settings::InlayHints) -> Self {
|
||||
Self {
|
||||
allowed_hint_kinds: allowed_inlay_hint_types(inlay_hint_settings),
|
||||
@@ -55,10 +64,9 @@ impl InlayCache {
|
||||
|
||||
pub fn apply_settings(
|
||||
&mut self,
|
||||
multi_buffer: ModelHandle<MultiBuffer>,
|
||||
inlay_hint_settings: editor_settings::InlayHints,
|
||||
currently_visible_ranges: Vec<(ModelHandle<Buffer>, Range<usize>, ExcerptId)>,
|
||||
currently_shown_inlays: Vec<(Anchor, InlayId)>,
|
||||
mut currently_shown_inlay_hints: HashMap<u64, HashMap<ExcerptId, Vec<(Anchor, InlayId)>>>,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
) -> Option<InlaySplice> {
|
||||
let new_allowed_hint_kinds = allowed_inlay_hint_types(inlay_hint_settings);
|
||||
@@ -69,33 +77,88 @@ impl InlayCache {
|
||||
let mut to_remove = Vec::new();
|
||||
let mut to_insert = Vec::new();
|
||||
|
||||
let mut considered_inlay_ids = HashSet::default();
|
||||
for (_, shown_inlay_id) in currently_shown_inlays {
|
||||
if let Some(inlay_hint) = self.inlay_hints.get(&shown_inlay_id) {
|
||||
if !self.allowed_hint_kinds.contains(&inlay_hint.kind) {
|
||||
to_remove.push(shown_inlay_id);
|
||||
let mut considered_hints =
|
||||
HashMap::<u64, HashMap<ExcerptId, HashSet<InlayId>>>::default();
|
||||
for (visible_buffer, _, visible_excerpt_id) in currently_visible_ranges {
|
||||
let visible_buffer = visible_buffer.read(cx);
|
||||
let visible_buffer_id = visible_buffer.remote_id();
|
||||
match currently_shown_inlay_hints.entry(visible_buffer_id) {
|
||||
hash_map::Entry::Occupied(mut o) => {
|
||||
let shown_hints_per_excerpt = o.get_mut();
|
||||
for (_, shown_hint_id) in shown_hints_per_excerpt
|
||||
.remove(&visible_excerpt_id)
|
||||
.unwrap_or_default()
|
||||
{
|
||||
considered_hints
|
||||
.entry(visible_buffer_id)
|
||||
.or_default()
|
||||
.entry(visible_excerpt_id)
|
||||
.or_default()
|
||||
.insert(shown_hint_id);
|
||||
match self.inlay_hints.get(&shown_hint_id) {
|
||||
Some(shown_hint) => {
|
||||
if !self.allowed_hint_kinds.contains(&shown_hint.kind) {
|
||||
to_remove.push(shown_hint_id);
|
||||
}
|
||||
}
|
||||
None => to_remove.push(shown_hint_id),
|
||||
}
|
||||
}
|
||||
if shown_hints_per_excerpt.is_empty() {
|
||||
o.remove();
|
||||
}
|
||||
}
|
||||
considered_inlay_ids.insert(shown_inlay_id);
|
||||
hash_map::Entry::Vacant(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
let multi_buffer_snapshot = multi_buffer.read(cx).snapshot(cx);
|
||||
for (inlay_id, inlay_hint) in &self.inlay_hints {
|
||||
if self.allowed_hint_kinds.contains(&inlay_hint.kind)
|
||||
&& !considered_inlay_ids.contains(inlay_id)
|
||||
{
|
||||
if let Some(hint_to_readd) = currently_visible_ranges.iter()
|
||||
.filter(|(_, visible_range, _)| visible_range.contains(&inlay_hint.position.offset))
|
||||
.find_map(|(_, _, excerpt_id)| {
|
||||
let Some(anchor) = multi_buffer_snapshot
|
||||
.find_anchor_in_excerpt(*excerpt_id, inlay_hint.position) else { return None; };
|
||||
Some((Some(*inlay_id), anchor, inlay_hint.clone()))
|
||||
},
|
||||
) {
|
||||
to_insert.push(hint_to_readd);
|
||||
}
|
||||
}
|
||||
}
|
||||
let reenabled_hints = self
|
||||
.inlays_in_buffers
|
||||
.iter()
|
||||
.filter_map(|(cached_buffer_id, cached_hints_per_excerpt)| {
|
||||
let considered_hints_in_excerpts = considered_hints.get(cached_buffer_id)?;
|
||||
let not_considered_cached_inlays = cached_hints_per_excerpt
|
||||
.excerpt_inlays
|
||||
.iter()
|
||||
.filter_map(|(cached_excerpt_id, cached_hints)| {
|
||||
let considered_excerpt_hints =
|
||||
considered_hints_in_excerpts.get(&cached_excerpt_id)?;
|
||||
let not_considered_cached_inlays = cached_hints
|
||||
.iter()
|
||||
.filter(|(_, cached_hint_id)| {
|
||||
!considered_excerpt_hints.contains(cached_hint_id)
|
||||
})
|
||||
.copied();
|
||||
Some(not_considered_cached_inlays)
|
||||
})
|
||||
.flatten();
|
||||
Some(not_considered_cached_inlays)
|
||||
})
|
||||
.flatten()
|
||||
.filter_map(|(cached_anchor, cached_inlay_id)| {
|
||||
Some((
|
||||
cached_anchor,
|
||||
cached_inlay_id,
|
||||
self.inlay_hints.get(&cached_inlay_id)?,
|
||||
))
|
||||
})
|
||||
.filter(|(_, _, cached_inlay)| self.allowed_hint_kinds.contains(&cached_inlay.kind))
|
||||
.map(|(cached_anchor, cached_inlay_id, reenabled_inlay)| {
|
||||
(
|
||||
Some(cached_inlay_id),
|
||||
cached_anchor,
|
||||
reenabled_inlay.clone(),
|
||||
)
|
||||
});
|
||||
to_insert.extend(reenabled_hints);
|
||||
|
||||
to_remove.extend(
|
||||
currently_shown_inlay_hints
|
||||
.into_iter()
|
||||
.flat_map(|(_, hints_by_excerpt)| hints_by_excerpt)
|
||||
.flat_map(|(_, excerpt_hints)| excerpt_hints)
|
||||
.map(|(_, hint_id)| hint_id),
|
||||
);
|
||||
|
||||
Some(InlaySplice {
|
||||
to_remove,
|
||||
@@ -114,13 +177,13 @@ impl InlayCache {
|
||||
&mut self,
|
||||
multi_buffer: ModelHandle<MultiBuffer>,
|
||||
ranges_to_add: impl Iterator<Item = InlayHintQuery>,
|
||||
currently_shown_inlays: Vec<(Anchor, InlayId)>,
|
||||
currently_shown_inlay_hints: HashMap<u64, HashMap<ExcerptId, Vec<(Anchor, InlayId)>>>,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
) -> Task<anyhow::Result<InlaySplice>> {
|
||||
self.fetch_inlays(
|
||||
multi_buffer,
|
||||
ranges_to_add,
|
||||
currently_shown_inlays,
|
||||
currently_shown_inlay_hints,
|
||||
false,
|
||||
cx,
|
||||
)
|
||||
@@ -130,21 +193,52 @@ impl InlayCache {
|
||||
&mut self,
|
||||
multi_buffer: ModelHandle<MultiBuffer>,
|
||||
new_ranges: impl Iterator<Item = InlayHintQuery>,
|
||||
currently_shown_inlays: Vec<(Anchor, InlayId)>,
|
||||
currently_shown_inlay_hints: HashMap<u64, HashMap<ExcerptId, Vec<(Anchor, InlayId)>>>,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
) -> Task<anyhow::Result<InlaySplice>> {
|
||||
self.fetch_inlays(multi_buffer, new_ranges, currently_shown_inlays, true, cx)
|
||||
self.fetch_inlays(
|
||||
multi_buffer,
|
||||
new_ranges,
|
||||
currently_shown_inlay_hints,
|
||||
true,
|
||||
cx,
|
||||
)
|
||||
}
|
||||
|
||||
fn fetch_inlays(
|
||||
&mut self,
|
||||
multi_buffer: ModelHandle<MultiBuffer>,
|
||||
inlay_fetch_ranges: impl Iterator<Item = InlayHintQuery>,
|
||||
currently_shown_inlays: Vec<(Anchor, InlayId)>,
|
||||
inlay_queries: impl Iterator<Item = InlayHintQuery>,
|
||||
mut currently_shown_inlay_hints: HashMap<u64, HashMap<ExcerptId, Vec<(Anchor, InlayId)>>>,
|
||||
replace_old: bool,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
) -> Task<anyhow::Result<InlaySplice>> {
|
||||
// TODO kb
|
||||
let multi_buffer_snapshot = multi_buffer.read(cx).snapshot(cx);
|
||||
let inlay_queries_per_buffer = inlay_queries.fold(
|
||||
HashMap::<u64, BufferInlays<InlayHintQuery>>::default(),
|
||||
|mut queries, new_query| {
|
||||
let mut buffer_queries = queries
|
||||
.entry(new_query.buffer_id)
|
||||
.or_insert_with(|| BufferInlays::new(new_query.buffer_version.clone()));
|
||||
assert_eq!(buffer_queries.buffer_version, new_query.buffer_version);
|
||||
let queries = buffer_queries
|
||||
.excerpt_inlays
|
||||
.entry(new_query.excerpt_id)
|
||||
.or_default();
|
||||
// let z = multi_buffer_snapshot.anchor_in_excerpt(new_query.excerpt_id, text_anchor);
|
||||
// .push(new_query);
|
||||
// match queries
|
||||
// .binary_search_by(|probe| inlay.position.cmp(&probe.0, &multi_buffer_snapshot))
|
||||
// {
|
||||
// Ok(ix) | Err(ix) => {
|
||||
// excerpt_hints.insert(ix, (inlay.position, inlay.id));
|
||||
// }
|
||||
// }
|
||||
// queries
|
||||
todo!("TODO kb")
|
||||
},
|
||||
);
|
||||
|
||||
todo!("TODO kb")
|
||||
}
|
||||
|
||||
@@ -2617,15 +2617,6 @@ impl MultiBufferSnapshot {
|
||||
}
|
||||
|
||||
pub fn anchor_in_excerpt(&self, excerpt_id: ExcerptId, text_anchor: text::Anchor) -> Anchor {
|
||||
self.find_anchor_in_excerpt(excerpt_id, text_anchor)
|
||||
.unwrap_or_else(|| panic!("excerpt not found"))
|
||||
}
|
||||
|
||||
pub fn find_anchor_in_excerpt(
|
||||
&self,
|
||||
excerpt_id: ExcerptId,
|
||||
text_anchor: text::Anchor,
|
||||
) -> Option<Anchor> {
|
||||
let locator = self.excerpt_locator_for_id(excerpt_id);
|
||||
let mut cursor = self.excerpts.cursor::<Option<&Locator>>();
|
||||
cursor.seek(locator, Bias::Left, &());
|
||||
@@ -2633,15 +2624,15 @@ impl MultiBufferSnapshot {
|
||||
if excerpt.id == excerpt_id {
|
||||
let text_anchor = excerpt.clip_anchor(text_anchor);
|
||||
drop(cursor);
|
||||
return Some(Anchor {
|
||||
return Anchor {
|
||||
buffer_id: Some(excerpt.buffer_id),
|
||||
excerpt_id,
|
||||
text_anchor,
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
panic!("excerpt not found")
|
||||
}
|
||||
|
||||
pub fn can_resolve(&self, anchor: &Anchor) -> bool {
|
||||
|
||||
@@ -18,7 +18,7 @@ use workspace::WorkspaceId;
|
||||
use crate::{
|
||||
display_map::{DisplaySnapshot, ToDisplayPoint},
|
||||
hover_popover::hide_hover,
|
||||
inlay_cache::InlayRefreshReason,
|
||||
inlay_hint_cache::InlayRefreshReason,
|
||||
persistence::DB,
|
||||
Anchor, DisplayPoint, Editor, EditorMode, Event, MultiBufferSnapshot, ToPoint,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user