Generate proper inlay diffs for splice
This commit is contained in:
@@ -6,8 +6,8 @@ mod tab_map;
|
||||
mod wrap_map;
|
||||
|
||||
use crate::{
|
||||
display_map::inlay_map::InlayProperties, Anchor, AnchorRangeExt, MultiBuffer,
|
||||
MultiBufferSnapshot, ToOffset, ToPoint,
|
||||
display_map::inlay_map::InlayProperties, inlay_cache::InlayId, Anchor, AnchorRangeExt,
|
||||
MultiBuffer, MultiBufferSnapshot, ToOffset, ToPoint,
|
||||
};
|
||||
pub use block_map::{BlockMap, BlockPoint};
|
||||
use collections::{HashMap, HashSet};
|
||||
@@ -287,7 +287,8 @@ impl DisplayMap {
|
||||
|
||||
pub fn splice_inlays(
|
||||
&mut self,
|
||||
new_hints: Vec<(Anchor, project::InlayHint)>,
|
||||
to_remove: Vec<InlayId>,
|
||||
to_insert: Vec<(InlayId, Anchor, project::InlayHint)>,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) {
|
||||
let buffer_snapshot = self.buffer.read(cx).snapshot(cx);
|
||||
@@ -302,18 +303,19 @@ impl DisplayMap {
|
||||
.update(cx, |map, cx| map.sync(snapshot, edits, cx));
|
||||
self.block_map.read(snapshot, edits);
|
||||
|
||||
let new_inlays = new_hints
|
||||
let new_inlays = to_insert
|
||||
.into_iter()
|
||||
.map(|(hint_anchor, hint)| InlayProperties {
|
||||
position: hint_anchor.bias_left(&buffer_snapshot),
|
||||
text: hint.text(),
|
||||
.map(|(inlay_id, hint_anchor, hint)| {
|
||||
(
|
||||
inlay_id,
|
||||
InlayProperties {
|
||||
position: hint_anchor.bias_left(&buffer_snapshot),
|
||||
text: hint.text(),
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let (snapshot, edits, _) = self.inlay_map.splice(
|
||||
// TODO kb this is wrong, calc diffs in the editor instead.
|
||||
self.inlay_map.inlays.keys().copied().collect(),
|
||||
new_inlays,
|
||||
);
|
||||
let (snapshot, edits) = self.inlay_map.splice(to_remove, new_inlays);
|
||||
let (snapshot, edits) = self.tab_map.sync(snapshot, edits, tab_size);
|
||||
let (snapshot, edits) = self
|
||||
.wrap_map
|
||||
|
||||
@@ -5,8 +5,8 @@ use super::{
|
||||
},
|
||||
TextHighlights,
|
||||
};
|
||||
use crate::{Anchor, MultiBufferSnapshot, ToPoint};
|
||||
use collections::{BTreeMap, HashMap, HashSet};
|
||||
use crate::{inlay_cache::InlayId, Anchor, MultiBufferSnapshot, ToPoint};
|
||||
use collections::{BTreeMap, HashMap};
|
||||
use gpui::fonts::HighlightStyle;
|
||||
use language::{Chunk, Edit, Point, Rope, TextSummary};
|
||||
use parking_lot::Mutex;
|
||||
@@ -16,14 +16,9 @@ use std::{
|
||||
};
|
||||
use sum_tree::{Bias, Cursor, SumTree};
|
||||
use text::Patch;
|
||||
use util::post_inc;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct InlayId(usize);
|
||||
|
||||
pub struct InlayMap {
|
||||
snapshot: Mutex<InlaySnapshot>,
|
||||
next_inlay_id: usize,
|
||||
pub(super) inlays: HashMap<InlayId, Inlay>,
|
||||
}
|
||||
|
||||
@@ -247,7 +242,6 @@ impl InlayMap {
|
||||
(
|
||||
Self {
|
||||
snapshot: Mutex::new(snapshot.clone()),
|
||||
next_inlay_id: 0,
|
||||
inlays: HashMap::default(),
|
||||
},
|
||||
snapshot,
|
||||
@@ -372,21 +366,19 @@ impl InlayMap {
|
||||
|
||||
pub fn splice<T: Into<Rope>>(
|
||||
&mut self,
|
||||
to_remove: HashSet<InlayId>,
|
||||
to_insert: Vec<InlayProperties<T>>,
|
||||
) -> (InlaySnapshot, Vec<InlayEdit>, Vec<InlayId>) {
|
||||
to_remove: Vec<InlayId>,
|
||||
to_insert: Vec<(InlayId, InlayProperties<T>)>,
|
||||
) -> (InlaySnapshot, Vec<InlayEdit>) {
|
||||
let mut snapshot = self.snapshot.lock();
|
||||
|
||||
let mut inlays = BTreeMap::new();
|
||||
let mut new_ids = Vec::new();
|
||||
for properties in to_insert {
|
||||
for (id, properties) in to_insert {
|
||||
let inlay = Inlay {
|
||||
id: InlayId(post_inc(&mut self.next_inlay_id)),
|
||||
id,
|
||||
position: properties.position,
|
||||
text: properties.text.into(),
|
||||
};
|
||||
self.inlays.insert(inlay.id, inlay.clone());
|
||||
new_ids.push(inlay.id);
|
||||
|
||||
let buffer_point = inlay.position.to_point(snapshot.buffer_snapshot());
|
||||
let fold_point = snapshot
|
||||
@@ -501,20 +493,20 @@ impl InlayMap {
|
||||
snapshot.version += 1;
|
||||
snapshot.check_invariants();
|
||||
|
||||
(snapshot.clone(), inlay_edits.into_inner(), new_ids)
|
||||
(snapshot.clone(), inlay_edits.into_inner())
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
pub fn randomly_mutate(
|
||||
&mut self,
|
||||
rng: &mut rand::rngs::StdRng,
|
||||
) -> (InlaySnapshot, Vec<InlayEdit>, Vec<InlayId>) {
|
||||
) -> (InlaySnapshot, Vec<InlayEdit>) {
|
||||
use rand::prelude::*;
|
||||
|
||||
let mut to_remove = HashSet::default();
|
||||
let mut to_insert = Vec::default();
|
||||
let mut to_remove = Vec::new();
|
||||
let mut to_insert = Vec::new();
|
||||
let snapshot = self.snapshot.lock();
|
||||
for _ in 0..rng.gen_range(1..=5) {
|
||||
for i in 0..rng.gen_range(1..=5) {
|
||||
if self.inlays.is_empty() || rng.gen() {
|
||||
let buffer_snapshot = snapshot.buffer_snapshot();
|
||||
let position = buffer_snapshot.random_byte_range(0, rng).start;
|
||||
@@ -529,12 +521,15 @@ impl InlayMap {
|
||||
bias,
|
||||
text
|
||||
);
|
||||
to_insert.push(InlayProperties {
|
||||
position: buffer_snapshot.anchor_at(position, bias),
|
||||
text,
|
||||
});
|
||||
to_insert.push((
|
||||
InlayId(i),
|
||||
InlayProperties {
|
||||
position: buffer_snapshot.anchor_at(position, bias),
|
||||
text,
|
||||
},
|
||||
));
|
||||
} else {
|
||||
to_remove.insert(*self.inlays.keys().choose(rng).unwrap());
|
||||
to_remove.push(*self.inlays.keys().choose(rng).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -841,6 +836,7 @@ mod tests {
|
||||
use settings::SettingsStore;
|
||||
use std::env;
|
||||
use text::Patch;
|
||||
use util::post_inc;
|
||||
|
||||
#[gpui::test]
|
||||
fn test_basic_inlays(cx: &mut AppContext) {
|
||||
@@ -850,13 +846,17 @@ mod tests {
|
||||
let (suggestion_map, suggestion_snapshot) = SuggestionMap::new(fold_snapshot.clone());
|
||||
let (mut inlay_map, inlay_snapshot) = InlayMap::new(suggestion_snapshot.clone());
|
||||
assert_eq!(inlay_snapshot.text(), "abcdefghi");
|
||||
let mut next_inlay_id = 0;
|
||||
|
||||
let (inlay_snapshot, _, _) = inlay_map.splice(
|
||||
HashSet::default(),
|
||||
vec![InlayProperties {
|
||||
position: buffer.read(cx).snapshot(cx).anchor_after(3),
|
||||
text: "|123|",
|
||||
}],
|
||||
let (inlay_snapshot, _) = inlay_map.splice(
|
||||
Vec::new(),
|
||||
vec![(
|
||||
InlayId(post_inc(&mut next_inlay_id)),
|
||||
InlayProperties {
|
||||
position: buffer.read(cx).snapshot(cx).anchor_after(3),
|
||||
text: "|123|",
|
||||
},
|
||||
)],
|
||||
);
|
||||
assert_eq!(inlay_snapshot.text(), "abc|123|defghi");
|
||||
assert_eq!(
|
||||
@@ -932,17 +932,23 @@ mod tests {
|
||||
let (inlay_snapshot, _) = inlay_map.sync(suggestion_snapshot.clone(), suggestion_edits);
|
||||
assert_eq!(inlay_snapshot.text(), "abxyDzefghi");
|
||||
|
||||
let (inlay_snapshot, _, inlay_ids) = inlay_map.splice(
|
||||
HashSet::default(),
|
||||
let (inlay_snapshot, _) = inlay_map.splice(
|
||||
Vec::new(),
|
||||
vec![
|
||||
InlayProperties {
|
||||
position: buffer.read(cx).snapshot(cx).anchor_before(3),
|
||||
text: "|123|",
|
||||
},
|
||||
InlayProperties {
|
||||
position: buffer.read(cx).snapshot(cx).anchor_after(3),
|
||||
text: "|456|",
|
||||
},
|
||||
(
|
||||
InlayId(post_inc(&mut next_inlay_id)),
|
||||
InlayProperties {
|
||||
position: buffer.read(cx).snapshot(cx).anchor_before(3),
|
||||
text: "|123|",
|
||||
},
|
||||
),
|
||||
(
|
||||
InlayId(post_inc(&mut next_inlay_id)),
|
||||
InlayProperties {
|
||||
position: buffer.read(cx).snapshot(cx).anchor_after(3),
|
||||
text: "|456|",
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
assert_eq!(inlay_snapshot.text(), "abx|123||456|yDzefghi");
|
||||
@@ -959,8 +965,8 @@ mod tests {
|
||||
assert_eq!(inlay_snapshot.text(), "abx|123|JKL|456|yDzefghi");
|
||||
|
||||
// The inlays can be manually removed.
|
||||
let (inlay_snapshot, _, _) =
|
||||
inlay_map.splice::<String>(HashSet::from_iter(inlay_ids), Default::default());
|
||||
let (inlay_snapshot, _) =
|
||||
inlay_map.splice::<String>(inlay_map.inlays.keys().copied().collect(), Vec::new());
|
||||
assert_eq!(inlay_snapshot.text(), "abxJKLyDzefghi");
|
||||
}
|
||||
|
||||
@@ -996,8 +1002,8 @@ mod tests {
|
||||
let mut buffer_edits = Vec::new();
|
||||
match rng.gen_range(0..=100) {
|
||||
0..=29 => {
|
||||
let (snapshot, edits, _) = inlay_map.randomly_mutate(&mut rng);
|
||||
inlay_snapshot = snapshot;
|
||||
let (snapshot, edits) = inlay_map.randomly_mutate(&mut rng);
|
||||
log::info!("mutated text: {:?}", snapshot.text());
|
||||
inlay_edits = Patch::new(edits);
|
||||
}
|
||||
30..=59 => {
|
||||
|
||||
+48
-16
@@ -2,7 +2,7 @@ mod blink_manager;
|
||||
pub mod display_map;
|
||||
mod editor_settings;
|
||||
mod element;
|
||||
mod inlay_hint_storage;
|
||||
mod inlay_cache;
|
||||
|
||||
mod git;
|
||||
mod highlight_matching_bracket;
|
||||
@@ -26,8 +26,8 @@ use aho_corasick::AhoCorasick;
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use blink_manager::BlinkManager;
|
||||
use client::{ClickhouseEvent, TelemetrySettings};
|
||||
use clock::ReplicaId;
|
||||
use collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque};
|
||||
use clock::{Global, ReplicaId};
|
||||
use collections::{hash_map, BTreeMap, Bound, HashMap, HashSet, VecDeque};
|
||||
use copilot::Copilot;
|
||||
pub use display_map::DisplayPoint;
|
||||
use display_map::*;
|
||||
@@ -53,7 +53,7 @@ use gpui::{
|
||||
};
|
||||
use highlight_matching_bracket::refresh_matching_bracket_highlights;
|
||||
use hover_popover::{hide_hover, HoverState};
|
||||
use inlay_hint_storage::InlayHintStorage;
|
||||
use inlay_cache::{InlayCache, InlaysUpdate, OrderedByAnchorOffset};
|
||||
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_hint_storage: InlayHintStorage,
|
||||
inlay_hint_cache: InlayCache,
|
||||
_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_hint_storage: InlayHintStorage::default(),
|
||||
inlay_hint_cache: InlayCache::default(),
|
||||
gutter_hovered: false,
|
||||
_subscriptions: vec![
|
||||
cx.observe(&buffer, Self::on_buffer_changed),
|
||||
@@ -2604,7 +2604,14 @@ impl Editor {
|
||||
// TODO kb every time I reopen the same buffer, it's different.
|
||||
// Find a way to understand it's the same buffer. Use paths?
|
||||
let buffer_id = buffer_snapshot.remote_id();
|
||||
let buffer_version = buffer_snapshot.version().clone();
|
||||
let buffer_handle = multi_buffer.read(cx).buffer(buffer_id)?;
|
||||
if self
|
||||
.inlay_hint_cache
|
||||
.inlays_up_to_date(buffer_id, &buffer_version, excerpt_id)
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
let task = cx.spawn(|editor, mut cx| async move {
|
||||
let task = editor
|
||||
@@ -2622,6 +2629,8 @@ impl Editor {
|
||||
.context("inlay hints fecth task spawn")?;
|
||||
|
||||
anyhow::Ok((
|
||||
buffer_id,
|
||||
buffer_version,
|
||||
excerpt_id,
|
||||
match task {
|
||||
Some(task) => task.await.context("inlay hints for buffer task")?,
|
||||
@@ -2634,29 +2643,52 @@ impl Editor {
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
cx.spawn(|editor, mut cx| async move {
|
||||
let mut hints_to_draw: Vec<(Anchor, InlayHint)> = Vec::new();
|
||||
let mut hints_response: HashMap<
|
||||
u64,
|
||||
(Global, HashMap<ExcerptId, OrderedByAnchorOffset<InlayHint>>),
|
||||
> = HashMap::default();
|
||||
let multi_buffer_snapshot =
|
||||
editor.read_with(&cx, |editor, cx| editor.buffer().read(cx).snapshot(cx))?;
|
||||
|
||||
for task_result in futures::future::join_all(hint_fetch_tasks).await {
|
||||
match task_result {
|
||||
Ok((excerpt_id, excerpt_hints)) => {
|
||||
if !excerpt_hints.is_empty() {
|
||||
hints_to_draw.extend(excerpt_hints.into_iter().map(|hint| {
|
||||
let anchor = multi_buffer_snapshot
|
||||
.anchor_in_excerpt(excerpt_id, hint.position);
|
||||
(anchor, hint)
|
||||
}));
|
||||
Ok((buffer_id, buffer_version, excerpt_id, excerpt_hints)) => {
|
||||
let excerpt_hints_response = HashMap::from_iter([(
|
||||
excerpt_id,
|
||||
excerpt_hints.into_iter().fold(
|
||||
OrderedByAnchorOffset::default(),
|
||||
|mut ordered_hints, hint| {
|
||||
let anchor = multi_buffer_snapshot
|
||||
.anchor_in_excerpt(excerpt_id, hint.position);
|
||||
ordered_hints.add(anchor, hint);
|
||||
ordered_hints
|
||||
},
|
||||
),
|
||||
)]);
|
||||
match hints_response.entry(buffer_id) {
|
||||
hash_map::Entry::Occupied(mut o) => {
|
||||
o.get_mut().1.extend(excerpt_hints_response);
|
||||
}
|
||||
hash_map::Entry::Vacant(v) => {
|
||||
v.insert((buffer_version, excerpt_hints_response));
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => error!("Failed to update hints for buffer: {e:#}"),
|
||||
}
|
||||
}
|
||||
|
||||
if !hints_to_draw.is_empty() {
|
||||
if !hints_response.is_empty() {
|
||||
let InlaysUpdate {
|
||||
to_remove,
|
||||
to_insert,
|
||||
} = editor.update(&mut cx, |editor, _| {
|
||||
editor.inlay_hint_cache.update_inlays(hints_response)
|
||||
})?;
|
||||
|
||||
editor.update(&mut cx, |editor, cx| {
|
||||
editor.display_map.update(cx, |display_map, cx| {
|
||||
display_map.splice_inlays(hints_to_draw, cx);
|
||||
display_map.splice_inlays(to_remove, to_insert, cx);
|
||||
});
|
||||
})?;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
use std::cmp;
|
||||
|
||||
use crate::{Anchor, ExcerptId};
|
||||
use clock::Global;
|
||||
use project::InlayHint;
|
||||
use util::post_inc;
|
||||
|
||||
use collections::{BTreeMap, HashMap};
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct InlayCache {
|
||||
inlays_per_buffer: HashMap<u64, BufferInlays>,
|
||||
next_inlay_id: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OrderedByAnchorOffset<T>(pub BTreeMap<usize, (Anchor, T)>);
|
||||
|
||||
impl<T> OrderedByAnchorOffset<T> {
|
||||
pub fn add(&mut self, anchor: Anchor, t: T) {
|
||||
self.0.insert(anchor.text_anchor.offset, (anchor, t));
|
||||
}
|
||||
|
||||
fn into_ordered_elements(self) -> impl Iterator<Item = (Anchor, T)> {
|
||||
self.0.into_values()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Default for OrderedByAnchorOffset<T> {
|
||||
fn default() -> Self {
|
||||
Self(BTreeMap::default())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
struct BufferInlays {
|
||||
buffer_version: Global,
|
||||
inlays_per_excerpts: HashMap<ExcerptId, OrderedByAnchorOffset<(InlayId, InlayHint)>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct InlayId(pub usize);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InlaysUpdate {
|
||||
pub to_remove: Vec<InlayId>,
|
||||
pub to_insert: Vec<(InlayId, Anchor, InlayHint)>,
|
||||
}
|
||||
|
||||
impl InlayCache {
|
||||
pub fn inlays_up_to_date(
|
||||
&self,
|
||||
buffer_id: u64,
|
||||
buffer_version: &Global,
|
||||
excerpt_id: ExcerptId,
|
||||
) -> bool {
|
||||
let Some(buffer_inlays) = self.inlays_per_buffer.get(&buffer_id) 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)
|
||||
}
|
||||
|
||||
pub fn update_inlays(
|
||||
&mut self,
|
||||
new_inlays: HashMap<u64, (Global, HashMap<ExcerptId, OrderedByAnchorOffset<InlayHint>>)>,
|
||||
) -> InlaysUpdate {
|
||||
let mut old_inlays = self.inlays_per_buffer.clone();
|
||||
let mut to_remove = Vec::new();
|
||||
let mut to_insert = Vec::new();
|
||||
|
||||
for (buffer_id, (buffer_version, new_buffer_inlays)) in new_inlays {
|
||||
match old_inlays.remove(&buffer_id) {
|
||||
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) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let self_inlays_per_buffer = self
|
||||
.inlays_per_buffer
|
||||
.get_mut(&buffer_id)
|
||||
.expect("element expected: `old_inlays.remove` returned `Some`");
|
||||
let mut new_excerpt_inlays =
|
||||
new_excerpt_inlays.into_ordered_elements().fuse().peekable();
|
||||
if old_buffer_inlays
|
||||
.inlays_per_excerpts
|
||||
.remove(&excerpt_id)
|
||||
.is_some()
|
||||
{
|
||||
let self_excerpt_inlays = self_inlays_per_buffer
|
||||
.inlays_per_excerpts
|
||||
.get_mut(&excerpt_id)
|
||||
.expect("element expected: `old_excerpt_inlays` is `Some`");
|
||||
let mut hints_to_add = Vec::<(Anchor, (InlayId, InlayHint))>::new();
|
||||
self_excerpt_inlays.0.retain(
|
||||
|_, (old_anchor, (old_inlay_id, old_inlay))| {
|
||||
let mut retain = false;
|
||||
|
||||
while let Some(new_offset) = new_excerpt_inlays
|
||||
.peek()
|
||||
.map(|(new_anchor, _)| new_anchor.text_anchor.offset)
|
||||
{
|
||||
let old_offset = old_anchor.text_anchor.offset;
|
||||
match new_offset.cmp(&old_offset) {
|
||||
cmp::Ordering::Less => {
|
||||
let (new_anchor, new_inlay) =
|
||||
new_excerpt_inlays.next().expect(
|
||||
"element expected: `peek` returned `Some`",
|
||||
);
|
||||
hints_to_add.push((
|
||||
new_anchor,
|
||||
(
|
||||
InlayId(post_inc(&mut self.next_inlay_id)),
|
||||
new_inlay,
|
||||
),
|
||||
));
|
||||
}
|
||||
cmp::Ordering::Equal => {
|
||||
let (new_anchor, new_inlay) =
|
||||
new_excerpt_inlays.next().expect(
|
||||
"element expected: `peek` returned `Some`",
|
||||
);
|
||||
if &new_inlay == old_inlay {
|
||||
retain = true;
|
||||
} else {
|
||||
hints_to_add.push((
|
||||
new_anchor,
|
||||
(
|
||||
InlayId(post_inc(
|
||||
&mut self.next_inlay_id,
|
||||
)),
|
||||
new_inlay,
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
cmp::Ordering::Greater => break,
|
||||
}
|
||||
}
|
||||
|
||||
if !retain {
|
||||
to_remove.push(*old_inlay_id);
|
||||
}
|
||||
retain
|
||||
},
|
||||
);
|
||||
|
||||
for (new_anchor, (id, new_inlay)) in hints_to_add {
|
||||
self_excerpt_inlays.add(new_anchor, (id, new_inlay.clone()));
|
||||
to_insert.push((id, new_anchor, new_inlay));
|
||||
}
|
||||
}
|
||||
|
||||
for (new_anchor, new_inlay) in new_excerpt_inlays {
|
||||
let id = InlayId(post_inc(&mut self.next_inlay_id));
|
||||
self_inlays_per_buffer
|
||||
.inlays_per_excerpts
|
||||
.entry(excerpt_id)
|
||||
.or_default()
|
||||
.add(new_anchor, (id, new_inlay.clone()));
|
||||
to_insert.push((id, new_anchor, new_inlay));
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
let mut inlays_per_excerpts: HashMap<
|
||||
ExcerptId,
|
||||
OrderedByAnchorOffset<(InlayId, InlayHint)>,
|
||||
> = HashMap::default();
|
||||
for (new_excerpt_id, new_ordered_inlays) in new_buffer_inlays {
|
||||
for (new_anchor, new_inlay) in new_ordered_inlays.into_ordered_elements() {
|
||||
let id = InlayId(post_inc(&mut self.next_inlay_id));
|
||||
inlays_per_excerpts
|
||||
.entry(new_excerpt_id)
|
||||
.or_default()
|
||||
.add(new_anchor, (id, new_inlay.clone()));
|
||||
to_insert.push((id, new_anchor, new_inlay));
|
||||
}
|
||||
}
|
||||
self.inlays_per_buffer.insert(
|
||||
buffer_id,
|
||||
BufferInlays {
|
||||
buffer_version,
|
||||
inlays_per_excerpts,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (_, old_buffer_inlays) in old_inlays {
|
||||
for (_, old_excerpt_inlays) in old_buffer_inlays.inlays_per_excerpts {
|
||||
for (_, (id_to_remove, _)) in old_excerpt_inlays.into_ordered_elements() {
|
||||
to_remove.push(id_to_remove);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InlaysUpdate {
|
||||
to_remove,
|
||||
to_insert,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
use crate::Anchor;
|
||||
use project::InlayHint;
|
||||
|
||||
use collections::BTreeMap;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct InlayHintStorage {
|
||||
hints: BTreeMap<Anchor, InlayHint>,
|
||||
}
|
||||
|
||||
impl InlayHintStorage {
|
||||
fn insert(&mut self) -> bool {
|
||||
todo!("TODO kb")
|
||||
}
|
||||
}
|
||||
// TODO kb need to understand different inlay hint update cases:
|
||||
// * new hints from the new excerpt (no need to invalidate the cache)
|
||||
// * new hints after /refresh or a text edit (whole cache should be purged)
|
||||
// ??? revert/reopened files could get a speedup, if we don't truly delete the hints, but hide them in another var?
|
||||
|
||||
// let buffer_version =
|
||||
// cx.read(|cx| buffer.read(cx).version().clone());
|
||||
|
||||
// #[derive(Debug, Default, Clone)]
|
||||
// struct InlayHintVersions {
|
||||
// last_buffer_versions_with_hints: HashMap<InlayHintLocation, Global>,
|
||||
// }
|
||||
|
||||
// impl InlayHintVersions {
|
||||
// fn absent_or_newer(&self, location: &InlayHintLocation, new_version: &Global) -> bool {
|
||||
// self.last_buffer_versions_with_hints
|
||||
// .get(location)
|
||||
// .map(|last_version_with_hints| new_version.changed_since(&last_version_with_hints))
|
||||
// .unwrap_or(true)
|
||||
// }
|
||||
|
||||
// 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(location, new_version);
|
||||
// true
|
||||
// } else {
|
||||
// false
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
Reference in New Issue
Block a user