Allow buffer search to search deleted hunks (#23632)

Closes #ISSUE

Release Notes:

- N/A
This commit is contained in:
Conrad Irwin 2025-01-28 14:48:16 -07:00 committed by GitHub
parent 22afec32cf
commit 1973bf5268
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 80 additions and 50 deletions

View file

@ -1507,26 +1507,42 @@ impl SearchableItem for Editor {
search_within_ranges
};
for (search_buffer, search_range, excerpt_id) in
buffer.ranges_to_buffer_ranges(search_within_ranges.into_iter())
{
ranges.extend(
query
.search(search_buffer, Some(search_range.clone()))
.await
.into_iter()
.map(|match_range| {
let start =
search_buffer.anchor_after(search_range.start + match_range.start);
let end =
search_buffer.anchor_before(search_range.start + match_range.end);
Anchor::range_in_buffer(
excerpt_id,
search_buffer.remote_id(),
start..end,
)
}),
);
for range in search_within_ranges {
for (search_buffer, search_range, excerpt_id, deleted_hunk_anchor) in
buffer.range_to_buffer_ranges_with_deleted_hunks(range)
{
ranges.extend(
query
.search(search_buffer, Some(search_range.clone()))
.await
.into_iter()
.map(|match_range| {
if let Some(deleted_hunk_anchor) = deleted_hunk_anchor {
let start = search_buffer
.anchor_after(search_range.start + match_range.start);
let end = search_buffer
.anchor_before(search_range.start + match_range.end);
Anchor {
diff_base_anchor: Some(start),
..deleted_hunk_anchor
}..Anchor {
diff_base_anchor: Some(end),
..deleted_hunk_anchor
}
} else {
let start = search_buffer
.anchor_after(search_range.start + match_range.start);
let end = search_buffer
.anchor_before(search_range.start + match_range.end);
Anchor::range_in_buffer(
excerpt_id,
search_buffer.remote_id(),
start..end,
)
}
}),
);
}
}
ranges

View file

@ -3376,6 +3376,49 @@ impl MultiBufferSnapshot {
result
}
pub fn range_to_buffer_ranges_with_deleted_hunks<T: ToOffset>(
&self,
range: Range<T>,
) -> impl Iterator<Item = (&BufferSnapshot, Range<usize>, ExcerptId, Option<Anchor>)> + '_ {
let start = range.start.to_offset(&self);
let end = range.end.to_offset(&self);
let mut cursor = self.cursor::<usize>();
cursor.seek(&start);
std::iter::from_fn(move || {
let region = cursor.region()?;
if region.range.start > end {
return None;
}
let start_overshoot = start.saturating_sub(region.range.start);
let end_overshoot = end.saturating_sub(region.range.start);
let start = region
.buffer_range
.end
.min(region.buffer_range.start + start_overshoot);
let end = region
.buffer_range
.end
.min(region.buffer_range.start + end_overshoot);
let region_excerpt_id = region.excerpt.id;
let deleted_hunk_anchor = if region.is_main_buffer {
None
} else {
Some(self.anchor_before(region.range.start))
};
let result = (
region.buffer,
start..end,
region_excerpt_id,
deleted_hunk_anchor,
);
cursor.next();
Some(result)
})
}
/// Retrieves buffer metadata for the given range, and converts it into multi-buffer
/// coordinates.
///
@ -4205,36 +4248,7 @@ impl MultiBufferSnapshot {
where
D: TextDimension + Ord + Sub<D, Output = D>,
{
let mut cursor = self.excerpts.cursor::<ExcerptSummary>(&());
let locator = self.excerpt_locator_for_id(anchor.excerpt_id);
cursor.seek(locator, Bias::Left, &());
if cursor.item().is_none() {
cursor.next(&());
}
let mut excerpt_position = D::from_text_summary(&cursor.start().text);
if let Some(excerpt) = cursor.item() {
if excerpt.id == anchor.excerpt_id {
let excerpt_buffer_start =
excerpt.range.context.start.summary::<D>(&excerpt.buffer);
let excerpt_buffer_end = excerpt.range.context.end.summary::<D>(&excerpt.buffer);
let buffer_position = cmp::min(
excerpt_buffer_end,
anchor.text_anchor.summary::<D>(&excerpt.buffer),
);
if buffer_position > excerpt_buffer_start {
excerpt_position.add_assign(&(buffer_position - excerpt_buffer_start));
}
}
}
let mut diff_transforms_cursor = self
.diff_transforms
.cursor::<(ExcerptDimension<D>, OutputDimension<D>)>(&());
diff_transforms_cursor.seek(&ExcerptDimension(excerpt_position), Bias::Left, &());
self.resolve_summary_for_anchor(anchor, excerpt_position, &mut diff_transforms_cursor)
self.summaries_for_anchors([anchor])[0]
}
fn resolve_summary_for_anchor<D>(