History

Fix more panics when removing excerpts (#28836)

Release Notes: - Fixed a panic when an excerpt removed has an edit suggestion inlay in it ---------

Kirill Bulatov committed 1 year ago

Commit 486a9e41 parent 0d8f77b5 files · +26 −8Browse files

Unified · Split

5 files
  1. crates/editor/src/display_map.rs +17 −2
  2. crates/editor/src/editor.rs +4 −1
  3. crates/editor/src/inlay_hint_cache.rs +3 −3
  4. crates/multi_buffer/src/anchor.rs +1 −1
  5. crates/multi_buffer/src/multi_buffer.rs +1 −1
crates/editor/src/display_map.rs+17−2
@@ -49,8 +49,8 @@ use language::{ · 48 unmodified lines
4949 };
5050 use lsp::DiagnosticSeverity;
5151 use multi_buffer::{
52− Anchor, AnchorRangeExt, MultiBuffer, MultiBufferPoint, MultiBufferRow, MultiBufferSnapshot,
53− RowInfo, ToOffset, ToPoint,
52+ Anchor, AnchorRangeExt, ExcerptId, MultiBuffer, MultiBufferPoint, MultiBufferRow,
53+ MultiBufferSnapshot, RowInfo, ToOffset, ToPoint,
5454 };
5555 use serde::Deserialize;
5656 use std::{
@@ -574,6 +574,21 @@ impl DisplayMap { · 517 unmodified lines
574574 self.block_map.read(snapshot, edits);
575575 }
576576
577+ pub fn remove_inlays_for_excerpts(&mut self, excerpts_removed: &[ExcerptId]) {
578+ let to_remove = self
579+ .inlay_map
580+ .current_inlays()
581+ .filter_map(|inlay| {
582+ if excerpts_removed.contains(&inlay.position.excerpt_id) {
583+ Some(inlay.id)
584+ } else {
585+ None
586+ }
587+ })
588+ .collect::<Vec<_>>();
589+ self.inlay_map.splice(&to_remove, Vec::new());
590+ }
591+
577592 fn tab_size(buffer: &Entity<MultiBuffer>, cx: &App) -> NonZeroU32 {
578593 let buffer = buffer.read(cx).as_singleton().map(|buffer| buffer.read(cx));
579594 let language = buffer
crates/editor/src/editor.rs+4−1
@@ -4170,10 +4170,13 @@ impl Editor { · 4169 unmodified lines
41704170 if let Some(InlaySplice {
41714171 to_remove,
41724172 to_insert,
4173− }) = self.inlay_hint_cache.remove_excerpts(excerpts_removed)
4173+ }) = self.inlay_hint_cache.remove_excerpts(&excerpts_removed)
41744174 {
41754175 self.splice_inlays(&to_remove, to_insert, cx);
41764176 }
4177+ self.display_map.update(cx, |display_map, _| {
4178+ display_map.remove_inlays_for_excerpts(&excerpts_removed)
4179+ });
41774180 return;
41784181 }
41794182 InlayHintRefreshReason::NewLinesShown => (InvalidationStrategy::None, None),
crates/editor/src/inlay_hint_cache.rs+3−3
@@ -555,12 +555,12 @@ impl InlayHintCache { · 554 unmodified lines
555555 /// Completely forget of certain excerpts that were removed from the multibuffer.
556556 pub(super) fn remove_excerpts(
557557 &mut self,
558− excerpts_removed: Vec<ExcerptId>,
558+ excerpts_removed: &[ExcerptId],
559559 ) -> Option<InlaySplice> {
560560 let mut to_remove = Vec::new();
561561 for excerpt_to_remove in excerpts_removed {
562− self.update_tasks.remove(&excerpt_to_remove);
563− if let Some(cached_hints) = self.hints.remove(&excerpt_to_remove) {
562+ self.update_tasks.remove(excerpt_to_remove);
563+ if let Some(cached_hints) = self.hints.remove(excerpt_to_remove) {
564564 let cached_hints = cached_hints.read();
565565 to_remove.extend(cached_hints.ordered_hints.iter().copied());
566566 }
crates/multi_buffer/src/anchor.rs+1−1
@@ -71,7 +71,7 @@ impl Anchor { · 70 unmodified lines
7171 if self_excerpt_id == ExcerptId::min() || self_excerpt_id == ExcerptId::max() {
7272 return Ordering::Equal;
7373 }
74− if let Some(excerpt) = snapshot.excerpt(self.excerpt_id) {
74+ if let Some(excerpt) = snapshot.excerpt(self_excerpt_id) {
7575 let text_cmp = self.text_anchor.cmp(&other.text_anchor, &excerpt.buffer);
7676 if text_cmp.is_ne() {
7777 return text_cmp;
crates/multi_buffer/src/multi_buffer.rs+1−1
@@ -6041,7 +6041,7 @@ impl MultiBufferSnapshot { · 6040 unmodified lines
60416041 return &entry.locator;
60426042 }
60436043 }
6044− panic!("invalid excerpt id {:?}", id)
6044+ panic!("invalid excerpt id {id:?}")
60456045 }
60466046 }
60476047