diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 801b500e8c..8b12c2be50 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -132,7 +132,7 @@ pub use multi_buffer::{ }; use multi_buffer::{ ExcerptInfo, ExpandExcerptDirection, MultiBufferDiffHunk, MultiBufferPoint, MultiBufferRow, - ToOffsetUtf16, + MultiOrSingleBufferOffsetRange, ToOffsetUtf16, }; use project::{ lsp_store::{CompletionDocumentation, FormatTrigger, LspFormatTarget, OpenLspBufferHandle}, @@ -10738,7 +10738,10 @@ impl Editor { while let Some((node, containing_range)) = buffer.syntax_ancestor(new_range.clone()) { new_node = Some(node); - new_range = containing_range; + new_range = match containing_range { + MultiOrSingleBufferOffsetRange::Single(_) => break, + MultiOrSingleBufferOffsetRange::Multi(range) => range, + }; if !display_map.intersects_fold(new_range.start) && !display_map.intersects_fold(new_range.end) { diff --git a/crates/editor/src/hover_popover.rs b/crates/editor/src/hover_popover.rs index a343dbf323..9df8884965 100644 --- a/crates/editor/src/hover_popover.rs +++ b/crates/editor/src/hover_popover.rs @@ -15,7 +15,7 @@ use itertools::Itertools; use language::{DiagnosticEntry, Language, LanguageRegistry}; use lsp::DiagnosticSeverity; use markdown::{Markdown, MarkdownStyle}; -use multi_buffer::ToOffset; +use multi_buffer::{MultiOrSingleBufferOffsetRange, ToOffset}; use project::{HoverBlock, HoverBlockKind, InlayHintLabelPart}; use settings::Settings; use std::{borrow::Cow, cell::RefCell}; @@ -447,11 +447,13 @@ fn show_hover( }) .or_else(|| { let snapshot = &snapshot.buffer_snapshot; - let offset_range = snapshot.syntax_ancestor(anchor..anchor)?.1; - Some( - snapshot.anchor_before(offset_range.start) - ..snapshot.anchor_after(offset_range.end), - ) + match snapshot.syntax_ancestor(anchor..anchor)?.1 { + MultiOrSingleBufferOffsetRange::Multi(range) => Some( + snapshot.anchor_before(range.start) + ..snapshot.anchor_after(range.end), + ), + MultiOrSingleBufferOffsetRange::Single(_) => None, + } }) .unwrap_or_else(|| anchor..anchor); diff --git a/crates/multi_buffer/src/multi_buffer.rs b/crates/multi_buffer/src/multi_buffer.rs index 9ff81458e1..34988a6b2f 100644 --- a/crates/multi_buffer/src/multi_buffer.rs +++ b/crates/multi_buffer/src/multi_buffer.rs @@ -78,6 +78,12 @@ pub struct MultiBuffer { capability: Capability, } +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum MultiOrSingleBufferOffsetRange { + Single(Range), + Multi(Range), +} + #[derive(Clone, Debug, PartialEq, Eq)] pub enum Event { ExcerptsAdded { @@ -5682,13 +5688,19 @@ impl MultiBufferSnapshot { pub fn syntax_ancestor( &self, range: Range, - ) -> Option<(tree_sitter::Node, Range)> { + ) -> Option<(tree_sitter::Node, MultiOrSingleBufferOffsetRange)> { let range = range.start.to_offset(self)..range.end.to_offset(self); let mut excerpt = self.excerpt_containing(range.clone())?; let node = excerpt .buffer() .syntax_ancestor(excerpt.map_range_to_buffer(range))?; - Some((node, excerpt.map_range_from_buffer(node.byte_range()))) + let node_range = node.byte_range(); + let range = if excerpt.contains_buffer_range(node_range.clone()) { + MultiOrSingleBufferOffsetRange::Multi(excerpt.map_range_from_buffer(node_range)) + } else { + MultiOrSingleBufferOffsetRange::Single(node_range) + }; + Some((node, range)) } pub fn outline(&self, theme: Option<&SyntaxTheme>) -> Option> { @@ -6660,9 +6672,17 @@ impl<'a> MultiBufferExcerpt<'a> { /// Map a range within the [`Buffer`] to a range within the [`MultiBuffer`] pub fn map_range_from_buffer(&mut self, buffer_range: Range) -> Range { + if buffer_range.start < self.buffer_offset { + log::warn!("Attempting to map a range from a buffer offset that starts before the current buffer offset"); + return buffer_range; + } let overshoot = buffer_range.start - self.buffer_offset; let excerpt_offset = ExcerptDimension(self.excerpt_offset.0 + overshoot); self.diff_transforms.seek(&excerpt_offset, Bias::Right, &()); + if excerpt_offset.0 < self.diff_transforms.start().1 .0 { + log::warn!("Attempting to map a range from a buffer offset that starts before the current buffer offset"); + return buffer_range; + } let overshoot = excerpt_offset.0 - self.diff_transforms.start().1 .0; let start = self.diff_transforms.start().0 .0 + overshoot;