Fix more panics when removing excerpts (#28836)

Release Notes:

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

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
This commit is contained in:
Kirill Bulatov 2025-04-16 09:33:28 -06:00 committed by GitHub
parent 0d8f77b5de
commit 486a9e4d61
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 26 additions and 8 deletions

View file

@ -49,8 +49,8 @@ use language::{
}; };
use lsp::DiagnosticSeverity; use lsp::DiagnosticSeverity;
use multi_buffer::{ use multi_buffer::{
Anchor, AnchorRangeExt, MultiBuffer, MultiBufferPoint, MultiBufferRow, MultiBufferSnapshot, Anchor, AnchorRangeExt, ExcerptId, MultiBuffer, MultiBufferPoint, MultiBufferRow,
RowInfo, ToOffset, ToPoint, MultiBufferSnapshot, RowInfo, ToOffset, ToPoint,
}; };
use serde::Deserialize; use serde::Deserialize;
use std::{ use std::{
@ -574,6 +574,21 @@ impl DisplayMap {
self.block_map.read(snapshot, edits); self.block_map.read(snapshot, edits);
} }
pub fn remove_inlays_for_excerpts(&mut self, excerpts_removed: &[ExcerptId]) {
let to_remove = self
.inlay_map
.current_inlays()
.filter_map(|inlay| {
if excerpts_removed.contains(&inlay.position.excerpt_id) {
Some(inlay.id)
} else {
None
}
})
.collect::<Vec<_>>();
self.inlay_map.splice(&to_remove, Vec::new());
}
fn tab_size(buffer: &Entity<MultiBuffer>, cx: &App) -> NonZeroU32 { fn tab_size(buffer: &Entity<MultiBuffer>, cx: &App) -> NonZeroU32 {
let buffer = buffer.read(cx).as_singleton().map(|buffer| buffer.read(cx)); let buffer = buffer.read(cx).as_singleton().map(|buffer| buffer.read(cx));
let language = buffer let language = buffer

View file

@ -4170,10 +4170,13 @@ impl Editor {
if let Some(InlaySplice { if let Some(InlaySplice {
to_remove, to_remove,
to_insert, to_insert,
}) = self.inlay_hint_cache.remove_excerpts(excerpts_removed) }) = self.inlay_hint_cache.remove_excerpts(&excerpts_removed)
{ {
self.splice_inlays(&to_remove, to_insert, cx); self.splice_inlays(&to_remove, to_insert, cx);
} }
self.display_map.update(cx, |display_map, _| {
display_map.remove_inlays_for_excerpts(&excerpts_removed)
});
return; return;
} }
InlayHintRefreshReason::NewLinesShown => (InvalidationStrategy::None, None), InlayHintRefreshReason::NewLinesShown => (InvalidationStrategy::None, None),

View file

@ -555,12 +555,12 @@ impl InlayHintCache {
/// Completely forget of certain excerpts that were removed from the multibuffer. /// Completely forget of certain excerpts that were removed from the multibuffer.
pub(super) fn remove_excerpts( pub(super) fn remove_excerpts(
&mut self, &mut self,
excerpts_removed: Vec<ExcerptId>, excerpts_removed: &[ExcerptId],
) -> Option<InlaySplice> { ) -> Option<InlaySplice> {
let mut to_remove = Vec::new(); let mut to_remove = Vec::new();
for excerpt_to_remove in excerpts_removed { for excerpt_to_remove in excerpts_removed {
self.update_tasks.remove(&excerpt_to_remove); self.update_tasks.remove(excerpt_to_remove);
if let Some(cached_hints) = self.hints.remove(&excerpt_to_remove) { if let Some(cached_hints) = self.hints.remove(excerpt_to_remove) {
let cached_hints = cached_hints.read(); let cached_hints = cached_hints.read();
to_remove.extend(cached_hints.ordered_hints.iter().copied()); to_remove.extend(cached_hints.ordered_hints.iter().copied());
} }

View file

@ -71,7 +71,7 @@ impl Anchor {
if self_excerpt_id == ExcerptId::min() || self_excerpt_id == ExcerptId::max() { if self_excerpt_id == ExcerptId::min() || self_excerpt_id == ExcerptId::max() {
return Ordering::Equal; return Ordering::Equal;
} }
if let Some(excerpt) = snapshot.excerpt(self.excerpt_id) { if let Some(excerpt) = snapshot.excerpt(self_excerpt_id) {
let text_cmp = self.text_anchor.cmp(&other.text_anchor, &excerpt.buffer); let text_cmp = self.text_anchor.cmp(&other.text_anchor, &excerpt.buffer);
if text_cmp.is_ne() { if text_cmp.is_ne() {
return text_cmp; return text_cmp;

View file

@ -6041,7 +6041,7 @@ impl MultiBufferSnapshot {
return &entry.locator; return &entry.locator;
} }
} }
panic!("invalid excerpt id {:?}", id) panic!("invalid excerpt id {id:?}")
} }
} }