diff --git a/crates/editor/src/display_map.rs b/crates/editor/src/display_map.rs index 31a1f68300d6d24ef449f4f0eb0b072f0cbe0ea9..888a3729ca769551954712dc2e8c3fb197367551 100644 --- a/crates/editor/src/display_map.rs +++ b/crates/editor/src/display_map.rs @@ -113,6 +113,7 @@ use unicode_segmentation::UnicodeSegmentation; use ztracing::instrument; use std::cell::RefCell; +use std::collections::hash_map::Entry; use std::{ any::TypeId, borrow::Cow, @@ -175,9 +176,9 @@ pub trait ToDisplayPoint { fn to_display_point(&self, map: &DisplaySnapshot) -> DisplayPoint; } -type TextHighlights = TreeMap>)>>; +type TextHighlights = Arc>)>>>; type SemanticTokensHighlights = - TreeMap, Arc)>; + Arc, Arc)>>; type InlayHighlights = TreeMap>; #[derive(Debug)] @@ -478,7 +479,7 @@ impl DisplayMap { diagnostics_max_severity, text_highlights: Default::default(), inlay_highlights: Default::default(), - semantic_token_highlights: TreeMap::default(), + semantic_token_highlights: Default::default(), clip_at_line_ends: false, masked: false, companion: None, @@ -1226,22 +1227,25 @@ impl DisplayMap { cx: &App, ) { let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx); - let to_insert = match self.text_highlights.remove(&key) { - Some(mut previous) if merge => match Arc::get_mut(&mut previous) { - Some((_, previous_ranges)) => { + match Arc::make_mut(&mut self.text_highlights).entry(key) { + Entry::Occupied(mut slot) => match Arc::get_mut(slot.get_mut()) { + Some((_, previous_ranges)) if merge => { previous_ranges.extend(ranges); previous_ranges.sort_by(|a, b| a.start.cmp(&b.start, &multi_buffer_snapshot)); - previous } - None => Arc::new((style, { - ranges.extend(previous.1.iter().cloned()); + Some((previous_style, previous_ranges)) => { + *previous_style = style; + *previous_ranges = ranges; + } + None if merge => { + ranges.extend(slot.get().1.iter().cloned()); ranges.sort_by(|a, b| a.start.cmp(&b.start, &multi_buffer_snapshot)); - ranges - })), + slot.insert(Arc::new((style, ranges))); + } + None => _ = slot.insert(Arc::new((style, ranges))), }, - _ => Arc::new((style, ranges)), - }; - self.text_highlights.insert(key, to_insert); + Entry::Vacant(slot) => _ = slot.insert(Arc::new((style, ranges))), + } } #[instrument(skip_all)] @@ -1288,14 +1292,16 @@ impl DisplayMap { } pub fn clear_highlights(&mut self, key: HighlightKey) -> bool { - let mut cleared = self.text_highlights.remove(&key).is_some(); + let mut cleared = Arc::make_mut(&mut self.text_highlights) + .remove(&key) + .is_some(); cleared |= self.inlay_highlights.remove(&key).is_some(); cleared } pub fn clear_highlights_with(&mut self, f: &mut dyn FnMut(&HighlightKey) -> bool) -> bool { let mut cleared = false; - self.text_highlights.retain(|k, _| { + Arc::make_mut(&mut self.text_highlights).retain(|k, _| { let b = !f(k); cleared |= b; b @@ -1448,7 +1454,7 @@ impl DisplayMap { } pub fn invalidate_semantic_highlights(&mut self, buffer_id: BufferId) { - self.semantic_token_highlights.remove(&buffer_id); + Arc::make_mut(&mut self.semantic_token_highlights).remove(&buffer_id); } } diff --git a/crates/editor/src/display_map/inlay_map.rs b/crates/editor/src/display_map/inlay_map.rs index 8bc66123c41a1e7af4e2814bc79ea80c97219f14..9e853c8292c8073f20af58ee4d8f71c8db269cfa 100644 --- a/crates/editor/src/display_map/inlay_map.rs +++ b/crates/editor/src/display_map/inlay_map.rs @@ -1328,9 +1328,10 @@ mod tests { use super::*; use crate::{ MultiBuffer, - display_map::{HighlightKey, InlayHighlights, TextHighlights}, + display_map::{HighlightKey, InlayHighlights}, hover_links::InlayHighlight, }; + use collections::HashMap; use gpui::{App, HighlightStyle}; use multi_buffer::Anchor; use project::{InlayHint, InlayHintLabel, ResolveState}; @@ -1897,7 +1898,7 @@ mod tests { ); } - let mut text_highlights = TextHighlights::default(); + let mut text_highlights = HashMap::default(); let text_highlight_count = rng.random_range(0_usize..10); let mut text_highlight_ranges = (0..text_highlight_count) .map(|_| buffer_snapshot.random_byte_range(MultiBufferOffset(0), &mut rng)) @@ -1917,6 +1918,7 @@ mod tests { .collect(), )), ); + let text_highlights = Arc::new(text_highlights); let mut inlay_highlights = InlayHighlights::default(); if !inlays.is_empty() { diff --git a/crates/editor/src/semantic_tokens.rs b/crates/editor/src/semantic_tokens.rs index d2bbe533124efdb252dc80c5677165521ef76bab..8742ae82a80a7a623d5e6c98afc908f34f6e4b84 100644 --- a/crates/editor/src/semantic_tokens.rs +++ b/crates/editor/src/semantic_tokens.rs @@ -122,7 +122,10 @@ impl Editor { if !self.mode().is_full() || !self.semantic_token_state.enabled() { self.invalidate_semantic_tokens(None); self.display_map.update(cx, |display_map, _| { - display_map.semantic_token_highlights.clear(); + match Arc::get_mut(&mut display_map.semantic_token_highlights) { + Some(highlights) => highlights.clear(), + None => display_map.semantic_token_highlights = Arc::new(Default::default()), + }; }); self.semantic_token_state.update_task = Task::ready(()); cx.notify(); @@ -171,8 +174,8 @@ impl Editor { .display_map .read(cx) .semantic_token_highlights - .iter() - .map(|(buffer_id, _)| *buffer_id) + .keys() + .copied() .filter(|buffer_id| !buffers_to_query.contains_key(buffer_id)) .filter(|buffer_id| { !self @@ -308,7 +311,7 @@ impl Editor { token_highlights.sort_by(|a, b| { a.range.start.cmp(&b.range.start, &multi_buffer_snapshot) }); - display_map.semantic_token_highlights.insert( + Arc::make_mut(&mut display_map.semantic_token_highlights).insert( buffer_id, (Arc::from(token_highlights), Arc::new(interner)), ); diff --git a/crates/multi_buffer/src/multi_buffer.rs b/crates/multi_buffer/src/multi_buffer.rs index 6a90d9c410859324d31ebbd59c909e31127ecc6a..03615ffcabb2a5c46469bc16198adfce95e0c6ef 100644 --- a/crates/multi_buffer/src/multi_buffer.rs +++ b/crates/multi_buffer/src/multi_buffer.rs @@ -624,7 +624,7 @@ pub struct MultiBufferSnapshot { diffs: TreeMap, diff_transforms: SumTree, excerpt_ids: SumTree, - replaced_excerpts: TreeMap, + replaced_excerpts: Arc>, non_text_state_update_count: usize, edit_count: usize, is_dirty: bool, @@ -1967,7 +1967,10 @@ impl MultiBuffer { *has_deleted_file = false; *has_conflict = false; *has_inverted_diff = false; - replaced_excerpts.clear(); + match Arc::get_mut(replaced_excerpts) { + Some(replaced_excerpts) => replaced_excerpts.clear(), + None => *replaced_excerpts = Default::default(), + } let edits = Self::sync_diff_transforms( self.snapshot.get_mut(), diff --git a/crates/multi_buffer/src/path_key.rs b/crates/multi_buffer/src/path_key.rs index 475ed3c9d623382c5ed989918ee3224afc95cd25..eeaf3c5995dc446a704857b2a111c0aeb50e48a1 100644 --- a/crates/multi_buffer/src/path_key.rs +++ b/crates/multi_buffer/src/path_key.rs @@ -382,9 +382,7 @@ impl MultiBuffer { { last.context.end = last.context.end.max(existing_range.end); to_remove.push(*existing_id); - self.snapshot - .get_mut() - .replaced_excerpts + Arc::make_mut(&mut self.snapshot.get_mut().replaced_excerpts) .insert(*existing_id, *last_id); existing_iter.next(); continue; @@ -462,9 +460,7 @@ impl MultiBuffer { (Some(_), Some((_, existing_range))) => { let existing_id = existing_iter.next().unwrap(); let new_id = next_excerpt_id(); - self.snapshot - .get_mut() - .replaced_excerpts + Arc::make_mut(&mut self.snapshot.get_mut().replaced_excerpts) .insert(existing_id, new_id); to_remove.push(existing_id); let mut range = new_iter.next().unwrap();