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