multi_buffer: Refactor diff_transforms field into a separate struct (#32237)

A minor refactor ~needed to unblock #22546; it's pretty hard to add an
extra field to `diff_transforms` dimension, as it is a 2-tuple (which
uses a blanket impl)

Release Notes:

- N/A
This commit is contained in:
Piotr Osiewicz 2025-06-06 13:06:42 +02:00 committed by GitHub
parent cd0ef4b982
commit 7afee64119
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -43,7 +43,7 @@ use std::{
sync::Arc, sync::Arc,
time::{Duration, Instant}, time::{Duration, Instant},
}; };
use sum_tree::{Bias, Cursor, SumTree, TreeMap}; use sum_tree::{Bias, Cursor, Dimension, SumTree, Summary, TreeMap};
use text::{ use text::{
BufferId, Edit, LineIndent, TextSummary, BufferId, Edit, LineIndent, TextSummary,
locator::Locator, locator::Locator,
@ -417,8 +417,7 @@ struct Excerpt {
#[derive(Clone)] #[derive(Clone)]
pub struct MultiBufferExcerpt<'a> { pub struct MultiBufferExcerpt<'a> {
excerpt: &'a Excerpt, excerpt: &'a Excerpt,
diff_transforms: diff_transforms: sum_tree::Cursor<'a, DiffTransform, DiffTransforms<usize>>,
sum_tree::Cursor<'a, DiffTransform, (OutputDimension<usize>, ExcerptDimension<usize>)>,
offset: usize, offset: usize,
excerpt_offset: ExcerptDimension<usize>, excerpt_offset: ExcerptDimension<usize>,
buffer_offset: usize, buffer_offset: usize,
@ -506,10 +505,36 @@ pub struct ReversedMultiBufferBytes<'a> {
chunk: &'a [u8], chunk: &'a [u8],
} }
#[derive(Clone)]
struct DiffTransforms<D> {
output_dimension: OutputDimension<D>,
excerpt_dimension: ExcerptDimension<D>,
}
impl<'a, D: TextDimension> Dimension<'a, DiffTransformSummary> for DiffTransforms<D> {
fn zero(cx: &<DiffTransformSummary as sum_tree::Summary>::Context) -> Self {
Self {
output_dimension: OutputDimension::zero(cx),
excerpt_dimension: <ExcerptDimension<D> as Dimension<'a, DiffTransformSummary>>::zero(
cx,
),
}
}
fn add_summary(
&mut self,
summary: &'a DiffTransformSummary,
cx: &<DiffTransformSummary as sum_tree::Summary>::Context,
) {
self.output_dimension.add_summary(summary, cx);
self.excerpt_dimension.add_summary(summary, cx);
}
}
#[derive(Clone)] #[derive(Clone)]
struct MultiBufferCursor<'a, D: TextDimension> { struct MultiBufferCursor<'a, D: TextDimension> {
excerpts: Cursor<'a, Excerpt, ExcerptDimension<D>>, excerpts: Cursor<'a, Excerpt, ExcerptDimension<D>>,
diff_transforms: Cursor<'a, DiffTransform, (OutputDimension<D>, ExcerptDimension<D>)>, diff_transforms: Cursor<'a, DiffTransform, DiffTransforms<D>>,
diffs: &'a TreeMap<BufferId, BufferDiffSnapshot>, diffs: &'a TreeMap<BufferId, BufferDiffSnapshot>,
cached_region: Option<MultiBufferRegion<'a, D>>, cached_region: Option<MultiBufferRegion<'a, D>>,
} }
@ -5267,18 +5292,16 @@ impl MultiBufferSnapshot {
excerpts.seek(&Some(start_locator), Bias::Left, &()); excerpts.seek(&Some(start_locator), Bias::Left, &());
excerpts.prev(&()); excerpts.prev(&());
let mut diff_transforms = self let mut diff_transforms = self.diff_transforms.cursor::<DiffTransforms<usize>>(&());
.diff_transforms
.cursor::<(OutputDimension<usize>, ExcerptDimension<usize>)>(&());
diff_transforms.seek(&excerpts.start().1, Bias::Left, &()); diff_transforms.seek(&excerpts.start().1, Bias::Left, &());
if diff_transforms.end(&()).1 < excerpts.start().1 { if diff_transforms.end(&()).excerpt_dimension < excerpts.start().1 {
diff_transforms.next(&()); diff_transforms.next(&());
} }
let excerpt = excerpts.item()?; let excerpt = excerpts.item()?;
Some(MultiBufferExcerpt { Some(MultiBufferExcerpt {
excerpt, excerpt,
offset: diff_transforms.start().0.0, offset: diff_transforms.start().output_dimension.0,
buffer_offset: excerpt.range.context.start.to_offset(&excerpt.buffer), buffer_offset: excerpt.range.context.start.to_offset(&excerpt.buffer),
excerpt_offset: excerpts.start().1.clone(), excerpt_offset: excerpts.start().1.clone(),
diff_transforms, diff_transforms,
@ -6386,13 +6409,15 @@ where
self.cached_region.take(); self.cached_region.take();
self.diff_transforms self.diff_transforms
.seek(&OutputDimension(*position), Bias::Right, &()); .seek(&OutputDimension(*position), Bias::Right, &());
if self.diff_transforms.item().is_none() && *position == self.diff_transforms.start().0.0 { if self.diff_transforms.item().is_none()
&& *position == self.diff_transforms.start().output_dimension.0
{
self.diff_transforms.prev(&()); self.diff_transforms.prev(&());
} }
let mut excerpt_position = self.diff_transforms.start().1.0; let mut excerpt_position = self.diff_transforms.start().excerpt_dimension.0;
if let Some(DiffTransform::BufferContent { .. }) = self.diff_transforms.item() { if let Some(DiffTransform::BufferContent { .. }) = self.diff_transforms.item() {
let overshoot = *position - self.diff_transforms.start().0.0; let overshoot = *position - self.diff_transforms.start().output_dimension.0;
excerpt_position.add_assign(&overshoot); excerpt_position.add_assign(&overshoot);
} }
@ -6407,12 +6432,14 @@ where
self.cached_region.take(); self.cached_region.take();
self.diff_transforms self.diff_transforms
.seek_forward(&OutputDimension(*position), Bias::Right, &()); .seek_forward(&OutputDimension(*position), Bias::Right, &());
if self.diff_transforms.item().is_none() && *position == self.diff_transforms.start().0.0 { if self.diff_transforms.item().is_none()
&& *position == self.diff_transforms.start().output_dimension.0
{
self.diff_transforms.prev(&()); self.diff_transforms.prev(&());
} }
let overshoot = *position - self.diff_transforms.start().0.0; let overshoot = *position - self.diff_transforms.start().output_dimension.0;
let mut excerpt_position = self.diff_transforms.start().1.0; let mut excerpt_position = self.diff_transforms.start().excerpt_dimension.0;
if let Some(DiffTransform::BufferContent { .. }) = self.diff_transforms.item() { if let Some(DiffTransform::BufferContent { .. }) = self.diff_transforms.item() {
excerpt_position.add_assign(&overshoot); excerpt_position.add_assign(&overshoot);
} }
@ -6438,8 +6465,8 @@ where
self.cached_region.take(); self.cached_region.take();
self.diff_transforms self.diff_transforms
.seek(self.excerpts.start(), Bias::Left, &()); .seek(self.excerpts.start(), Bias::Left, &());
if self.diff_transforms.end(&()).1 == *self.excerpts.start() if self.diff_transforms.end(&()).excerpt_dimension == *self.excerpts.start()
&& self.diff_transforms.start().1 < *self.excerpts.start() && self.diff_transforms.start().excerpt_dimension < *self.excerpts.start()
&& self.diff_transforms.next_item().is_some() && self.diff_transforms.next_item().is_some()
{ {
self.diff_transforms.next(&()); self.diff_transforms.next(&());
@ -6448,12 +6475,17 @@ where
fn next(&mut self) { fn next(&mut self) {
self.cached_region.take(); self.cached_region.take();
match self.diff_transforms.end(&()).1.cmp(&self.excerpts.end(&())) { match self
.diff_transforms
.end(&())
.excerpt_dimension
.cmp(&self.excerpts.end(&()))
{
cmp::Ordering::Less => self.diff_transforms.next(&()), cmp::Ordering::Less => self.diff_transforms.next(&()),
cmp::Ordering::Greater => self.excerpts.next(&()), cmp::Ordering::Greater => self.excerpts.next(&()),
cmp::Ordering::Equal => { cmp::Ordering::Equal => {
self.diff_transforms.next(&()); self.diff_transforms.next(&());
if self.diff_transforms.end(&()).1 > self.excerpts.end(&()) if self.diff_transforms.end(&()).excerpt_dimension > self.excerpts.end(&())
|| self.diff_transforms.item().is_none() || self.diff_transforms.item().is_none()
{ {
self.excerpts.next(&()); self.excerpts.next(&());
@ -6474,12 +6506,17 @@ where
fn prev(&mut self) { fn prev(&mut self) {
self.cached_region.take(); self.cached_region.take();
match self.diff_transforms.start().1.cmp(self.excerpts.start()) { match self
.diff_transforms
.start()
.excerpt_dimension
.cmp(self.excerpts.start())
{
cmp::Ordering::Less => self.excerpts.prev(&()), cmp::Ordering::Less => self.excerpts.prev(&()),
cmp::Ordering::Greater => self.diff_transforms.prev(&()), cmp::Ordering::Greater => self.diff_transforms.prev(&()),
cmp::Ordering::Equal => { cmp::Ordering::Equal => {
self.diff_transforms.prev(&()); self.diff_transforms.prev(&());
if self.diff_transforms.start().1 < *self.excerpts.start() if self.diff_transforms.start().excerpt_dimension < *self.excerpts.start()
|| self.diff_transforms.item().is_none() || self.diff_transforms.item().is_none()
{ {
self.excerpts.prev(&()); self.excerpts.prev(&());
@ -6496,9 +6533,9 @@ where
} }
fn is_at_start_of_excerpt(&mut self) -> bool { fn is_at_start_of_excerpt(&mut self) -> bool {
if self.diff_transforms.start().1 > *self.excerpts.start() { if self.diff_transforms.start().excerpt_dimension > *self.excerpts.start() {
return false; return false;
} else if self.diff_transforms.start().1 < *self.excerpts.start() { } else if self.diff_transforms.start().excerpt_dimension < *self.excerpts.start() {
return true; return true;
} }
@ -6512,9 +6549,9 @@ where
} }
fn is_at_end_of_excerpt(&mut self) -> bool { fn is_at_end_of_excerpt(&mut self) -> bool {
if self.diff_transforms.end(&()).1 < self.excerpts.end(&()) { if self.diff_transforms.end(&()).excerpt_dimension < self.excerpts.end(&()) {
return false; return false;
} else if self.diff_transforms.end(&()).1 > self.excerpts.end(&()) } else if self.diff_transforms.end(&()).excerpt_dimension > self.excerpts.end(&())
|| self.diff_transforms.item().is_none() || self.diff_transforms.item().is_none()
{ {
return true; return true;
@ -6535,7 +6572,7 @@ where
let buffer = &excerpt.buffer; let buffer = &excerpt.buffer;
let buffer_context_start = excerpt.range.context.start.summary::<D>(buffer); let buffer_context_start = excerpt.range.context.start.summary::<D>(buffer);
let mut buffer_start = buffer_context_start; let mut buffer_start = buffer_context_start;
let overshoot = self.diff_transforms.end(&()).1.0 - self.excerpts.start().0; let overshoot = self.diff_transforms.end(&()).excerpt_dimension.0 - self.excerpts.start().0;
buffer_start.add_assign(&overshoot); buffer_start.add_assign(&overshoot);
Some(buffer_start) Some(buffer_start)
} }
@ -6557,8 +6594,8 @@ where
let buffer_range_len = rope_cursor.summary::<D>(base_text_byte_range.end); let buffer_range_len = rope_cursor.summary::<D>(base_text_byte_range.end);
let mut buffer_end = buffer_start; let mut buffer_end = buffer_start;
buffer_end.add_assign(&buffer_range_len); buffer_end.add_assign(&buffer_range_len);
let start = self.diff_transforms.start().0.0; let start = self.diff_transforms.start().output_dimension.0;
let end = self.diff_transforms.end(&()).0.0; let end = self.diff_transforms.end(&()).output_dimension.0;
return Some(MultiBufferRegion { return Some(MultiBufferRegion {
buffer, buffer,
excerpt, excerpt,
@ -6577,28 +6614,32 @@ where
let buffer = &excerpt.buffer; let buffer = &excerpt.buffer;
let buffer_context_start = excerpt.range.context.start.summary::<D>(buffer); let buffer_context_start = excerpt.range.context.start.summary::<D>(buffer);
let mut start = self.diff_transforms.start().0.0; let mut start = self.diff_transforms.start().output_dimension.0;
let mut buffer_start = buffer_context_start; let mut buffer_start = buffer_context_start;
if self.diff_transforms.start().1 < *self.excerpts.start() { if self.diff_transforms.start().excerpt_dimension < *self.excerpts.start() {
let overshoot = self.excerpts.start().0 - self.diff_transforms.start().1.0; let overshoot =
self.excerpts.start().0 - self.diff_transforms.start().excerpt_dimension.0;
start.add_assign(&overshoot); start.add_assign(&overshoot);
} else { } else {
let overshoot = self.diff_transforms.start().1.0 - self.excerpts.start().0; let overshoot =
self.diff_transforms.start().excerpt_dimension.0 - self.excerpts.start().0;
buffer_start.add_assign(&overshoot); buffer_start.add_assign(&overshoot);
} }
let mut end; let mut end;
let mut buffer_end; let mut buffer_end;
let has_trailing_newline; let has_trailing_newline;
if self.diff_transforms.end(&()).1.0 < self.excerpts.end(&()).0 { if self.diff_transforms.end(&()).excerpt_dimension.0 < self.excerpts.end(&()).0 {
let overshoot = self.diff_transforms.end(&()).1.0 - self.excerpts.start().0; let overshoot =
end = self.diff_transforms.end(&()).0.0; self.diff_transforms.end(&()).excerpt_dimension.0 - self.excerpts.start().0;
end = self.diff_transforms.end(&()).output_dimension.0;
buffer_end = buffer_context_start; buffer_end = buffer_context_start;
buffer_end.add_assign(&overshoot); buffer_end.add_assign(&overshoot);
has_trailing_newline = false; has_trailing_newline = false;
} else { } else {
let overshoot = self.excerpts.end(&()).0 - self.diff_transforms.start().1.0; let overshoot =
end = self.diff_transforms.start().0.0; self.excerpts.end(&()).0 - self.diff_transforms.start().excerpt_dimension.0;
end = self.diff_transforms.start().output_dimension.0;
end.add_assign(&overshoot); end.add_assign(&overshoot);
buffer_end = excerpt.range.context.end.summary::<D>(buffer); buffer_end = excerpt.range.context.end.summary::<D>(buffer);
has_trailing_newline = excerpt.has_trailing_newline; has_trailing_newline = excerpt.has_trailing_newline;
@ -6994,9 +7035,9 @@ impl<'a> MultiBufferExcerpt<'a> {
} }
fn map_offset_to_buffer_internal(&self, offset: usize) -> usize { fn map_offset_to_buffer_internal(&self, offset: usize) -> usize {
let mut excerpt_offset = self.diff_transforms.start().1.clone(); let mut excerpt_offset = self.diff_transforms.start().excerpt_dimension.clone();
if let Some(DiffTransform::BufferContent { .. }) = self.diff_transforms.item() { if let Some(DiffTransform::BufferContent { .. }) = self.diff_transforms.item() {
excerpt_offset.0 += offset - self.diff_transforms.start().0.0; excerpt_offset.0 += offset - self.diff_transforms.start().output_dimension.0;
}; };
let offset_in_excerpt = excerpt_offset.0.saturating_sub(self.excerpt_offset.0); let offset_in_excerpt = excerpt_offset.0.saturating_sub(self.excerpt_offset.0);
self.buffer_offset + offset_in_excerpt self.buffer_offset + offset_in_excerpt
@ -7019,22 +7060,22 @@ impl<'a> MultiBufferExcerpt<'a> {
let overshoot = buffer_range.start - self.buffer_offset; let overshoot = buffer_range.start - self.buffer_offset;
let excerpt_offset = ExcerptDimension(self.excerpt_offset.0 + overshoot); let excerpt_offset = ExcerptDimension(self.excerpt_offset.0 + overshoot);
self.diff_transforms.seek(&excerpt_offset, Bias::Right, &()); self.diff_transforms.seek(&excerpt_offset, Bias::Right, &());
if excerpt_offset.0 < self.diff_transforms.start().1.0 { if excerpt_offset.0 < self.diff_transforms.start().excerpt_dimension.0 {
log::warn!( log::warn!(
"Attempting to map a range from a buffer offset that starts before the current buffer offset" "Attempting to map a range from a buffer offset that starts before the current buffer offset"
); );
return buffer_range; return buffer_range;
} }
let overshoot = excerpt_offset.0 - self.diff_transforms.start().1.0; let overshoot = excerpt_offset.0 - self.diff_transforms.start().excerpt_dimension.0;
let start = self.diff_transforms.start().0.0 + overshoot; let start = self.diff_transforms.start().output_dimension.0 + overshoot;
let end = if buffer_range.end > buffer_range.start { let end = if buffer_range.end > buffer_range.start {
let overshoot = buffer_range.end - self.buffer_offset; let overshoot = buffer_range.end - self.buffer_offset;
let excerpt_offset = ExcerptDimension(self.excerpt_offset.0 + overshoot); let excerpt_offset = ExcerptDimension(self.excerpt_offset.0 + overshoot);
self.diff_transforms self.diff_transforms
.seek_forward(&excerpt_offset, Bias::Right, &()); .seek_forward(&excerpt_offset, Bias::Right, &());
let overshoot = excerpt_offset.0 - self.diff_transforms.start().1.0; let overshoot = excerpt_offset.0 - self.diff_transforms.start().excerpt_dimension.0;
self.diff_transforms.start().0.0 + overshoot self.diff_transforms.start().output_dimension.0 + overshoot
} else { } else {
start start
}; };
@ -7201,7 +7242,7 @@ impl sum_tree::Summary for ExcerptSummary {
fn add_summary(&mut self, summary: &Self, _: &()) { fn add_summary(&mut self, summary: &Self, _: &()) {
debug_assert!(summary.excerpt_locator > self.excerpt_locator); debug_assert!(summary.excerpt_locator > self.excerpt_locator);
self.excerpt_locator = summary.excerpt_locator.clone(); self.excerpt_locator = summary.excerpt_locator.clone();
self.text.add_summary(&summary.text, &()); Summary::add_summary(&mut self.text, &summary.text, &());
self.widest_line_number = cmp::max(self.widest_line_number, summary.widest_line_number); self.widest_line_number = cmp::max(self.widest_line_number, summary.widest_line_number);
} }
} }
@ -7310,16 +7351,11 @@ impl<D: TextDimension + Ord> sum_tree::SeekTarget<'_, DiffTransformSummary, Diff
} }
} }
impl<D: TextDimension + Ord> impl<D: TextDimension + Ord> sum_tree::SeekTarget<'_, DiffTransformSummary, DiffTransforms<D>>
sum_tree::SeekTarget<'_, DiffTransformSummary, (OutputDimension<D>, ExcerptDimension<D>)>
for ExcerptDimension<D> for ExcerptDimension<D>
{ {
fn cmp( fn cmp(&self, cursor_location: &DiffTransforms<D>, _: &()) -> cmp::Ordering {
&self, Ord::cmp(&self.0, &cursor_location.excerpt_dimension.0)
cursor_location: &(OutputDimension<D>, ExcerptDimension<D>),
_: &(),
) -> cmp::Ordering {
Ord::cmp(&self.0, &cursor_location.1.0)
} }
} }
@ -7333,6 +7369,14 @@ impl<'a, D: TextDimension> sum_tree::Dimension<'a, DiffTransformSummary> for Exc
} }
} }
impl<D: TextDimension + Ord> sum_tree::SeekTarget<'_, DiffTransformSummary, DiffTransforms<D>>
for OutputDimension<D>
{
fn cmp(&self, cursor_location: &DiffTransforms<D>, _: &()) -> cmp::Ordering {
Ord::cmp(&self.0, &cursor_location.output_dimension.0)
}
}
impl<'a, D: TextDimension> sum_tree::Dimension<'a, DiffTransformSummary> for OutputDimension<D> { impl<'a, D: TextDimension> sum_tree::Dimension<'a, DiffTransformSummary> for OutputDimension<D> {
fn zero(_: &()) -> Self { fn zero(_: &()) -> Self {
OutputDimension(D::default()) OutputDimension(D::default())
@ -7401,7 +7445,7 @@ impl Iterator for MultiBufferRows<'_> {
if let Some(next_region) = self.cursor.region() { if let Some(next_region) = self.cursor.region() {
region = next_region; region = next_region;
} else { } else {
if self.point == self.cursor.diff_transforms.end(&()).0.0 { if self.point == self.cursor.diff_transforms.end(&()).output_dimension.0 {
let multibuffer_row = MultiBufferRow(self.point.row); let multibuffer_row = MultiBufferRow(self.point.row);
let last_excerpt = self let last_excerpt = self
.cursor .cursor